From 7037df2eb2563c4add78a38551e185f9ee0f5cd5 Mon Sep 17 00:00:00 2001 From: northking-super Date: Thu, 9 Dec 2021 06:50:11 +0000 Subject: [PATCH] add hispark_aries Signed-off-by: northking-super --- hispark_aries/BUILD.gn | 8 + hispark_aries/NOTICE | 3002 +++++++++++ hispark_aries/OAT.xml | 101 + hispark_aries/README.md | 109 + hispark_aries/README_zh.md | 109 + .../figures/en-us_image_0000001133374179.png | Bin 0 -> 45752 bytes .../figures/zh-cn_image_0000001133374179.png | Bin 0 -> 45752 bytes hispark_aries/liteos_a/BUILD.gn | 24 + hispark_aries/liteos_a/board/BUILD.gn | 48 + hispark_aries/liteos_a/board/LICENSE | 177 + hispark_aries/liteos_a/board/Makefile | 27 + hispark_aries/liteos_a/board/board.c | 78 + .../liteos_a/board/include/asm/dma.h | 22 + .../board/include/asm/hal_platform_ints.h | 115 + .../liteos_a/board/include/asm/platform.h | 141 + hispark_aries/liteos_a/board/include/board.h | 49 + .../liteos_a/board/include/hisoc/clock.h | 42 + .../liteos_a/board/include/hisoc/cpu.h | 60 + .../liteos_a/board/include/hisoc/dmac.h | 202 + .../liteos_a/board/include/hisoc/flash.h | 240 + .../liteos_a/board/include/hisoc/mmc.h | 223 + .../liteos_a/board/include/hisoc/nand.h | 55 + .../liteos_a/board/include/hisoc/net.h | 37 + .../liteos_a/board/include/hisoc/random.h | 37 + .../liteos_a/board/include/hisoc/spinand.h | 95 + .../liteos_a/board/include/hisoc/spinor.h | 121 + .../liteos_a/board/include/hisoc/sys_ctrl.h | 52 + .../liteos_a/board/include/hisoc/timer.h | 60 + .../liteos_a/board/include/hisoc/uart.h | 130 + .../liteos_a/board/include/hisoc/usb3.h | 54 + .../liteos_a/board/include/platform_config.h | 36 + .../liteos_a/board/include/reset_shell.h | 48 + .../liteos_a/board/include/system_config.h | 62 + .../liteos_a/board/libs/debug/libbsp_config.a | Bin 0 -> 80896 bytes .../board/libs/release/libbsp_config.a | Bin 0 -> 75260 bytes hispark_aries/liteos_a/board/target_config.h | 123 + hispark_aries/liteos_a/config.gni | 61 + hispark_aries/liteos_a/drivers/BUILD.gn | 38 + hispark_aries/liteos_a/drivers/Kconfig | 1 + hispark_aries/ohos.build | 10 + hispark_aries/uboot/Makefile | 86 + hispark_aries/uboot/out/boot/README | 4 + .../uboot/out/boot/u-boot-hi3518ev300.bin | Bin 0 -> 288623 bytes hispark_aries/uboot/reg/LICENSE | 60 + .../uboot/reg/reg_info_hi3518ev300.bin | Bin 0 -> 3936 bytes hispark_aries/uboot/secureboot_ohos/sec_os.sh | 259 + .../secureboot_ohos/x509_creater/creater.sh | 35 + .../uboot/secureboot_release/LICENSE | 339 ++ .../uboot/secureboot_release/Makefile | 36 + .../uboot/secureboot_release/aeskey2reg.c | 99 + .../secureboot_release/create_secure_boot.sh | 432 ++ .../secureboot_release/ddr_init/Makefile | 59 + .../secureboot_release/ddr_init/boot/Makefile | 19 + .../ddr_init/boot/_udivsi3.S | 76 + .../boot/hi3518ev300/lowlevel_init_v300.c | 433 ++ .../ddr_init/boot/init_regs.c | 153 + .../secureboot_release/ddr_init/boot/start.S | 202 + .../secureboot_release/ddr_init/boot/uart.S | 120 + .../uboot/secureboot_release/ddr_init/cfg.mk | 2 + .../secureboot_release/ddr_init/drv/Makefile | 20 + .../ddr_init/drv/ddr_cmd_loc.S | 9 + .../ddr_init/drv/ddr_ddrc_v500.h | 140 + .../ddr_init/drv/ddr_ddrc_v510.h | 212 + .../ddr_init/drv/ddr_ddrc_v520.h | 246 + .../ddr_init/drv/ddr_ddrt_s40.h | 93 + .../ddr_init/drv/ddr_ddrt_t12_v100.h | 93 + .../ddr_init/drv/ddr_ddrt_t16.h | 93 + .../ddr_init/drv/ddr_ddrt_t28.h | 93 + .../ddr_init/drv/ddr_ddrt_v2_0_shf0.h | 93 + .../ddr_init/drv/ddr_ddrt_v2_0_shf1.h | 93 + .../ddr_init/drv/ddr_ddrt_v2_0_shf2.h | 93 + .../ddr_init/drv/ddr_interface.h | 145 + .../ddr_init/drv/ddr_phy_s40.h | 303 ++ .../ddr_init/drv/ddr_phy_t12_v100.h | 495 ++ .../ddr_init/drv/ddr_phy_t12_v101.h | 496 ++ .../ddr_init/drv/ddr_phy_t16.h | 458 ++ .../ddr_init/drv/ddr_phy_t28.h | 459 ++ .../ddr_init/drv/ddr_training_boot.c | 248 + .../ddr_init/drv/ddr_training_console.c | 256 + .../ddr_init/drv/ddr_training_ctl.c | 300 ++ .../ddr_init/drv/ddr_training_custom.c | 106 + .../ddr_init/drv/ddr_training_custom.h | 104 + .../ddr_init/drv/ddr_training_impl.c | 4372 +++++++++++++++++ .../ddr_init/drv/ddr_training_impl.h | 449 ++ .../drv/ddr_training_internal_config.h | 173 + .../ddr_init/include/asm/sizes.h | 52 + .../ddr_init/include/barriers.h | 51 + .../ddr_init/include/common.h | 51 + .../secureboot_release/ddr_init/include/io.h | 17 + .../ddr_init/include/linux/ctype.h | 54 + .../ddr_init/include/platform.h | 50 + .../ddr_init/include/types.h | 73 + .../secureboot_release/ddr_init/linker.lds | 56 + .../secureboot_release/ddr_init/linker.lds.mk | 56 + .../secureboot_release/ddr_init/mkddrinit.sh | 25 + .../uboot/secureboot_release/hash_modify.c | 75 + .../uboot/secureboot_release/rsa2048pem.sh | 15 + .../secureboot_release/rsa2048pem/ReadMe.txt | 1 + .../uboot/secureboot_release/rsa4096pem.sh | 15 + .../secureboot_release/rsa4096pem/ReadMe.txt | 1 + .../uboot/secureboot_release/sha256.cfg | 2 + hispark_taurus/liteos_a/BUILD.gn | 4 +- hispark_taurus/liteos_a/board/BUILD.gn | 48 + hispark_taurus/liteos_a/board/LICENSE | 177 + hispark_taurus/liteos_a/board/Makefile | 27 + hispark_taurus/liteos_a/board/board.c | 174 + .../liteos_a/board/include/asm/dma.h | 22 + .../board/include/asm/hal_platform_ints.h | 128 + .../liteos_a/board/include/asm/platform.h | 156 + hispark_taurus/liteos_a/board/include/board.h | 58 + .../liteos_a/board/include/hisoc/clock.h | 42 + .../liteos_a/board/include/hisoc/cpu.h | 60 + .../liteos_a/board/include/hisoc/dmac.h | 202 + .../liteos_a/board/include/hisoc/flash.h | 240 + .../liteos_a/board/include/hisoc/mmc.h | 170 + .../liteos_a/board/include/hisoc/mmu_config.h | 127 + .../liteos_a/board/include/hisoc/nand.h | 55 + .../liteos_a/board/include/hisoc/net.h | 37 + .../liteos_a/board/include/hisoc/random.h | 37 + .../liteos_a/board/include/hisoc/spinand.h | 95 + .../liteos_a/board/include/hisoc/spinor.h | 121 + .../liteos_a/board/include/hisoc/sys_ctrl.h | 52 + .../liteos_a/board/include/hisoc/timer.h | 60 + .../liteos_a/board/include/hisoc/uart.h | 137 + .../liteos_a/board/include/hisoc/usb3.h | 53 + .../liteos_a/board/include/platform_config.h | 36 + .../liteos_a/board/include/reset_shell.h | 48 + .../liteos_a/board/include/system_config.h | 61 + .../liteos_a/board/libs/debug/libbsp_config.a | Bin 0 -> 72548 bytes .../board/libs/release/libbsp_config.a | Bin 0 -> 66912 bytes hispark_taurus/liteos_a/board/target_config.h | 135 + 131 files changed, 21007 insertions(+), 2 deletions(-) create mode 100755 hispark_aries/BUILD.gn create mode 100755 hispark_aries/NOTICE create mode 100755 hispark_aries/OAT.xml create mode 100755 hispark_aries/README.md create mode 100755 hispark_aries/README_zh.md create mode 100755 hispark_aries/figures/en-us_image_0000001133374179.png create mode 100755 hispark_aries/figures/zh-cn_image_0000001133374179.png create mode 100755 hispark_aries/liteos_a/BUILD.gn create mode 100755 hispark_aries/liteos_a/board/BUILD.gn create mode 100755 hispark_aries/liteos_a/board/LICENSE create mode 100755 hispark_aries/liteos_a/board/Makefile create mode 100755 hispark_aries/liteos_a/board/board.c create mode 100755 hispark_aries/liteos_a/board/include/asm/dma.h create mode 100755 hispark_aries/liteos_a/board/include/asm/hal_platform_ints.h create mode 100755 hispark_aries/liteos_a/board/include/asm/platform.h create mode 100755 hispark_aries/liteos_a/board/include/board.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/clock.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/cpu.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/dmac.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/flash.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/mmc.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/nand.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/net.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/random.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/spinand.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/spinor.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/sys_ctrl.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/timer.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/uart.h create mode 100755 hispark_aries/liteos_a/board/include/hisoc/usb3.h create mode 100755 hispark_aries/liteos_a/board/include/platform_config.h create mode 100755 hispark_aries/liteos_a/board/include/reset_shell.h create mode 100755 hispark_aries/liteos_a/board/include/system_config.h create mode 100755 hispark_aries/liteos_a/board/libs/debug/libbsp_config.a create mode 100755 hispark_aries/liteos_a/board/libs/release/libbsp_config.a create mode 100755 hispark_aries/liteos_a/board/target_config.h create mode 100755 hispark_aries/liteos_a/config.gni create mode 100755 hispark_aries/liteos_a/drivers/BUILD.gn create mode 100755 hispark_aries/liteos_a/drivers/Kconfig create mode 100755 hispark_aries/ohos.build create mode 100755 hispark_aries/uboot/Makefile create mode 100755 hispark_aries/uboot/out/boot/README create mode 100755 hispark_aries/uboot/out/boot/u-boot-hi3518ev300.bin create mode 100755 hispark_aries/uboot/reg/LICENSE create mode 100755 hispark_aries/uboot/reg/reg_info_hi3518ev300.bin create mode 100755 hispark_aries/uboot/secureboot_ohos/sec_os.sh create mode 100755 hispark_aries/uboot/secureboot_ohos/x509_creater/creater.sh create mode 100755 hispark_aries/uboot/secureboot_release/LICENSE create mode 100755 hispark_aries/uboot/secureboot_release/Makefile create mode 100755 hispark_aries/uboot/secureboot_release/aeskey2reg.c create mode 100755 hispark_aries/uboot/secureboot_release/create_secure_boot.sh create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/Makefile create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/Makefile create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/_udivsi3.S create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/hi3518ev300/lowlevel_init_v300.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/init_regs.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/start.S create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/boot/uart.S create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/cfg.mk create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/Makefile create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_cmd_loc.S create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v500.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v510.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v520.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_s40.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t12_v100.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t16.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t28.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf0.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf1.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf2.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_interface.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_s40.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v100.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v101.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t16.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t28.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_boot.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_console.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_ctl.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.c create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_internal_config.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/asm/sizes.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/barriers.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/common.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/io.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/linux/ctype.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/platform.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/include/types.h create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/linker.lds create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/linker.lds.mk create mode 100755 hispark_aries/uboot/secureboot_release/ddr_init/mkddrinit.sh create mode 100755 hispark_aries/uboot/secureboot_release/hash_modify.c create mode 100755 hispark_aries/uboot/secureboot_release/rsa2048pem.sh create mode 100755 hispark_aries/uboot/secureboot_release/rsa2048pem/ReadMe.txt create mode 100755 hispark_aries/uboot/secureboot_release/rsa4096pem.sh create mode 100755 hispark_aries/uboot/secureboot_release/rsa4096pem/ReadMe.txt create mode 100755 hispark_aries/uboot/secureboot_release/sha256.cfg create mode 100755 hispark_taurus/liteos_a/board/BUILD.gn create mode 100755 hispark_taurus/liteos_a/board/LICENSE create mode 100755 hispark_taurus/liteos_a/board/Makefile create mode 100755 hispark_taurus/liteos_a/board/board.c create mode 100755 hispark_taurus/liteos_a/board/include/asm/dma.h create mode 100755 hispark_taurus/liteos_a/board/include/asm/hal_platform_ints.h create mode 100755 hispark_taurus/liteos_a/board/include/asm/platform.h create mode 100755 hispark_taurus/liteos_a/board/include/board.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/clock.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/cpu.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/dmac.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/flash.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/mmc.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/mmu_config.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/nand.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/net.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/random.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/spinand.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/spinor.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/sys_ctrl.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/timer.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/uart.h create mode 100755 hispark_taurus/liteos_a/board/include/hisoc/usb3.h create mode 100755 hispark_taurus/liteos_a/board/include/platform_config.h create mode 100755 hispark_taurus/liteos_a/board/include/reset_shell.h create mode 100755 hispark_taurus/liteos_a/board/include/system_config.h create mode 100755 hispark_taurus/liteos_a/board/libs/debug/libbsp_config.a create mode 100755 hispark_taurus/liteos_a/board/libs/release/libbsp_config.a create mode 100755 hispark_taurus/liteos_a/board/target_config.h diff --git a/hispark_aries/BUILD.gn b/hispark_aries/BUILD.gn new file mode 100755 index 00000000..3c1ac2ec --- /dev/null +++ b/hispark_aries/BUILD.gn @@ -0,0 +1,8 @@ +# Copyright (C) 2020 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + +group("hispark_aries") { + deps = [] + if (ohos_kernel_type == "liteos_a") { + deps += [ "//device/soc/hisilicon/hi3518ev300/mpp:copy_mpp_libs" ] + } +} diff --git a/hispark_aries/NOTICE b/hispark_aries/NOTICE new file mode 100755 index 00000000..332078a8 --- /dev/null +++ b/hispark_aries/NOTICE @@ -0,0 +1,3002 @@ +OPEN SOURCE SOFTWARE NOTICE + +Please note we provide an open source software notice for the third party open source software along with this software and/or this software component (in the following just “this SOFTWARE”). The open source software licenses are granted by the respective right holders. + +Warranty Disclaimer +THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + +Copyright Notice and License Texts + + + +Software: Das U-Boot 2020.01 + +Copyright notice: +Copyright (C) ARM Limited +Copyright (C) 2000-2001 Deep Blue Solutions Ltd. +Copyright 2015-2016 Freescale Semiconductor, Inc. +Copyright 2017 NXP +Copyright 2017-2018 NXP +Copyright (C) 2018, STMicroelectronics - All Rights Reserved +Copyright (C) 2019, STMicroelectronics - All Rights Reserved +Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved +Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. +(C) Copyright 2014 Andreas Bießmann +(C) Copyright 2008 Semihalf +Copyright (c) 2013, Google Inc. +Copyright (c) 2017 Heinrich Schuchardt +Copyright (C) 1993, 1996, 2001, 2002 Free Software Foundation, Inc. +Copyright 2014 Google, Inc +Copyright (C) 2011 The ChromiumOS Authors. +COPYRIGHT (c) 2000 BY ABATRON AG +Copyright 2018 NXP +(C) Copyright 2013 Thomas Petazzoni +(c) 2012 Daniel Stodden +(C) Copyright 2015 DENX Software Engineering GmbH +Copyright (c) 2014 Google, Inc +Copyright 2008 Extreme Engineering Solutions, Inc. +Copyright (c) 2005-2006 Gianluigi Tiesi +Copyright (c) 2017 Imagination Technologies Ltd. +(C) Copyright 2011 Free Electrons +Copyright (C) 2012 Samsung Electronics +Copyright (C) 2016 Marvell International Ltd. +Copyright (C) 2018 MediaTek Inc. +Copyright (C) 2011 Marek Vasut +Copyright (C) 2012-2013 Marek Vasut +Copyright (C) 2012 Marek Vasut +Copyright 2009 Extreme Engineering Solutions, Inc. +Copyright 2012-2014 Freescale Semiconductor, Inc. +Copyright 2012 Freescale Semiconductor, Inc. +Copyright (C) 2017 Andes Technology +Copyright (c) 2013 Google, Inc +Copyright 2013 Freescale Semiconductor, Inc. +(C) Copyright 2015 Google, Inc +(C) 2017 Theobroma Systems Design und Consulting GmbH +(C) Copyright 2015 Google, Inc +Copyright 2019 Google LLC +Copyright (C) 2014 Charles Manning +Copyright (c) 2019, Simon Goldschmidt +Copyright © 2016 NextThing Co. +Copyright © 2016 Free Electrons +(C) Copyright 2016 DENX Software Engineering GmbH +Copyright (C) 2015 Nathan Rossi +Copyright (C) 2018 Alexander Graf +Copyright (C) 2016 Michal Simek +Copyright (C) 2019 Luca Ceresoli +Copyright (C) 2018 Michal Simek +Copyright (C) 2015 Beckhoff Automation GmbH +Copyright (C) 2011 Freescale Semiconductor, Inc. +Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG +Copyright (C) 2012 Freescale Semiconductor, Inc. +Copyright (C) 2013 Ludovic Desroches +Copyright (C) 2018 Álvaro Fernández Rojas +Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com +Copyright 2014 Maxime Ripard +(C) Copyright 2011 Freescale Semiconductor, Inc. +(C) Copyright 2009 Freescale Semiconductor, Inc. +Copyright (C) 2017 Beckhoff Automation GmbH & Co. KG +Copyright (C) 2016 Imagination Technologies +Copyright (C) 1999-2015 Tensilica Inc. +Copyright (C) 1999-2015 Cadence Design Systems Inc. +(C) Copyright 2015 Texas Insturments +(C) Copyright 2008 Texas Insturments +Copyright (c) 2018 Heinrich Schuchardt +Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2016 Chen-Yu Tsai +Copyright (C) 2013 - ARM Ltd +Copyright (C) 2014 STMicroelectronics All Rights Reserved +(C) Copyright 2016 Beniamino Galvani +(C) Copyright 2018 Neil Armstrong +(C) Copyright 2019 Julien Masson +(C) Copyright 2019 Neil Armstrong +Copyright 2008 Freescale Semiconductor, Inc. +Copyright 2004, 2007 Freescale Semiconductor, Inc. +Copyright (C) Freescale Semiconductor, Inc. 2006-2007 +Copyright (C) 2015 Paul Kocialkowski +Copyright (C) 2014 STMicroelectronics +Copyright (C) 2017, STMicroelectronics - All Rights Reserved +(C) Copyright 2009 Magnus Lilja +(c) 2007 Pengutronix, Sascha Hauer +Copyright 2013 Broadcom Corporation. +Copyright 2014 Broadcom Corporation. +Copyright (c) 2015 Samsung Electronics +Copyright 2018 Google LLC +Copyright (C) 2015 Google, Inc +(C) 2018 Theobroma Systems Design und Consulting GmbH +Copyright (C) 2019 Intel Corporation +Copyright (C) 2018 Texas Instruments Incorporated +Copyright (C) 2019 STMicroelectronics - All Rights Reserved +Copyright (c) 2015 National Instruments +Copyright (C) 2018 Xilinx, Inc. +Copyright (C) 2013 Google, Inc +Copyright (c) 2016, NVIDIA CORPORATION. +(C) Copyright 2019 - Texas Instruments Incorporated - http://www.ti.com/ +Copyright (c) 2018 Google, Inc +Copyright (C) 2019 Ramon Fried +Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2017 Google, Inc +Copyright (c) 2018, STMicroelectronics +Copyright (C) 2018 Ramon Fried +(C) Copyright 2015 Mateusz Kulikowski +Copyright (C) 2018 Linaro Limited +Copyright (C) 2015 Thomas Chou +Copyright (C) 2018, Bin Meng +Copyright 2017 Google, Inc +Copyright (C) 2012 Altera Corporation +(c) Copyright 2015 Xilinx, Inc. All rights reserved. +Copyright (C) 2010 Albert ARIBAUD +Copyright (C) Marvell International Ltd. and its affiliates +Copyright (C) 2006 Freescale Semiconductor, Inc. +Copyright (C) 2007 Logic Product Development, Inc. +Copyright (C) 2007 MontaVista Software, Inc. +Copyright (C) 2015-2016 Wills Wang +Copyright (C) 2001 Red Hat, Inc. +Copyright 2014 Freescale Semiconductor +Copyright 2014 Freescale Semiconductor, Inc. +Copyright 2008-2014 Freescale Semiconductor, Inc. +Copyright 2007-2014 Freescale Semiconductor, Inc. +Copyright 2009-2013 Freescale Semiconductor, Inc. +Copyright 2010-2011 Freescale Semiconductor, Inc. +Copyright (c) 1999 Dan Malek (dmalek@jlc.net) +Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com) +Copyright (c) 2003 Motorola,Inc. +Copyright 2004,2007-2011 Freescale Semiconductor, Inc. +(C) Copyright 2002, 2003 Motorola Inc. +Copyright 2007-2011 Freescale Semiconductor, Inc. +(C) Copyright 2003 Motorola Inc. +Copyright 2009-2012 Freescale Semiconductor, Inc +Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) +(C) Copyright 2000 Sysgo Real-Time Solutions, GmbH +Copyright 2009-2011 Freescale Semiconductor, Inc. +Copyright 2009-2010 Freescale Semiconductor, Inc. +(C) Copyright 2003 Motorola Inc. (MPC85xx port) +Copyright 2008-2011 Freescale Semiconductor, Inc. +Copyright 2008,2010 Freescale Semiconductor, Inc. +Copyright 2010 Freescale Semiconductor, Inc. +Copyright 2011 Freescale Semiconductor, Inc. +Copyright 2004 Freescale Semiconductor. +Copyright (C) 2003 Motorola Inc. +Copyright 2004, 2007-2011 Freescale Semiconductor, Inc. +Copyright 2009 Freescale Semiconductor, Inc. +Copyright 2007 Freescale Semiconductor. +Copyright (C) 2003 Motorola +Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) +Copyright (C) 2011 by Vladimir Zapolskiy +Copyright (C) 2011-2015 Vladimir Zapolskiy +Copyright (C) 2008 by NXP Semiconductors +(C) Copyright 2014 DENX Software Engineering GmbH +Copyright (C) 2011 Vladimir Zapolskiy +Copyright (C) 2013 Texas Instruments, Inc. +(C)Copyright 2016 Rockchip Electronics Co., Ltd +Copyright (c) 1999-2002 Vojtech Pavlik +Copyright (c) 2015 Hans de Goede +Copyright (C) 2007,2010 Freescale Semiconductor, Inc. +Copyright (C) 2006-2009 Freescale Semiconductor, Inc. +(C) Copyright 2003, Psyent Corporation +Copyright (C) 2009, Wind River Systems Inc +Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004,2005 Free Software Foundation, Inc. +Copyright 2018 Google +Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2018 Microsemi Corporation +Copyright (c) 2019 Microsemi Corporation +Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc. +(C) Copyright 2015 Stephen Warren +(C) Copyright 2014 Suriyan Ramasami +Copyright (C) 1999 Magnus Damm +Copyright 2012 Stefan Roese +Copyright (c) 2015 Andreas Bießmann +Copyright (c) 2011 The Chromium OS Authors. +Copyright (C) 2018 Stefan Roese +Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2015 Simon Arlott +Copyright (C) 2008 Maxime Bizon +Copyright (C) 2000-2010 Broadcom Corporation +Copyright (C) 2010 Broadcom Corporation +Copyright (C) 2015 - 2018 Texas Instruments Incorporated +Copyright 2004,2007,2008 Freescale Semiconductor, Inc. +Copyright (c) 2015 Tyco Fire Protection Products. +Copyright (C) 2004-2007 Freescale Semiconductor, Inc. +Copyright (c) 2005-2008 Analog Devices Inc. +Copyright (C) 2010 Thomas Chou +Copyright 2017 Andes Technology, Inc. +Copyright (C) 2015 Atmel Corporation +Copyright (C) 2018 Cryptera A/S +Copyright (C) 2007 Atmel Corporation +Copyright (C) 2017 Álvaro Fernández Rojas +Copyright (C) 2012-2013 Jonas Gorski +Copyright (C) 2009-2012 Florian Fainelli +Copyright (C) 2010 Tanguy Bouzeloc +(C) Copyright 2018 Cisco Systems, Inc. +Copyright (C) 2004-2009 Freescale Semiconductor, Inc. +Copyright (C) 2018 Angelo Dureghello +Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2014 Stefan Roese +Copyright (c) 2009, Intel Corporation. +(C) Copyright 2012 SAMSUNG Electronics +Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. +Copyright 2013-2015 Freescale Semiconductor, Inc. +Copyright 2013-2014 Freescale Semiconductor, Inc. +Copyright (c) 2011-12 The Chromium OS Authors. +Copyright (C) 2014 Beniamino Galvani +Copyright (C) 2018 BayLibre, SAS +Copyright (c) 2006 Ben Warren, Qstreams Networks Inc. +Copyright (c) 2001 Navin Boppuri / Prashant Patel +Copyright (c) 2001 Gerd Mennchen +Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, . +Copyright (C) 2011 Sergiy +Copyright (C) 2011-2013 Gabor Juhos +Copyright (C) 2014-2015 Felix Fietkau +Copyright (C) 2019 MediaTek Inc. All Rights Reserved. +Copyright (C) 2015 Marvell International Ltd. +Copyright (C) 2016 Stefan Roese +Copyright (C) 2008, Guennadi Liakhovetski +Copyright (C) 2019 DENX Software Engineering +Copyright (C) 2016 Jagan Teki +Copyright (C) 2010 Dirk Behme +Copyright (C) 2005, 2006 Nokia Corporation +Copyright (c) 2015, Microchip Technology Inc. +Copyright (C) 2018 Marek Vasut +(C) 2019 Theobroma Systems Design und Consulting GmbH +(C) Copyright 2008-2013 Rockchip Electronics +Copyright (c) 2011-2013 The Chromium OS Authors. +Copyright (C) 2013 Renesas Electronics Corporation +Copyright (C) 2013 Nobuhiro Iwamatsu +Copyright (C) 2011-2012 Renesas Solutions Corp. +Copyright (C) 2011 Renesas Solutions Corp. +Copyright (C) 2018 Exceet Electronics GmbH +Copyright (C) 2018 Bootlin +Copyright 2018 SiFive, Inc. +Copyright 2019 Bhargav Shah +(C) Copyright 2017 Whitebox Systems / Northend Systems B.V. +(C) Copyright 2017 Olimex Ltd.. +Copyright (C) 2012 - 2014 Allwinner Tech +Copyright (C) 2014 Maxime Ripard +Copyright (c) 2010-2013 NVIDIA Corporation +(C) Copyright 2015 NVIDIA Corporation +(C) Copyright 2014 Google, Inc +Copyright (C) 2013, Texas Instruments, Incorporated +Copyright 2019 Socionext, Inc. +Copyright (c) 2015 Jagan Teki +Copyright (c) 2012 Stephan Linz +Copyright (c) 2010 Graeme Smecher +Copyright (c) 2010 Thomas Chou +(C) Copyright 2018 Xilinx +(C) Copyright 2013 Xilinx, Inc. +(C) Copyright 2015 Jagan Teki +Copyright 2007,2009-2011 Freescale Semiconductor, Inc. +Copyright (C) 2008 Advanced Micro Devices, Inc. +Copyright (C) 2009 coresystems GmbH +Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. +Copyright (C) 2004-2008, 2012 Freescale Semiconductor, Inc. +(C) Copyright 2004-2008, 2012 Freescale Semiconductor, Inc. +Copyright (C) 2015, Bin Meng +(C) Copyright 2016 Google, Inc +(C) Copyright 2019 Rockchip Electronics Co., Ltd +Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ +(c) Copyright 2010-2014 Xilinx, Inc. All rights reserved. +Copyright (C) 2017 Jagan Teki +Copyright (C) 2015 Hans de Goede +Copyright (C) 2014 Roman Byshko +Copyright (C) 2014 Google, Inc +(C) Copyright 2016 Savoir-faire Linux Inc. +(C) Copyright 2011 Andes Technology Corp +(C) Copyright 2019 Vasily Khoruzhick +Copyright (C) 2016, Imagination Technologies Ltd. +Copyright (C) 2019,STMicroelectronics - All Rights Reserved +Copyright (C) 2012-2013 Texas Instruments, Inc. +Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2008 Eric Jarrige +Copyright (c) 2009 Ilya Yanok +Copyright (c) 2019 Linaro Limited +Copyright (c) 2019 Heinrich Schuchardt +(C) Copyright 2018 Simon Goldschmidt +Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) STMicroelectronics 2019 - All Rights Reserved +Copyright (C) 2018-2019 Xilinx, Inc. +Copyright 2010-2012 Freescale Semiconductor, Inc. +Copyright (C) 2012 rockchips +Copyright (C) 2019 ROHM Semiconductors +Copyright (C) 2015 Samsung Electronics +(C) Copyright 2016 Texas Instruments Incorporated, +Copyright (C) 2012-2015 Samsung Electronics +Copyright (C) 2016 Rockchip Electronics Co., Ltd +Copyright (C) 2014 - STMicroelectronics Inc. +Copyright (C) 2014-2015 Samsung Electronics +Copyright (C) 2019 Disruptive Technologies Research AS +Copyright (C) 2018 Samsung Electronics +Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (c) 2015 Google, Inc +Copyright (C) EETS GmbH, 2017, Felix Brack +Copyright (c) Marc A. Viredaz, 1998 +Copyright 2018-2019 NXP +Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ +Copyright (C) 2017, Grinn - http://grinn-global.com/ +Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/ +Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ +Copyright (C) 2013, Adeneo Embedded +Copyright (C) 2009, Texas Instruments, Incorporated +Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +Copyright 2017 Texas Instruments, Inc. +(C) Copyright 2017 Linaro Ltd. +Copyright (C) 2017, Konsulko Group +Copyright (c) 2019 Western Digital Corporation or its affiliates. +Copyright (C) 2017 Impinj +Copyright (C) 2018 Pengutronix, Lucas Stach +Copyright (c) 2019 BayLibre, SAS +Copyright (C) 2016 Glider bvba +Copyright (C) 2016 Cogent Embedded Inc. +Copyright (C) 2018 Jacopo Mondi +Copyright (C) 2017 Cogent Embedded Inc. +Copyright (C) 2018 Renesas Electronics Corp. +Copyright (C) 2018 Cogent Embedded, Inc. +Copyright (C) 2017 Glider bvba +Copyright © 2015 Broadcom +Copyright (c) 2015-2016, NVIDIA CORPORATION. +Copyright 2016 Timesys Corporation +Copyright 2016 Advantech Corporation +Copyright 2015 Timesys Corporation. +Copyright 2015 General Electric Company +(C) Copyright 2011-2012 +Copyright 2019 Toradex +Copyright (C) 2014 Renesas Electronics Corporation +(C) Copyright 2007 - 2013 Tensilica Inc. +(C) Copyright 2014 - 2016 Cadence Design Systems Inc. +Copyright (C) 2018 Marek Behun +Copyright (C) 2013 Boundary Devices +Copyright (C) 2013-2017, ISEE 2007 SL - http://www.isee.biz/ +Copyright (C) 2013, ISEE 2007 SL - http://www.isee.biz/ +Copyright (C) 2015 Sakari Ailus +Copyright (C) 2018 Marvell International Ltd. +Copyright 2013-2016 Freescale Semiconductor, Inc. +Copyright (C) 2014 Freescale Semiconductor +Copyright (c) 2017 Amlogic, Inc. All rights reserved. +Copyright (c) 2018 Amlogic, Inc. All rights reserved. +Copyright (C) 2016 Endless Mobile, Inc. +Copyright (C) 2017 Socionext Inc. +Copyright (c) 2014, Steffen Trumtrar +Copyright (C) 2016-2018 Intel Corporation. All rights reserved +Copyright (C) 2016 Altera Corporation. All rights reserved +Copyright (c) 2018 Baylibre SAS. +Copyright (c) 2016 BayLibre, SAS. +Copyright (c) 2017 Amlogic, inc. +Copyright (c) 2019 BayLibre, SAS. +Copyright (c) 2016 BayLibre, SAS +Copyright (c) 2018 Amlogic, inc. +Copyright (C) Broadcom Corporation +Copyright (C) 2017 Impinj, Inc. +Copyright (C) 2018 Zodiac Inflight Innovations +Copyright (C) 2019 MediaTek Inc. +Copyright (C) STMicroelectronics 2018 - All Rights Reserved +Copyright (C) 2017 Priit Laes +Copyright (C) 2016 Maxime Ripard +Copyright (C) 2017 Icenowy Zheng +Copyright (C) 2016 Icenowy Zheng +Copyright 2016 Maxime Ripard +Copyright (C) 2016 Chen-Yu Tsai +Copyright (C) 2017 Chen-Yu Tsai +Copyright (C) 2016 Icenowy Zheng +Copyright (c) 2015, NVIDIA CORPORATION. +Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2018, EETS GmbH, http://www.eets.ch/ +Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ +Copyright (c) 2013 Imagination Technologies +Copyright (c) 2006-2013 Ingenic Semiconductor +Copyright (C) 2013 Marek Vasut +(C) Copyright 2019 Matthias Brugger +Copyright (C) 2012 Vikram Narayananan +(C) Copyright 2012,2015 Stephen Warren +Copyright (C) 2014-2015 Freescale Semiconductor, Inc. +Copyright (C) Jasbir Matharu +Copyright (C) UDOO Team +Copyright (C) 2017 Microchip +Copyright (C) 2016 Andes Technology Corporation +Copyright 2016 Google Inc. +Copyright (C) 2015 Broadcom Corporation +Copyright (c) 2014 Samsung Electronics Co., Ltd. +Copyright (c) 2016-2017 Linaro Ltd. +Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd. +Copyright (c) 2015 Hisilicon Limited. +Copyright (c) 2016 HiSilicon Technologies Co., Ltd. +Copyright 2013 Lucas Stach, Pengutronix +Copyright (C) 2016 Freescale Semiconductor, Inc. +Copyright (C) 2014 Freescale Semiconductor, Inc. +Copyright (C) 2015 Freescale Semiconductor, Inc. +Copyright 2016 Freescale Semiconductor, Inc. +(c) 2015 Purna Chandra Mandal +Copyright (c) 2018 BayLibre, SAS +Copyright (c) 2018 MediaTek Inc. +Copyright (c) 2019 MediaTek Inc. +Copyright (c) 2017 Rockchip Electronics Co. Ltd. +Copyright (C) 2014 Renesas Solutions Corp. +Copyright (C) 2014 Wolfram Sang, Sang Engineering +Copyright 2013 Ideas On Board SPRL +Copyright (C) 2015 Renesas Electronics Corp. +Copyright (C) 2016 Cogent Embedded, Inc. +Copyright (C) 2014 Renesas Electronics Corporation +Copyright (C) 2016 Renesas Electronics Corp. +Copyright (C) 2017 Cogent Embedded, Inc. +Copyright (c) 2014 MundoReader S.L. +(C) Copyright 2017 Rockchip Electronics Co., Ltd +(C) Copyright 2017 Rockchip Electronics Co., Ltd. +Copyright (c) 2019 Rockchip Electronics Co. Ltd. +(C) Copyright 2016 Rockchip Electronics Co., Ltd +Copyright (c) 2015 Heiko Stuebner +Copyright (c) 2016 Rockchip Electronics Co. Ltd. +Copyright (C) 2015 Actions Semi Co., Ltd. +Copyright (C) 2018 Manivannan Sadhasivam +Copyright (C) 2018-2019 SiFive, Inc. +Copyright (C) 2017 Synopsys +Copyright (C) 2016 STMicroelectronics +Copyright 2015 Maxime Ripard +Copyright (c) 2017 Icenowy Zheng +Copyright (c) 2016 Icenowy Zheng +Copyright (C) 2018 Jernej Skrabec +Copyright (C) 2014-2018 Xilinx, Inc. +Copyright (C) 2015-2016 Marvell International Ltd. +Copyright (C) 2015 Stefan Roese +(C) Copyright 2014 - 2018 Xilinx, Inc. +Copyright (C) 2010-2013 Freescale Semiconductor, Inc. +Copyright (C) 2013, Boundary Devices +Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD +Copyright (C) 2015 Stefan Wahren +Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (c) 2015 Linaro Limited. +Copyright (C) 2018 Texas Instruments +Copyright (C) 2009 Nokia +Copyright (C) 2009-2010 Texas Instruments +(C) Copyright 2018 Ramon Fried +Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2013 MundoReader S.L. +Copyright (C) STMicroelectronics 2017 - All Rights Reserved +Copyright (C) 2019 Jagan Teki +(C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +Copyright (c) 2013 The Chromium OS Authors. +Copyright (C) 2014 STMicroelectronics -- All Rights Reserved +Copyright (C) 2017 Stefano Babic +Copyright 2009-2014 Freescale Semiconductor, Inc. +(C) Copyright 2014 Freescale Semiconductor, Inc. +(C) Copyright 2014 Angelo Dureghello +Copyright (c) 2016 Rockchip Electronics Co., Ltd +Copyright (C) 2011 Andes Technology Corporation +(C) Copyright 2009 Faraday Technology +(c) Copyright 2016 Topic Embedded Products. +(c) 2009 Ilya Yanok, Emcraft Systems +Copyright (C) 2012 Philippe Reynes +(C) Copyright 2009 Samsung Electronics +(C) Copyright 2009 SAMSUNG Electronics +Copyright (c) 2009 Samsung Electronics +Copyright (C) 2009 Samsung Electronics +(C) Copyright 2010 Samsung Electronics +Copyright (C) 2009 Samsung Electrnoics +Copyright (C) 2011 Samsung Electronics +Copyright (C) 2019 Philippe Reynes +Copyright (c) 2018 BayLibre, SAS. +Copyright (C) 2016 BayLibre, SAS +Copyright (C) 2015 Amlogic, Inc. All rights reserved. +(C) Copyright 2013-2014 Luc Verhaegen +(C) Copyright 2014-2015 Hans de Goede +(C) Copyright 2017 Icenowy Zheng +Copyright (C) 2012 Ilya Yanok +(C) Copyright 2011, Ilya Yanok, Emcraft Systems +Copyright 2019 NXP +Copyright (C) 1996-2000 Russell King +Copyright (c) 1996 Russell King. +Copyright (C) 2016 ARM Ltd. +Original copyright in armv7.h was: +(C) Copyright 2010 Texas Instruments, Aneesh V +Copyright 1995, Russell King. +(C) Copyright 2017 NVIDIA Corporation +Copyright (C) 2012 ARM Ltd. +Copyright (C) 1994-2002 Russell King +Copyright (C) 2003-2012 ARM Ltd. +Copyright (C) 2014 ARM Ltd. +Copyright (C) 2007 Sergey Kubushyn +Copyright (C) 2006 Texas Instruments. +Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2009-2010 Texas Instruments, Inc. +Copyright 2015 Freescale Semiconductor, Inc. +Copyright (C) 1996 Russell King +Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD +Copyright (C) 2000-2002 Russell King +Copyright (c) 2009 Wind River Systems, Inc. +Copyright (C) 2003-2005 Nokia Corporation +Copyright (C) 2012, Ilya Yanok +Copyright (C) 2012 ARM Limited +Copyright (C) 2012 Linaro Limited +Copyright (C) 1996-1998 Russell King. +Copyright (C) 1995-2002 Russell King +Copyright (c) 2012 The Chromium OS Authors. +(C) Copyright 2016 Alexander Graf +Copyright (C) 1997-1999 Russell King +Copyright (C) 2008 ARM Limited +Copyright (c) 2017 Google, Inc +Copyright (c) 2016 Google, Inc +Copyright (C) 1999-2010 Tensilica Inc. +Copyright (c) 2017 Intel Corporation +(C) Copyright 2018 Theobroma Systems Design und Consulting GmbH +Copyright (c) 2017 General Electric Company. All rights reserved. +(C) Copyright 2016 Linaro +Copyright (C) 2014, Barco (www.barco.com) +Copyright (C) 2014 Gateworks Corporation +Copyright (C) 2018 Armadeus Systems +Copyright (c) 2012 Michael Walle +Copyright 2015 Timesys Corporation +Copyright (C) 2019 BayLibre, SAS +Copyright (C) 2013, Intel Corporation +Copyright (C) 2014, Bin Meng +Copyright 2007-2008 Freescale Semiconductor, Inc. +Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2012-2017 Marek Vasut +Copyright (C) 2014-2017 Olaf Mandel +Copyright (C) 2010 Freescale Semiconductor, Inc. +Copyright (C) 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.com +Copyright (C) 2007 Freescale Semiconductor, Inc. +(C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com +Copyright (C) 2015-2016 Freescale Semiconductor, Inc. +Copyright 2018 Linaro +Copyright 2006, 2008-2009, 2011 Freescale Semiconductor +Copyright (C) 2018 Synopsys +Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved. +Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. +Copyright (C) 2004, 2007-2010, 2011-2015 Synopsys, Inc. All rights reserved. +Copyright (C) 2015 Synopsys, Inc. All rights reserved. +Copyright (C) 2014 Synopsys, Inc. All rights reserved. +Copyright 2002 by Kai Germaschewski +Copyright abandoned, Michael Chastain, . +Copyright 2017 General Electric Company +Copyright 2016 General Electric Company +Copyright (C) 2017 Renesas Electronics +Copyright (C) Chris Brandt +Copyright (C) 2013 Google Inc. +Copyright (C) 2016 Bin Meng +Copyright (C) 2016, Bin Meng +Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD +Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr +Copyright (C) 2007 Miguel Gaio +Copyright (C) 2008 Florian Fainelli +Copyright (C) 2013 Altera Corporation +(c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com) +Copyright 2017 CS Systemes d'Information +Copyright (C) 2011 Gabor Juhos +Copyright (C) 2013 John Crispin +(c) Copyright 2000 Oleg Drokin +Copyright (c) 2004 Texas Instruments. +Copyright (c) 2005 David Brownell +Copyright (c) 2011-2018 Xilinx Inc. +Copyright (C) 2003 Ralf Baechle +Copyright (C) 2003, 2004 Ralf Baechle +Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle +Copyright (C) 2000, 2002 Maciej W. Rozycki +Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. +Copyright (C) 2015 - 2016 Xilinx, Inc. +Copyright (C) 2017 National Instruments Corp +Copyright (c) 2017 Andy Yan +Copyright (C) 2011-2015 by Vladimir Zapolskiy +Copyright 2019 NXP Semiconductors +Copyright 2016-2018 NXP +Copyright 2015, Freescale Semiconductor +Copyright 2014-2015, Freescale Semiconductor +Copyright 2015 Freescale Semiconductor +Copyright 2017-2019 NXP +Copyright 2016 NXP Semiconductor, Inc. +Copyright 2014-2015, Freescale Semiconductor, Inc. +Copyright 2017 NXP Semiconductor, Inc. +Copyright 2015-2018 NXP +Copyright (C) 2016 Amarula Solutions B.V. +Copyright (C) 2016 Engicam S.r.l. +Copyright (C) 2016 Masahiro Yamada +Copyright 2004, 2011 Freescale Semiconductor. +(C) Copyright 2002 Scott McNutt +Copyright (C) 2018 Marek Vasut +Copyright (C) 2017 Marek Vasut +Copyright (C) 2013 Ideas On Board SPRL +Copyright (C) 2015-2017 Glider bvba +Copyright (C) 2015 Glider bvba +Copyright (C) 2017-2018 Marek Vasut +Copyright (C) 2015-2016 Glider bvba +Copyright (c) 2015-2018 National Instruments +Copyright (c) 2015-2018 Joe Hershberger +Copyright (c) 2011-2012 The Chromium OS Authors. +Copyright (C) 2017, Bin Meng +Copyright (C) Freescale Semiconductor, Inc. 2006. +Copyright (C) 2017 The Android Open Source Project +Copyright (C) 2008 The Android Open Source Project +Copyright (C) 2007 The Android Open Source Project +(C) Copyright 2007-2008 Semihalf +copyright (c) 2013-2016, ARM Limited and Contributors. All rights +Copyright (C) 2016-2017 Rockchip Electronic Co.,Ltd +Copyright (C) 2012 Atmel Corporation +Copyright (C) 2005-2006 Atmel Corporation +Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com +2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com +2017 Marek Behun, CZ.NIC, marek.behun@nic.cz +(C) Copyright 2018, Linaro Limited +(C) Copyright 2012 Henrik Nordstrom +(C) Copyright 2013 Oliver Schinagl +(C) Copyright 2016 Chen-Yu Tsai +(C) Copyright 2015 Vishnu Patekar +(C) Copyright 2015 Hans de Goede +Copyright (C) 1996-1999 SciTech Software, Inc. +Copyright 2018 Google, Inc +Copyright (C) 2017 Texas Instruments +Copyright (C) 1996-2002 Julian R Seward. All rights reserved. +Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +Copyright (c) 2017 Rob Clark +Copyright (c) 2009 Analog Devices Inc. +Copyright 2014 Red Hat, Inc. +Copyright 2012 Texas Instruments +Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ +Copyright(c) 2009 Dialog Semiconductor Ltd. +Copyright 2014 Google Inc. +Copyright (C) 2003 Bernardo Innocenti +Copyright (C) 2006-2015 Nicolas Pitre +Copyright (C) 2013 Texas Instruments +Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com +Copyright 2014 Rockchip Inc. +(C) Copyright 2017 Jernej Skrabec +Copyright 2003 Motorola,Inc. +Copyright (c) 2018 The Chromium OS Authors. All rights reserved. +Copyright (C) Nalin Dahyabhai +(C) Copyright 2009-2016 CompuLab, Ltd. +Copyright (C) 1999 VA Linux Systems +Copyright (C) 1999 Walt Drummond +Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. +Copyright (c) 2017 Heinrich Schuchardt +Copyright (c) 2016 Alexander Graf +Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com +(C) Copyright 2001 Sysgo Real-Time Solutions, GmbH +Copyright (C) 2014 Samsung Electronics +Copyright (c) 2018, Heinrich Schuchardt +(C) Copyright 2011 - 2012 Samsung Electronics +Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com +Copyright (C) 2003, 2004 Free Software Foundation, Inc. +Copyright 2011 Sebastian Andrzej Siewior +Copyright 2014 Linaro, Ltd. +Copyright 2015 Free Electrons. +Copyright (C) 2008 Freescale Semiconductor, Inc. +Copyright 2009-2012 Freescale Semiconductor, Inc. +Copyright 2008-2016 Freescale Semiconductor, Inc. +Copyright 2017-2018 NXP Semiconductor +Copyright 2007, 2011 Freescale Semiconductor, Inc. +Copyright (C) 2004-2007, 2015 Freescale Semiconductor, Inc. +Copyright 2013 - 2015 Freescale Semiconductor, Inc. +Copyright 2007-2008,2010-2011 Freescale Semiconductor, Inc +Copyright 2009-2012, 2013 Freescale Semiconductor, Inc. +(C) Copyright 2015 Freescale Semiconductor, Inc. +Copyright (C) 2018 Intel Corporation +(C) Copyright 2009-2013 ADVANSEE +Copyright 2008 Silicon Turnkey Express, Inc. +Copyright (C) 2000, 2004, 2005 MIPS Technologies, Inc. +Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) +Copyright (C) 2018 Synopsys, Inc. All rights reserved. +Copyright 2019 Heinrich Schuchardt +Copyright (c) 2009 MontaVista Software, Inc. +Copyright (c) 2012 Samsung Electronics +Copyright (C) 2009 Sergey Kubushyn +Copyright (C) 2009 - 2013 Heiko Schocher +(C) 2000 by Paolo Scaffardi (arsenio@tin.it) +(C) Copyright 2002 ELTEC Elektronik AG +(C) Copyright 2018 Linaro Ltd. +Copyright 2016 Freescale Semiconductors, Inc. +(C) Copyright 2014 Freescale Semiconductor, Inc +Copyright (C) 1997-2001, 2004, 2007 Free Software Foundation, Inc. +Copyright (c) 2014 Google, Inc. +(C) Copyright 2005-2010 Freescale Semiconductor, Inc. +Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/ +Copyright 2003-2004 Red Hat, Inc. All rights reserved. +Copyright 2003-2004 Jeff Garzik +(C) Copyright 2012 Samsung Electronics +Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) +Copyright (C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) +Copyright (C) 2001 Peter Bergner, IBM Corp. +Copyright (C) 2004 by FS Forth-Systeme GmbH. +(C) Copyright 2012 Freescale Semiconductor, Inc. +Copyright (C) 2009 Marc Kleine-Budde +Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2009, Guennadi Liakhovetski +Copyright (c) 1992 Simon Glass +Copyright 2010-2011 Calxeda, Inc. +(C) Copyright 2009 Industrie Dial Face S.p.A. +Copyright (C) 2010 Guennadi Liakhovetski +Copyright (C) 2006 Nokia Corporation +Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. +Copyright (C) 2018 STMicroelectronics - All Rights Reserved +Copyright 2008,2010 Freescale Semiconductor, Inc +Copyright (C) 2004-2007, 2010 Freescale Semiconductor, Inc. +Copyright 2004, 2007 Freescale Semiconductor. +Copyright(c) 2003 Motorola Inc. +Copyright 2006 Freescale Semiconductor. +Copyright (C) 2013 Imagination Technologies +Copyright (C) 2018 Toradex +Copyright 1994 - 2000 Neil Russell. +(C) 2009 by Detlev Zundel, DENX Software Engineering GmbH +(c) Rob Taylor, Flying Pig Systems. 2000. +(C) 2005 Wind River Systems +Copyright (C) 2017 NXP Semiconductors +Copyright (C) 2017 Bin Meng +Copyright (C) 2005-2007 Samsung Electronics +(C) Copyright 2012-2013 +Copyright (C) 2008 RuggedCom, Inc. +Copyright 2009 CJSC "NII STT", http://www.niistt.ru/ +Copyright (C) 2013 Gabor Juhos +Copyright (c) 2018 Toradex, Inc. +Copyright 2015 Stephen Warren +Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +Copyright (c) 2011 samsung electronics +(C) Copyright 2015 Miao Yan +(C) Copyright 2008-2014 Rockchip Electronics +Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README +Copyright (C) 2000, 2001 Free Software Foundation, Inc. +(C) Copyright 2003 Sysgo Real-Time Solutions, AG +Copyright (c) 2013, Henrik Nordstrom +Copyright (c) 2012, Google Inc. +Copyright (c) 2013, Compulab Inc. +Copyright 2011, Marvell Semiconductor Inc. +Copyright (C) 2017 Toradex +Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. +Copyright (C) 2010-2013 Wolfgang Denk +Copyright (C) 2015 Renesas Electronics Corporation +Copyright (c) 2008 Magnus Damm +Copyright 2009, Matthias Fuchs +Copyright (c) 2004-2005 Sergey Lyubka +Copyright (c) 2018 Ramon Fried +Copyright (C) 2010 The Android Open Source Project +Copyright (C) 2003 Arabella Software Ltd. +Copyright (C) 2008 Atmel Corporation +Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. +Copyright (C) STMicroelectronics SA 2017 +Copyright 2013 Texas Instruments, Inc. +Copyright (c) 2018 Linaro Limited +Copyright (C) 2013 Samsung Electronics +Copyright (c) 2014 Texas Instruments Incorporated - http://www.ti.com +Copyright (c) 2012 Samsung Electronics Co., Ltd. +Coypright (c) 2013 Guntermann & Drunck GmbH +Copyright (c) 2018 Bootlin +Copyright 2004, 2007, 2009, 2011, 2013 Freescale Semiconductor, Inc. +(C) Copyright 2003, Motorola, Inc. +(C) Copyright 2009 Reinhard Arlt, reinhard.arlt@esd-electronics.com +(C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com +Copyright (C) 2007-2009 Texas Instruments, Inc. +Copyright (C) 2006-2008 Nokia Corporation +(C) Copyright 2008-2009 +Copyright (c) Thomas Gleixner +(C) Copyright 2010 - 2011 NVIDIA Corporation +Copyright (c) 2000, 2001, 2002 Lineo +Copyright (c) 2001 Hewlett Packard +Copyright (C) 2011 Samsung Electrnoics +Copyright (c) 2004, 2008 IBM Corporation +Copyright (c) 2009 Pattrick Hueper +(C) Copyright 2019 Xilinx, Inc, +Siva Durga Prasad Paladugu +(C) Copyright 1997-2002 ELTEC Elektronik AG +Copyright (C) 2018, Tuomas Tynkkynen +Copyright 2008 Freescale Semiconductor, Inc. This file is licensed +Copyright 2013, 2015 Freescale Semiconductor, Inc. +Copyright (c) 2015 Free Electrons +Copyright (c) 2015 NextThing Co +Copyright (c) 2018 Microchip Technology, Inc. +(C) Copyright 2015 Xilinx, Inc, +Michal Simek +(C) Copyright 2012-2013, Xilinx, Michal Simek +Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. +(C) Copyright 2010,2011 NVIDIA Corporation +Copyright (C) 2014 Sage Electronics Engineering, LLC. +Copyright (C) 2018 Marek Vasut +(C) Copyright 2014, Cavium Inc. +Copyright (C) 2018 Amarula Solutions. +Copyright (C) 2018 Amarula Solutions B.V. +Copyright (C) 2002 Roman Zippel +Copyright (C) 2002-2003 Romain Lievin +Copyright (c) 2009-2010 Wind River Systems, Inc. +Copyright 2011 Linaro +Copyright (C) 2008 Nir Tzachar +Copyright (C) 2002-2005 Roman Zippel +Copyright (C) 2002-2005 Sam Ravnborg +Copyright (C) 2017 Intel Corporation +Copyright Altera Corporation (C) 2014-2015 +Copyright (C) 2016-2018 Intel Corporation +Copyright (C) 2017-2018 Intel Corporation +Copyright Altera Corporation (C) 2012-2015 +Copyright (C) 2016 Google, Inc +Copyright (C) Nelson Integration, LLC 2016 +Copyright (C) 2013 Henrik Nordstrom +Copyright (c) 2018 Microsemi Coprporation +Copyright (C) 2015 Phil Sutter +Copyright (C) 2015 Phil Sutter +Copyright (C) 1999-2007 Tensilica Inc. +Copyright (C) 2011 Simon Guinot +Copyright (C) 2012 Renesas Solutions Corp. +(C) Copyright 2015 Savoir-faire Linux Inc. +(C) Copyright 2007-2018 Michal Simek +(C) Copyright 2007 Michal Simek +Copyright (C) 2008-2009 Samsung Electronics +Copyright (C) 2014-2019, Toradex AG +Copyright (C) 2014-2016, Toradex AG +Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries +Copyright (C) 2012 Stefan Roese +Copyright 2007,2009 Wind River Systems, Inc. +Copyright 2007 Embedded Specialties, Inc. +Copyright (C) 2015, Intel Corporation +Copyright (C) 2016 Nelson Integration, LLC +(C) Copyright 2013 Atmel Corporation +Copyright (C) 2005 David Brownell +Copyright (C) 2005 Ivan Kokshaysky +Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries +Copyright (C) 2011 The Chromium OS Authors. All rights reserved. +Copyright (C) 2008-2009 coresystems GmbH +Copyright (C) 2012 The Chromium OS Authors. All rights reserved. +Copyright (c) 2011, Google Inc. +Copyright (C) 2007-2008 coresystems GmbH +Copyright (C) 2011 Google Inc. +Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2008 by Sascha Hauer +Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, +(C) Copyright 2009-2010 Freescale Semiconductor, Inc. +Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com +Copyright 2008,2011 Freescale Semiconductor, Inc. +Copyright 2008,2010-2011 Freescale Semiconductor, Inc. +Copyright 2006, 2007, 2010-2011 Freescale Semiconductor. +Copyright (c) 2010 Texas Instruments Incorporated +Copyright (C) 2005 Texas Instruments. +(c) 2011 Comelit Group SpA, Luca Ceresoli +Copyright 2000 Roland Borde +Copyright 2000 Paolo Scaffardi +Copyright 2000-2002 Wolfgang Denk, wd@denx.de +Copyright 1994, 1995, 2000 Neil Russell. +Copyright 2000-2004 Wolfgang Denk, wd@denx.de +Copyright (c) 2001 Charles Mott +Copyright (c) 2008 coresystems GmbH +Copyright (c) 2008 Pieter Voorthuijsen +Copyright (c) 2009 Robin Getz +(C) Masami Komiya 2005 +Copyright 2009, Robin Getz +Copyright (C) 2016 The Android Open Source Project +Copyright (C) 2003 by Arthur van Hoff (avh@strangeberry.com) +Copyright (C) 2004 by David Brownell +Copyright (C) 2010 by Joe Hershberger +(C) Masami Komiya 2004 +Copyright 2019 Ramon Fried +Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de +Copyright 2011 Comelit Group SpA, +Luca Ceresoli +Copyright 2018 Lothar Felten, lothar.felten@gmail.com +(C) Copyright 2016 Vladimir Zapolskiy +(C) Copyright 2007 Nobuhiro Iwamatsu +Copyright (C) 2013 Lothar Waßmann +Copyright 2014 - 2015 Freescale Semiconductor, Inc. +Copyright (C) 2017 NXP +Copyright 2017 - 2018 NXP +© 2001-2006 Red Hat, Inc. +(C) Copyright 2018-2019 Rockchip Electronics Co., Ltd +(C) Copyright 2016 Heiko Stuebner +(C) Copyright 2017-2019 Rockchip Electronics Co., Ltd +Copyright 2016 Rockchip Electronics Co., Ltd +(C) Copyright 2009 Atin Malaviya (atin.malaviya@gmail.com) +Copyright (C) 2004-2007 Texas Instruments +Copyright (C) 2008 Nokia Corporation +Copyright 2015-2019 Toradex, Inc. +Copyright 2017 Toradex AG +Copyright 2014 Toradex, Inc. +Copyright (C) 2004 by Thomas Rathbone +Copyright (C) 2005 by HP Labs +Copyright (C) 2005 by David Brownell +Copyright (C) 2004 by Thomas Rathbone, HP Labs +Copyright (C) 2005 by Ivan Kokshaysky +Copyright (C) 2006 by SAN People +Copyright (C) 2005-2013 Atmel Corporation +Copyright 2015 Broadcom Corporation. +Copyright (C) 2006-2008 David Brownell +Copyright (C) 2003 David Brownell +Copyright (C) 2008 for Samsung Electronics +Copyright (C) 2005 for Samsung Electronics +Copyright (C) 2004 Herbert Poetzl +Copyright (C) 2009 for Samsung Electronics +Copyright (C) 2004 David Brownell +Copyright (C) 2003-2005,2008 David Brownell +Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger +(C) Copyright 2010 Faraday Technology +(C) 2007 by OpenMoko, Inc. +(C) Copyright 2006 by Harald Welte +Copyright (C) 2011-2012 Samsung Electronics +Copyright (C) 2003-2008 Alan Stern +Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) +Copyright (C) 2003 Robert Schwebel, Pengutronix +Copyright (C) 2003 Benedikt Spranger, Pengutronix +Copyright (C) 2003 Joshua Wise +Copyright (C) 2012 Lukasz Dalek +Copyright (C) 2003 Robert Schwebel , Pengutronix +Copyright (C) 2007 Rodolfo Giometti +Copyright (C) 2007 Eurotech S.p.A. +Copyright (C) 2008 Vivek Kutal +Copyeight (C) 2009 Samsung Electronics +(C) Copyright 2009, 2011 Freescale Semiconductor, Inc. +(C) Copyright 2008, Excito Elektronik i Sk=E5ne AB +Copyright 2016 Texas Instruments, Inc. +Copyright (C) 2008 Renesas Solutions Corp. +Copyright (C) 2008 Nobuhiro Iwamatsu +Copyright (C) 2007 Kenati Technologies, Inc. +(C) Copyright 2017 Angelo Dureghello +Copyright (C) 2004 Patrik Kluba,University of Szeged, Hungary +Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer +Copyright © 2004 Ferenc Havasi ,Zoltan Sogor ,Patrik Kluba , +Copyright (C) 2011-2014 Freescale Semiconductor, Inc. +Copyright (C) 2010-2011 Freescale Semiconductor, Inc. +Copyright (C) 2007, Guennadi Liakhovetski +(C) Copyright 2008-2010 Freescale Semiconductor, Inc. +Copyright (C) 2011, Stefano Babic +Copyright (C) 2016 Paul Kocialkowski +Copyright 2008, 2010-2011 Freescale Semiconductor, Inc. +(C) Copyright 2007,2008 Nobuhiro Iwamatsu +(C) Copyright 2008 Renesas Solutions Corp. +(C) Copyright 2008, 2011 Renesas Solutions Corp. +Copyright (C) 2011 Renesas Solutions Corp. +Copyright (C) 2007,2008 Nobuhiro Iwamatsu +Copyright (c) 2007,2008 Nobuhiro Iwamatsu +Copyright (c) 2008 Yusuke Goda +Copyright (C) 2008 Yoshihiro Shimoda +Copyright (C) 2012 Nobuhiro Iwamatsu +Copyright (C) 2012 Renesas Solutions Corp. +(C) Dustin McIntire (dustin@sensoria.com) +(C) 2007,2008 Nobuhiro Iwamatsu +(C) 2008 Yusuke Goda +Copyright (C) 1999, 2000 Niibe Yutaka +Copyright (C) 1999 Niibe Yutaka +Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima +Copyright (C) 2002 Paul Mundt +Copyright (C) 2018 Philippe Reynes +Copyright (C) 2018 Jerome Brunet +Copyright (C) 2017 Xingyu Chen +(C) Copyright (C) 2018 Neil Armstrong +Copyright (C) 2017 Jerome Brunet +(C) Copyright (C) 2019 Jerome Brunet +(C) Copyright 2016 - Beniamino Galvani +Copyright 2016 Broadcom Corporation. +Copyright (C) 2018-2019 Toradex AG +Copyright (C) 2018 Toradex AG +Copyright (C) 2013 Lothar Felten +(C) Copyright 2015, Freescale Semiconductor, Inc. +(C) Copyright 2013-2015, Freescale Semiconductor, Inc. +Copyright (C) 2009-2012 +Copyright 1992, Linus Torvalds. +Copyright (C) 2003 John Williams +Copyright (C) 2001 NEC Corporation +Copyright (C) 2001 Miles Bader +(C) Copyright 2004 Atmark Techno, Inc. +Copyright (C) 2003 John Williams +Copyright (C) 2001,02 NEC Corporation +Copyright (C) 2001,02 Miles Bader +Copyright (C) 2003 John Williams +Copyright (C) 2001,2002 NEC Corporation +Copyright (C) 2001,2002 Miles Bader +Copyright (C) 2011 Michal Simek +(C) Copyright 2013 - 2014 Xilinx, Inc +Copyright (C) 2003 John Williams (jwilliams@itee.uq.edu.au) +Copyright (C) 2001 NEC Corporation +Copyright (C) 2001 Miles Bader +(C) Copyright 2007 Semihalf +(C) Copyright 2007 Stanislav Galabov +Copyright (C) 2012 Lucas Stach +(C) Copyright 2004, Psyent Corporation +Copyright (C) 2004-2007 ARM Limited. +Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek +Copyright (C) 2004-2006 Atmel Corporation +(C) Copyright 2004-2007 Freescale Semiconductor, Inc. +(C) Copyright 2015 Angelo Dureghello +(C) Copyright 2018 Angelo Dureghello +Copyright (c) 2014 The Chromium OS Authors. +Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) +(C) Copyright 2016 Stephen Warren +Copyright (c) 2018 Alexander Graf +(C) Copyright 2013-2016 Freescale Semiconductor, Inc. +(c) 2007 Sascha Hauer +(c) 2015 Paul Thacker +(C) Copyright 2003, 2004 +Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) +(C) Copyright 2016 Marcel Ziswiler +Copyright (C) 2013 Renesas Electronics Corporation +Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu +Copyright (C) 2002 - 2008 Paul Mundt +Copyright (C) 2018 Anup Patel +Copyright (C) 2016, STMicroelectronics - All Rights Reserved +Copyright (C) 2012-2015 Panasonic Corporation +Copyright (C) 2015-2016 Socionext Inc. +(C) Copyright 2008 - 2015 Michal Simek +Copyright (C) 2012 Michal Simek +Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved. +Copyright (C) 2011-2014 Panasonic Corporation +Copyright (C) 2017 Microchip Corporation +Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2016 Grinn +Copyright (C) 2013 Boundary Devices Inc. +Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2014 - 2016 Freescale Semiconductor, Inc. +Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2017 Armadeus Systems +Copyright (C) 2013 Jon Nettleton +Copyright (C) 2014 Marek Vasut +Copyright (C) 2019 Eugeniu Rosca +Copyright (c) 2018 JJ Hiblot +(C) Copyright 2011-2013 Pali Rohár +Copyright (c) 2012, Google Inc. All rights reserved. +Copyright (C) 2013 Xilinx, Inc. +Copyright (C) 2017 Masahiro Yamada +Copyright (c) 2017 Álvaro Fernández Rojas +Copyright (c) 2016 The Chromium OS Authors. +Copyright (c) 2016 National Instruments Corp +Copyright (c) 2018 AKASHI Takahiro, Linaro Limited +Copyright (c) 2001 William L. Pitts +Copyright 2008 - 2009 Windriver, +(C) Copyright 2014 Linaro, Ltd. +Copyright (C) 2014, Bachmann electronic GmbH +Copyright (c) 2009, Code Aurora Forum. All rights reserved. +Copyright (c) 2008-2011 Analog Devices Inc. +Copyright (c) 2009, Brush Technology +Copyright 2002 SYSGO Real-Time Solutions GmbH +(C) Copyright 2007 by OpenMoko, Inc. +(C) Copyright 2013 Patrice Bouchand +Copyright 2006 Freescale Semiconductor +(C) Copyright 2011 Freescale Semiconductor, Inc +Copyright 2008-2009 Freescale Semiconductor, Inc. +(c) 1999 Machine Vision Holdings, Inc. +(c) 1999, 2000 David Woodhouse +(C) 2010 Nanometrics, Inc. +(C) Copyright 2006-2007 OpenMoko, Inc. +(C) 2004 Texas Instruments +Copyright 2010, 2012 Freescale Semiconductor +Copyright (C) 2005-2008 Samsung Electronics +Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2017 Eddie Cai +Copyright (C) 2000-2005, DENX Software Engineering +Copyright (C) Procsys. All rights reserved. +Copyright 2018, Google Inc. +Copyright 2013 Wolfgang Denk +Copyright (c) 2008 Analog Devices Inc. +(C) Copyright 2007 OpenMoko, Inc. +Copyright (C) 2013 Lukasz Majewski +Copyright (C) 2008 Samsung Electronics +Copyright 2008-2009 Stefan Roese , DENX Software Engineering +Copyright (C) 2016 Toradex +Copyright (c) 2019 Michael Walle +Copyright (C) 2016 samtec automotive software & electronics gmbh +Copyright (C) 2017-2019 softing automotive electronics gmbH +Copyright (C) 2017, Intel Corporation +Copyright (C) 2009-2010 Amit Kucheria +Copyright (C) 2009-2012 Genesi USA, Inc. +(C) Copyright 2013 ADVANSEE +Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2010-2011 Jaiganesh Narayanan +Copyright (C) 2008-2010 Gabor Juhos +Copyright (C) 2008 Imre Kaloz +Copyright (C) 2018-2019 Rosy Song +Copyright (C) 2008-2011 Gabor Juhos +Copyright © 2016 Intel Corporation +Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2012 Oleksandr Tymoshenko +Copyright (C) 2012 Samsung Electronics Co.Ltd +(C) Copyright 2009, 2011, 2016 Freescale Semiconductor, Inc. +Copyright (C) 2015 Alexey Brodkin +Copyright (c) 2007-2008, Juniper Networks, Inc. +Copyright (c) 2008, Excito Elektronik i Skåne AB +Copyright (c) 2008, Michael Trimarchi +Copyright (c) 2009 Daniel Mack +(C) Copyright 2011 Ilya Yanok, Emcraft Systems +Copyright (C) 2013,2014 Renesas Electronics Corporation +Copyright (C) 2014 Nobuhiro Iwamatsu +Copyright (c) 2009-2015 NVIDIA Corporation +Copyright (c) 2013 Lucas Stach +(C) Copyright 2009 Stefan Roese , DENX Software Engineering +Copyright (c) 2015 Sanchayan Maity +Copyright (C) 2015 Toradex AG +(C) Copyright 2014, Xilinx, Inc +Copyright (C) 2012 Sughosh Ganu +(C) Copyright 1999 Roman Weissgaerber +(C) Copyright 2000-2002 David Brownell +(C) Copyright 2000-2001 David Brownell +Copyright (C) 2008 Yoshihiro Shimoda +Copyright (c) 2003/06, Courage Co., Ltd. +Copyright 2015,2016 Freescale Semiconductor, Inc. +Copyright (C) 2008 Intel Corp. +Copyright (C) 2013 Samsung Electronics Co.Ltd +Copyright (c) 2015, Google, Inc +Copyright (c) 2014, Renesas Electronics Corporation +Copyright (c) 2016 Rockchip, Inc. +Copyright (C) 2017 Renesas Electronics Corporation +Copyright (C) 1991-2004 SciTech Software, Inc. +Copyright (C) David Mosberger-Tang +Copyright (C) 1999 Egbert Eich +Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2011 Sascha Hauer, Pengutronix +Copyright (C) 2011 Richard Zhao, Linaro +Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd +Copyright (C) 2010-2011 Canonical Ltd +Copyright (c) 2018, Theobroma Systems Design und Consulting GmbH +Copyright (C) 2015 Purna Chandra Mandal +(C) Copyright 2019 Xilinx, Inc. +Copyright (C) 2018 Arm Ltd +Copyright (C) 2017 Weidmüller Interface GmbH & Co. KG +Copyright (C) 2013 Soren Brinkmann +Copyright (C) 2013 Xilinx, Inc. All rights reserved. +Copyright (C) 2016 Xilinx, Inc. +(C) Copyright 2015 Linaro +Copyright (C) 2015 Linaro +Copyright (C) 2012 TQ-Systems GmbH +Copyright (C) 2015, Google, Inc +Copyright (c) International Business Machines Corp., 2006 +Copyright (C) 2004 Ray Lehtiniemi +Copyright (C) 2003 Cirrus Logic, Inc +Copyright (C) 1999 ARM Limited. +Copyright 2008-2012 Freescale Semiconductor, Inc. +Copyright 2014-2016 Freescale Semiconductor, Inc. +Copyright 2014-2015 Freescale Semiconductor, Inc. +Copyright 2010-2016 Freescale Semiconductor, Inc. +Copyright 2008, 2010-2016 Freescale Semiconductor, Inc. +Copyright (C) 2016-2017 Micron Technology, Inc. +Copyright (c) 2016-2017 Micron Technology, Inc. +Copyright (c) 2018 Macronix +Copyright (c) 2017 exceet electronics GmbH +Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at) +Copyright (C) 2009 Jean-Christopher PLAGNIOL-VILLARD +Copyright (C) 2014 - 2015 Xilinx, Inc. +(C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas +(C) Copyright 2012 ATMEL, Hong Xu Based on Linux DaVinci NAND driver by TI. Original copyright follows: +Copyright (C) 2014 Panasonic Corporation +Copyright (C) 2013-2014, Altera Corporation +Copyright (C) 2009-2010, Intel Corporation and its suppliers. +Copyright (C) 2013-2014 Altera Corporation +Copyright (C) 2014-2015 Masahiro Yamada +Copyright (c) 2006-2008 Freescale Semiconductor +Copyright (c) 2008 Freescale Semiconductor, Inc. +Copyright (c) 2012 Freescale Semiconductor, Inc +(C) Copyright 2014 3ADEV +(C) Copyright 2015-2018 Vladimir Zapolskiy +Copyright 2004-2007 Freescale Semiconductor, Inc. +Copyright 2008 Sascha Hauer, kernel@pengutronix.de +Copyright 2009 Ilya Yanok, +(c) 2009 Magnus Lilja +Copyright (C) 2008 Embedded Alley Solutions, Inc. +Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) +2002-2006 Thomas Gleixner (tglx@linutronix.de) +Copyright © 2004 Thomas Gleixner (tglx@linutronix.de) +Copyright © 2011 Ivan Djelic +Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) +Copyright (C) 2006 Thomas Gleixner +Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) +Copyright (c) 2006-2009 Analog Devices Inc. +Copyright (C) 2014 Free Electrons +Copyright (C) 2006 by Weiss-Electronic GmbH. +Copyright (C) 2008 Nokia Corporation: dropffs() function by Artem Bityutskiy from mtd-utils +Copyright 2010 Freescale Semiconductor +(C) Copyright 2010-2011 Texas Instruments, +(C) Copyright 2004-2008 Texas Instruments, +Copyright © 2005 Intel Corporation +Copyright © 2006 Marvell International Ltd. +Copyright (C) STMicroelectronics 2019 +Copyright (C) 2013 Boris BREZILLON +Copyright (C) 2015 Roy Spliet +Copyright (C) 2013 Qiang Yu +Copyright (C) 2013 Henrik Nordström +Copyright (C) 2013 Dmitriy B. +Copyright (C) 2013 Sergey Lapin +Copyright (c) 2014-2015, Antmicro Ltd +Copyright (c) 2015, AW-SOM Technologies +(C) Copyright 2011 NVIDIA Corporation +(C) Copyright 2006 Detlev Zundel, dzu@denx.de +(C) Copyright 2006 DENX Software Engineering +Copyright 2009-2015 Freescale Semiconductor, Inc. and others +(C) Copyright 2016 Xilinx, Inc. +(C) Copyright 2018 Rockchip Electronics Co., Ltd +Copyright (C) 2016 Stefano Babic +Copyright 2014, Freescale Semiconductor +Copyright (c) 2018, Google Inc. All rights reserved. +Copyright (c) 2012, The Chromium Authors +Copyright (c) 2013, The Chromium Authors +Copyright (c) 2018 Heinrich Schuchardt +Copyright (C) 2014, STMicroelectronics - All Rights Reserved +Copyright (c) 2017 Microsemi Corporation +Copyright (C) 2008-2013 Tensilica Inc. +Copyright (C) 2016 Cadence Design Systems Inc. +Copyright (C) 2005 - 2013 Tensilica Inc. +Copyright (C) 2014 - 2016 Cadence Design Systems Inc. +Copyright (C) 2001 - 2012 Tensilica Inc. +Copyright (C) 2001 - 2009 Tensilica Inc. +Copyright (C) 2001 - 2007 Tensilica Inc. +Copyright (C) 2009 Tensilica Inc. +Copyright (C) 2006 Tensilica Inc. +(C) Copyright 2007, Tensilica Inc. +Copyright (C) 2001-2007 Tensilica Inc. +(C) Copyright 2007 Tensilica, Inc. +(C) Copyright 2008, Tensilica Inc. +Copyright (C) 2007, Tensilica Inc. +Copyright (C) 1997 Tensilica Inc. +Copyright (c) 2006 Tensilica, Inc. All Rights Reserved. +Copyright (C) 2010 Texas Instruments +Copyright (C) 2016-2017 Socionext Inc. +Copyright (C) 2014 Panasonic Corporation +Copyright (C) 2015-2017 Socionext Inc. +Copyright (c) 2014 DENX +Copyright (C) DENX +(C) Copyright 2010 +Copyright 2004-2012 Freescale Semiconductor, Inc. +Copyright (C) 2004-2008 Freescale Semiconductor, Inc. +Copyright (c) 1997 Dan Malek (dmalek@jlc.net) +Copyright 2006 Freescale Semiconductor, Inc. +Copyright (c) 2003 Josef Baumgartner +2006 Zachary P. Landau +Copyright (c) 2005 Arthur Shipkowski +Copyright (c) 2003 Josef Baumgartner +(C) Copyright 1999, Greg Ungerer (gerg@snapgear.com) +(C) Copyright 2000, Lineo Inc. (www.lineo.com) +(C) Copyright 2006, Lab X Technologies +Copyright (C) 2003-2004, Greg Ungerer (gerg@snapgear.com) +Copyright (C) 2004-2008 Arthur Shipkowski (art@videon-central.com) +Copyright (C) 2019 Oliver Graute +Copyright (C) 2015 Masahiro Yamada +Copyright (c) 2006 SUSE Linux Products GmbH +Copyright (c) 2006 Tejun Heo +Copyright (C) 1996-2005 Paul Mackerras. +(C) Copyright 2017 Jorge Ramirez-Ortiz +Copyright (C) 2015-2019 Stefan Roese +Copyright (c) 2013, Andreas Oetken. +Copyright (C) 2003-2006 Christophe Devine +Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler +Copyright 2019 Broadcom +Copyright (C) 2010 Shawn Lin (nobuhiro@andestech.com) +Copyright (C) 2011 Macpaul Lin (macpaul@andestech.com) +Copyright (C) 2013 Andes Technology Corporation +Copyright (c) 2005-2007 Analog Devices Inc. +Copyright (C) 2008 Andes Technology Corporation +Copyright (C) 2013 Ken Kuo (kenkuo@andestech.com) +Copyright (C) 2018 Collabora Ltd. +Copyright (C) 2015-2016 Stefan Roese +Copyright (C) 2016 Samsung Electronics +(C) Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +(C) Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2010 Samsung Electronics +Copyright (c) 2015 Sjoerd Simons +Copyright (c) 2019 Heinrich Schuchardt +Copyright 2013 Albert ARIBAUD +Copyright (C) 2016 Peng Fan +Copyright 2008-2013 Analog Devices Inc. +Copyright (C) 2015 Thomas Chou +Copyright (C) 2011 Missing Link Electronics +Copyright (C) 2013 Bo Shen +Copyright (C) 2009 Jens Scharsig (jsatng@scharsoft.de) +Copyright (C) 2005 HP Labs +Copyright (C) 2008-2011 Florian Fainelli +(C) Copyright 2011 Guralp Systems Ltd. +Copyright (C) 2008,2009 STMicroelectronics +Copyright (C) 2009 Alessandro Rubini +Copyright (C) 2010 Joakim Axelsson +(C) Copyright 2015 Marek Vasut +Copyright (C) 2019 Marek Vasut +Copyright 2010 eXMeritus, A Boeing Company +Copyright (C) 2009-2011 Gabor Juhos +Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2007 David Brownell +Copyright (c) 2015 Microchip Technology Inc +Copyright (C) 2008 Magnus Damm +Copyright (C) 2019 SiFive, Inc. +Copyright (c) 2010-2016, NVIDIA CORPORATION. +(C) Copyright 2010-2012,2015 +Copyright (c) 2013 - 2018 Xilinx, Michal Simek +Copyright (C) 2015 DAVE Embedded Systems +Copyright (C) 2009 - 2014 Xilinx, Inc. +Copyright (C) 2015 Reinhard Pfau +Copyright 2007-2012 Freescale Semiconductor, Inc. +Copyright (C) 2018-2019 Marek Vasut +Copyright (C) 2014 Renesas Electronics Europe Ltd +Copyright (C) 2009 - 2011 Paul Mundt +(C) Copyright 2002, 2003 +Copyright (C) 2018 Texas Instruments, Inc +Copyright (C) 2013-2018 Intel Corporation. All rights reserved +Copyright (c) 2017-2019 MediaTek Inc. +Copyright 2000 MontaVista Software Inc. +Copyright 2015 Google, Inc +Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc. +Copyright (C) 1998 Gabriel Paubert. +Copyright (C) 2003-2004 Linux Networx +Copyright (C) 2003-2006 Ronald G. Minnich +Copyright (C) 2004-2005 Li-Ta Lo +Copyright (C) 2005-2006 Tyan +Copyright (C) 2005-2009 coresystems GmbH +Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,David Mosberger-Tang +Copyright 1997 -- 1999 Martin Mares +Copyright (c) 2010, CompuLab, Ltd. +Copyright (c) 2008-2009, NVIDIA Corporation. +Copyright (c) 2013-2014, NVIDIA Corporation. +(c) 2011 Graf-Syteco, Matthias Weisser +(C) Copyright 2009 DENX Software Engineering +Copyright (C) 2008,2009 Eric Jarrige +Copyright (C) 2009 Ilya Yanok +Copyright 2010 Maxim Integrated Products +Copyright 2011 Maxim Integrated Products +Copyright 2014 Rockchip Electronics Co., Ltd. +Copyright 2018 Google, LLC +Copyright 2013 Realtek Semiconductor Corp. +Copyright (C) 2012-2014 Panasonic Corporation +Copyright (C) 2016 Socionext Inc. +Copyright (C) 2012-2015 Masahiro Yamada +Copyright 2016 - AmLogic, Inc. +Copyright 2018 - Beniamino Galvani +Copyright 2018 - BayLibre, SAS +(C) Copyright 2017 - Beniamino Galvani +Copyright 2017 - Beniamino Galvani +(C) Copyright 2016 Carlo Caione +Copyright (C) 2017 Marek Vasut +Copyright 2013-2015 Freescale Semiconductor Inc. +Copyright (C) 2013-2015 Freescale Semiconductor, Inc. +Copyright (C) 2015 Freescale Semiconductor +Copyright (C) 2010 Marek Vasut +Copyright (C) 2016 Marcel Ziswiler +Copyright (C) 2014 NVIDIA Corporation +(C) Copyright 2017 Texas Instruments Incorporated, +Copyright (C) 2015 Freescale Semiconductor, Inc +(C) Copyright 2014 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2016 Toradex AG +(C) Copyright 2019 Texas Instruments Incorporated, +Copyright (C) 2017 Andes Technology Corporation +Copyright (C) 2015 ARM Limited +Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +Copyright © 1999-2010 David Woodhouse et al. +Copyright © International Business Machines Corp., 2006 +Copyright (C) Nokia Corporation, 2007 +Copyright (C) Samsung Electronics, 2009 +Copyright(c) 2005-2008 Samsung Electronics +Copyright (C) 2005-2009 Samsung Electronics +Copyright (c) 2008 Texas Instruments +Copyright 2008 Mentor Graphics Corporation +Copyright (C) 2008 by Texas Instruments +(C) Copyright 2008 Texas Instruments Incorporated. +Copyright (c) 2009 Texas Instruments +Copyright (c) 2005 Ben Gardner +Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved +Copyright (c) 2014 Rene Griessl +Copyright (c) 2017 Microchip Technology Inc. All rights reserved. +Copyright (c) 2013 Gerhard Sittig +Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved. +Copyright (C) 2009 NVIDIA, Corporation +Copyright (C) 2007-2008 SMSC (Steve Glendinning) +Copyright (C) 2009 Florian Fainelli +Copyright (c) 2016-2019 Toradex, Inc. +Copyright (c) 2016 Toradex, Inc. +Copyright (c) 2016 Xilinx, Inc +(C) Copyright 2014 CompuLab, Ltd. +(C) Copyright 2011 CompuLab, Ltd. +(C) Copyright 2012 - 2013 CompuLab, Ltd. +Copyright 2009: Marvell Technology Group Ltd. +Copyright (C) 2016 Google Inc. +Copyright (C) 2014 Google Inc. +Copyright (C) 2016 Google, Inc. +Copyright (C) 2014, 2015 Renesas Electronics Corporation +Copyright 2009 Lattice Semiconductor Corp. +Copyright (C) 2012-2017 Altera Corporation +Copyright (C) 2017-2019 Intel Corporation +(C) Copyright 2019, Xilinx, Inc, +Copyright (c) 2019 SED Systems, a division of Calian Ltd. +(C) Copyright 2015 - 2016, Xilinx, Inc, +Copyright (c) 2017 Rockchip Electronics Co., Ltd +Copyright (C) 2015 Altera Corporation +Copyright (C) 2015 Nobuhiro Iwamatsu +(C) Copyright 2015-2016, Freescale Semiconductor, Inc. +(C) Copyright 2013-2016, Freescale Semiconductor, Inc. +Copyright (C) 2012 Xilinx, Inc. All rights reserved. +Copyright (C) 2012 - 2013 Michal Simek +Copyright (C) 2012 - 2017 Xilinx, Inc. All rights reserved. +Copyright (c) 2013 Xilinx Inc. +Copyright (c) 2013 Xilinx, Inc. +Copyright (c) 2015 DAVE Embedded Systems +(c) Copyright 2010-2017 Xilinx, Inc. All rights reserved. +Copyright (c) 2013 - 2017 Xilinx Inc. +(C) Copyright 2014 - 2017 Xilinx, Inc. Michal Simek +Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved. +Copyright (c) 2018 Emlid Limited +Copyright (C) 2013 Freescale Semiconductor, Inc. +Copyright (C) 2014 O.S. Systems Software LTDA. +Copyright (C) 2015 Technexion Ltd. +Copyright (C) 2011-2015 Panasonic Corporation +Copyright (C) 2013-2014 Panasonic Corporation +Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. +Copyright 2010 Sun Microsystems, Inc. All rights reserved. +Copyright 2009 Sun Microsystems, Inc. All rights reserved. +Copyright 2007 Sun Microsystems, Inc. All rights reserved. +Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +(C) Copyright 2011 DENX Software Engineering GmbH +(C) Copyright 2002 SIXNET, dge@sixnetio.com. +(C) Copyright 2004, Li-Pro.Net +(C) Copyright 2019 NXP +(C) Copyright 2009-2012 ADVANSEE +Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright 2010 Orex Computed Radiography +Alexander Bigga , 2006 (c) mycable GmbH +Copyright (C) 2008 Kim B. Heino +Copyright (C) 2016 by NXP Semiconductors Inc. +Copyright (C) 2004 Gary Jennejohn garyj@denx.de +Copyright (C) 2005-06 Tower Technologies +Copyright (c) 2017, General Electric Company +Copyright 2004 Karen Spearel +Copyright 2005 Alessandro Zummo +Copyright (C) 2015 Wenyou Yang +Copyright (C) 2012-2013 Atmel Corporation +Copyright (C) 2014 Atmel +Copyright (C) 2017 Martin Blumenstingl +(C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd +Copyright (C) 2019, Rick Chen +Copyright (C) 2019 Western Digital Corporation or its affiliates. +Copyright (c) 2016-17 Microsemi Corporation. +Copyright (C) 2018, Anup Patel +Copyright (C) 2014 Linaro Ltd. +Copyright (C) 1999 Hewlett-Packard Co. +Copyright (C) 2019 Fraunhofer AISEC,Lukas Auer +Copyright (C) 2012 Bluegiga Technologies Oy +Copyright 2011 Freescale Semiconductor +Copyright 2011,2012 Freescale Semiconductor, Inc. +Copyright (C) 1996 David S. Miller +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle +Copyright (C) 1999, 2000 Silicon Graphics, Inc. +Copyright (C) 2000 MIPS Technologies, Inc. +Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle +Copyright (C) 1995, 1996 Paul M. Antoine +Copyright (C) 1998 Ulf Carlsson +Copyright (C) 1999 Silicon Graphics, Inc. +Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki +Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. +Copyright (C) 2014, Imagination Technologies Ltd. +(C) Copyright 2008 - 2013 Tensilica Inc. +(C) Copyright 2014 Cadence Design Systems Inc. +Copyright (c) 2011, Google Inc. All rights reserved. +Copyright (C) 2000,2001 Larry Doolittle +Copyright (c) 2011 Sebastian Andrzej Siewior +Copyright (c) 2008-2009 Analog Devices Inc. +Copyright 2009 Analog Devices Inc. +(C) Copyright 2001-2002 +Copyright (c) Orbacom Systems, Inc +Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +(C) Copyright Linus Torvalds 1999 +(C) Copyright Johannes Erdfelt 1999-2001 +(C) Copyright Andreas Gal 1999 +(C) Copyright Gregory P. Smith 1999 +(C) Copyright Deti Fliegl 1999 (new USB architecture) +(C) Copyright Randy Dunlap 2000 +(C) Copyright David Brownell 2000 (kernel hotplug, usbdeviceid) +(C) Copyright Yggdrasil Computing, Inc. 2000 +(C) Copyright 2001 Denis Peter, MPL AG Switzerland +(c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) +(c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) +(c) 1999 Michael Gee (michael@linuxspecific.com) +(c) 2000 Yggdrasil Computing, Inc. +Copyright (C) 2015 Compulab, Ltd. +Copyright (C) 2016 Compulab, Ltd. +Copyright (C) 2009 Matthias Kaehlcke +Copyright (C) 2010, 2009 Matthias Kaehlcke +Copyright (C) 2009, 2010 Matthias Kaehlcke +Copyright 2019, Heinrich Schuchardt +Copyright 2006 - 2016 Unified EFI, Inc.
+Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
+Copyright 2017 Theobroma Systems Design und Consulting GmbH +(C) Copyright 2017 Heiko Stuebner +(C) Copyright 2015 Rockchip Electronics Co., Ltd +Copyright (c) 2016 Heiko Stuebner +Copyright 2016 Rockchip Inc. +Copyright (C) 2019 Collabora Inc - https://www.collabora.com/ +(C) Copyright 2018 Rockchip Electronics Co., Ltd. +Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd +Copyright (C) 2017 Rockchip Electronics Co., Ltd. +Copyright (C) 2018 Rockchip Electronics Co., Ltd +Copyright (C) 2019 Rockchip Electronics Co., Ltd +Copyright (C) 2016-2017 Rockchip Electronics Co., Ltd +(C) Copyright 2016 Rockchip Electronics Co.,Ltd +Copyright (C) 2016 Daniel Schwierzeck +Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd +Copyright (c) 2018 Rockchip Electronics Co., Ltd +(C) Copyright 2012 Stephen Warren +Copyright (c) 2015 Stephen Warren +Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2015 ECA Sinters +(C) Copyright 2018 Allied Telesis +Copyright (C) 2018 Lukasz Majewski +Copyright (C) 2012, Stefano Babic +(C) Copyright 2008-2009 Freescale Semiconductor, Inc. +(C) Copyright 2013 Siemens Schweiz AG +(C) Heiko Schocher, DENX Software Engineering, hs@denx.de. +Copyright (C) 2017 PHYTEC Messtechnik GmbH +Copyright (C) 2015, Kodak Alaris, Inc +(C) Copyright 2015 Chen-Yu Tsai +Copyright 2007, Embedded Specialties, Inc. +Copyright 2007 Wind River Systems, Inc. +Copyright 2007 Wind River Systemes, Inc. +Copyright (c) 2018, Bootlin +Copyright (C) 2013 Guntermann & Drunck, GmbH +Copyright (C) 2011 Infineon Technologies +Copyright (C) 2013-2016, Yann Collet. +Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +Copyright (C) 2016, Yann Collet. +Copyright (C) 2013-2015, Yann Collet. +Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. +Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2008-2013 Eric Jarrige +(C) Copyright 2002-2013 +Copyright (C) 2004 +Copyright (C) 2019 Texas Instruments Incorporated - http:www.ti.com +(C) 2000 Red Hat. GPL'd. +Copyright © 2002 Robert Kaiser +Copyright © 2002-2010 David Woodhouse +Copyright © 1999-2010 David Woodhouse +Copyright © 2006 Red Hat UK Limited +Copyright © 2000 Nicolas Pitre +Copyright © 2002 Thomas Gleixner +Copyright © 2000-2010 David Woodhouse +Copyright (C) 2016 Renesas Electronics Corporation +Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved. +Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. +Copyright (C) 1989-2013 Free Software Foundation, Inc. +Copyright (c) 2003-2005 by Peter Astrand +Copyright (c) 2012-2014 Birdland Audio - http://birdland.com/oem +Copyright (c) 2012-2014, Birdland Audio - http://birdland.com/oem +(C) Copyright 2011 - 2013 CompuLab, Ltd. +(C) 2006 Andrew Victor +Copyright (C) 2007 Atmel Corporation. +Copyright (C) SAN People +(C) 2007 Atmel Corporation. +Copyright (C) 2006 Atmel Corporation. +(C) 2008 Atmel Corporation. +Copyright (C) 2008 Atmel Corporation. +Copyright (C) 2012-2013 Atmel Corporation. +Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD +Copyright (C) 2007 Andrew Victor +Copyright (C) 2018 Microchip Technology Inc. +Copyright (C) 2013 Atmel Corporation +Copyright (C) 2015 Atmel Corporation. +Copyright (c) 2015 Atmel Corporation +Copyright (C) 2015 Atmel +Copyright (C) 2017 Microchip Corporation. +(C) 2012 - 2013 Atmel Corporation. +Copyright (C) 2012 Atmel Corporation. +Copyright (C) 2016 Marek Vasut +Copyright 2012 Calxeda, Inc. +Copyright (c) 2010, by Texas Instruments +Copyright (c) 2008-2009, MontaVista Software, Inc. +Copyright (c) 2019, by Texas Instruments +Copyright (c) 2008-2019, MontaVista Software, Inc. +Copyright (c) 2016 Petr Kulhavy +Copyright 2005 Mentor Graphics Corporation +Copyright (C) 2005-2006 by Texas Instruments +Copyright (C) 2006-2007 Nokia Corporation +Copyright (C) 2012, by Texas Instruments +Copyright (C) 2009 MontaVista Software, Inc. +Copyright (C) 2008-2009 MontaVista Software, Inc. +Copyright © 2015 Hans de Goede +Copyright (C) 2005-2007 by Texas Instruments +Copyright (C) 2015, Microchip Technology Inc. +Copyright © 2013 Jussi Kivilinna +Copyright 2007-2012 (C) Allwinner Technology Co., Ltd. +Copyright (c) 2008-2009 MontaVista Software, Inc. +Copyright (C) 2013 Lars Poeschel, Lemonage Software GmbH +Copyright (C) 2015 Wadim Egorov, PHYTEC Messtechnik GmbH +Copyright (C) 2019 DENX Software Engineering GmbH +Copyright (C) 2012 Jonas Gorski +Copyright (c) 2019, Linaro Limited +Copyright (C) 2019 Synopsys, Inc. All rights reserved. +Copyright (c) 2017, Impinj, Inc. +Copyright 2014 Steffen Trumtrar +Copyright 2013 Maxime Ripard +Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH +Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd +Copyright (C) 2018 Dennis Gilmore +Copyright (C) 2011 Andreas Bießmann +Copyright (C) 2016 Vladimir Zapolskiy +(c) Copyright 2008 Nobuhiro Iwamatsu +(c) Copyright 2008 Renesas Solutions Corp. +Copyright (C) 2007,2008 Nobobuhiro Iwamatsu +Copyright (C) 2015 Cogent Embedded, Inc. +Copyright (C) 2019 Andes Technology Corporation +(C) Copyright 2017 Renesas Electronics Europe Ltd +Copyright 2015 ATS Advanced Telematics Systems GmbH +Copyright 2015 Konsulko Group, Matt Porter +Copyright (C) 2006-2008 Nokia Corporation. +Copyright (C) 2006, 2007 University of Szeged, Hungary +Copyright (C) 2015 Marek Vasut +Copyright (C) 2019 BayLibre SAS +(C) Copyright David Gibson , IBM Corporation. 2007. +(C) Copyright David Gibson , IBM Corporation. 2005. +Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. +Copyright 2011 The Chromium Authors, All Rights Reserved. +Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. +Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (c) 2010-2012 NVIDIA Corporation +Copyright 2011-2012 NVIDIA Corporation +Copyright (C) 2005-2008 Arthur Shipkowski (art@videon-central.com) +Copyright (C) 2011 The Chromium Authors. +Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007 +Copyright (C) ST-Ericsson SA 2010 +Copyright 2019 IBM Corp. +and hence presumably (C) 2012 Oleksandr Tymoshenko +(C) 2012 Stephen Warren +The Linux kernel code has the following (c) and license, which is hence +Based on sdhci-bcm2708.c (c) 2010 Broadcom +Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd. +(C) Copyright 2019 Synamedia +Copyright (C) 2010 Texas Instruments Incorporated +Copyright 2007, 2010-2011 Freescale Semiconductor, Inc +Copyright 2018 Andes Technology, Inc. +Copyright 2019 Broadcom. +Copyright 2008, Freescale Semiconductor, Inc +Copyright (C) 2009 Ilya Yanok, +Copyright (C) 2008 Sascha Hauer, Pengutronix +Copyright (C) 2006 Pavel Pisa, PiKRON +Copyright 2007, Freescale Semiconductor, Inc +Copyright (C) 2015 Microchip Technology Inc. +(C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd +Copyright 2014, Staubli Faverges +Copyright (C) 2011 Renesas Solutions Corp. +Copyright (C) 2011,2013-2017 Renesas Electronics Corporation +Copyright (C) 2008-2009 Renesas Solutions Corp. +Copyright (C) 2019 Synopsys +(C) Copyright 2013 Altera Corporation +Copyright 2011-2016 NVIDIA Corporation +Copyright (C) 2016 Marvell, All Rights Reserved. +(C) Copyright 2013 - 2015 Xilinx, Inc. +(C) Copyright 2016 Broadcom Ltd. +(C) Copyright 2011 Bluewater Systems +(C) Copyright 2011 NVIDIA Corporation www.nvidia.com +Copyright © 2011 Parrot S.A. +Copyright (C) 1995-1998 Mark Adler +Copyright (c) 2004 Cisco Systems, Inc. +Copyright (c) 2008 Herbert Xu +Copyright (C) 1991, 1992 Linus Torvalds +Copyright (C) 1999 Hewlett-Packard Co +Copyright (C) 1999 David Mosberger-Tang +Copyright (c) 2014 +Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. +Copyright (c) 2009, Google Inc. +Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. +Copyright (C) 1992, 1997 Free Software Foundation, Inc. +Copyright (C) 2001 Peter Bergner. +Copyright (C) 2011-2015, Yann Collet. +Copyright 2015 Google Inc. +Copyright 2009 Dirk Behme, dirk.behme@googlemail.com +Copyright 2009 Benjamin Herrenschmidt, IBM Corp +(C) 1999 Andrea Arcangeli +(C) 2002 David Woodhouse +(C) 2012 Michel Lespinasse +Copyright (C) 2001-2003 Christophe Devine +Copyright (C) 2004,2008 Kustaa Nyholm +Copyright 2011 Calxeda, Inc. +Copyright (C) 2012-2016, Yann Collet. +(C) Copyright 2014-2015 +Copyright (C) 2015 Udoo +(C) Copyright 2017 Jorge Ramirez Ortiz +(C) Copyright 2019 Ramon Fried +(C) Copyright 2016 Mateusz Kulikowski +Copyright (C) 2015, Bachmann electronic GmbH +Copyright (C) 2017 Amarula Solutions +Copyright 2011-2012 Freescale Semiconductor, Inc. +Copyright (C) 2018 Technexion Ltd. +Copyright (C) 2017-2018 STMicroelectronics - All Rights Reserved +Copyright (C) 2014-2016 Stefan Roese +Copyright (C) 2015-2016 Reinhard Pfau +(C) Copyright 2008 Marvell Semiconductor +(c) 2004 Sascha Hauer +Copyright (C) 2014 Eukréa Electromatique +Copyright (C) 2013 SolidRun ltd. +Copyright (C) 2013 Jon Nettleton . +Copyright (c) 2019 Intel Corporation +(C) Copyright 2015-2016 Texas Instruments Incorporated, +Copyright (C) 2012-2019 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2015, Saket Sinha +Copyright (C) 2007 Advanced Micro Devices, Inc. +Copyright (C) 2009-2010 coresystems GmbH +Copyright (C) 2001 Ronald G. Minnich +Copyright (C) 2005 Nick.Barker9@btinternet.com +Copyright (C) 2007-2009 coresystems GmbH +Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) +Copyright (C) 2015 Bin Meng +Copyright (C) 2005 Intel Co. +Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc. +Copyright (c) 2015, Sony Mobile Communications AB. +Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. +Copyright (c) 2018, Ramon Fried +Copyright (C) 2014 Andrew Ruder +Copyright (C) 2012 Łukasz Dałek +(C) Copyright 2007, 2012 Freescale Semiconductor, Inc. +(C) Copyright 2010 Freescale Semiconductor, Inc. +Copyright (C) 2015 Masahiro Yamada +Copyright (c) 2013 Google, Inc. +Copyright (C) 2015 Free Electrons +Copyright (C) 2014-2017 Altera Corporation +Copyright (C) 2016-2017 Intel Corporation +Copyright (C) 2013-2017 Altera Corporation +Copyright (C) 2016-2017 Intel Corporation +Copyright (C) 2015-2017 Intel Corporation +Copyright 2016 Freescale Semiconductor +(C) Copyright 2012 Nobuhiro Iwamatsu +(C) Copyright 2012 Renesas Solutions Corp. +(C) Copyright 2010 Linaro +Copyright (C) 2011 Mistral Solutions Pvt Ltd +Copyright (C) 2013 Magnus Damm +Copyright (C) 2012 Kuninori Morimoto +Copyright (C) 2014-2017 Cogent Embedded, Inc. +Copyright (C) 2013-2014 Renesas Electronics Corporation +Copyright (C) 2016 Cogent Embedded, Inc., +Copyright (C) 2014-2015 Renesas Electronics Corporation +Copyright (C) 2015 Renesas Solutions Corp. +Copyright (C) 2015-2017 Cogent Embedded, Inc. +Copyright (C) 2015-2019 Renesas Electronics Corporation +Copyright (C) 2016-2019 Renesas Electronics Corp. +Copyright (C) 2015 Renesas Electronics Corporation +Copyright (C) 2017 Cogent Embedded, Inc. +Copyright (C) 2018-2019 Renesas Electronics Corp. +Copyright (C) 2016-2017 Renesas Electronics Corp. +Copyright (C) 2017 Renesas Electronics Corp. +Copyright (C) 2009 - 2012 Paul Mundt +Copyright (C) 2017 Marek Vasut +Copyright (c) 2003,Motorola Inc. +Copyright 2004 Freescale Semiconductor, Inc. +Copyright (C) 2004-2008,2010-2011 Freescale Semiconductor, Inc. +Copyright 2012-2016 Freescale Semiconductor, Inc. +Copyright 2007,2009-2012 Freescale Semiconductor, Inc. +Copyright 2004-2011 Freescale Semiconductor, Inc. +Copyright(c) 2002,2003 Motorola Inc. +Copyright 2004, 2011 Freescale Semiconductor +Copyright 2008 Qstreams Networks, Inc. +(C) Copyright 2000 - 2002 +Copyright (c) 2006 Wind River Systems, Inc. +Copyright (c) 2006-2007 Wind River Systems, Inc. +Copyright (C) 2012-2019 Altera Corporation +(C) Copyright 2010-2014 +Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2019 Linaro Ltd. +Copyright (C) 2016 NXP Semiconductors +Copyright 2016-2017 Texas Instruments, Inc. +(C) Copyright 2016-2017 +Copyright 2011 Linaro Limited +Copyright (C) 2016-2018 Toradex AG +2015 Toradex AG +(C) Copyright 2018,2019 Arm Ltd. +(C) Copyright 2017 Icenowy Zheng +(C) Copyright 2010-2013 +(C) Copyright 2014-2016, Freescale Semiconductor, Inc. +(C) Copyright 2018 Texas Instruments, +Copyright (c) 2018, Linaro Limited +(C) Copyright 2018 Michal Simek +Copyright (C) 2014-2015, Bin Meng +Copyright (c) 2011 IDS GmbH, Germany +Copyright (C) 2019 Socionext Inc. +Copyright (C) 2016-2018 Socionext Inc. +Copyright (C) 2016 Socionext Inc. +Copyright (C) 2011-2015 Copyright (C) 2011-2015 Panasonic Corporation +Copyright (C) 2015-2017 Renesas Electronics Corporation +Copyright (C) 2013 Gateworks Corporation +Copyright 2007,2009-2014 Freescale Semiconductor, Inc. +Copyright (C) 2015 Socionext Inc. +Copyright (C) 2019 Marek Vasut +Copyright (C) 2009 Texas Instruments Incorporated +Copyright (C) 2008 Lyrtech +copyright (C) 2007 Sergey Kubushyn +Copyright (C) 2011 OMICRON electronics GmbH +Copyright (C) 2011 DENX Software Engineering GmbH +(C) Copyright 2015-2016 +Copyright 2014-2017 Broadcom. +(C) Copyright 2004-2007, 2012 Freescale Semiconductor, Inc. +(C) Copyright 2014 - 2015 Xilinx, Inc. +Copyright 2016 - 2017 Xilinx, Inc. +Copyright 2015 Xilinx, Inc. +Copyright 2018 Xilinx, Inc. +Copyright 2015 - 2016 Xilinx, Inc. +Copyright (C) 2017 DENX Software Engineering +(C) Copyright 2014 Hans de Goede +Copyright (C) 2016 Jean-Francois Moine +Copyright (c) 2016 Allwinnertech Co., Ltd. +(C) Copyright 2015 Roy Spliet +(C) Copyright 2017 Icenowy Zheng +(C) Copyright 2007-2015 Allwinner Technology Co. +(C) Copyright 2015 Vishnu Patekar +(C) Copyright 2016 Theobroma Systems Design und Consulting GmbH +(C) Copyright 2015 Jens Kuske +(C) Copyright 2016 Theobroma Systems Design und Consulting GmbH +Copyright 2014 - Hans de Goede +(c) Copyright 2013 Oliver Schinagl +(C) Copyright 2016 Hans de Goede +Copyright (C) 2004 Nokia Corporation +(C) Copyright 2018 - Beniamino Galvani +(C) Copyright 2018 - BayLibre, SAS +Copyright 2019 NXP. +Copyright 2014-2015 Freescale Semiconductor +Copyright (C) 2016 George McCollister +Copyright (c) 2015 Imagination Technologies +Copyright (c) Nokia Corporation, 2007 +Copyright (c) 2012 Linutronix GmbH +Copyright (c) 2014 sigma star gmbh +Copyright (c) Nokia Corporation, 2006, 2007 +Copyright (c) Nokia Corporation, 2006 +Copyright (C) 2015, Miao Yan +(C) Copyright 2019 Bin Meng +(C) Copyright 2019 Rockchip Electronics Co., Ltd. +(C) Copyright 2016-2017 Rockchip Inc. +Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au) +Copyright (c) 2015, Linaro Limited +Copyright (C) 2014 Felix Fietkau +Copyright (C) 2004 - 2009 Ivo van Doorn +Copyright (c) 2010-2011 Jeremy Kerr +Copyright (C) 2011-2012 Linaro Ltd +(C) Copyright 2001 Linus Torvalds +Copyright © 2008 Keith Packard +Copyright (C) 2002, 2003, 2004 Dell Inc. +Copyright (C) 1998 David S. Miller (davem@redhat.com) +Copyright 2001 Jeff Garzik +Copyright 2001 Sun Microsystems (thockin@sun.com) +Copyright 2002 Intel (eli.kupermann@intel.com,christopher.leech@intel.com,scott.feldman@intel.com) +Copyright (C) Sun Microsystems 2008 +Copyright (c) 2006-2009, 2011 Freescale Semiconductor, Inc. +Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. +Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. +Copyright (C) 1996-2005 Markus F.X.J. Oberhumer +Copyright (C) 2008 Marvell Semiconductor +Copyright Torsten Duwe 1993 +Copyright Motorola 1984 (!). +Copyright 2006-2009 Solarflare Communications Inc. +Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) +Copyright (C) 2014 Linaro Ltd. +Copyright (C) 1992, 1994 by Theodore Ts'o. +Copyright (C) 2015, Inverse Path +Copyright (c) 2005, 2009 Freescale Semiconductor, Inc +Copyright (c) 2005 MontaVista Software +Copyright (c) 2008 Excito Elektronik i Sk=E5ne AB +Copyright (C) 2007 Eurotech S.p.A. +Copyright (C) 2011 Jana Rapava +Copyright (C) 2011 CompuLab, Ltd. +Copyright (C) 2010 Nokia Corporation +Copyright 2007-2013 Freescale Semiconductor, Inc. +Copyright 2011-2013 Freescale Semiconductor, Inc. +Copyright 2008-2013 Freescale Semiconductor, Inc. +Copyright 2004-2009 Analog Devices Inc. +Copyright (C) 2016 Atmel Corporation +Copyright (C) 2018 Microhip / Atmel Corporation +Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. +Copyright (c) 2015 Microchip Technology Inc. +Copyright (C) 2015-2018 Intel Corporation. +Copyright (C) 2018 Siemens AG +Copyright (C) 2000 Ronald G. Minnich +Copyright (C) 2012 Google Inc. +Copyright (c) Xilinx, Inc. +(C) Copyright 2007-2008 Semihalf, Rafal Jaworowski +(C) Copyright 2016 Vasily Khoruzhick +(c) Copyright 2016 by VRT Technology +(c) Copyright 2011 by Tigris Elektronik GmbH +(C) Copyright 2008-2011 Freescale Semiconductor, Inc. +(C) Copyright 2010 DENX Software Engineering +(C) Copyright 2005-2009 Samsung Electronics +(C) Copyright 2011-2012 Freescale Semiconductor, Inc. +(C) Copyright 2010-2016 Freescale Semiconductor, Inc. +(C) Copyright 2008 Atmel Corporation +(c) Copyright 2012 by National Instruments,Joe Hershberger +Copyright (c) 2015 Vladimir Zapolskiy +Copyright (c) 2015 Angelo Dureghello +Copyright (c) 2016 Marcel Ziswiler +Copyright (c) 2014 Nobuhiro Iwamatsu +Copyright (c) 2014 Renesas Electronics Corporation +Copyright (c) 2018 Angelo Dureghello +Copyright (C) 2018 Jagan Teki +Copyright © 2010-2015 Broadcom Corporation +Copyright 2016 - 2018 Xilinx, Inc. +Copyright (C) 2013 DENX Software Engineering, hs@denx.de +(C) Copyright 2014 DENX Software Engineering +Copyright 2018 NXP. +Copyright 2011-2015 Freescale Semiconductor, Inc. +Copyright 2010-2011 Freescale Semiconductor +Copyright 2006,2010 Freescale Semiconductor +Copyright 2016 Google, Inc +Copyright (C) 2018 DENX Software Engineering +(C) Copyright 2013 Keymile AG +Copyright (C) 1989-2015 Free Software Foundation, Inc. +(C) Copyright 2007 Freescale Semiconductor Inc +Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +(C) Copyright 2003 Josef Baumgartner +Copyright (C) 2018-2019 Intel Corporation +Copyright (c) 2014 Imagination Technologies +(C) Copyright 2010 Stefano Babic +(C) Copyright 2019, Microchip Technology, Inc. +Copyright 2007,2011 Freescale Semiconductor, Inc. +Copyright (C) 2008 MontaVista Software, Inc. +Copyright 2017, Theobroma Systems Design und Consulting GmbH +Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd +Copyright 2019 Rockchip Electronics Co., Ltd. +(C) Copyright 2015 General Electric Company +Copyright (C) 2019, Texas Instruments, Incorporated +Copyright (C) 2016, Texas Instruments, Incorporated +Copyright (C) 2010-2018 Texas Instruments Incorporated - http://www.ti.com/ +Copyright (C) 2011 Ilya Yanok, Emcraft Systems +Copyright (C) 2014 Soeren Moch +Copyright (C) 2017 Soeren Moch +Copyright (c) 2019, Texas Instrument +(C) Copyright 2016 Angelo Dureghello +Copyright (C) 2018 ROHM Semiconductors +Copyright (C) 2019 Vasily Khoruzhick +(C) Copyright 2014 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH +Copyright (c) 2016 NextThing Co +Copyright (c) 2016 Free Electrons +Copyright (C) 2011-2012 +Copyright (C) 2014 Wandboard +Copyright (C) 2012-2014 Daniel Schwierzeck, daniel.schwierzeck@gmail.com +Copyright (C) 2010 Reinhard Meyer, EMK Elektronik +Copyright (C) 2005, Intec Automation Inc. +Copyright (C) 2014, Freescale Semiconductor, Inc. +Copyright (C) 2016 Jagan Teki +Copyright (C) 2017 Linaro +Copyright (C) 2008 Embedded Alley Solutions Inc. +Copyright (C) 2012 Marek Vasut +Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2012 Robert Delien +Copyright (C) 2013 Andreas Wass +Copyright (C) 2019 Hannes Schmelzer +Copyright (C) 2013 Hannes Schmelzer +Copyright (C) 2007,2008 Nobuhiro Iwamatsu +Copyright (C) 2008 Yusuke Goda +Copyright (C) 2007 Nobuhiro Iwamatsu +(C) Copyright 2018 Xilinx, Inc. +(C) Copyright 2019 Luca Ceresoli +Copyright (C) 2014 Evgeni Dobrev +(C) Copyright 2016 Linaro Limited +Copyright (C) 2014, Gumstix, Incorporated - http://www.gumstix.com/ +Copyright (C) 2014, Gumstix, Inc. - http://www.gumstix.com/ +Copyright 2008 (C) Bryan O'Donoghue +Copyright (C) 2006-2014 Texas Instruments. +(C) Copyright TechNexion 2010 +Copyright (C) 2017 Grinn +Copyright (C) 2011, Texas Instruments Incorporated - http://www.ti.com/ +Copyright (c) 2017 Free Electrons +Copyright (C) 2004 Texas Instruments. +Copyright (C) 2009 David Brownell +Copyright (C) 2009 Nick Thompson, GE Fanuc Ltd, +Copyright (C) 2012 Dmitry Bondar +(C) Copyright 2015 Vishnu Patekar +Copyright (C) 2010 Andes Technology Corporation +(C) Copyright 2014-2016 +Copyright (c) 2013-2014, Stefan Agner +Copyright (C) 2019 Rockchip Electronic Co.,Ltd +(C) Copyright 2015-2019 Rockchip Electronics Co., Ltd +Copyright (C) 2002-2011 Aleph One Ltd. +Copyright (C) 2002-2007 Aleph One Ltd. +Copyright 2013 Freescale Semiconductor +Copyright (c) 2005-2011 Analog Devices Inc. +Copyright (C) 2019 Rosy Song +Copyright (C) 2017 Vasily Khoruzhick +Copyright (C) 2018 SiFive, Inc. +Copyright (C) 2018 Robert Bosch Power Tools GmbH +Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2014, Marcel Ziswiler +Copyright (c) 2016 Andreas Färber +Copyright (c) 2016, Alexander Graf +Copyright (c) 2017, Heinrich Schuchardt +Copyright (c) 2018, Xilinx Inc. +Copyright (c) 2017 Alison Chaiken +Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2016, Google Inc. +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2016, Xilinx Inc. Michal Simek +Copyright (c) 2017, Xiphos Systems Corp. All rights reserved. +Copyright (C) 2005 Silicon Graphics, Inc. +Copyright (c) 2011, NVIDIA Corp. All rights reserved. +Copyright (c) 2016 Imagination Technologies Ltd. +Copyright (C) Stefano Babic +(C) 2018 Google, Inc +Copyright (C) 2012-2017 Texas Instruments Incorporated, +Copyright (C) 2012 - 2013 Atmel Corporation +Copyright (C) 2012 Boundary Devices Inc. +Copyright 2008-2015 Freescale Semiconductor, Inc. +Copyright (C) 2016 Sergey Kubushyn +Copyright 2015 Toradex, Inc. +Copyright (C) 2010-2015 Freescale Semiconductor, Inc. +Copyright (C) 2004-2011 Freescale Semiconductor, Inc. +Copyright 2013 Stefan Roese +Copyright (C) 2011-2012 Freescale Semiconductor, Inc. +Copyright (c) 2018 Flowbird +Copyright (c) 2015 NextThing Co. +Copyright (c) 2009 esd gmbh. +Copyright (c) 2008-2009 esd gmbh. +Copyright (C) 2014 Nobuhiro Iwamatsu +Copyright (C) 2014 Renesas Electronics Corporation +Copyright (C) 2011 Kuninori Morimoto +Copyright (C) 2012 Renesas Solutions Corp. +Copyright (C) 2013, 2014 Nobuhiro Iwamatsu +Copyright (C) 2013, 2014 Renesas Electronics Corporation +Copyright (C) 2013-2017 Renesas Electronics Corporation +Copyright (C) 2018 Xilinx, Inc. - Michal Simek +Copyright (C) 2019 Pepperl+Fuchs +Copyright (C) 2013, Applied Micro Circuits Corporation +(C) Copyright 2016 Cadence Design Systems Inc. +Copyright (C) 2007 Free Software Foundation, Inc. +(C) Copyright 2011-2012 Pali Rohár +.. Copyright 2010 Nicolas Palix +.. Copyright 2010 Julia Lawall +.. Copyright 2010 Gilles Muller +Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2016 Tormod Volden and Stefan Schmidt +(C) Copyright 2014 Red Hat Inc. +Copyright (C) 2015 K. Merker +(C) Copyright 2014 Samsung Electronics +Copyright (C) 2015 Google. Inc +(C) 2003 Arun Dharankar +Copyright (C) Thomas Gleixner +Copyright (C) 2013, Miao Yan +Copyright (C) 2015-2018, Bin Meng +Copyright (C) 2019, Lihua Zhao +(C) Copyright 2013 Samsung Electronics +Copyright (C) 2013 The Chromium OS Authors. +Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com +Copyright (C) 2016 - 2018 Xilinx, Inc. +Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com +(C) Copyright 2015 Vladimir Zapolskiy +Copyright (c) 2012 Samsung Electronics Co. Ltd +(C) Copyright 2002-2004 by David Brownell +(C) Copyright 2013 O.S. Systems Software LTDA. +(C) Copyright 2012-2016 Stephen Warren +Copyright (c) 2015, Intel Corporation +Copyright (C) 2012-2020 ASPEED Technology Inc. +Copyright (c) 2014-2016, NVIDIA CORPORATION. +Copyright (c) 2019 NVIDIA Corporation. All rights reserved. +Copyright 2010-2011 NVIDIA Corporation +Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2011-2012 NVIDIA Corporation +Copyright (c) 2013 NVIDIA Corporation +(c) 2004 by Andre Renaud from logogurnardsmall.ppm +Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +(C) Copyright 2014 Pierrick Hascoet, Abilis Systems +Copyright (C) 2015-2019 Socionext Inc. +Copyright (C) 2007-2010 coresystems GmbH +Copyright (C) 2011 The Chromium Authors +Copyright (C) 2008 Altera Corporation. +Copyright (C) 2009 BuS Elektronik GmbH & Co. KG +(c) 2007 Nobuhiro Iwamatsu +(C) 2009 Ben Warren , biggerbadderben@gmail.com +(C) 2003 Wolfgang Denk, wd@denx.de +Copyright (C) 1999 Ben Williamson +Copyright (C) 1997 Sten Wang +(C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. +Copyright (C) 2008 Dave S.r.l. +Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. +Copyright (C) Archway Digital Solutions. +Copyright (C) Linux Networx. +Copyright (C) 2007-2008 Avionic Design Development GmbH +Copyright (C) 2008-2009 Avionic Design GmbH +(C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd +(C) Copyright 2008,2009 Eric Jarrige +(C) Copyright 2008 Armadeus Systems nc +(C) Copyright 2007 Pengutronix, Sascha Hauer +(C) Copyright 2007 Pengutronix, Juergen Beisert +(C) Copyright 2008 Armadeus Systems, nc +(C) Copyright 2008 Eric Jarrige +(C) Copyright Motorola, Inc., 2000 +(C) Copyright 2007 Freescale Semiconductor, Inc. +Copyright 2009-2010, 2013 Freescale Semiconductor, Inc. +(C) Copyright 2010 Andes Technology +Copyright (C) 2018, IBM Corporation. +(C) Copyright 2013 Faraday Technology +(C) Copyright 2015 Sjoerd Simons +Copyright (c) 2011 Roberto Cerati +Copyright (c) 2009 Micrel Inc. +(c) 2011 Bticino s.p.a, Roberto Cerati +Copyright (C) 2001 Standard Microsystems Corporation (SMSC) +Copyright (C) 1996 by Erik Stahlman (ES) +Copyright (C) 2002 rabeeh@galileo.co.il +Copyright (C) 2014-2015 Stefan Roese +Copyright (C) 2012 Marvell +Copyright (C) 2014 Marvell +Copyright (C) 2016-2017 Stefan Roese +Copyright (C) 2001 Entity Cyber, Inc. +copyright 1999-2001 by Donald Becker. +Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +copyright 1999-2002 by Donald Becker. +(C) Copyright 2002 Wolfgang Grandegger, wg@denx.de. +Copyright 2015 Microchip Inc. +Copyright (C) 2015-2017 Renesas Electronics Corporation +Copyright (c) 2018 National Instruments +Copyright (c) 2018 Joe Hershberger +Copyright (C) 2008, 2011 Renesas Solutions Corp. +Copyright (c) 2008, 2011, 2014 2014 Nobuhiro Iwamatsu +Copyright (c) 2007 Carlos Munoz +Copyright (C) 2008 - 2012 Renesas Solutions Corp. +Copyright (c) 2008 - 2012 Nobuhiro Iwamatsu +Copyright (C) 2001 Standard Microsystems Corporation (SMSC) +Copyright (C) 1996 by Erik Stahlman (ES) +Copyright 2016-2018 Socionext inc. +(C) Copyright 2012, Stefan Roese +Copyright 2004-2011, 2013 Freescale Semiconductor, Inc. +Copyright 2007, 2010 Freescale Semiconductor, Inc. +Copyright (C) 2011 PetaLogix +Copyright (C) 2010 Xilinx, Inc. All rights reserved. +(C) Copyright 2007-2009 Michal Simek +(C) Copyright 2003 Xilinx Inc. +(C) Copyright 2011 Michal Simek +(C) Copyright 2011 Xilinx +Copyright (C) 1996, 99 Ralf Baechle +Copyright (C) 1990, 1999 by Silicon Graphics, Inc. +Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle +Copyright (C) 1999 by Silicon Graphics, Inc. +Copyright (C) 2001 MIPS Technologies, Inc. +Copyright (C) 2002 Maciej W. Rozycki +Copyright (c) 1994 - 1997, 1999, 2000 Ralf Baechle (ralf@gnu.org) +Copyright (c) 2000 Silicon Graphics, Inc. +Copyright (C) 1996, 99, 2003 by Ralf Baechle +Copyright (C) 1994, 1995, 1996 by Ralf Baechle +(C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle +(C) Copyright 1999 Silicon Graphics, Inc. +Copyright (C) 2004 Maciej W. Rozycki +Copyright (C) 1994, 1995 Waldorf GmbH +Copyright (C) 1994 - 2000, 06 Ralf Baechle +Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. +Copyright (c) 1998 Harald Koerfgen +Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle +Copyright (C) 2000 Silicon Graphics, Inc. +Copyright (C) 2000, 07 MIPS Technologies, Inc. +Copyright (C) 2003, 2004 Maciej W. Rozycki +Copyright (C) 1994 - 2002 by Ralf Baechle +Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. +Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle +Copyright (C) 1994 Waldorf GMBH +Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Ralf Baechle +Copyright (C) 1996 Paul M. Antoine +Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle +Copyright (C) 1997, 1999, 2001, 06 by Ralf Baechle +Copyright (C) 1995, 1999 by Ralf Baechle +Copyright (C) 1995, 1999 Silicon Graphics +Copyright (C) 1985 MIPS Computer Systems, Inc. +Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle +Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. +Copyright (C) 2011 Wind River Systems, +written by Ralf Baechle +Copyright (C) 1996, 1999, 2001 Ralf Baechle +Copyright (c) 1994, 95, 96, 97, 98, 2000, 01 Ralf Baechle +Copyright (c) 2000 by Silicon Graphics, Inc. +Copyright (c) 2001 MIPS Technologies, Inc. +Copyright (C) 1994 - 1999 by Ralf Baechle +Copyright (C) 1996 by Paul M. Antoine +Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle +Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) +Copyright (C) 2017 Allied Telesis Labs +Copyright (C) 2010 Eric C. Cooper +Copyright 2008, 2010 Freescale Semiconductor, Inc. +Copyright 2008-2010 Freescale Semiconductor, Inc. +Copyright (C) 2015-2019 Variscite Ltd. +Copyright (C) 2019 Parthiban Nallathambi +Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. +(C) Copyright 2014 Albert ARIBAUD +Copyright (c) 2014, NVIDIA Corporation. +Copyright (c) 2011-2013, NVIDIA Corporation. +Copyright (C) 2005, 2007 Olivier Gay +Copyright (c) 2016-2018 Toradex, Inc. +Copyright (c) 2012-2016 Toradex, Inc. +Copyright (c) 2016-2019, Toradex, Inc. +(C) Copyright 2014 - 2019 Xilinx, Inc. +Copyright 2013-2019 Arcturus Networks Inc. +Copyright 2013-2015 Arcturus Networks, Inc. +original copyright follows: +Copyright 2013-2015 Arcturus Networks, Inc +Copyright 2013-2019 Arcturus Networks, Inc. +Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (c) 2017-2018 Vasily Khoruzhick +(C) Copyright 2018 Xilinx, Inc. (Michal Simek) +(C) Copyright 2017 Linaro +Copyright (C) 2003 Manuel Novoa III +Copyright (C) 2013, Compulab Ltd - http://compulab.co.il/ +Copyright (C) 2017 Google, Inc. +Copyright (C) 2017 Logic PD, Inc. +Copyright (c) 2016, NVIDIA CORPORATION +Copyright (C) 2012 Nobuhiro Iwamatsu +Copyright (C) 2010 Renesas Solutions Corp. +Copyright (C) 2010 NISHIMOTO Hiroki +(C) Copyright 2013-2016, NVIDIA CORPORATION. +Copyright (C) 2013 Simon Guinot +(C) Copyright Siemens AG +Copyright (C) 2009 Freescale Semiconductor, Inc. +Copyright 2009-2010 Freescale Semiconductor. +Copyright (C) 2014, 2015 O.S. Systems Software LTDA. +Copyright (C) 2014 Kynetics LLC. +Copyright (C) 2014 Revolution Robotics, Inc. +(C) Copyright 2004 DENX Software Engineering, Wolfgang Denk, wd@denx.de +Copyright (C) 2015 Regents of the University of California +Copyright (C) 2013 Regents of the University of California +Copyright (C) 2017 SiFive +Copyright (c) 2018 Western Digital Corporation or its affiliates. +Copyright (c) 2017 Microsemi Corporation. +Copyright (C) 2017 Rick Chen (rick@andestech.com) +Copyright (c) 2017 Padmarao Begari +(C) Copyright 2018 Alexander Graf +Copyright (C) 2018 Rosy Song +Copyright © 2005 Samsung Electronics +Copyright © 2000-2005 +Copyright © 2000-2010 David Woodhouse et al. +Copyright © 2002 Robert Kaiser +Copyright © 1999 Machine Vision Holdings, Inc. +Copyright © 2002-2003 Greg Ungerer +Copyright © 2002-2003 SnapGear Inc +Copyright © 2000 Red Hat UK Limited +Copyright 2017 - Free Electrons +Copyright (C) 2000-2010 Steven J. Hill +Copyright (c) 2006 Thomas Gleixner +(C) Copyright 2013 Andreas Bießmann +(C) 2000 Nicolas Pitre +Copyright (C) 2017 Stefan Roese +Copyright (C) 2017 Marvell +Copyright (C) 2013 Lemonage Software GmbH +Copyright (C) 2013, Lemonage Software GmbH +Bloat-o-meter code used here Copyright 2004 Matt Mackall +Copyright (c) 2011-2019, Ulf Magnusson +Copyright (C) 2018 Allied Telesis Labs +Copyright (C) ARM Ltd 2015 +(C) Copyright 2010 Andreas Bießmann +Copyright (C) 2018 Microchip Technology, Inc. +Copyright (C) 2014 Atmel Corporation +Copyright (C) 2013 Stefan Roese +Copyright (C) 2018 Simone CIANNI +Copyright (C) 2018 Raffaele RECALCATI +Copyright (C) 2017 Hannes Schmelzer +Copyright (C) 2017 Hannes Schmelzer +Copyright (c) 2013 Corscience GmbH & Co.KG +Copyright (C) 2010-2017 CS Systemes d'Information +Copyright (C) 2017 Marek Behun +Copyright (C) 2016 Tomas Hlavacek +Copyright (C) 2017 Marek Vasut +Copyright (c) 2017 Tuomas Tynkkynen +Copyright 2016-2019 NXP Semiconductors +(C) 2001-2006 Red Hat, Inc. +Copyright 2007,2009-2010 Freescale Semiconductor, Inc. +Copyright 2004, 2007, 2009-2011 Freescale Semiconductor, Inc. +Copyright 2008, 2011 Freescale Semiconductor, Inc. +Copyright 2010-2011, 2013 Freescale Semiconductor, Inc. +Copyright (C) 2019 Stefan Roese +Copyright (C) 2016 Mario Six +(C) Copyright 2019 Linaro +IT6251 code based on code Copyright (C) 2014 Sean Cross +Copyright (C) 2016 David Lechner +Copyright (C) 2016-2017 +Copyright (C) 2019 Microchip Technology Inc. +(C) Copyright 2015 Inter Act B.V. +(c) Copyright 2017 Opal Kelly Inc. +Copyright 2015 3ADEV +Copyright (C) 2013 Renesas Solutions Corp. +Copyright (C) 2015 Renesas Electronics Europe GmbH +(C) Copyright 2013 SAMSUNG Electronics +Copyright (C) 2013 Suriyan Ramasami +Copyright (C) 2013 Seco USA Inc +(C) Copyright 2013 Siemens AG +(C) Copyright 2002,2003, Motorola Inc. +(C) Copyright 2012-2013 Henrik Nordstrom +(C) Copyright 2013 Luke Kenneth Casson Leighton +Copyright (c) 2010 Texas Instruments, Inc. +Copyright (C) 2013, 2014 Markus Niebel +Copyright (C) 2013, 2014 TQ Systems (ported SabreSD to TQMa6x) +Copyright (C) 2014 - 2015 Markus Niebel +Copyright (C) 2013, 2014 TQ Systems +Copyright 2010 Extreme Engineering Solutions, Inc. +(C) Copyright 2012 Michal Simek +(C) Copyright 2013 - 2018 Xilinx, Inc. +of logo, copyright and system information on the LCD +Copyright (C) 2006-2011 Freescale Semiconductor, Inc. +Copyright (C) 2006-2010 Freescale Semiconductor, Inc. +Copyright (C) 2005,2010-2011 Freescale Semiconductor, Inc. +Copyright (C) 2005, 2011 Freescale Semiconductor, Inc. +Copyright 2006,2009-2010 Freescale Semiconductor, Inc. +Copyright 2004,2009-2011 Freescale Semiconductor, Inc. +(C) Copyright 2004, 2007 Freescale Semiconductor. (MPC86xx Port) +Copyright (C) 2006 David Gibson, IBM Corporation. +Copyright 2012 Kim Phillips, Freescale Semiconductor. +Copyright (C) 2014 David Gibson +Copyright (C) 2018 embedded brains GmbH +Copyright (C) 2012 David Gibson, IBM Corporation. +Copyright (C) 2016 Free Electrons +Copyright (C) 2016 NextThing Co. +Copyright (C) 2009, DENX Software Engineering +Copyright (C) 2009 Ilya Yanok, +Emcraft Systems +Copyright (C) 2007 Pengutronix, +Sascha Hauer +Copyright (C) 2009 by Lothar Wassmann +Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH +Copyright 2004-2009 Freescale Semiconductor, Inc. +Copyright (C) 2010, STMicroelectronics - All Rights Reserved +Copyright (C) 2009, STMicroelectronics - All Rights Reserved +Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved. +Copyright (C) 1999 Russell King. +Copyright (C) 1996-1999 Russell King. +Copyright (C) 1996-1999 Russell King +Copyright 2011, 2013 Freescale Semiconductor, Inc. +Copyright 2017 Bernecker & Rainer Industrieelektronik GmbH +Copyright (C) 2016 BayLibre, SAS. All rights reserved. +(C) 2012 NetModule AG, David Andrey, added KSZ9031 +(C) Copyright 2017 Adaptrum, Inc. +(C) Copyright 2009 Industrie Dial Face S.p.A. +Copyright (c) 2016 Microsemi Corporation +Copyright 2010-2011, 2015 Freescale Semiconductor, Inc. +Copyright 2016 Karsten Merker +Copyright (c) 2006 Herbert Valerio Riedel +Copyright 2010-2014 Freescale Semiconductor, Inc. +Copyright (C) 2007-2009 Industrie Dial Face S.p.A. +(C) Copyright 2016 - 2018 Xilinx, Inc. +(C) Copyright 2015, Siemens AG +Copyright (C) 2005-2011 Canonical Ltd +(C) Copyright 2005-2009 Freescale Semiconductor, Inc. +(C) Copyright 2004-2009 Freescale Semiconductor, Inc. +(C) Copyright 2004-2010 Freescale Semiconductor, Inc. +Copyright (C) 2018 Xilinx, Inc. (Michal Simek) +(C) Copyright 2017 Rob Clark +Copyright (c) 2017 Leif Lindholm +Copyright (c) 2016-2018 Alexander Graf et al. +Copyright (C) 2008 Arthur Shipkowski (art@videon-central.com) +Copyright (c) 2009 Freescale Semiconductor, Inc. +Copyright (C) 2007,2008 Oracle. All rights reserved. +Copyright (C) 2010 coresystems GmbH +Copyright 2002 Andy Grover +Copyright(c) 2009 Intel Corporation. All rights reserved. +Copyright (c) 2015 Gooogle, Inc +2012 secunet Security Networks AG +Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. +Copyright 2012 Linaro Ltd. +Copyright 2017-2019 NXP. +(C) Copyright 2017 Vasily Khoruzhick +Copyright (C) 1999 Linus Torvalds +Copyright (C) 2000-2002 Transmeta Corporation +Copyright (C) 2003 Kai-Uwe Bloem,Auerswald GmbH & Co KG, +Copyright (C) 2018 Masahiro Yamada +Copyright (C) 2016 Rockchip Electronic Co.,Ltd +Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH +Copyright (C) 2017 Theobroma Systems Design und Consulting GmH +(C) Copyright 2016 Toradex +Copyright 2008 Maxime Bizon +Copyright 2013 Florian Fainelli +Copyright (C) 2018 Martin Blumenstingl +Copyright (C) 2017 John Crispin +Copyright (c) 2015 - 2019 MediaTek Inc. +Copyright (C) 2010 Samsung Electrnoics +Copyright (c) 2012 Samsung Electronics. +Copyright (c) 2010 Samsung Electronics. +(C) Copyright 2005, Psyent Corporation +(C) Copyright 2010, Thomas Chou +Copyright (C) 2016 Timesys Corporation +Copyright (C) 2016 Advantech Corporation +Copyright (C) 2018 sjoerd Simons +Copyright (C) 2015 Toby Churchill Ltd - http://www.toby-churchill.com/ +Copyright (C) 2011 Mistral Solutions pvt Ltd +Copyright (c) 2017 Toradex, Inc. +Copyright 2013-2019 Toradex, Inc. +Copyright (c) 2014-2016 Marcel Ziswiler +Copyright 2016 IBM Corporation +Copyright (C) 2010 Andreas Bießmann +(C) Copyright 2013 Atmel Corporation. +Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved. +(C) Copyright 2018 Michal Simek +Copyright 2016 3ADEV +Copyright (C) 2013 Hannes Schmelzer - +Copyright (C) 2017 Hannes Schmelzer - +Copyright (C) 2016 Hannes Schmelzer - +Copyright (c) 2008, 2009 esd gmbh Hannover Germany +(c) Copyright 2016, Data61 +Copyright (C) 2017 Grinn - http://grinn-global.com/ +Copyright (C) 2015 CompuLab, Ltd. +(C) Copyright 2011 CompuLab, Ltd. +Copyright 2018-2019 Toradex AG +Copyright 2016-2018 Toradex AG +Copyright (C) 2015-2016 Marcel Ziswiler +Copyright (c) 2013-2016 Stefan Agner +Copyright (C) 2019 Renesas Electronics Corporation +Copyright (C) 2018 Renesas Electronics Corporation +(C) Copyright 2005-2009 BuS Elektronik GmbH & Co.KG +Copyright (c) 2017 Intel Corp. +Copyright 2016 Google Inc +(C) Copyright 2011, Stefano Babic +Copyright (C) 2015 Timesys Corporation +Copyright (C) 2015 General Electric Company +Copyright (C) 2014 Advantech +Copyright (C) 2017-2019 Renesas Electronics +Copyright (C) 2017 Synopsys, Inc. All rights reserved. +Copyright (C) 2010 Heiko Schocher +Copyright (C) 2012 Nobuhiro Iwamatsu +Copyright (C) 2017 Baylibre, SAS +Copyright 2016-2018 NXP Semiconductors +Copyright 2019 Vladimir Oltean +Copyright 2017, 2019 NXP +Copyright (C) 2005 Videon Central, Inc. +Copyright (C) 2019 Baylibre, SAS +(C) Copyright 2007-2010 Michal Simek +Copyright (C) 2007 Nobuhiro Iwamatsu +Copyright (C) 2009-2010 Freescale Semiconductor, Inc. +Copyright (C) Freescale Semiconductor, Inc. 2006, 2010. +Copyright (C) 2007-2010 Freescale Semiconductor, Inc. +Copyright 2007-2009,2010-2012 Freescale Semiconductor, Inc. +(C) Copyright 2002,2003 Motorola,Inc. +Copyright 2007, 2010-2011 Freescale Semiconductor, Inc. +Copyright 2004, 2007, 2010-2011 Freescale Semiconductor. +Copyright 2004-2007, 2010-2011 Freescale Semiconductor. +Copyright 2007-2008,2010-2011 Freescale Semiconductor, Inc. +Copyright 2006, 2010-2011 Freescale Semiconductor. +Copyright (C) 2013 Otavio Salvador +(C) Copyright 2008 Magnus Lilja +(C) Copyright 2010, Stefano Babic +Copyright (C) 2010-2011 Freescale Semiconductor. +Copyright (C) 2010-2018 Freescale Semiconductor, Inc. +Copyright (C) 2014 Evgeni Dobrev +Copyright (C) DENX GmbH +Copyright (C) 2006-2011 Texas Instruments Incorporated - http://www.ti.com/ +(C) Copyright 2011 Logic Product Development +Copyright (C) 2014 Bachmann electronic GmbH +Copyright (c) 2013-2016, NVIDIA CORPORATION. +Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2011 Texas Instruments Inc. +Copyright (C) 2013 Gumstix, Inc. - http://www.gumstix.com/ +Copyright 2011-2014 Freescale Semiconductor, Inc. +(C) Copyright 2015-2016 Freescale Semiconductor, Inc. +Copyright (C) 2018 Microchip Corporation +Copyright (C) 2017 Microchip Technology Inc. +Copyright (C) 2012 - 2013 Atmel +Copyright (c) 2006, 2007 Wind River Systems, Inc. +Copyright 2007,2009 Wind River Systems +Copyright 2007 Wind River Systems +(C) Copyright 2016 Allied Telesis +Copyright (C) 2013 Seco S.r.l +Copyright (C) 2015-2019 Altera Corporation +Copyright (C) 2016 Pavel Machek +Copyright (C) 2015-2019 Marek Vasut +(C) Copyright 2017 Angelo Dureghello +(C) Copyright 2013 Maxime Ripard +(C) Copyright 2014 Chen-Yu Tsai +(C) Copyright 2012-2012 Henrik Nordstrom +(C) Copyright 2012 Xilinx +(C) Copyright 2017 Opal Kelly Inc. +Copyright (C) 2009 TechNexion Ltd. +Copyright (C) 2011-2014 Pierrick Hascoet, Abilis Systems +Copyright 2013-2016, NVIDIA CORPORATION. +Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +(C) Copyright 2014 Topic Embedded Products +Copyright (C) 2013, 2014, 2017 Markus Niebel +Copyright (C) 2013 - 2017 Markus Niebel +Copyright (C) 2015, Savoir-faire Linux Inc. +Copyright Jasbir Matharu +Copyright 2015 UDOO Team +(C) Copyright 2013 Linaro +(C) Copyright 2011 Linaro +(C) Copyright 2011 ARM Limited +Copyright (C) 2012, 2015 Stefan Roese +(C) Copyright 2018-2019 Xilinx, Inc. +Copyright 2004-2008 Freescale Semiconductor, Inc. +Copyright (C) 2007-2013 Tensilica, Inc. +(C) Copyright 2013 - 2017 Xilinx. +(C) Copyright 2015 Hans de Goede +Copyright (C) 2016 Siarhei Siamashka +(C) Copyright 2009 Wolfgang Denk +(C) Copyright 2004 Texas Insturments +Copyright 2014 Broadcom Corporation +Copyright (C) 2017-2018 Cadence Design Systems, Inc. +Copyright (C) 2012-2018 Cadence Design Systems, Inc. +Copyright (C) 2012-2019 Cadence Design Systems, Inc. +Copyright (c) 2015-2018, Linaro Limited +Copyright (c) 2016-2018, Linaro Limited +(C) Copyright 2017, Xilinx Inc. +Copyright (C) 2018-2019 Cadence. +Copyright (C) 2017-2018 NXP +Copyright (C) 2019 Texas Instruments +Copyright (C) 2018 Cadence Design Systems. +Copyright (C) 2018-2019 Cadence Design Systems. +Copyright (C) 2017 Rockchip Electronics Co., Ltd +Copyright 2019 +Copyright 2011 Comelit Group SpA +Copyright (C) 1999,2000,2001,2002,2003,2004 +Copyright 2004 Sun Microsystems, Inc. +Copyright (C) 1996-2010 Julian Seward +Copyright 2017 Google, Inc. +(C) Copyright 2016 Songjun Wu +(C) Copyright 2007 Sergey Kubushyn +Copyright (c) 2016, Google Inc +Copyright 2006,2009 Freescale Semiconductor, Inc. +2012, Heiko Schocher, DENX Software Engineering, hs@denx.de. +Copyright (C) 2015 Moritz Fischer +(C) Copyright 2015, Samsung Electronics +Copyright (c) 2018 Arm Ltd. +(C) Copyright 2014-2015 DENX Software Engineering GmbH +Copyright (c) 2010 Albert Aribaud. +(C) Copyright 2003 Pengutronix e.K. +(C) Copyright 2011 Marvell Inc. +(c) 2011 Marek Vasut +Copyright (C) 2005 Torsten Koschorrek +Copyright (C) 2005 Matthias Blaschke +Copyright (C) 2007 RightHand Technologies, Inc. +Copyright (C) 2008 Darius Augulis +Copyright (c) 2004 Texas Instruments +Copyright (c) 2003 Wolfgang Denk, wd@denx.de +Copyright (c) 2013 Lubomir Popov , MM Solutions +Copyright (c) 2014 Hannes Schmelzer , B&R +Copyright (C) 2014-15 Wolfram Sang +Copyright (C) 2011-2015 Renesas Electronics Corporation +Copyright (C) 2012-14 Renesas Solutions Corp. +Copyright (C) 2011, 2013 Renesas Solutions Corp. +Copyright (C) 2011, 2013 Nobuhiro Iwamatsu +(C) Copyright 2017 STMicroelectronics +Copyright (c) 2010-2011 NVIDIA Corporation +Copyright (c) 2002-2007 Xilinx Inc. +Copyright (c) 2009-2010 Intel Corporation +Copyright (C) 1995-2004 Mark Adler +Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler +Copyright (C) 1995-2010 Jean-loup Gailly +Copyright (C) 1995-2003 Mark Adler +Copyright (C) 1995-2005 Mark Adler +Copyright (C) 1995-2005 Jean-loup Gailly. +Copyright (C) 2016 Synopsys, Inc. All rights reserved. +Copyright (C) 2015, Texas Instruments, Incorporated +Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2016-2018, NVIDIA CORPORATION. +Copyright (c) 2010-2019, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. +Copyright (C) 2011 Google, Inc. +Copyright (C) 2009 Daniel Mack +Copyright (c) 2017 Cadence +Copyright (c) 2019 Ramon Fried +Copyright (C) 1999-2005 Igor Pavlov +Copyright (C) 2007-2008 Industrie Dial Face S.p.A. +Copyright (C) 2007-2011 Freescale Semiconductor, Inc. +Copyright 2007 Freescale Semiconductor, Inc. +Copyright (C) Freescale Semiconductor, Inc. 2007 +Copyright (C) 2007-2009 Freescale Semiconductor, Inc. +Copyright (C) 2008-2009 MontaVista Software, Inc. +(C) Copyright 2006-2007 Freescale Semiconductor, Inc. +Copyright (C) 2004-2006 Freescale Semiconductor, Inc. +Copyright (C) 2013, Masahiro Yamada +Copyright (C) 2016, Lukasz Majewski +Copyright (C) 2013-2018 Hannes Schmelzer +Copyright (C) 2013-2018 Hannes Schmelzer - +(C) 2015 Hans de Goede +Copyright (C) 2008-2009 MontaVista Software Inc. +Copyright (C) 2008-2009 Texas Instruments Inc +Copyright 2017 Jernej Skrabec +Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd +Copyright 2019 Toradex AG +Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. +(C) Copyright 2016-2018 ARM Ltd. +Copyright (C) 2011-2013 Marek Vasut +Copyright (c) 2013 Adapted from Linux driver: +Copyright (c) 2012 Anders Electronics plc. All Rights Reserved. +Copyright (c) 2012 CompuLab, Ltd +(C) 2015 Siarhei Siamashka +(C) Copyright 2018 Liviu Dudau +(C) 2012 Texas Instruments +Copyright (C) 2012 Andes Technology Corporation +Copyright (C) 2015 Linaro. +Copyright (C) 2016 Microchip +(C) Copyright 2019 NXP, Inc. +Copyright (C) 2008,2010 Freescale Semiconductor, Inc. +Copyright (C) 2007-2008 Freescale Semiconductor, Inc. +(C) Copyright 2015 - 2016 Xilinx, Inc. +Copyright (C) Excito Elektronik i Skåne AB, 2010. +Copyright (C) 2015, 2019 Stefan Roese +Copyright (C) Excito Elektronik i Skåne AB, All rights reserved. + +License: +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +Preamble +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Programs +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the program's name and an idea of what it does. +Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details +type `show w'. This is free software, and you are welcome +to redistribute it under certain conditions; type `show c' +for details. +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright +interest in the program `Gnomovision' +(which makes passes at compilers) written +by James Hacker. + +signature of Ty Coon, 1 April 1989 +Ty Coon, President of Vice +This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + +Software: mbed TLS 2.16.6 + +Copyright notice: +Copyright (C) 2006-2015, ARM Limited, All Rights Reserved +Copyright (C) 2016, ARM Limited, All Rights Reserved +Copyright (C) 2006-2016, ARM Limited, All Rights Reserved +Copyright (c) 2014-2017, ARM Limited, All Rights Reserved +Copyright (c) 2016, ARM Limited, All Rights Reserved +Copyright (c) 2018, Arm Limited, All Rights Reserved +Copyright (c) 2018, ARM Limited, All Rights Reserved +Copyright (c) 2015-2019, ARM Limited, All Rights Reserved +Copyright (C) 2018, Arm Limited, All Rights Reserved +Copyright (C) 2018, ARM Limited, All Rights Reserved +Copyright (c) 2017, ARM Limited, All Rights Reserved +Copyright (C) 2006-2017, ARM Limited, All Rights Reserved +Copyright (C) 2016-2018, ARM Limited, All Rights Reserved +Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved +Copyright (C) 2019, ARM Limited, All Rights Reserved +Copyright (c) 2012-2016, ARM Limited, All Rights Reserved +Copyright (c) 2015-2016, ARM Limited, All Rights Reserved +Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. +Copyright (C) 2006-2018, ARM Limited, All Rights Reserved +Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved +Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved +Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved +Copyright (C) 2016-2019, ARM Limited, All Rights Reserved +Copyright (C) 2006-2019, ARM Limited, All Rights Reserved + +License: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +Software: fdk-aac v2.0.1 + +Copyright notice: +Copyright (C) 2011 Martin Storsjo +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Copyright (C) 2009 Martin Storsjo +Copyright (C) 2008, 2009, 2011, 2012, MinGW.org Project. + +License: +Software License for The Fraunhofer FDK AAC Codec Library for Android +© Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1.INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") issoftware that implements the MPEG Advanced Audio Coding ("AAC") encoding anddecoding scheme for digital audio. This FDK AAC Codec software is intended tobe used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficientgeneral perceptual audio codecs. AAC-ELD is considered the best-performingfull-bandwidth communications codec by independent studies and is widelydeployed. AAC has been standardized by ISO and IEC as part of the MPEGspecifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec(including those of Fraunhofer) may be obtained through Via Licensing(www.vialicensing.com) or through the respective patent owners individuallyfor the purpose of encoding or decoding bit streams in products that arecompliant with the ISO/IEC MPEG audio standards. Please note that mostmanufacturers of Android devices already license these patent claims throughVia Licensing or directly from the patent owners, and therefore FDK AAC Codecsoftware may already be covered under those patent licenses when it is usedfor those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-pointversions with enhanced sound quality, are also available from Fraunhofer.Users are encouraged to check the Fraunhofer website for additionalapplications information and documentation. + + +2.COPYRIGHT LICENSE +Redistribution and use in source andbinary forms, with or without modification, are permitted without paymentof copyright license fees provided that you satisfy the following conditions: + +You must retain the complete textof this software license in redistributions of the FDK AAC Codec or yourmodifications thereto in source code form. + +You must retain the complete text of this software license in thedocumentation and/or other materials provided with redistributions of the FDKAAC Codec or your modifications thereto in binary form. You must make available free ofcharge copies of the complete source code of the FDK AAC Codec and yourmodifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be usedto endorse or promote products derived from this library without prior writtenpermission. + +You may not charge copyright license fees for anyone to use, copy ordistribute the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDKAAC Codec must carry prominent notices stating that you changed the softwareand the date of any change. For modified versions of the FDK AAC Codec,the term "Fraunhofer FDK AAC Codec Library for Android" must be replaced bythe term "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Libraryfor Android." + + + + +3.NO PATENT LICENSE +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including withoutlimitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.Fraunhofer provides no warranty of patent non-infringement with respect tothis software. + +You may use this FDK AAC Codec software or modifications thereto only forpurposes that are authorized by appropriate patent licenses. + + +4.DISCLAIMER +This FDK AAC Codec software is provided by Fraunhofer on behalf of thecopyright holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIEDWARRANTIES, including but not limited to the implied warranties ofmerchantability and fitness for a particular purpose. IN NO EVENT SHALL THECOPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE for any direct, indirect,incidental, special, exemplary, or consequential damages, including but notlimited to procurement of substitute goods or services; loss of use, data, orprofits, or business interruption, however caused and on any theory ofliability, whether in contract, strict liability, or tort (includingnegligence), arising in any way out of the use of this software, even ifadvised of the possibility of such damage. + + +5.CONTACT INFORMATION +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio andMultimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen,Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de + + \ No newline at end of file diff --git a/hispark_aries/OAT.xml b/hispark_aries/OAT.xml new file mode 100755 index 00000000..cab70c52 --- /dev/null +++ b/hispark_aries/OAT.xml @@ -0,0 +1,101 @@ + + + + + + NOTICE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hispark_aries/README.md b/hispark_aries/README.md new file mode 100755 index 00000000..b04087d0 --- /dev/null +++ b/hispark_aries/README.md @@ -0,0 +1,109 @@ +# hispark\_aries + +- [Introduction](#section11660541593) +- [Directory Structure](#section161941989596) +- [Constraints](#section119744591305) +- [Compilation and Building](#section137768191623) +- [hispark\_aries License Agreement](#section1312121216216) + - [third\_party License Notice](#section129654513264) + +- [Repositories Involved](#section1371113476307) + +## Introduction + +The media software development kit from HiSilicon \(Shanghai\) can adapt to complex underlying layers of different chips. It also provides basic multimedia processing functions for the multimedia subsystem, including audio/video collection, audio/video encoding and decoding, audio/video output, video pre-processing, encapsulation, decapsulation, file management, storage management, and log system. The multimedia subsystem architecture is shown as [Figure 1](#fig4460722185514) + +**Figure 1** Multimedia subsystem architecture + + +![](figures/en-us_image_0000001133374179.png) + +## Directory Structure + +``` +/device/hisilicon/hispark_aries/sdk_liteos +├── config # Hi3518E V300 device configuration information +├── mpp +│ ├── lib # Media library files and license files of Hi3518E V300 +│ └── module_init # Libraries and license files of corresponding media module drivers of Hi3518E V300 +└── uboot + ├── out # U-Boot compiled using third_party\uboot\u-boot-2020.01 + ├── reg # U-Boot configuration files and license files + ├── secureboot_ohos # Compilation scripts for secure booting + └── secureboot_release # Source code and license files for generating the secure U-Boot +``` + +## Constraints + +Currently, the Hi3518E V300 chip is supported. + +## Compilation and Building + +- Compiling the U-Boot + +1. Download the GCC toolchain from [https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Currently, the toolchain version for compiling U-Boot is **gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2**. You can also select other GCC versions. +2. Copy the GCC toolchain to the **prebuilts** directory and decompress it. +3. Go to the **hispark\_aries\\sdk\_liteos\\uboot\\out\\boot** directory and modify the path of the toolchain defined by **OSDRV\_CROSS** in the **makefile** of the directory. +4. Run the **make clean;make all;** command to compile the U-Boot. + +The generated U-Boot is stored in the **hispark\_aries\\sdk\_liteos\\uboot\\out\\boot** directory. + +## hispark\_aries License Agreement + +- The **hispark\_aries\\sdk\_liteos\\mpp\\module\_init\\lib** and **hispark\_aries\\sdk\_liteos\\mpp\\lib** directories store the HiSilicon-developed libraries, which comply with the license of HiSilicon \(Shanghai\). You can see the following license and copyright information at the end of license files that are stored in the two directories: + + ``` + Copyright (C) 2020 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + ``` + +- The **hispark\_aries\\sdk\_liteos\\mpp\\module\_init\\src** directory stores the HiSilicon-developed code, which complies with the HiSilicon \(Shanghai\) copyright statement based on the Apache License Version 2.0. You can see the following license and copyright information at the beginning of a license file that is stored in this directory: + + ``` + / *Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. Licensed under the Apache License,* ... * / + ``` + +- The **hispark\_aries\\sdk\_liteos\\uboot\\reg** directory stores a binary file, which complies with the license of HiSilicon \(Shanghai\). You can see the following copyright information at the end of a license file that is stored in this directory: + + ``` + Copyright (C) 2020 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + ``` + +- The **hispark\_aries\\sdk\_liteos\\uboot\\out\\boot** directory stores a binary U-Boot file compiled using **u-boot-2020.01** and **reg\_info\_hi3518ev300.bin** and following the **u-boot-2020.01** protocol. For details, see the readme files in the **third\_party\\uboot\\u-boot-2020.01\\Licenses** directory. +- The **hispark\_aries\\sdk\_liteos\\uboot\\secureboot\_release** directory stores the open-source code of the secure U-Boot, in which the HiSilicon-developed code complies with the HiSilicon \(Shanghai\) copyright statement based on the GPL license. You can see the following license and copyright information at the beginning of a license file that is stored in this directory: + + ``` + / *Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * ... * / + ``` + +- The notice file stored in the **hispark\_aries** directory describes three open-source software, namely **Das U-Boot 2020.01**, **mbed TLS 2.16.6**, and **fdk-aac v2.0.1**. + +### third\_party License Notice + +The **third\_party\\ffmpeg\\ffmpeg-y** directory stores the open-source code of **ffmpeg**, in which the code complies with the open-source license notice of its own software version. For details, see the readme files in the **third\_party\\ffmpeg\\ffmpeg-y** directory. + +The **third\_party\\uboot\\u-boot-2020.01** directory stores the open-source code of U-Boot, which complies with the open-source license notice of its own software version. For details, see the readme files in the **third\_party\\uboot\\u-boot-2020.01\\Licenses** directory. + +## Repositories Involved + +device/hisilicon/build + +device/hisilicon/drivers + +device/hisilicon/hardware + +**device/hisilicon/hispark\_aries** + +device/hisilicon/modules + +device/hisilicon/third\_party/ffmpeg + +device/hisilicon/third\_party/uboot + +vendor/hisilicon + diff --git a/hispark_aries/README_zh.md b/hispark_aries/README_zh.md new file mode 100755 index 00000000..04876def --- /dev/null +++ b/hispark_aries/README_zh.md @@ -0,0 +1,109 @@ +# HiSpark\_aries介绍 + +- [简介](#section11660541593) +- [目录](#section161941989596) +- [约束](#section119744591305) +- [编译构建](#section137768191623) +- [hispark\_aries协议说明](#section1312121216216) + - [third\_party许可说明](#section129654513264) + +- [相关仓](#section1371113476307) + +## 简介 + +上海海思媒体软件开发包用于适配不同芯片复杂的底层处理,为“媒体子系统”提供基础的多媒体处理功能。主要功能有:音视频采集、音视频编解码、音视频输出、视频前处理、封装、解封装、文件管理、存储管理、日志系统等。该软件包功能对应"媒体子系统"框架中红色框标注部分,如图1所示。 + +**图 1** 多媒体子系统架构图 + + +![](figures/zh-cn_image_0000001133374179.png) + +## 目录 + +``` +/device/hisilicon/hispark_aries/sdk_liteos +├── config # Hi3518EV300设备配置信息 +├── mpp +│ ├── lib # Hi3518EV300芯片的媒体库文件、LICENSE文件 +│ └── module_init # Hi3518EV300芯片媒体各模块驱动对应的库、LICENSE文件 +└── uboot + ├── out # 采用third_party\uboot\u-boot-2020.01编译成的uboot + ├── reg # uboot配置文件、LICENSE文件 + ├── secureboot_ohos # 安全启动相关的编译脚本 + └── secureboot_release # 生成安全uboot的源代码、License目录 +``` + +## 约束 + +当前支持Hi3518EV300芯片。 + +## 编译构建 + +- 编译uboot + +1. 从开源社区\(https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads\)下载GCC工具链,当前用于编译uboot的工具链版本为gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2,也可以选择其他的GCC版本。 +2. 将GCC工具链拷贝到prebuilts目录,并解压。 +3. 进入hispark\_aries\\sdk\_liteos\\uboot\\out\\boot目录,修改该目录下的Makefile中的OSDRV\_CROSS所定义的工具链的路径。 +4. 编译uboot,命令:make clean;make all; + +生成的uboot存放在hispark\_aries\\sdk\_liteos\\uboot\\out\\boot目录下。 + +## hispark\_aries协议说明 + +- hispark\_aries\\sdk\_liteos\\mpp\\module\_init\\lib和hispark\_aries\\sdk\_liteos\\mpp\\lib里面为上海海思的自研库,遵循上海海思的LICENSE,这两个目录下均有LICENSE文件,LICENSE文件结尾可以看到版权信息: + + ``` + Copyright (C) 2020 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + ``` + +- hispark\_aries\\sdk\_liteos\\mpp\\module\_init\\src目录下为上海海思自研代码,使用基于Apache License Version 2.0许可的Hisilicon \(Shanghai\) 版权声明,在该目录下有Apache License Version 2.0的LICENSE文件,许可信息和版权信息通常可以在文件开头看到: + + ``` + / *Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. Licensed under the Apache License,* ... * / + ``` + +- hispark\_aries\\sdk\_liteos\\uboot\\reg为上海海思的二进制文件,遵循上海海思的LICENSE,该目录下有LICENSE文件,LICENSE文件结尾可以看到: + + ``` + Copyright (C) 2020 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + ``` + +- hispark\_aries\\sdk\_liteos\\uboot\\out\\boot是由u-boot-2020.01和reg\_info\_hi3518ev300.bin编译成的uboot二进制文件,完全遵从u-boot-2020.01的整体协议,具体请参看third\_party\\uboot\\u-boot-2020.01\\Licenses目录下的README。 +- hispark\_aries\\sdk\_liteos\\uboot\\secureboot\_release为安全uboot的开源代码,其中自研的部分使用基于GPL许可的Hisilicon \(Shanghai\) 版权声明,在该目录下有License目录,许可信息和版权信息通常可以在文件开头看到: + + ``` + / *Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * ... * / + ``` + +- hispark\_aries\\NOTICE文件描述了使用到的三款开源软件:Das U-Boot 2020.01、mbed TLS 2.16.6、fdk-aac v2.0.1。 + +### third\_party许可说明 + +third\_party\\ffmpeg\\ffmpeg-y为ffmpeg开源代码,遵循软件版本自带的开源许可声明,具体请参看third\_party\\ffmpeg\\ffmpeg-y目录下的README。 + +third\_party\\uboot\\u-boot-2020.01为uboot开源代码,遵循软件版本自带的开源许可声明,具体请参看third\_party\\uboot\\u-boot-2020.01\\Licenses目录下的README。 + +## 相关仓 + +device/hisilicon/build + +device/hisilicon/drivers + +device/hisilicon/hardware + +**device/hisilicon/hispark\_aries** + +device/hisilicon/modules + +device/hisilicon/third\_party/ffmpeg + +device/hisilicon/third\_party/uboot + +vendor/hisilicon + diff --git a/hispark_aries/figures/en-us_image_0000001133374179.png b/hispark_aries/figures/en-us_image_0000001133374179.png new file mode 100755 index 0000000000000000000000000000000000000000..f02d124d80cfe532c27d07d3e67b33be58d2f835 GIT binary patch literal 45752 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 oivBqWJbVt-wgyH?W> 2) & 0x7) +/* SDR/DDR clock */ +#define FMC_CLK_24M 0 +#define FMC_CLK_75M 1 +#define FMC_CLK_125M 2 +#define FMC_CLK_150M 3 +#define FMC_CLK_200M 4 +#define FMC_CLK_250M 5 +/* Only DDR clock */ +#define FMC_CLK_300M 6 +#define FMC_CLK_400M 7 +#define FMC_CLK_ENABLE (0x1 << 1) +#define FMC_SOFT_RST_REQ (0x1 << 0) + +/* bit[9]=0: 3-Byte address mode; bit[9]=1: 4-Byte address mode */ +#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 9) & 0x1) + +/****************************************************************************/ +/* REG_SYSSTAT 0: 3 Bytes address boot mode; 1: 4Bytes address boot mode */ +#define REG_SYSSTAT 0x008C +#define GET_FMC_BOOT_MODE ({ \ + unsigned int regval; \ + unsigned int boot_mode = 0; \ + regval = readl(SYS_CTRL_REG_BASE + REG_SYSSTAT); \ + boot_mode = GET_SPI_NOR_ADDR_MODE(regval); \ + boot_mode; }) + + +/* This define just for Padctrl, PHY and DC configuration + * of nand flash */ +#define MISC_CTRL28 0x28 +#define EMMC_PHY_INIT_CTRL IO_DEVICE_ADDR(0x12160004) +#define PHY_INIT_EN 0x1 +#define PHY_ZCAL_EN (0x1 << 3) + +#define EMMC_PHY_IOCTL_RONSEL_1_0 IO_DEVICE_ADDR(0x12160264) +#define RG_EMMC_RONSEL1 0x7ff +#define RG_EMMC_RONSEL0 0x7ff +#define EMMC_PHY_IOCTL_OD_RONSEL_2 IO_DEVICE_ADDR(0x12160268) +#define EMMC_PHY_IOCTL_IOE IO_DEVICE_ADDR(0x1216026c) +#define NAND_IO_EN 0x00ff00ff + +static inline void nand_io_config(void) +{ + /* Padctrl, PHY and DC configuration */ + unsigned int reg_val = 0; + unsigned int timeout = 20; + + /* set pad ctrl reg for nand */ + writel(0x1a3, IO_MUX_REG_BASE + 0x91c); + writel(0x103, IO_MUX_REG_BASE + 0x920); + writel(0x100, IO_MUX_REG_BASE + 0x924); + writel(0x1a3, IO_MUX_REG_BASE + 0x928); + writel(0x100, IO_MUX_REG_BASE + 0x92c); + writel(0x100, IO_MUX_REG_BASE + 0x930); + + /* disable emmc io isolation mode */ + reg_val = readl(MISC_REG_BASE + MISC_CTRL28); + reg_val &= ~0x1; + writel(reg_val, MISC_REG_BASE + MISC_CTRL28); + + /* enable phy init */ + reg_val = readl(EMMC_PHY_INIT_CTRL); + reg_val |= (PHY_INIT_EN | PHY_ZCAL_EN); + writel(reg_val, EMMC_PHY_INIT_CTRL); + + /* wait phy init and zcal done */ + for(; ; ) { + reg_val = readl(EMMC_PHY_INIT_CTRL); + if (!(reg_val & (PHY_INIT_EN | PHY_ZCAL_EN))) + break; + udelay(100); + if (timeout-- == 0) { + dprintf("ERROR: wait mmc phy cal done time out\n"); + return; + } + } + + /* DRV50 */ + writel((RG_EMMC_RONSEL1 << 16) | RG_EMMC_RONSEL0, + EMMC_PHY_IOCTL_RONSEL_1_0); + /* DRV50, OD = 0 */ + writel(0, EMMC_PHY_IOCTL_OD_RONSEL_2); + + writel(NAND_IO_EN, EMMC_PHY_IOCTL_IOE); + + writel(0x2, IO_MUX_REG_BASE + 69 * 4); + writel(0x2, IO_MUX_REG_BASE + 70 * 4); + writel(0x2, IO_MUX_REG_BASE + 71 * 4); + writel(0x2, IO_MUX_REG_BASE + 72 * 4); + writel(0x2, IO_MUX_REG_BASE + 73 * 4); + writel(0x2, IO_MUX_REG_BASE + 74 * 4); + writel(0x2, IO_MUX_REG_BASE + 75 * 4); + writel(0x2, IO_MUX_REG_BASE + 76 * 4); + writel(0x2, IO_MUX_REG_BASE + 79 * 4); + writel(0x2, IO_MUX_REG_BASE + 80 * 4); + writel(0x2, IO_MUX_REG_BASE + 81 * 4); + writel(0x2, IO_MUX_REG_BASE + 82 * 4); + writel(0x2, IO_MUX_REG_BASE + 83 * 4); + writel(0x2, IO_MUX_REG_BASE + 84 * 4); +} + +static inline void spi_io_config(void) +{ + /* set pad ctrl reg for spi */ + writel(0x1C0, IO_MUX_REG_BASE + 0x91c); + writel(0x130, IO_MUX_REG_BASE + 0x920); + writel(0x130, IO_MUX_REG_BASE + 0x924); + writel(0x130, IO_MUX_REG_BASE + 0x928); + writel(0x130, IO_MUX_REG_BASE + 0x92c); + writel(0x103, IO_MUX_REG_BASE + 0x930); + + /* set mux ctrl reg for spi */ + writel(0x1, IO_MUX_REG_BASE + 0x13c); + writel(0x1, IO_MUX_REG_BASE + 0x140); + writel(0x1, IO_MUX_REG_BASE + 0x144); + writel(0x1, IO_MUX_REG_BASE + 0x148); + writel(0x1, IO_MUX_REG_BASE + 0x14c); + writel(0x1, IO_MUX_REG_BASE + 0x150); +} + +/*---------------------------------------------------------------------------*/ +/* hifmc100_set_fmc_system_clock */ +/*---------------------------------------------------------------------------*/ +static inline void hifmc100_set_system_clock(unsigned clock, int clk_en) +{ + unsigned int old_val, regval; + + old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG); + + regval &= ~FMC_CLK_SEL_MASK; + + if (clock) + regval |= clock & FMC_CLK_SEL_MASK; + else { + regval |= FMC_CLK_SEL(FMC_CLK_24M); /* Default Clock */ + spi_io_config(); + } + + if (clk_en) + regval |= FMC_CLK_ENABLE; + else + regval &= ~FMC_CLK_ENABLE; + + if (regval != old_val) + writel(regval, (CRG_REG_BASE + REG_FMC_CRG)); +} + +/*---------------------------------------------------------------------------*/ +/* hifmc100_get_best_clock */ +/*---------------------------------------------------------------------------*/ +static inline void hifmc100_get_best_clock(unsigned int *clock) +{ + int ix; + unsigned int clk_reg, clk_type; + +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sys_2X_clk[] = { + CLK_2X(24), FMC_CLK_SEL(FMC_CLK_24M), + CLK_2X(75), FMC_CLK_SEL(FMC_CLK_75M), + CLK_2X(125), FMC_CLK_SEL(FMC_CLK_125M), + CLK_2X(150), FMC_CLK_SEL(FMC_CLK_150M), + CLK_2X(200), FMC_CLK_SEL(FMC_CLK_200M), + // CLK_2X(250), FMC_CLK_SEL(FMC_CLK_250M), + 0, 0, + }; +#undef CLK_2X + + clk_type = FMC_CLK_24M; + clk_reg = FMC_CLK_SEL(clk_type); + for (ix = 0; sys_2X_clk[ix]; ix += 2) { + if (*clock < sys_2X_clk[ix]) + break; + clk_reg = sys_2X_clk[ix + 1]; + clk_type = GET_CLK_TYPE(clk_reg); + } + + *clock = clk_reg; +} + +static inline void hifmc100_nand_clk_enable(int enable) +{ + unsigned int old_val, regval; + + old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG); + + regval |= FMC_CLK_SEL(FMC_CLK_200M); + + if (enable) + regval |= FMC_CLK_ENABLE; + else + regval &= ~FMC_CLK_ENABLE; + + regval &= ~FMC_SOFT_RST_REQ; + if (regval != old_val) + writel(regval, (CRG_REG_BASE + REG_FMC_CRG)); + nand_io_config(); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/mmc.h b/hispark_aries/liteos_a/board/include/hisoc/mmc.h new file mode 100755 index 00000000..16206f64 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/mmc.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_MMC_H_ +#define __HISOC_MMC_H_ + +/************************************************************************/ + +#include "asm/platform.h" +#include "asm/dma.h" +#include "asm/io.h" +#include "los_bitmap.h" +#include "mmc/mmc_caps.h" +#include "sdhci/sdhci_reg.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/************************************************************************/ + +#define MAX_MMC_NUM 2 +#define USE_MMC0 1 +#define USE_MMC1 1 + +#define MMC0 0 +#define MMC1 1 + +// sdio0 & emmc +#define CONFIG_MMC0_CCLK_MIN 100000 // 100KHz + +#ifdef LOSCFG_DRIVERS_EMMC_HS400 +#define CONFIG_MMC0_CCLK_MAX 90000000 // 90MHz +#else +#define CONFIG_MMC0_CCLK_MAX 150000000 // 150MHz +#endif + +// sdio1 +#define CONFIG_MMC1_CCLK_MIN 100000 // 100KHz +#define CONFIG_MMC1_CCLK_MAX 50000000 // 200MHz + + +///// not exist +#define PERI_CRG86 (CRG_REG_BASE + 0x158) +#define PERI_CRG87 (CRG_REG_BASE + 0x15C) +#define PERI_CRG94 (CRG_REG_BASE + 0x178) +#define PERI_CRG95 (CRG_REG_BASE + 0x17C) +#define PERI_CRG96 (CRG_REG_BASE + 0x180) + +#define PERI_CRG106 (CRG_REG_BASE + 0x1A8) +#define PERI_CRG117 (CRG_REG_BASE + 0x01D4) +#define PERI_CRG123 (CRG_REG_BASE + 0x1EC) +#define PERI_CRG133 (CRG_REG_BASE + 0x214) +#define PERI_CRG143 (CRG_REG_BASE + 0x23C) +////// + +#define PERI_CRG125 (CRG_REG_BASE + 0x01F4) + +// eMMC DRV DLL +#define PERI_CRG127 (CRG_REG_BASE + 0x01FC) +#define PERI_SAM_DRV_SHFT (24) +#define PERI_SAM_DRV_MASK (0x1f << 24) + +// SDIO1 DRV DLL +#define PERI_CRG136 (CRG_REG_BASE + 0x0220) +#define PERI_CRG139 (CRG_REG_BASE + 0x022C) + +#define PERI_SDIO0_SAMPLB_DLL_CTRL (CRG_REG_BASE + 0x1f8) +#define PERI_SDIO1_SAMPLB_DLL_CTRL (CRG_REG_BASE + 0x21c) +#define SDIO_SAMPLB_DLL_CLK_MASK (0x1fU << 0) +#define SDIO_SAMPLB_SEL(phase) ((phase) << 0) + +#define PERI_SDIO0_DRV_DLL_CTRL (CRG_REG_BASE + 0x210) +#define PERI_SDIO1_DRV_DLL_CTRL (CRG_REG_BASE + 0x228) + +#define SDIO_DRV_DLL_LOCK (1U << 15) + +#define PERI_SDIO0_SAMPL_DLL_STATUS (CRG_REG_BASE + 0x208) +#define PERI_SDIO1_SAMPL_DLL_STATUS (CRG_REG_BASE + 0x224) + +#define SDIO_SAMPL_DLL_SLAVE_READY (1) +#define SDIO_SAMPL_DLL_SLAVE_EN (1U << 16) + +#define PERI_CRG106_EMMC_CRG_REQ (1U << 27) +#define PERI_CRG106_EMMC_CKEN (1U << 28) +#define PERI_CRG106_EMMC_DLL_RST (1U << 29) +#define PERI_CRG106_EMMC_SAM_RST (1U << 30) + +#define EMMC_PHY_BASE IO_DEVICE_ADDR(0x12160000) + +#define MMC_FREQ_100K 100000 +#define MMC_FREQ_400K 400000 +#define MMC_FREQ_25M 25000000 +#define MMC_FREQ_50M 50000000 +// only support for EMMC chip +#define MMC_FREQ_90M 90000000 +#define MMC_FREQ_112P5M 112500000 +#define MMC_FREQ_150M 150000000 + + +#define MMC_FREQ_MASK 0x7 +#define MMC_FREQ_SHIFT 24 +#define SDIO0_CKEN (1U << 28) +#define SDIO0_CLK_SEL_100K (0) +#define SDIO0_CLK_SEL_400K (7) +#define SDIO0_CLK_SEL_25M (1) +#define SDIO0_CLK_SEL_50M (2) +#define SDIO0_CLK_SEL_100M (3) +#define SDIO0_CLK_SEL_125M (4) +#define SDIO0_CLK_SEL_150M (5) +#define SDIO0_CLK_SEL_200M (6) + + +#define REG_CTRL_BASE IO_DEVICE_ADDR(0x100C0040) + +#define REG_CTRL_SDIO0_CLK IO_DEVICE_ADDR(0x100C0040) +#define REG_CTRL_SDIO0_CMD IO_DEVICE_ADDR(0x100C0044) +#define REG_CTRL_SDIO0_DATA0 IO_DEVICE_ADDR(0x100C0048) +#define REG_CTRL_SDIO0_DATA1 IO_DEVICE_ADDR(0x100C004C) +#define REG_CTRL_SDIO0_DATA2 IO_DEVICE_ADDR(0x100C0050) +#define REG_CTRL_SDIO0_DATA3 IO_DEVICE_ADDR(0x100C0054) + +#define REG_CTRL_SDIO0_CD_DET IO_DEVICE_ADDR(0x100C005C) + +#define REG_CTRL_SDIO0_CD_POW IO_DEVICE_ADDR(0x120C0020) + +#ifdef LOSCFG_PLATFORM_HI3516EV200 +#define REG_CTRL_SDIO1_CLK IO_DEVICE_ADDR(0x112c0048) +#define REG_CTRL_SDIO1_CMD IO_DEVICE_ADDR(0x112c004c) +#define REG_CTRL_SDIO1_DATA0 IO_DEVICE_ADDR(0x112c0064) +#define REG_CTRL_SDIO1_DATA1 IO_DEVICE_ADDR(0x112c0060) +#define REG_CTRL_SDIO1_DATA2 IO_DEVICE_ADDR(0x112c005c) +#define REG_CTRL_SDIO1_DATA3 IO_DEVICE_ADDR(0x112c0058) +#elif defined(LOSCFG_PLATFORM_HI3516EV300) +#define REG_CTRL_SDIO1_CLK IO_DEVICE_ADDR(0x100C0060) +#define REG_CTRL_SDIO1_CMD IO_DEVICE_ADDR(0x100C0064) +#define REG_CTRL_SDIO1_DATA0 IO_DEVICE_ADDR(0x100C0068) +#define REG_CTRL_SDIO1_DATA1 IO_DEVICE_ADDR(0x100C006C) +#define REG_CTRL_SDIO1_DATA2 IO_DEVICE_ADDR(0x100C0070) +#define REG_CTRL_SDIO1_DATA3 IO_DEVICE_ADDR(0x100C0074) +#elif defined(LOSCFG_PLATFORM_HI3518EV300) +#define REG_CTRL_SDIO1_CLK IO_DEVICE_ADDR(0x112C0048) +#define REG_CTRL_SDIO1_CMD IO_DEVICE_ADDR(0x112C004C) +#define REG_CTRL_SDIO1_DATA0 IO_DEVICE_ADDR(0x112C0064) +#define REG_CTRL_SDIO1_DATA1 IO_DEVICE_ADDR(0x112C0060) +#define REG_CTRL_SDIO1_DATA2 IO_DEVICE_ADDR(0x112C005C) +#define REG_CTRL_SDIO1_DATA3 IO_DEVICE_ADDR(0x112C0058) +#endif + +#define REG_CTRL_EMMC_CLK IO_DEVICE_ADDR(0x100C0014) +#define REG_CTRL_EMMC_CMD IO_DEVICE_ADDR(0x100C0018) +#define REG_CTRL_EMMC_DATA0 IO_DEVICE_ADDR(0x100C0020) +#define REG_CTRL_EMMC_DATA1 IO_DEVICE_ADDR(0x100C001c) +#define REG_CTRL_EMMC_DATA2 IO_DEVICE_ADDR(0x100C0028) +#define REG_CTRL_EMMC_DATA3 IO_DEVICE_ADDR(0x100C0024) +#define REG_CTRL_EMMC_DATA4 IO_DEVICE_ADDR(0x100C0030) +#define REG_CTRL_EMMC_DATA5 IO_DEVICE_ADDR(0x100C0034) +#define REG_CTRL_EMMC_DATA6 IO_DEVICE_ADDR(0x100C0038) +#define REG_CTRL_EMMC_DATA7 IO_DEVICE_ADDR(0x100C003c) + +#define REG_CTRL_EMMC_DS IO_DEVICE_ADDR(0x100C0058) +#define REG_CTRL_EMMC_RST IO_DEVICE_ADDR(0x100C005C) + +// macro for io_mux +#define IO_CFG_SR BIT(10) +#define IO_CFG_PULL_DOWN BIT(9) +#define IO_CFG_PULL_UP BIT(8) +#define IO_CFG_DRV_STR_MASK (0xfU << 4) +#define IO_DRV_MASK (0x7f0) + +#define IO_DRV_STR_SEL(str) ((str) << 4) + +#define IO_MUX_CLK_TYPE_EMMC 0x0 +#define IO_MUX_CLK_TYPE_SD 0x1 +#define IO_MUX_SHIFT(type) ((type) << 0) +#define IO_MUX_MASK (0xfU << 0) + +enum mmc_width_seletion_mode { + /* The bus width is auto determined by capabilities of a card and host */ + MMC_WIDTH_SELCTION_AUTO = 0, + /* + * The bus width of host and card are both manually forced into 1 bit mode + * whether the card and host supports 4-bit or not. + */ + MMC_WIDTH_FORCED_1_BIT, +}; + +/* + * Description: + * This API is used to set the bus width selection mode of sd and sdio host devices. + * Param: host_id [IN] ranging from 0 to (MAX_MMC_NUM - 1). The types of hosts, either sd or sdio, + * can be inqueried from user's guide according to the param host_id. + * Param: type [IN] the width selection mode, either MMC_WIDTH_SELCTION_AUTO, or MMC_WIDTH_FORCED_1_BIT. + * please refer to enum mmc_width_seletion_mode for more details. + * Attention: The width selection mode is default auto mode if this API is not called. + * This API should be called before initial and registration of mmc driver. + */ +extern void mmc_width_seletion_mode_set(unsigned int host_id, enum mmc_width_seletion_mode type); + +void SDHCI_EnableSample(void *base); +void SDHCI_CardClk(void *base, int action); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/nand.h b/hispark_aries/liteos_a/board/include/hisoc/nand.h new file mode 100755 index 00000000..27cf42a2 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/nand.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_NAND_H__ +#define __HISOC_NAND_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define PERI_CRG52 (CRG_REG_BASE + 0x00D0) +#define PERI_CRG52_CLK_EN (1U << 1) +#define PERI_CRG52_CLK_SEL_198M (1U << 2) + +#define REG_SYSSTAT 0x008C +#define BOOT_FROM_NAND 2 + +static void hinfc620_clk_enable(int enable) +{ + unsigned int reg_val = readl(PERI_CRG52); + + if (enable) + reg_val |= (PERI_CRG52_CLK_EN | PERI_CRG52_CLK_SEL_198M); + else + reg_val &= ~PERI_CRG52_CLK_EN; + + writel(reg_val, (PERI_CRG52)); +} +#define check_boot_type() ((readl(SYS_CTRL_REG_BASE + REG_SYSSTAT) >> 4) & 0x3); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/net.h b/hispark_aries/liteos_a/board/include/hisoc/net.h new file mode 100755 index 00000000..70e98775 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/net.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_NET_H__ +#define __HISOC_NET_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define HIETH_CRG_IOBASE (CRG_REG_BASE + 0x016c) +#define ETH_CORE_CLK_SELECT_54M (1 << 7) +#define ETH_PHY_RESET (1 << 3) + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/board/include/hisoc/random.h b/hispark_aries/liteos_a/board/include/hisoc/random.h new file mode 100755 index 00000000..f483883a --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/random.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HISOC_RANDOM_H +#define _HISOC_RANDOM_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +VOID HiRandomHwInit(VOID); +VOID HiRandomHwDeinit(VOID); +INT32 HiRandomHwGetInteger(UINT32 *result); +INT32 HiRandomHwGetNumber(CHAR *buffer, size_t bufLen); + +VOID PlatformRandomOperationsInit(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif diff --git a/hispark_aries/liteos_a/board/include/hisoc/spinand.h b/hispark_aries/liteos_a/board/include/hisoc/spinand.h new file mode 100755 index 00000000..8d6762ad --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/spinand.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SPINAND_H__ +#define __HISOC_SPINAND_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ +/*****************************************************************************/ +#define CRG48 0xc0 +#define CRG48_SPI_NAND_CLK_SEL(_clk) (((_clk) & 0x3) << 6) +#define CRG48_SPI_NAND_CLK_EN (1 << 5) +#define CRG48_SPI_NAND_SOFT_RST_REQ (1 << 4) + +#define SPI_NAND_CLK_SEL_MASK (0x3 << 6) +#define DEVICE_TYPE_SHIFT 1 +#define DEVICE_TYPE_MASK (0x1 << 1) + +#define CLK_24M 0 +#define CLK_75M 1 +#define CLK_125M 2 + +#define SPI_NAND_CLK_SEL_24M CRG48_SPI_NAND_CLK_SEL(CLK_24M) +#define SPI_NAND_CLK_SEL_75M CRG48_SPI_NAND_CLK_SEL(CLK_75M) +#define SPI_NAND_CLK_SEL_125M CRG48_SPI_NAND_CLK_SEL(CLK_125M) + +#define GET_CLK_TYPE(_reg) (((_reg) >> 2) & 0x3) + +/*****************************************************************************/ +static void hisnfc100_set_system_clock(int clock, int clk_en) +{ + unsigned base = CRG_REG_BASE; + unsigned regval = readl(base + CRG48); + + if (!clock) + clock = SPI_NAND_CLK_SEL_75M; + regval = (regval & SPI_NAND_CLK_SEL_MASK) | clock; + + if (clk_en) + regval |= CRG48_SPI_NAND_CLK_EN; + else + regval &= ~CRG48_SPI_NAND_CLK_EN; + + if (readl(base + CRG48) != regval) + writel(regval, (base + CRG48)); +} + +/*****************************************************************************/ +static void hisnfc100_get_best_clock(unsigned int *clock) +{ + int ix; + int clk_reg; +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sysclk[] = { + CLK_2X(24), SPI_NAND_CLK_SEL_24M, + CLK_2X(75), SPI_NAND_CLK_SEL_75M, + CLK_2X(125), SPI_NAND_CLK_SEL_125M, + 0, 0, + }; +#undef CLK_2X + + clk_reg = SPI_NAND_CLK_SEL_24M; + for (ix = 0; sysclk[ix]; ix += 2) { + if (*clock < sysclk[ix]) + break; + clk_reg = sysclk[ix + 1]; + } + *clock = clk_reg; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/spinor.h b/hispark_aries/liteos_a/board/include/hisoc/spinor.h new file mode 100755 index 00000000..5fb6c9a0 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/spinor.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SPINOR_H__ +#define __HISOC_SPINOR_H__ + +#include "asm/platform.h" +#include "asm/io.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define PERI_CRG48 (CRG_REG_BASE + 0x00C0) +#define PERI_CRG48_RST (1 << 0) +#define PERI_CRG48_CLKEN (1 << 1) +#define PERI_CRG48_CLK_24M (0 << 2) +#define PERI_CRG48_CLK_75M ((0 << 3) | (1 << 2)) +#define PERI_CRG48_CLK_125M ((1 << 2) | (1 << 3)) + +#define SFC_ADDR_MODE_REG (0x8C) +#define SFC_ADDR_MODE_MASK (0x80) +#define SFC_CLSEL_MASK (0xC) +#define SFC_PERI_CLKDIV1_SHIFT (28) +#define SFC_PERI_CLKDIV1_MASK (0xF) + +/*****************************************************************************/ +#undef GET_SFC_ADDR_MODE +#define GET_SFC_ADDR_MODE ({ \ + int start_up_mode = 0; \ + start_up_mode = readl(IO_ADDRESS(SYS_CTRL_REG_BASE + SFC_ADDR_MODE_REG)); \ + start_up_mode &= SFC_ADDR_MODE_MASK; \ + start_up_mode; }) + +/*****************************************************************************/ +static inline void hisfc350_set_system_clock(unsigned clock, int clk_en) +{ + unsigned int regval = readl(PERI_CRG48); + + regval = regval & (~SFC_CLSEL_MASK); + + if (clock) { + regval &= ~SFC_CLSEL_MASK; + regval |= clock & SFC_CLSEL_MASK; + } else { + regval &= ~SFC_CLSEL_MASK; + regval |= PERI_CRG48_CLK_24M; /* Default Clock */ + } + + if (clk_en) + regval |= PERI_CRG48_CLKEN; + + if (regval != readl(PERI_CRG48)) + writel(regval, (PERI_CRG48)); +} + +/*****************************************************************************/ +static inline void hisfc350_get_best_clock(unsigned int *clock) +{ + int ix; + int clk_reg; + +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sysclk[] = { + CLK_2X(24), PERI_CRG48_CLK_24M, + CLK_2X(75), PERI_CRG48_CLK_75M, + CLK_2X(125), PERI_CRG48_CLK_125M, + 0, 0, + }; +#undef CLK_2X + + clk_reg = PERI_CRG48_CLK_24M; + for (ix = 0; sysclk[ix]; ix += 2) { + if (*clock < sysclk[ix]) + break; + clk_reg = sysclk[ix + 1]; + } + + *clock = clk_reg; +} + +/*****************************************************************************/ +#ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING +static inline char * hisfc350_get_clock_str(unsigned int clk_reg) +{ + static char buffer[40]; + + /* calculate reference PERI_CLKDIV1[31:28] */ + SFC_PR(BT_DBG, "clk_reg=0x%0x.\n", clk_reg); + clk_reg = 216 / ((clk_reg >> SFC_PERI_CLKDIV1_SHIFT) + & SFC_PERI_CLKDIV1_MASK); + (VOID)sprintf_s(buffer, sizeof(buffer), "%dM", clk_reg); + + return buffer; +} +#endif /* CONFIG_PERI_SHOW_CYCLE_TIMING */ + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/sys_ctrl.h b/hispark_aries/liteos_a/board/include/hisoc/sys_ctrl.h new file mode 100755 index 00000000..79dd0b1a --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/sys_ctrl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SYS_CTRL_H__ +#define __HISOC_SYS_CTRL_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define REG_SC_CTRL 0 +#define REG_SC_SYSRES 0x4 +#define PERIPHCTRL24 0x94 + +#define REG_SC_GEN0 0x0138 +#define REG_SC_GEN1 0x013c +#define REG_SC_GEN2 0x0140 +#define REG_SC_GEN3 0x0144 +#define REG_SC_GEN4 0x0148 + +#define REG_SC_DDRT0 0x0090 +#define NORMAL_BOOTMODE_OFFSET 9 +#define NORMAL_BOOTMODE_MASK 3 + +/********** Communication Register and flag used by bootrom *************/ +#define REG_START_FLAG (SYS_CTRL_REG_BASE + REG_SC_GEN1) +#define CONFIG_START_MAGIC (0x444f574e) + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/timer.h b/hispark_aries/liteos_a/board/include/hisoc/timer.h new file mode 100755 index 00000000..264d521a --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/timer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_TIMER_H__ +#define __HISOC_TIMER_H__ + +#include "asm/platform.h" +#include "los_bitmap.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define TIMER_LOAD 0x0 +#define TIMER_VALUE 0x4 +#define TIMER_CONTROL 0x8 +#define TIMER_INT_CLR 0xc +#define TIMER_RIS 0x10 +#define TIMER_MIS 0x14 +#define TIMER_BGLOAD 0x18 + +#define TIMER0_ENABLE BIT(16) +#define TIMER1_ENABLE BIT(17) +#define TIMER2_ENABLE BIT(18) +#define TIMER3_ENABLE BIT(19) +#define TIMER4_ENABLE BIT(20) +#define TIMER5_ENABLE BIT(21) +#define TIMER6_ENABLE BIT(22) +#define TIMER7_ENABLE BIT(23) +#define TIMER8_ENABLE BIT(24) +#define TIMER9_ENABLE BIT(25) +#define TIMER10_ENABLE BIT(26) +#define TIMER11_ENABLE BIT(27) + +unsigned int arch_timer_rollback(void); +VOID LOS_Udelay(UINT32 usecs); +VOID LOS_Mdelay(UINT32 msecs); +VOID reset_timer_masked(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif + diff --git a/hispark_aries/liteos_a/board/include/hisoc/uart.h b/hispark_aries/liteos_a/board/include/hisoc/uart.h new file mode 100755 index 00000000..cc5a72c7 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/uart.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_UART_H__ +#define __HISOC_UART_H__ + +#include "asm/platform.h" +#include "los_typedef.h" +#include "los_base.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define CONFIG_UART0_BAUDRATE 115200 +#define CONFIG_UART_CLK_INPUT (24000000) // 24M or 6M + +#define UART0 0 +#define UART1 1 +#define UART2 2 + +#define UART0_ENABLE 1 +#define UART1_ENABLE 1 +#define UART2_ENABLE 1 + +#define UART0_DMA_RX_PERI 4 +#define UART1_DMA_RX_PERI 6 +#define UART2_DMA_RX_PERI 8 + +#define uart_pin_mux_cfg(uart_num) ({ \ + if (UART0 == uart_num) {} \ + else if (UART1 == uart_num) { \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x07C); \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x084); \ + } \ + else if (UART2 == uart_num) { \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x088); \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x08C); \ + } \ + else if (UART3 ==uart_num) { \ + WRITE_UINT16(0x02, IO_MUX_REG_BASE + 0x078); \ + WRITE_UINT16(0x02, IO_MUX_REG_BASE + 0x080); \ + } \ + }) +#define uart_clk_cfg(uart_num, flag) ({ \ + unsigned int tmp = 0; \ + tmp = GET_UINT32(CRG_REG_BASE + 0x0198); \ + if (flag) \ + tmp |= (1<<(uart_num + 24)); \ + else \ + tmp &= ~(1<<(uart_num + 24)); \ + WRITE_UINT32(tmp, CRG_REG_BASE + 0x0198); \ + }) +#define get_uart_dma_peri(uart_num) ({ \ + unsigned int peri_num = -1; \ + if (UART0 == uart_num) \ + peri_num = UART0_DMA_RX_PERI; \ + else if (UART1 == uart_num) \ + peri_num = UART1_DMA_RX_PERI; \ + else if (UART2 == uart_num) \ + peri_num = UART2_DMA_RX_PERI; \ + else if (UART3 == uart_num) \ + peri_num = UART3_DMA_RX_PERI; \ + peri_num; \ + }) + + +#define TTYS0 "/dev/ttyS0" + +#define CONSOLE_UART UART0 + +#define CONSOLE_UART_BAUDRATE 115200 +#define UART_NUM 4 +#if (CONSOLE_UART == UART0) + #define TTY_DEVICE "/dev/uartdev-0" + #define UART_REG_BASE UART0_REG_BASE + #define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART0 +#elif (CONSOLE_UART == UART1) + #define TTY_DEVICE "/dev/uartdev-1" + #define UART_REG_BASE UART1_REG_BASE + #define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART1 +#elif (CONSOLE_UART == UART2) + #define TTY_DEVICE "/dev/uartdev-2" + #define UART_REG_BASE UART2_REG_BASE + #define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART2 +#endif + +#ifdef LOSCFG_PLATFORM_HISI_AMP +#undef TTY_DEVICE +#define TTY_DEVICE "/dev/virt-tty" +#endif + +typedef struct { + UINT32 base; + INT32 msec_timeout; + int isr_vector; +} channel_data_t; + +extern void uart_init(void); +extern void uart_interrupt_unmask(void); +extern int uart_hwiCreate(void); +extern UINT8 uart_getc(void); +extern char uart_fputc(char c, void *f); + +extern UINT32 UartPutsReg(UINTPTR base, const CHAR *s, UINT32 len, BOOL isLock); +extern VOID UartPuts(const CHAR *s, UINT32 len, BOOL isLock); + +#define UART_WITHOUT_LOCK 0 +#define UART_WITH_LOCK 1 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/board/include/hisoc/usb3.h b/hispark_aries/liteos_a/board/include/hisoc/usb3.h new file mode 100755 index 00000000..0fa59826 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/hisoc/usb3.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_USB3_H__ +#define __HISOC_USB3_H__ + +#include "los_base.h" +#include "board.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define CONFIG_HIUSB_XHCI_IOBASE 0x10030000 +#define CONFIG_HIUSB_XHCI_IOSIZE 0x10000 + +#define DWC_USB3_PORT1_BASE_ADDR CONFIG_HIUSB_XHCI_IOBASE +#define DWC_USB3_PORT1_ADDR_OFFSET 0xc000 + +#define USB_CACHE_ALIGN_SIZE 64 +#define ALIGNBYTES 3 +#define SKB_DATA_ALIGN(X) ALIGN(X, USB_CACHE_ALIGN_SIZE) +#define UVC_USE_CTRL_EP 1 + +#define FMASS_DEV_PATH "/dev/mmcblk0p" + +extern VOID HiUsb3StartHcd(VOID); +extern VOID HiUsb3StopHcd(VOID); +extern VOID HiUsb3Host2Device(VOID); +extern BOOL HiUsbIsDeviceMode(VOID); +extern VOID UsbOtgSwSetDeviceState(VOID); +extern VOID UsbOtgSwClearDeviceState(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/board/include/platform_config.h b/hispark_aries/liteos_a/board/include/platform_config.h new file mode 100755 index 00000000..62280cf4 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/platform_config.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PLATFORM_CONFIG_H__ +#define __PLATFORM_CONFIG_H__ + +#include "hisoc/clock.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define LOSCFG_PLATFORM_HWI_LIMIT 96 +#define OS_SYS_CLOCK 50000000 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/board/include/reset_shell.h b/hispark_aries/liteos_a/board/include/reset_shell.h new file mode 100755 index 00000000..38020dae --- /dev/null +++ b/hispark_aries/liteos_a/board/include/reset_shell.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RESET_SHELL_H +#define _RESET_SHELL_H +#include "los_task.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +typedef VOID* (*STORAGE_HOOK_FUNC)(VOID*); + +typedef struct tagHookFuncNode { + STORAGE_HOOK_FUNC pHandler; + VOID *pParam; + struct tagHookFuncNode *pNext; +}Hook_Func_Node; + +extern Hook_Func_Node *g_hook_func_node; + +UINT32 osReHookFuncAdd(STORAGE_HOOK_FUNC handler, VOID *param); +UINT32 osReHookFuncDel(STORAGE_HOOK_FUNC handler); +VOID osReHookFuncHandle(VOID); +extern void cmd_reset(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/board/include/system_config.h b/hispark_aries/liteos_a/board/include/system_config.h new file mode 100755 index 00000000..5f3be608 --- /dev/null +++ b/hispark_aries/liteos_a/board/include/system_config.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*************************************************************/ +#ifndef _SYSTEM_CONFIG_H +#define _SYSTEM_CONFIG_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** system source configuration **/ +/** + * @ingroup los_config + * Maximum supported number of tasks except the idle task rather than the number of usable tasks + */ +#define LOSCFG_BASE_CORE_TSK_CONFIG 64 +/** + * @ingroup los_config + * Maximum supported number of semaphores + */ +#define LOSCFG_BASE_IPC_SEM_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of mutexes + */ +#define LOSCFG_BASE_IPC_MUX_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of queues rather than the number of usable queues + */ +#define LOSCFG_BASE_IPC_QUEUE_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of software timers rather than the number of usable software timers + */ +#define LOSCFG_BASE_CORE_SWTMR_CONFIG 1024 + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +#endif /* _SYSTEM_CONFIG_H */ +/*************************************************************/ diff --git a/hispark_aries/liteos_a/board/libs/debug/libbsp_config.a b/hispark_aries/liteos_a/board/libs/debug/libbsp_config.a new file mode 100755 index 0000000000000000000000000000000000000000..ccb9d552fab6cdef83fca740ce8a27122604d05b GIT binary patch literal 80896 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 EKPh+eQ2+n{ literal 0 HcmV?d00001 diff --git a/hispark_aries/liteos_a/board/libs/release/libbsp_config.a b/hispark_aries/liteos_a/board/libs/release/libbsp_config.a new file mode 100755 index 0000000000000000000000000000000000000000..e3ad6aa17ad65f7115111db0701a77c6d53496fe GIT binary patch literal 75260 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 literal 0 HcmV?d00001 diff --git a/hispark_aries/liteos_a/board/target_config.h b/hispark_aries/liteos_a/board/target_config.h new file mode 100755 index 00000000..bf8481b3 --- /dev/null +++ b/hispark_aries/liteos_a/board/target_config.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TARGET_CONFIG_H +#define _TARGET_CONFIG_H + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define OS_SYS_CLOCK 50000000 +#define SYS_CTRL_REG_BASE IO_DEVICE_ADDR(0x12020000) +#define REG_SC_CTRL 0 + +/* memory */ +#define CACHE_ALIGNED_SIZE 64 + +/* physical memory base and size */ +#define DDR_MEM_ADDR 0x40000000 +#define DDR_MEM_SIZE 0x04000000 + +/* Peripheral register address base and size */ +#define PERIPH_PMM_BASE 0x10000000 +#define PERIPH_PMM_SIZE 0x10000000 + +#define SYS_MEM_SIZE_DEFAULT 0x2000000 + + +/* hwi */ +/** + * Maximum number of supported hardware devices that generate hardware interrupts. + * The maximum number of hardware devices that generate hardware interrupts is 128. + */ +#define OS_HWI_MAX_NUM 96 + +/** + * Maximum interrupt number. + */ +#define OS_HWI_MAX ((OS_HWI_MAX_NUM) - 1) + +/** + * Minimum interrupt number. + */ +#define OS_HWI_MIN 0 +/** + * Maximum usable interrupt number. + */ +#define OS_USER_HWI_MAX OS_HWI_MAX +/** + * Minimum usable interrupt number. + */ +#define OS_USER_HWI_MIN OS_HWI_MIN + +#define NUM_HAL_INTERRUPT_CNTPSIRQ 29 +#define NUM_HAL_INTERRUPT_CNTPNSIRQ 30 +#define OS_TICK_INT_NUM NUM_HAL_INTERRUPT_CNTPSIRQ // use secure physical timer for now +#define NUM_HAL_INTERRUPT_TIMER0 37 +#define NUM_HAL_INTERRUPT_TIMER3 38 +#define NUM_HAL_INTERRUPT_UART0 39 + +/* gic config */ +#define GIC_BASE_ADDR IO_DEVICE_ADDR(0x10300000) +#define GICD_OFFSET 0x1000 /* interrupt distributor offset */ +#define GICC_OFFSET 0x2000 /* CPU interface register offset */ + +/* timer config */ +#define BIT(n) (1U << (n)) +#define TIMER0_ENABLE BIT(16) +#define TIMER1_ENABLE BIT(17) +#define TIMER2_ENABLE BIT(18) +#define TIMER3_ENABLE BIT(19) + +#define TIMER0_REG_BASE IO_DEVICE_ADDR(0x12000000) +#define TIMER1_REG_BASE IO_DEVICE_ADDR(0x12000020) +#define TIMER2_REG_BASE IO_DEVICE_ADDR(0x12001000) +#define TIMER3_REG_BASE IO_DEVICE_ADDR(0x12001020) + +#define TIMER_TICK_REG_BASE TIMER0_REG_BASE /* timer for tick */ +#define TIMER_TICK_ENABLE TIMER0_ENABLE +#define TIMER_TIME_REG_BASE TIMER1_REG_BASE /* timer for time */ +#define TIMER_TIME_ENABLE TIMER1_ENABLE +#define HRTIMER_TIMER_REG_BASE TIMER3_REG_BASE /* timer for hrtimer */ +#define HRTIMER_TIMER_ENABLE TIMER3_ENABLE + +#define NUM_HAL_INTERRUPT_TIMER NUM_HAL_INTERRUPT_TIMER0 +#define NUM_HAL_INTERRUPT_HRTIMER NUM_HAL_INTERRUPT_TIMER3 + +#define TIMER_LOAD 0x0 +#define TIMER_VALUE 0x4 +#define TIMER_CONTROL 0x8 +#define TIMER_INT_CLR 0xc +#define TIMER_RIS 0x10 +#define TIMER_MIS 0x14 +#define TIMER_BGLOAD 0x18 + +/* uart config */ +#define UART0_REG_BASE IO_DEVICE_ADDR(0x12040000) +#define TTY_DEVICE "/dev/uartdev-0" +#define UART_REG_BASE UART0_REG_BASE +#define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART0 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_aries/liteos_a/config.gni b/hispark_aries/liteos_a/config.gni new file mode 100755 index 00000000..3c809c3c --- /dev/null +++ b/hispark_aries/liteos_a/config.gni @@ -0,0 +1,61 @@ +# Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Kernel type, e.g. "linux", "liteos_a", "liteos_m". +kernel_type = "liteos_a" + +# Kernel version. +kernel_version = "" + +# Board CPU type, e.g. "cortex-a7", "riscv32". +board_cpu = "cortex-a7" + +# Board arch, e.g. "armv7-a", "rv32imac". +board_arch = "" + +# Toolchain name used for system compiling. +# E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. +# Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toolchain. +board_toolchain = "" + +# The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc. +board_toolchain_path = "" + +# Compiler prefix. +board_toolchain_prefix = "" + +# Compiler type, "gcc" or "clang". +board_toolchain_type = "clang" + +# Board related common compile flags. +board_cflags = [ + "-mfloat-abi=softfp", + "-mfpu=neon-vfpv4", +] +board_cxx_flags = [ + "-mfloat-abi=softfp", + "-mfpu=neon-vfpv4", +] +board_ld_flags = [] + +# Board related headfiles search path. +board_include_dirs = [] + +# Board adapter dir for OHOS components. +board_adapter_dir = "//device/soc/hisilicon/common/hi35xx_hal" + +# Sysroot path. +board_configed_sysroot = "" + +# Board storage type, it used for file system generation. +storage_type = "spinor" diff --git a/hispark_aries/liteos_a/drivers/BUILD.gn b/hispark_aries/liteos_a/drivers/BUILD.gn new file mode 100755 index 00000000..865ee135 --- /dev/null +++ b/hispark_aries/liteos_a/drivers/BUILD.gn @@ -0,0 +1,38 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//drivers/adapter/khdf/liteos/hdf.gni") + +group("drivers") { + public_deps = [ "//device/soc/hisilicon/common/platform:drivers" ] +} + +config("public") { + configs = [ "//device/soc/hisilicon/common/platform:public" ] +} diff --git a/hispark_aries/liteos_a/drivers/Kconfig b/hispark_aries/liteos_a/drivers/Kconfig new file mode 100755 index 00000000..d3e0e663 --- /dev/null +++ b/hispark_aries/liteos_a/drivers/Kconfig @@ -0,0 +1 @@ +source "../../device/soc/hisilicon/common/platform/Kconfig" diff --git a/hispark_aries/ohos.build b/hispark_aries/ohos.build new file mode 100755 index 00000000..b182a1ba --- /dev/null +++ b/hispark_aries/ohos.build @@ -0,0 +1,10 @@ +{ + "parts": { + "device_hispark_aries": { + "module_list": [ + ":hispark_aries" + ] + } + }, + "subsystem": "device_hispark_aries" +} \ No newline at end of file diff --git a/hispark_aries/uboot/Makefile b/hispark_aries/uboot/Makefile new file mode 100755 index 00000000..e7e719d2 --- /dev/null +++ b/hispark_aries/uboot/Makefile @@ -0,0 +1,86 @@ +########################################################################################## +# prepare param +########################################################################################## +export OSDRV_DIR=$(shell pwd) +export OSDRV_CROSS +export CHIP?=hi3518ev300 +export ARCH=arm +export CROSS_COMPILE=$(OSDRV_CROSS)- +BOOT_MEDIA?=spi + +ifneq ($(BOOT_MEDIA),spi) +ifneq ($(BOOT_MEDIA),emmc) +$(error you must set valid BOOT_MEDIA:spi or emmc!) +endif +endif + +ifeq ($(OSDRV_CROSS), ) +OSDRV_CROSS=$(OSDRV_DIR)/../../../../../prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi +endif + +UBOOT_VER:=u-boot-2020.01 +UBOOT_TAR:=$(UBOOT_VER).tgz +UBOOT:=u-boot-$(CHIP).bin +UBOOT_REG_BIN:=reg_info_$(CHIP).bin +ifeq ($(BOOT_MEDIA),emmc) +export UBOOT_CONFIG:=$(CHIP)_$(BOOT_MEDIA)_config +else +export UBOOT_CONFIG:=$(CHIP)_config +endif + +NORMAL_UBOOT_DIR:=$(OSDRV_DIR)/../../../third_party/uboot + +########################################################################################## +# set task +########################################################################################## +all: prepare hiboot hipctools build_done + +clean: hiboot_clean hipctools_clean + +distclean: clean pub_clean clean_done + +########################################################################################## +##task [0] prepare out directory +########################################################################################## +prepare: + @echo "------- task [0] prepare out dir -------" + mkdir $(OSDRV_DIR)/out/boot -p + +########################################################################################## +#task [1] build uboot +########################################################################################## +hiboot: + @echo "---------task [1] build boot" + find $(NORMAL_UBOOT_DIR)/$(UBOOT_VER) | xargs touch + make -C $(NORMAL_UBOOT_DIR)/$(UBOOT_VER) ARCH=arm CROSS_COMPILE=$(OSDRV_CROSS)- $(UBOOT_CONFIG) + pushd $(NORMAL_UBOOT_DIR)/$(UBOOT_VER);make ARCH=arm CROSS_COMPILE=$(OSDRV_CROSS)- -j 20 >/dev/null;popd + chmod +x $(NORMAL_UBOOT_DIR)/$(UBOOT_VER)/arch/arm/cpu/armv7/$(CHIP)/hw_compressed/gzip + cp $(OSDRV_DIR)/reg/$(UBOOT_REG_BIN) $(NORMAL_UBOOT_DIR)/$(UBOOT_VER)/.reg + pushd $(NORMAL_UBOOT_DIR)/$(UBOOT_VER);make ARCH=arm CROSS_COMPILE=$(OSDRV_CROSS)- u-boot-z.bin >/dev/null;popd + cp $(NORMAL_UBOOT_DIR)/$(UBOOT_VER)/u-boot-$(CHIP).bin $(OSDRV_DIR)/out/boot + cp $(NORMAL_UBOOT_DIR)/$(UBOOT_VER)/u-boot-$(CHIP).bin $(OSDRV_DIR)/secureboot_release + +hiboot_clean: + @cd $(NORMAL_UBOOT_DIR)/$(UBOOT_VER)/;make distclean + @echo "---------boot clean" + +########################################################################################## +##task [2] make hipctools +########################################################################################## +hipctools:prepare + @echo "---------task [2] build tools run on pc" + +hipctools_clean: + +########################################################################################## +#task [4] clean out +########################################################################################## +pub_clean: + rm $(OSDRV_DIR)/out/* -rf + +build_done: + @echo "------- osdrv build done -------" + +clean_done: + @echo "------- clean done -------" + diff --git a/hispark_aries/uboot/out/boot/README b/hispark_aries/uboot/out/boot/README new file mode 100755 index 00000000..e2224da5 --- /dev/null +++ b/hispark_aries/uboot/out/boot/README @@ -0,0 +1,4 @@ +u-boot-hi3518ev300.bin is obtained by compiling u-boot-2020.01 in hi35xx\third_party\uboot and reg_info_hi3518ev300.bin in hi35xx\hi3518ev300\uboot\reg. +u-boot-hi3518ev300.bin complies with the overall protocol of u-boot-2020.01. For details, see the README file in hi35xx\third_party\uboot\u-boot-2020.01\Licenses. +The toolchain used for compiling u-boot-hi3518ev300.bin is the GCC toolchain downloaded from the open-source community. The version is gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2. +For details, visit https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads. diff --git a/hispark_aries/uboot/out/boot/u-boot-hi3518ev300.bin b/hispark_aries/uboot/out/boot/u-boot-hi3518ev300.bin new file mode 100755 index 0000000000000000000000000000000000000000..a917ba76c041732e4b9e24bbce749370839736dd GIT binary patch literal 288623 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

Ou!tZuq4^ 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 r|I?) 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%0AgACx{kOi1O1-)QsU}Cad$NA$GL7#)Q;Q%n*WOO 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 z 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 GU;76;qG06! literal 0 HcmV?d00001 diff --git a/hispark_aries/uboot/secureboot_ohos/sec_os.sh b/hispark_aries/uboot/secureboot_ohos/sec_os.sh new file mode 100755 index 00000000..148caf25 --- /dev/null +++ b/hispark_aries/uboot/secureboot_ohos/sec_os.sh @@ -0,0 +1,259 @@ +#!/bin/bash +# +# Copyright (c) 2020 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -e + +function usage() { + echo ""; + echo "usage:"; + echo " sec_os.sh "; + echo " e.g." + echo " sec_os.sh kernel.bin 0x100000 rootfs.img 0xA00000"; + echo ""; + exit 1; +} + +function dec2hex(){ + printf "0x%08x" $1 +} + +function h2nl() { + local tmp1=$[$1 & 0xff] + local tmp2=$[$[$1 & 0xff00] >> 8] + local tmp3=$[$[$1 & 0xff0000] >> 16] + local tmp4=$[$[$1 & 0xff000000] >> 24] + local val=$[$[$tmp1 << 24] | $[$tmp2 << 16] | $[$tmp3 << 8] | $tmp4] + + echo $val +} + +if [ $# == 0 ] || [ $(($#%2)) != 0 ]; then + usage +fi + +sig_num=$(expr $# / 2) + +# for 2048 +if [ -f rsa_priv_2048.pem ]; then + +if [ -f x509_2048.bin ]; then + rm x509_2048.bin +fi + +#add x509 len +cp x509_creater/rsa_public_key_2048.der rsa_public_key_2048.der +filesize=`wc -c < rsa_public_key_2048.der` + +a=$(($filesize % 16)) +if [ "$a" == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp rsa_public_key_2048.der rsa_public_key_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> rsa_public_key_16byte_alig.bin +done +rm rsa_public_key_2048.der; +filesize=`wc -c < rsa_public_key_16byte_alig.bin` + +# add total length +all_len=0; +all_len=$[filesize+all_len]; +all_len=$[256+all_len]; +all_len=$[12+all_len]; +all_len=$[264*sig_num+all_len]; + +all_len=$(dec2hex $all_len) +all_len=$(h2nl $all_len) +all_len=$(dec2hex $all_len) + +echo $all_len | xxd -r > all_len.txt +cat all_len.txt >>x509_2048.bin +rm all_len.txt + +sig_num_2048=$(dec2hex $sig_num) +sig_num_2048=$(h2nl $sig_num_2048) +sig_num_2048=$(dec2hex $sig_num_2048) +echo $sig_num_2048 | xxd -r > sig_num.txt +cat sig_num.txt >>x509_2048.bin +rm sig_num.txt + +x509_len=$filesize +x509_len=$(dec2hex $x509_len) +x509_len=$(h2nl $x509_len) +x509_len=$(dec2hex $x509_len) +echo $x509_len | xxd -r > x509_len.txt +cat x509_len.txt >>x509_2048.bin +rm x509_len.txt + +cat rsa_public_key_16byte_alig.bin >>x509_2048.bin +rm rsa_public_key_16byte_alig.bin + +#generate the signature +for((i=1;i<=sig_num;i++)) +do + bin_name_num=$(($i * 2 - 1)) + bin_addr_num=$(($i * 2)) + bin_name=${!bin_name_num} + bin_addr=${!bin_addr_num} + bin_addr_head=${bin_addr:0:2} + + if [ "$bin_addr_head" != "0x" ] && [ "$bin_addr_head" != "0X" ]; then + echo "addr err!" + usage + fi + + if [ -f "$bin_name" ]; then + #add signature + openssl dgst -sha256 -sign x509_creater/rsa_private_2048.key -sigopt rsa_padding_mode:pss\ + -sigopt rsa_pss_saltlen:-1 -out {$bin_name}.txt $bin_name + cat {$bin_name}.txt>> x509_2048.bin + rm {$bin_name}.txt + #add length + filesize=`wc -c < $bin_name` + filesize=$(dec2hex $filesize) + filesize=$(h2nl $filesize) + filesize=$(dec2hex $filesize) + echo $filesize | xxd -r > filesize.txt + cat filesize.txt >>x509_2048.bin + rm filesize.txt + #add address + addr=$(dec2hex $bin_addr) + addr=$(h2nl $addr) + addr=$(dec2hex $addr) + echo $addr | xxd -r > addr.txt + cat addr.txt >>x509_2048.bin + rm addr.txt + else + echo "no $bin_name!" + fi +done + +openssl dgst -sha256 -sign rsa_priv_2048.pem -sigopt rsa_padding_mode:pss\ + -sigopt rsa_pss_saltlen:-1 -out cert_sig.bin x509_2048.bin +cat cert_sig.bin >> x509_2048.bin +rm cert_sig.bin + +else + echo "no rsa_priv_2048.pem!" +fi + + +# for 4096 +if [ -f rsa_priv_4096.pem ]; then + +if [ -f x509_4096.bin ]; then + rm x509_4096.bin +fi +cp x509_creater/rsa_public_key_4096.der rsa_public_key_4096.der +#add x509 len +filesize=`wc -c < rsa_public_key_4096.der` +a=$(($filesize % 16)) +if [ "$a" == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp rsa_public_key_4096.der rsa_public_key_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> rsa_public_key_16byte_alig.bin +done +rm rsa_public_key_4096.der +filesize=`wc -c < rsa_public_key_16byte_alig.bin` +# add total length +all_len=0; +all_len=$[filesize+all_len]; +all_len=$[512+all_len]; +all_len=$[12+all_len]; +all_len=$[520*sig_num+all_len]; + +all_len=$(dec2hex $all_len) +all_len=$(h2nl $all_len) +all_len=$(dec2hex $all_len) + +echo $all_len | xxd -r > all_len.txt +cat all_len.txt >>x509_4096.bin +rm all_len.txt + +sig_num_4096=$(dec2hex $sig_num) +sig_num_4096=$(h2nl $sig_num_4096) +sig_num_4096=$(dec2hex $sig_num_4096) +echo $sig_num_4096 | xxd -r > sig_num.txt +cat sig_num.txt >>x509_4096.bin +rm sig_num.txt + +x509_len=$filesize +x509_len=$(dec2hex $x509_len) +x509_len=$(h2nl $x509_len) +x509_len=$(dec2hex $x509_len) +echo $x509_len | xxd -r > x509_len.txt +cat x509_len.txt >>x509_4096.bin +rm x509_len.txt + +cat rsa_public_key_16byte_alig.bin >>x509_4096.bin +rm rsa_public_key_16byte_alig.bin + +#generate the signature +for((i=1;i<=sig_num;i++)) +do + bin_name_num=$(($i * 2 - 1)) + bin_addr_num=$(($i * 2)) + bin_name=${!bin_name_num} + bin_addr=${!bin_addr_num} + bin_addr_head=${bin_addr:0:2} + + if [ "$bin_addr_head" != "0x" ] && [ "$bin_addr_head" != "0X" ]; then + echo "addr err!" + usage + fi + + if [ -f "$bin_name" ]; then + #add signature + openssl dgst -sha256 -sign x509_creater/rsa_private_4096.key -sigopt rsa_padding_mode:pss\ + -sigopt rsa_pss_saltlen:-1 -out {$bin_name}.txt $bin_name + cat {$bin_name}.txt>> x509_4096.bin + rm {$bin_name}.txt + #add length + filesize=`wc -c < $bin_name` + filesize=$(dec2hex $filesize) + filesize=$(h2nl $filesize) + filesize=$(dec2hex $filesize) + echo $filesize | xxd -r > filesize.txt + cat filesize.txt >>x509_4096.bin + rm filesize.txt + #add address + addr=$(dec2hex $bin_addr) + addr=$(h2nl $addr) + addr=$(dec2hex $addr) + echo $addr | xxd -r > addr.txt + cat addr.txt >>x509_4096.bin + rm addr.txt + else + echo "no $bin_name!" + fi +done + +openssl dgst -sha256 -sign rsa_priv_4096.pem -sigopt rsa_padding_mode:pss\ + -sigopt rsa_pss_saltlen:-1 -out cert_sig.bin x509_4096.bin +cat cert_sig.bin >> x509_4096.bin +rm cert_sig.bin + +else + echo "no rsa_priv_4096.pem!" +fi \ No newline at end of file diff --git a/hispark_aries/uboot/secureboot_ohos/x509_creater/creater.sh b/hispark_aries/uboot/secureboot_ohos/x509_creater/creater.sh new file mode 100755 index 00000000..2b84d80d --- /dev/null +++ b/hispark_aries/uboot/secureboot_ohos/x509_creater/creater.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# Copyright (c) 2020 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +set -e + +if [ -f rsa_public_key_2048.der ]; then + echo already have the cert! + else + openssl genrsa -out rsa_private_2048.key 2048 + openssl rsa -in rsa_private_2048.key -pubout -out rsa_public_2048.key + openssl req -new -x509 -sha256 -key rsa_private_2048.key -out ca_2048.crt + openssl x509 -outform der -inform pem -in ca_2048.crt -out rsa_public_key_2048.der +fi + + +if [ -f rsa_public_key_4096.der ]; then + echo already have the cert! + else + openssl genrsa -out rsa_private_4096.key 4096 + openssl rsa -in rsa_private_4096.key -pubout -out rsa_public_4096.key + openssl req -new -x509 -sha256 -key rsa_private_4096.key -out ca_4096.crt + openssl x509 -outform der -inform pem -in ca_4096.crt -out rsa_public_key_4096.der +fi diff --git a/hispark_aries/uboot/secureboot_release/LICENSE b/hispark_aries/uboot/secureboot_release/LICENSE new file mode 100755 index 00000000..d159169d --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/hispark_aries/uboot/secureboot_release/Makefile b/hispark_aries/uboot/secureboot_release/Makefile new file mode 100755 index 00000000..8c938c19 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/Makefile @@ -0,0 +1,36 @@ +.PHONY:all +export SOC + + +SOC := hi3518ev300 + +all:prepare ddrinit rsa2048pem_gen rsa4096pem_gen u-boot-rsa.bin aeskey2reg +#all:prepare rsa2048pem_gen rsa4096pem_gen u-boot-rsa.bin aeskey2reg +prepare: + gcc hash_modify.c -o HASH + gcc aeskey2reg.c -o AES +ddrinit: + pushd ddr_init;make;./mkddrinit.sh u-boot-original.bin;popd + cp ./ddr_init/ddr_init_reg_info.bin ./ + +rsa2048pem_gen: prepare ddrinit +#rsa2048pem_gen: prepare + ./rsa2048pem.sh + +rsa4096pem_gen: prepare ddrinit +#rsa4096pem_gen: prepare + ./rsa4096pem.sh + +u-boot-rsa.bin: prepare ddrinit rsa2048pem_gen rsa4096pem_gen +#u-boot-rsa.bin: prepare rsa2048pem_gen rsa4096pem_gen + ./create_secure_boot.sh + +#aeskey2reg: + ./AES ./create_secure_boot.sh > aes_otp_cfg.txt +clean: + pushd ddr_init;make clean;popd + find . -name "*.bin" -exec rm -rf {} \; +distclean:clean + rm rsa2048pem/* + rm rsa4096pem/* + rm -rf aes_otp_cfg.txt diff --git a/hispark_aries/uboot/secureboot_release/aeskey2reg.c b/hispark_aries/uboot/secureboot_release/aeskey2reg.c new file mode 100755 index 00000000..11b1d6c4 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/aeskey2reg.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MaxCols 80 + +int getlinetxt(FILE *fp,int line,char *stri){ + int i; + fseek(fp,0,0); + for(i=0;i= 0; j--) { + if (j == 3) + printf("mw 0x100900%02x 0x", (i * 4) + 0xc); + printf("%02x", buf[i * 4 + j]); + if (j == 0) + printf("\n"); + } + } + printf("==================================================================================\n"); + + fclose(fp1); + return 0; +} + diff --git a/hispark_aries/uboot/secureboot_release/create_secure_boot.sh b/hispark_aries/uboot/secureboot_release/create_secure_boot.sh new file mode 100755 index 00000000..d99fd352 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/create_secure_boot.sh @@ -0,0 +1,432 @@ +#! /bin/sh + +#If want to decrypt ddr_init.bin,u-boot.bin and their signatures, +#you must to set the KEY and IV for aes, and IV can't be zero; +#otherwise, ddr_init.bin, u-boot.bin and their signatures would +#not be decrypted. + +#The IV and KEY must be used at the same time. + +#The length of IV should be 16 Byte. +IV= + +#The length of KEY should be 32 Byte. +KEY= + +#please set ddr_file uboot_file +ddr_init_file=ddr_init_reg_info.bin +uboot_file=u-boot-original.bin + +echo "please set ddr_init_file/uboot_file !!!" +echo ""; +echo "usage:"; +echo " ddr_init_file = $ddr_init_file"; +echo "" +echo " uboot_file = $uboot_file"; +echo ""; +echo " IV = $IV"; +echo ""; +echo " KEY = $KEY"; +echo ""; + + +dec2hex(){ + printf "0x%08x" $1 +} + +function H_TO_NL { + local tmp1=$[$1 & 0xff] + local tmp2=$[$[$1 & 0xff00] >> 8] + local tmp3=$[$[$1 & 0xff0000] >> 16] + local tmp4=$[$[$1 & 0xff000000] >> 24] + local val=$[$[$tmp1 << 24] | $[$tmp2 << 16] | $[$tmp3 << 8] | $tmp4] + + echo $val +} + +##################2048############################ +if [ -f rsa2048pem/rsa_pub_2048.pem ]; then +echo "....................rsa_2048........................." +#4:RSA_pub +openssl base64 -d -in rsa2048pem/rsa_pub_2048.pem -out private.bin +dd if=./private.bin of=./fb1 bs=1 skip=33 count=256 +for((i=1;i<=253;i++)) +do + echo 0x00 | xxd -r >> fb2 +done +dd if=./private.bin of=./fb3 bs=1 skip=291 count=3 +cat fb1 fb2 fb3 > all.bin +cp all.bin rsa2048pem/rsa_pub_2048.bin +filesize=`wc -c < all.bin` +if [ $filesize == 512 ];then +echo "" +echo 0:RSA_PUB creat OK! +echo RSA_PUB file_size = $filesize +echo "" +else +echo 0:RSA_PUB creat error! +echo RSA_PUB file_size = $filesize +echo "" +fi +rm -f fb1 fb2 fb3 private.bin + +#5:IV +if [ $IV ];then +echo 0x$IV | xxd -r >> all.bin +else +echo 0x00000000000000000000000000000000 | xxd -r >> all.bin +fi + +#6:DDR_len +#1)The ddr image must be filled with 16 bytes. +filesize=`wc -c < $ddr_init_file` +echo "1:The ddr image must be 16-byte aligned!" +echo $ddr_init_file dec_size = $filesize +a=$(($filesize % 16)) +if [ $a == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp $ddr_init_file ddr_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> ddr_16byte_alig.bin +done +filesize=`wc -c < ddr_16byte_alig.bin` +echo ddr_16byte_alig.bin dec_size = $filesize +echo "" +#2)fill iamge len +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r > ddr_len.txt +#big_lit ddr_len.txt +cat ddr_len.txt >> all.bin + +#7:DDR.BIN +cat ddr_16byte_alig.bin >> all.bin + +#8:ddr_sig +openssl dgst -sha256 -sign rsa2048pem/rsa_priv_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out ddr_sig.bin ddr_16byte_alig.bin +if [ -f ddr_sig.bin ]; then +echo 2:creat ddr_sig.bin ok! +echo "" +fi + +cat ddr_sig.bin >> all.bin + +#9:u-boot_len +#1)The boot image must be filled with 16 bytes. +filesize=`wc -c < $uboot_file` +echo "3:The boot image must be 16-byte aligned!" +echo $uboot_file dec_size = $filesize +a=$(($filesize % 16)) +if [ $a == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp $uboot_file uboot_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> uboot_16byte_alig.bin +done +#2)fill iamge len +filesize=`wc -c < uboot_16byte_alig.bin` +filesize=$[filesize] +echo uboot_16byte_alig.bin dec_size = $filesize +echo "" +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r > uboot_len.txt +#big_lit uboot_len.txt +cat uboot_len.txt >> all.bin + +#10:u-boot.bin + uboot_sing.bin +if [ $KEY ]; then +#IV and KEY have set, +#1) Obtain a new KEY by decrypting the ECB mode. +echo 0x50db86c592c52f0c436cca6f2ffecaf5 | xxd -r > seed_1.bin +echo 0x4a96ae013fc60e205e9da4c9d5ad9b99 | xxd -r > seed_2.bin +openssl enc -nopad -d -nosalt -aes-256-ecb -K "$KEY" -in seed_1.bin -out out_1.bin +openssl enc -nopad -d -nosalt -aes-256-ecb -K "$KEY" -in seed_2.bin -out out_2.bin +cat out_2.bin >> out_1.bin +KEY_ecb=$(xxd -ps out_1.bin | sed 'N;s/\n//g') +rm out_*.bin seed_*.bin +echo 4:Obtain a new KEY by decrypting the ECB mode! +echo new_KEY = $KEY_ecb +echo "" +#boot_sig+boot ---->> openssl_cbc ------>> cbc mode boot +#2)boot_sig+boot +openssl dgst -sha256 -sign rsa2048pem/rsa_priv_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out uboot_sig.bin uboot_16byte_alig.bin +if [ -f uboot_sig.bin ];then +echo 5:AES:creat uboot_sig.bin OK! +echo "" +else +echo 5:AES:creat uboot_sig.bin error! +echo "" +fi +cp uboot_16byte_alig.bin u-cbc.bin +cat uboot_sig.bin >> u-cbc.bin +#3) Use the new KEY and IV to encrypt the image in CBC mode. +if [ $IV ];then +openssl enc -aes-256-cbc -nopad -K "$KEY_ecb" -iv "$IV" -in u-cbc.bin -out cbc_boot.bin +else +echo error: please set IV! +fi +cat cbc_boot.bin >> all.bin +rm u-cbc.bin cbc_boot.bin + +else +#If the IV and KEY are not set, use the default image. +#1)boot_bin +cat uboot_16byte_alig.bin >> all.bin +#2):boot_sig +openssl dgst -sha256 -sign rsa2048pem/rsa_priv_2048.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out uboot_sig.bin uboot_16byte_alig.bin +if [ -f uboot_sig.bin ];then +echo 4:RSA:creat uboot_sig.bin OK! +echo "" +else +echo 4:RSA:creat uboot_sig.bin error! +fi +cat uboot_sig.bin >> all.bin +fi + +#1:MAGIC +touch head.txt +val=0x4253424D +val=$(H_TO_NL $val) +val=$(dec2hex $val) +echo $val | xxd -r > head.txt + +#2:TOTAL_LEN +filesize=`wc -c < all.bin` +filesize=$[$filesize+16] +echo all.bin dec_size = $filesize +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r >> head.txt + +#3:RSA2048 +a=0x00000100 +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r >> head.txt +echo $a | xxd -r >> head.txt + +#######big->lit########## +#touch head_e.txt +#Fill in the first 16 bytes of the image. +cat all.bin >> head.txt +cat head.txt > u-boot-rsa2048.bin + +#Gets the hash value of the public KEY +echo Gets the hash value of the public KEY! +dd if=./u-boot-rsa2048.bin of=rsa2048pem/rsa_pub_2048.bin bs=1 skip=16 count=512 +openssl dgst -sha256 -r -hex rsa2048pem/rsa_pub_2048.bin >rsa2048pem/rsa_pub_2048_sha256.txt +./HASH rsa2048pem/rsa_pub_2048_sha256.txt +./HASH rsa2048pem/rsa_pub_2048_sha256.txt > rsa2048pem/rsa2048_pem_hash_val.txt +#clean +rm ddr_16byte_alig.bin uboot_16byte_alig.bin all.bin +rm *.txt *_sig.bin +echo "....................................................." +echo +echo +fi + +################################################## +####################4096########################## +################################################# +if [ -f rsa4096pem/rsa_pub_4096.pem ]; then +echo "....................rsa_4096........................." +#4:RSA_pub +openssl base64 -d -in rsa4096pem/rsa_pub_4096.pem -out private_4096.bin +dd if=./private_4096.bin of=./fb1 bs=1 skip=33 count=512 +for((i=1;i<=509;i++)) +do + echo 0x00 | xxd -r >> fb2 +done +dd if=./private_4096.bin of=./fb3 bs=1 skip=547 count=3 +cat fb1 fb2 fb3 > all.bin + +filesize=`wc -c < all.bin` +if [ $filesize == 1024 ];then + echo "" + echo 0:RSA_PUB creat OK! + echo RSA_PUB file_size = $filesize + echo "" +else + echo 0:RSA_PUB creat error! + echo RSA_PUB file_size = $filesize + echo "" +fi +rm -f fb1 fb2 fb3 private.bin + +#5:IV +if [ $IV ];then +echo 0x$IV | xxd -r >> all.bin +else +echo 0x00000000000000000000000000000000 | xxd -r >> all.bin +fi + +#6:DDR_len +#1)The ddr image must be filled with 16 bytes. +filesize=`wc -c < $ddr_init_file` +echo "1:The ddr image must be 16-byte aligned!" +echo $ddr_init_file dec_size = $filesize +a=$(($filesize % 16)) +if [ $a == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp $ddr_init_file ddr_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> ddr_16byte_alig.bin +done +filesize=`wc -c < ddr_16byte_alig.bin` +echo ddr_16byte_alig.bin dec_size = $filesize +echo "" +#2)fill iamge len +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r > ddr_len.txt +#big_lit ddr_len.txt +cat ddr_len.txt >> all.bin + +#7:DDR.BIN +openssl dgst -sha256 -sign rsa4096pem/rsa_priv_4096.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out ddr_sig.bin ddr_16byte_alig.bin +cat ddr_16byte_alig.bin >> all.bin + +#8:ddr_sig +cat ddr_sig.bin >> all.bin +if [ -f ddr_sig.bin ]; then +echo 2:creat ddr_sig.bin ok! +echo "" +fi + +#9:u-boot_len +#1)The boot image must be filled with 16 bytes. +filesize=`wc -c < $uboot_file` +echo "3:The boot image must be 16-byte aligned!" +echo $uboot_file dec_size = $filesize +a=$(($filesize % 16)) +if [ $a == 0 ];then +b=0 +else +b=$((16-$a)) +fi +cp $uboot_file uboot_16byte_alig.bin +for((i=1;i<=$b;i++)) +do + echo 0x00 | xxd -r >> uboot_16byte_alig.bin +done +#2)fill iamge len +filesize=`wc -c < uboot_16byte_alig.bin` +filesize=$[filesize] +echo uboot_16byte_alig.bin dec_size = $filesize +echo "" +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r > uboot_len.txt +#big_lit uboot_len.txt +cat uboot_len.txt >> all.bin + +#10:u-boot.bin + uboot_sing.bin +if [ $KEY ]; then +#IV and KEY have set, +#1) Obtain a new KEY by decrypting the ECB mode. +echo 0x50db86c592c52f0c436cca6f2ffecaf5 | xxd -r > seed_1.bin +echo 0x4a96ae013fc60e205e9da4c9d5ad9b99 | xxd -r > seed_2.bin +openssl enc -nopad -d -nosalt -aes-256-ecb -K "$KEY" -in seed_1.bin -out out_1.bin +openssl enc -nopad -d -nosalt -aes-256-ecb -K "$KEY" -in seed_2.bin -out out_2.bin +cat out_2.bin >> out_1.bin +KEY_ecb=$(xxd -ps out_1.bin | sed 'N;s/\n//g') +rm out_*.bin seed_*.bin +echo 4:Obtain a new KEY by decrypting the ECB mode! +echo new_KEY = $KEY_ecb +echo "" +#boot_sig+boot ---->> openssl_cbc ------>> cbc mode boot +#2)boot_sig+boot +openssl dgst -sha256 -sign rsa4096pem/rsa_priv_4096.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out uboot_sig.bin uboot_16byte_alig.bin +if [ -f uboot_sig.bin ];then +echo 5:AES:creat uboot_sig.bin OK! +echo "" +else +echo 5:AES:creat uboot_sig.bin error! +echo "" +fi + +cp uboot_16byte_alig.bin u-cbc.bin +cat uboot_sig.bin >> u-cbc.bin +#3) Use the new KEY and IV to encrypt the image in CBC mode. +if [ $IV ];then +openssl enc -aes-256-cbc -nopad -K "$KEY_ecb" -iv "$IV" -in u-cbc.bin -out cbc_boot.bin +fi +cat cbc_boot.bin >> all.bin +rm u-cbc.bin cbc_boot.bin + +else +#If the IV and KEY are not set, use the default image. +#1)boot_bin +cat uboot_16byte_alig.bin >> all.bin +#2):boot_sig +openssl dgst -sha256 -sign rsa4096pem/rsa_priv_4096.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out uboot_sig.bin uboot_16byte_alig.bin +if [ -f uboot_sig.bin ];then +echo 4:RSA:creat uboot_sig.bin OK! +echo "" +else +echo 4:RSA:creat uboot_sig.bin error! +echo "" +fi +cat uboot_sig.bin >> all.bin +fi + +#1:MAGIC +touch head.txt +val=0x4253424D +val=$(H_TO_NL $val) +val=$(dec2hex $val) +echo $val | xxd -r > head.txt + +#2:TOTAL_LEN +filesize=`wc -c < all.bin` +filesize=$[$filesize+16] +echo all.bin dec_size = $filesize +a=$(dec2hex $filesize) +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r >> head.txt + +#3:RSA4096 +a=0x00000200 +a=$(H_TO_NL $a) +a=$(dec2hex $a) +echo $a | xxd -r >> head.txt +echo $a | xxd -r >> head.txt + +#######big->lit########## +#touch head_e.txt +#Fill in the first 16 bytes of the image. +cat all.bin >> head.txt +cat head.txt > u-boot-rsa4096.bin + +#Gets the hash value of the public KEY +echo Gets the hash value of the public KEY! +dd if=./u-boot-rsa4096.bin of=rsa4096pem/rsa_pub_4096.bin bs=1 skip=16 count=1024 +openssl dgst -sha256 -r -hex rsa4096pem/rsa_pub_4096.bin >rsa4096pem/rsa_pub_4096_sha256.txt +./HASH rsa4096pem/rsa_pub_4096_sha256.txt +./HASH rsa4096pem/rsa_pub_4096_sha256.txt > rsa4096pem/rsa4096_pem_hash_val.txt + +#clean +rm ddr_16byte_alig.bin uboot_16byte_alig.bin all.bin +rm *.txt *_sig.bin +echo "....................................................." +fi + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/Makefile b/hispark_aries/uboot/secureboot_release/ddr_init/Makefile new file mode 100755 index 00000000..507b5099 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/Makefile @@ -0,0 +1,59 @@ +include cfg.mk + +export CROSS_COMPILE := $(shell pwd)/../../../../../../../prebuilts/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi- + +export CC := $(CROSS_COMPILE)gcc +export AR := $(CROSS_COMPILE)ar +export RANLIB := $(CROSS_COMPILE)ranlib +export LD := $(CROSS_COMPILE)ld +export OBJCOPY := $(CROSS_COMPILE)objcopy +export OBJDUMP := $(CROSS_COMPILE)objdump + +CSRC = $(wildcard *.c) +SSRC = $(wildcard *.S) + +OBJS := $(patsubst %.c,%.o,$(CSRC) ) +OBJS += $(patsubst %.S,%.o,$(SSRC) ) + +export CFLAGS := -fno-builtin -fno-common +CFLAGS += -Wall -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) +CFLAGS += -I$(PWD)/include/ + +CFLAGS += -march=armv7-a +CFLAGS += -mno-unaligned-access + +CFLAGS += -c + +CFLAGS += -O2 + +TARGET = ddr_init + +LDSCRIPT := linker.lds +LDFLAGS := -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) +LDFLAGS += drv/libdrv.a + +.SILENT: + +default: + make -C drv/ + make -C boot/ + sed -e 's/RAM_BASE/$(RAM_BASE)/' \ + $(LDSCRIPT).mk > $(LDSCRIPT) + + echo " LD $(OBJS) -Map $(TARGET).map -o $(TARGET)" + $(LD) $(OBJS) $(LDFLAGS) -Map $(TARGET).map -o $(TARGET) + $(OBJCOPY) -O binary $(TARGET) $(TARGET).bin + + mkdir -p ./out + $(OBJDUMP) -D $(TARGET) > deasm.s + cp $(TARGET).map ./out + mv deasm.s ./out + +clean: + echo " rm boot/*.o" + make -C boot/ clean + echo " rm drv/*.o libdrv.a" + make -C drv/ clean + echo " rm $(TARGET) $(TARGET).bin* ./out" + rm -rf $(TARGET) $(TARGET).map $(TARGET).bin* ./out + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/Makefile b/hispark_aries/uboot/secureboot_release/ddr_init/boot/Makefile new file mode 100755 index 00000000..dfca6187 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/Makefile @@ -0,0 +1,19 @@ +CSRC = $(wildcard *.c) +SSRC = $(wildcard *.S) + +CFLAGS += -nostdinc +SFLAGS += $(CFLAGS) + +CSRC += $(SOC)/lowlevel_init_v300.c + +#.SILENT: + +default: + echo " CC $(CSRC)" + echo "$(CC) $(CFLAGS) $(CSRC)" + $(CC) $(CFLAGS) $(CSRC) -I ../drv + echo " CC $(SSRC)" + $(CC) $(SFLAGS) $(SSRC) + +clean: + rm *.o *.a -f diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/_udivsi3.S b/hispark_aries/uboot/secureboot_release/ddr_init/boot/_udivsi3.S new file mode 100755 index 00000000..48caa4bf --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/_udivsi3.S @@ -0,0 +1,76 @@ +/* # 1 "libgcc1.S" */ +@ libgcc1 routines for ARM cpu. +@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) +dividend .req r0 +divisor .req r1 +result .req r2 +curbit .req r3 +/* ip .req r12 */ +/* sp .req r13 */ +/* lr .req r14 */ +/* pc .req r15 */ + .text + .globl __udivsi3 + .type __udivsi3 ,function + .globl __aeabi_uidiv + .type __aeabi_uidiv ,function + .align 0 + __udivsi3: + __aeabi_uidiv: + cmp divisor, #0 + beq Ldiv0 + mov curbit, #1 + mov result, #0 + cmp dividend, divisor + bcc Lgot_result +Loop1: + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. + cmp divisor, #0x10000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #4 + movcc curbit, curbit, lsl #4 + bcc Loop1 +Lbignum: + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. + cmp divisor, #0x80000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #1 + movcc curbit, curbit, lsl #1 + bcc Lbignum +Loop3: + @ Test for possible subtractions, and note which bits + @ are done in the result. On the final pass, this may subtract + @ too much from the dividend, but the result will be ok, since the + @ "bit" will have been shifted out at the bottom. + cmp dividend, divisor + subcs dividend, dividend, divisor + orrcs result, result, curbit + cmp dividend, divisor, lsr #1 + subcs dividend, dividend, divisor, lsr #1 + orrcs result, result, curbit, lsr #1 + cmp dividend, divisor, lsr #2 + subcs dividend, dividend, divisor, lsr #2 + orrcs result, result, curbit, lsr #2 + cmp dividend, divisor, lsr #3 + subcs dividend, dividend, divisor, lsr #3 + orrcs result, result, curbit, lsr #3 + cmp dividend, #0 @ Early termination? + movnes curbit, curbit, lsr #4 @ No, any more bits to do? + movne divisor, divisor, lsr #4 + bne Loop3 +Lgot_result: + mov r0, result + mov pc, lr +Ldiv0: + str lr, [sp, #-4]! + bl __div0 (PLT) + mov r0, #0 @ about as wrong as it could be + ldmia sp!, {pc} + .size __udivsi3 , . - __udivsi3 + +__div0: + b . diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/hi3518ev300/lowlevel_init_v300.c b/hispark_aries/uboot/secureboot_release/ddr_init/boot/hi3518ev300/lowlevel_init_v300.c new file mode 100755 index 00000000..e17c1a55 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/hi3518ev300/lowlevel_init_v300.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#include +#include +#include + +static inline void delay(unsigned int num) +{ + volatile unsigned int i; + + for (i = 0; i < (100 * num); i++) { + __asm__ __volatile__("nop"); + } +} + +extern void reset_cpu(unsigned long addr); + +static inline void DWB(void) /* drain write buffer */ +{ +} + +static inline unsigned int readl(unsigned addr) +{ + unsigned int val; + + val = (*(volatile unsigned int *)(addr)); + return val; +} + +static inline void writel(unsigned val, unsigned addr) +{ + DWB(); + (*(volatile unsigned *) (addr)) = (val); + DWB(); +} + +#define REG_BASE_RNG_GEN 0x10090000 +#define TRNG_DSTA_FIFO_DATA_OFST 0x204 +#define TRNG_DATA_ST_OFST 0x208 +#define BIT_TRNG_FIFO_DATA_CNT 0x8 +#define TRNG_FIFO_DATA_CNT_MASK 0xff +#define REG_PERI_CRG104 0x1a0 +#define TRNG_CLK_ENABLE (0x1<<3) +#define TRNG_CLK_DISABLE ~(0x1<<3) +#define TRNG_CTRL_DEF_VAL 0xa +#define HISEC_COM_TRNG_CTRL_OFST 0x200 + +#define REG_BASE_MISC 0x12030000 +#define DDR_CA0_OFST 0x28 +#define DDR_CA1_OFST 0x2C +#define DDR_CA2_OFST 0x30 + +#define REG_BASE_DDRC 0x120d0000 +#define DDRC_CTRL_SREF_OFST (0x8000 + 0x0) +#define DDRC_CFG_DDRMODE_OFST (0x8000 + 0x50) +#define DDRC_CURR_FUNC_OFST (0x8000 + 0x294) + +#define DDRC_CHANNEL_VALID_MASK (0xf) +#define DDRC_SELF_REFURBISH_MASK (0x1) + +#define DDRC_SELF_REFURBISH_EN 0x1 +#define DDRC_SELF_REFURBISH_EXIT (0x1 << 1) + +#undef reg_get +#undef reg_set +#define reg_get(addr) readl(addr) +#define reg_set(addr, val) writel(val, (unsigned int)addr) + +void trng_init(void) +{ + unsigned int reg_val = 0; + /* open rsa and trng clock */ + reg_val = reg_get(CRG_REG_BASE + REG_PERI_CRG104); + reg_val |= TRNG_CLK_ENABLE; + reg_set(CRG_REG_BASE + REG_PERI_CRG104, reg_val); + + /* set trng ctrl register */ + reg_set(REG_BASE_RNG_GEN + HISEC_COM_TRNG_CTRL_OFST, + TRNG_CTRL_DEF_VAL); +} + +void trng_deinit(void) +{ + unsigned int reg_val = 0; + + /* close rsa and trng clock */ + reg_val = reg_get(CRG_REG_BASE + REG_PERI_CRG104); + reg_val &= TRNG_CLK_DISABLE; + reg_set(CRG_REG_BASE + REG_PERI_CRG104, reg_val); + +} + +//svb +#define SVB_VER_18EV300 0x10 + +#define CYCLE_NUM 4 +#define HPM_CORE_REG0 0x120280d8 +#define HPM_CORE_REG1 0x120280dc + +#define PWM0_REG 0X12080000 +#define PWM_REG_OFFSET 0x20 +#define PWM_CFG1 0X04 +#define PWM_CTRL 0X0C + +#define SVB_VER_REG 0x12020168 +#define HPM_CHECK_REG 0x1202015c +#define SYS_CTRL_VOLT_REG 0x12020158 +#define SVB_PWM_SEL 0x1202009c + +#define TSENSOR_STATUS0 0x120280bc +#define OTP_HPM_CORE_REG 0x100a002c + + +static unsigned hpm_value_avg(unsigned int* val) +{ + unsigned int i = 0; + unsigned tmp = 0; + + for (i = 0; i < 4; i++) { + tmp += val[i] >> 2; + } + + return tmp >> 2; +} + +static void get_hpm_value(unsigned int* hpm_core) +{ + int i = 0; + unsigned int temp = 0; + unsigned int core_value[4]; + + core_value[0] = 0; + core_value[1] = 0; + core_value[2] = 0; + core_value[3] = 0; + + for (i = 0; i < CYCLE_NUM; i++) { + //delay(10); + + temp = readl(HPM_CORE_REG0); + core_value[1] += (temp >> 16) & 0x3ff; + core_value[0] += temp & 0x3ff; + temp = readl(HPM_CORE_REG1); + core_value[3] += (temp >> 16) & 0x3ff; + core_value[2] += temp & 0x3ff; + } + + *hpm_core = hpm_value_avg(core_value); +} + +static void start_hpm(unsigned int* hpm_core) +{ + get_hpm_value(hpm_core); +} + +static void hpm_check(unsigned int* hpm_core) +{ + union { + struct { + unsigned int reserved_0 : 16; /* [15..0]*/ + unsigned int sys_hpm_core : 9; /* [24..16]*/ + unsigned int reserved_1 : 1; /* [25]*/ + unsigned int hpm_core_err : 1; /* [26]*/ + unsigned int reserved_2 : 5; /* [27..31]*/ + } bits; + + unsigned int u32; + } sysboot10; + sysboot10.u32 = readl(HPM_CHECK_REG); + sysboot10.bits.sys_hpm_core = 0; + sysboot10.bits.hpm_core_err = 0; + + if(*hpm_core < 150) { + *hpm_core = 150; + sysboot10.bits.hpm_core_err = 1; + } + if(*hpm_core > 350) { + *hpm_core = 350; + sysboot10.bits.hpm_core_err = 1; + } + + sysboot10.bits.sys_hpm_core = *hpm_core; + + writel(sysboot10.u32, HPM_CHECK_REG); + +} + +static void get_temperature(unsigned int *temperature) +{ + unsigned int value = 0; + + value = readl(TSENSOR_STATUS0); + value = value & 0x3ff; + + if (value <= 117) { + *temperature = -40; + } else if (value >= 841) { + *temperature = 110; + } else { + *temperature = (((value - 117) * 212) >> 10) - 40; + } +} + +static void adjust_hpm(unsigned int *hpm_core, unsigned int temperature) +{ + + if ((*hpm_core >= 283) && (temperature >= 70)) { + *hpm_core = *hpm_core + 4 + (((temperature - 70) * 205) >> 10); + } else if ((*hpm_core <= 222) && (temperature >= 70)) { + *hpm_core = *hpm_core - 4; + } else { + } +} + + +//max: 1099 min:654 +//y = 965 , x <= 190 +//y = -1.399x + 1231, 190= 310 + +static void set_hpm_core_volt(unsigned int hpm_core_value, unsigned int pwm_id) +{ + unsigned int volt; + unsigned int duty; + unsigned int otp_vmin_core = readl(OTP_HPM_CORE_REG); + + if(hpm_core_value <= 190) { + volt = 966; + } else if(hpm_core_value >= 310) { + volt = 796; + } else { + volt = 1234 - ((1445 * hpm_core_value) >> 10); + } + + volt = volt + (int)((short int)(otp_vmin_core >> 16)); + + writel(volt, SYS_CTRL_VOLT_REG); + duty = ((unsigned int)((1099 - volt) * 460) >> 10); + writel(duty, PWM0_REG + pwm_id * PWM_REG_OFFSET + PWM_CFG1); + writel(0x5, PWM0_REG + pwm_id * PWM_REG_OFFSET + PWM_CTRL); +} + +void start_svb(void) +{ + unsigned int hpm_core = 0; + unsigned int pwm_id = 0; + unsigned int temperature = 0; + + unsigned int tmp_reg = readl(SVB_VER_REG); + tmp_reg = (tmp_reg & 0xff00ffff) | (SVB_VER_18EV300 << 16); + writel(tmp_reg, SVB_VER_REG); + + get_temperature(&temperature); + start_hpm(&hpm_core); + adjust_hpm(&hpm_core, temperature); + hpm_check(&hpm_core); + + pwm_id = readl(SVB_PWM_SEL) & 0xf; + set_hpm_core_volt(hpm_core, pwm_id); + delay(160); +} + +/* [CUSTOM] DDR PHY0-PHY1 base register */ +#define DDR_REG_BASE_PHY0 0x120dc000 + +/* [CUSTOM] DDR DMC0-DMC3 base register */ +#define DDR_REG_BASE_DMC0 0x120d8000 +#define DDR_REG_BASE_DMC1 0x120d8000 + +#ifdef DDR_REG_BASE_PHY1 +#define DDR_REG_BASE_DMC2 0x120d9000 +#define DDR_REG_BASE_DMC3 0x120d9000 +#endif + +#define CRG_REG_BASE 0x12010000 +#define PERI_CRG_DDRT 0x198 + +#define DDR_REG_BASE_SYSCTRL 0x12020000 +/* [SYSCTRL]RAM Retention control register 0 */ +#define SYSCTRL_MISC_CTRL4 0x8010 + +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ + +#define BYTE_NUM 2 + +/** + * ddr_boot_prepare + * @void + * + * Do some prepare before ddr training. + * Keep empty when nothing to do. + */ +static void ddr_boot_prepare(struct tr_relate_reg *reg) +{ + /* select ddrt bus path */ + reg->custom.ive_ddrt_mst_sel = readl(DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + writel(reg->custom.ive_ddrt_mst_sel & 0xffffffdf, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + + /* turn on ddrt clock */ + reg->custom.ddrt_clk_reg = readl(CRG_REG_BASE + PERI_CRG_DDRT); + /* enable ddrt0 clock */ + writel(reg->custom.ddrt_clk_reg | (0x1 << 1), CRG_REG_BASE + PERI_CRG_DDRT); + __asm__ __volatile__("nop"); + /* disable ddrt0 soft reset */ + writel(readl(CRG_REG_BASE + PERI_CRG_DDRT) & (~(0x1 << 0)), CRG_REG_BASE + PERI_CRG_DDRT); + + /* disable rdqs anti-aging */ + reg->custom.phy0_age_compst_en = readl(DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); + writel((reg->custom.phy0_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); +#ifdef DDR_REG_BASE_PHY1 + reg->custom.phy1_age_compst_en = readl(DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); + writel((reg->custom.phy1_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); +#endif +} + +/** + * ddr_boot_restore + * @void + * + * Restore register config after ddr training. + * Keep empty when nothing to do. + */ +static void ddr_boot_restore(struct tr_relate_reg *reg) +{ + /* restore ddrt bus path */ + writel(reg->custom.ive_ddrt_mst_sel, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + + /* restore ddrt clock */ + writel(reg->custom.ddrt_clk_reg, CRG_REG_BASE + PERI_CRG_DDRT); + + /* restore rdqs anti-aging */ + writel(reg->custom.phy0_age_compst_en, DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); +#ifdef DDR_REG_BASE_PHY1 + writel(reg->custom.phy1_age_compst_en, DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); +#endif +} + +/** + * ddr_rdqs_bdl_adj + * @void + * + * Adjust rdqs/rdq/rdm bdl to avoid problem cause by ddr anti-aging. + */ +static void ddr_rdqs_bdl_adj(void) +{ + int i; + unsigned int rdqs; + unsigned int rdq03, rdq47; + unsigned int rdm; + unsigned int tmp; + + for (i = 0; i < BYTE_NUM; i++) { + rdqs = readl(DDR_REG_BASE_PHY0 + 0x22c + i * 0x80); + rdq03 = readl(DDR_REG_BASE_PHY0 + 0x21c + i * 0x80); + rdq47 = readl(DDR_REG_BASE_PHY0 + 0x220 + i * 0x80); + rdm = readl(DDR_REG_BASE_PHY0 + 0x224 + i * 0x80); + + /* rdqs bdl lower two bit shoud be 0x11 */ + while ((rdqs & 0x3) < 0x3) { + /* rdqs/rdq/rdm bdl + 1 */ + rdqs = rdqs + 0x1; + rdq03 = rdq03 + 0x01010101; + rdq47 = rdq47 + 0x01010101; + rdm = rdm + 0x1; + + writel(rdqs, DDR_REG_BASE_PHY0 + 0x22c + i * 0x80); + writel(rdq03, DDR_REG_BASE_PHY0 + 0x21c + i * 0x80); + writel(rdq47, DDR_REG_BASE_PHY0 + 0x220 + i * 0x80); + writel(rdm, DDR_REG_BASE_PHY0 + 0x224 + i * 0x80); + } + + } + + tmp = readl(DDR_REG_BASE_PHY0 + DDR_PHY_MISC); + tmp |= (1 << PHY_MISC_UPDATE_BIT); + /* update new config to PHY */ + writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_MISC); + tmp &= ~(1 << PHY_MISC_UPDATE_BIT); + writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_MISC); + tmp = readl(DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL); + /* set 1 to issue PHY counter reset signal */ + tmp |= (1 << PHY_PHYCONN_RST_BIT); + writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL); + /* set 0 to end the reset signal */ + tmp &= ~(1 << PHY_PHYCONN_RST_BIT); + writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL); +} + +void start_ddr_training(unsigned int base) +{ + struct tr_relate_reg relate_reg; + struct tr_relate_reg *reg = &relate_reg; + + start_svb(); + + ddr_boot_prepare(reg); + + /* ddr pcode training */ + ddr_pcode_training_if(0); + /* ddr hw training */ + ddr_hw_training_if(0); + /* ddr sw training */ + ddr_sw_training_if(0); + + ddr_rdqs_bdl_adj(); + + ddr_boot_restore(reg); + + /*the value should config after trainning, or + it will cause chip compatibility problems*/ + if ((readl(DDR_REG_BASE_PHY0 + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_MASK) == PHY_DRAMCFG_TYPE_LPDDR4) { + writel(0x401, DDR_REG_BASE_DMC0 + 0x28); + writel(0x401, DDR_REG_BASE_DMC1 + 0x28); + } else { + writel(0x401, DDR_REG_BASE_DMC0 + 0x28); + } +#ifdef DDR_REG_BASE_PHY1 + if ((readl(DDR_REG_BASE_PHY1 + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_MASK) == PHY_DRAMCFG_TYPE_LPDDR4) { + writel(0x401, DDR_REG_BASE_DMC2 + 0x28); + writel(0x401, DDR_REG_BASE_DMC3 + 0x28); + } else { + writel(0x401, DDR_REG_BASE_DMC1 + 0x28); + } +#endif + /* enable ddr scramb */ +} diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/init_regs.c b/hispark_aries/uboot/secureboot_release/ddr_init/boot/init_regs.c new file mode 100755 index 00000000..ac5db006 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/init_regs.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#include + +#define W_WHETHER_WRITE (1<<0) +#define W_WHETHER_PM (1<<1) +#define W_WHETHER_BOOT_NORMAL (1<<2) +#define W_BIT_OFFSET (3) +#define W_BIT_MASK (0x1f<attr&R_REG_BIT_MASK)>>R_REG_BIT_OFFSET); + bit_num_r = ((reg->attr&R_BIT_MASK)>>R_BIT_OFFSET)+1; + reg_val_r = (*(volatile unsigned *) (reg->reg_addr)); + + if (32 != bit_num_r) { + reg_val_r >>= bit_start_r; + reg_val_r &= ((1<value)?0:1); +} + +static inline void reg_write(struct regentry *reg) +{ + unsigned int reg_val_w; + unsigned int delay_2; + unsigned int bit_start_w; + unsigned int bit_num_w; + + delay_2 = reg->delay; + bit_start_w = ((reg->attr&W_REG_BIT_MASK)>>W_REG_BIT_OFFSET); + bit_num_w = ((reg->attr&W_BIT_MASK)>>W_BIT_OFFSET)+1; + reg_val_w = (*(volatile unsigned *) (reg->reg_addr)); + + if (32 == bit_num_w) { + reg_val_w = reg->value; + } else { + reg_val_w &= (~(((1<value)<reg_addr); + + do { + delay(); + } while (delay_2--); +} + +static inline void read_write(struct regentry *reg, unsigned int pm) +{ + unsigned int ret; + unsigned int delay_1; + + ret = 0; + delay_1 = reg->delay; + + if(pm) { + if(reg->attr&W_WHETHER_PM) { + reg_write(reg); + } else if(reg->attr&R_WHETHER_PM) { + do { + reg_read(reg,&ret); + delay(); + } while(ret); + + do { + delay(); + } while (delay_1--); + } else { + do { + delay(); + } while(delay_1--); + } + } else { + if (reg->attr&W_WHETHER_BOOT_NORMAL) { + reg_write(reg); + } else if (reg->attr&R_WHETHER_BOOT_NORMAL) { + do { + reg_read(reg,&ret); + delay(); + } while(ret); + + do { + delay(); + } while(delay_1--); + } else { + do { + delay(); + } while(delay_1--); + } + } +} + +static inline void part_read_write(struct regentry *reg_table, unsigned int pm) +{ + unsigned int i; + + for (i=0; ; i++) { + if ((!reg_table[i].reg_addr) && (!reg_table[i].value) + && (!reg_table[i].delay) && (!reg_table[i].attr)) + goto main_end; + + read_write(®_table[i],pm); + } + +main_end: + delay(); + +} + +/* + * base - reg base address + * pm - is suspend + * 0 normal + * 1 pm + */ +void init_registers(unsigned int base, unsigned int pm) +{ + struct regentry *reg_table = (struct regentry *)base; + + part_read_write(reg_table, pm); +} + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/start.S b/hispark_aries/uboot/secureboot_release/ddr_init/boot/start.S new file mode 100755 index 00000000..187f0421 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/start.S @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + +#include + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + +.globl _start +_start: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +__blank_zone_start: +.fill 1024*8,1,0 +__blank_zone_end: + +.globl _blank_zone_start +_blank_zone_start: +.word __blank_zone_start + + +.globl _blank_zone_end +_blank_zone_end: +.word __blank_zone_end + +.balignl 16,0xdeadbeef + + +_TEXT_BASE: + .word TEXT_BASE + + + /* + * the actual reset code + */ + +reset: + + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + +/************************************************************************* + * + * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless + * CONFIG_SYS_ICACHE_OFF is defined. + * + *************************************************************************/ + /* + * Invalidate L1 I/D + */ + mov r0, #0 @ set up for MCR + 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 BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_ICACHE_OFF + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif + mcr p15, 0, r0, c1, c0, 0 + + /* + * read system register REG_SC_GEN2 + * check if ziju flag + */ + ldr r0, =SYS_CTRL_REG_BASE + mov r1, sp /* save sp */ + str r1, [r0, #REG_SC_GEN2] /* clear ziju flag */ + + /* init PLL/DDRC/pin mux/... */ + ldr r0, _blank_zone_start + ldr r1, _TEXT_BASE + sub r0, r0, r1 + + @ldr r1, =RAM_START_ADRS + ldr sp, =STACK_TRAINING + + adrl r1, _start + add r0, r0, r1 + mov r1, #0x0 /* flags: 0->normal 1->pm */ + bl init_registers /* init PLL/DDRC/... */ + + /* after ziju, we need ddr traning */ + ldr r0, =REG_BASE_SCTL + bl start_ddr_training /* DDR training */ + + ldr r0, =SYS_CTRL_REG_BASE + ldr r1, [r0, #REG_SC_GEN2] + mov sp, r1 /* restore sp */ + ldr r1, [r0, #REG_SC_GEN3] + mov pc, r1 /* return to bootrom */ + nop + nop + nop + nop + nop + nop + nop + nop + b . /* bug here */ + +.global reset_cpu +reset_cpu: + ldr r1, rstctl @ get addr for global reset + @ reg + mov r3, #0x2 @ full reset pll + mpu + str r3, [r1] @ force reset + mov r0, r0 + +_loop_forever: + b _loop_forever +rstctl: + .word 0x12020004 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ +@ void memcpy(r1, r0, r2); +@ +.align 2 +memcpy: + add r2, r0, r2 +memcpy_loop: + ldmia r0!, {r3 - r10} + stmia r1!, {r3 - r10} + cmp r0, r2 + ble memcpy_loop + mov pc, lr + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +.align 2 +msg_main_cpu_startup: + mov r5, lr + add r0, pc, #4 + bl uart_early_puts + mov pc, r5 +L10: +#ifndef CONFIG_SUPPORT_CA_RELEASE + .ascii "\r\n\r\nSystem startup\r\n\0" +#else + .ascii "\r\n\r\n\r\n\0" +#endif + +/* + * exception handlers + */ + .align 5 +undefined_instruction: +software_interrupt: +prefetch_abort: +data_abort: +not_used: +irq: +fiq: + /* reset */ + ldr r1, =REG_BASE_SCTL + ldr r0, =1 + str r0, [r1, #REG_SC_SYSRES] + b . + +/*#include "lowlevel_init.S"*/ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/boot/uart.S b/hispark_aries/uboot/secureboot_release/ddr_init/boot/uart.S new file mode 100755 index 00000000..1b2dbcc3 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/boot/uart.S @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + +#include + +@****************************************************************************** +@ +@ void uart_early_init(void); +@ +.text +.align 2 +.global uart_early_init +.type uart_early_init, %function +uart_early_init: + ldr a4, uart_base_addr_L0 + mov a3, #0 + /* Disable UART */ + str a3, [a4, #48] + /* Set baud rate to 115200, uart clock:24M */ + add a3, a3, #13 + str a3, [a4, #36] + mov a3, #1 + str a3, [a4, #40] + /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. */ + ldr a3, =112 + str a3, [a4, #44] + /* Enable UART */ + ldr a3, =769 + str a3, [a4, #48] + bx lr +uart_base_addr_L0: + .word UART0_REG_BASE + +@****************************************************************************** +@ +@ void uart_early_puts(const char *ss); +@ +.align 2 +.global uart_early_puts +.type uart_early_puts, %function +uart_early_puts: +#if !defined(CONFIG_SUPPORT_CA_RELEASE) + ldr a2, uart_base_addr_L1 + b next_char +output: + ldr a4, [a2, #24] + tst a4, #32 + bne output + str a3, [a2, #0] + add a1, a1, #1 +next_char: + ldrb a3, [a1] + cmp a3, #0 + bne output +#endif /* CONFIG_SUPPORT_CA_RELEASE */ + bx lr +uart_base_addr_L1: + .word UART0_REG_BASE + +@****************************************************************************** +@ +@ void uart_early_put_hex(int hex); +@ +@ call example: +@ mov r0, sp +@ bl uart_early_put_hex +@ +.align 2 +.global uart_early_put_hex +.type uart_early_put_hex, %function +uart_early_put_hex: +#if !defined(CONFIG_SUPPORT_CA_RELEASE) + ldr a2, uart_base_addr_L2 + mov a3, #28 +wait2: + ldr a4, [a2, #24] + tst a4, #32 + bne wait2 + + mov a4, #0xF + and a4, a4, a1, lsr a3 + cmp a4, #9 + addle a4, a4, #0x30 @ a4 = a4 + '0' + addgt a4, a4, #55 @ a4 = a4 - 10 + 'A' + str a4, [a2, #0] + cmp a3, #0 + beq exit2 + sub a3, a3, #4 + b wait2 +exit2: +#endif /* CONFIG_SUPPORT_CA_RELEASE */ + bx lr +uart_base_addr_L2: + .word UART0_REG_BASE + +@****************************************************************************** +@ +@ void uart_early_putc(int chr); +@ +@ call example: +@ mov r0, #'A' +@ bl uart_early_putc +@ +.align 2 +.global uart_early_putc +.type uart_early_putc, %function +uart_early_putc: +#if !defined(CONFIG_SUPPORT_CA_RELEASE) + ldr a2, uart_base_addr_L3 +wait3: + ldr a4, [a2, #24] + tst a4, #32 + bne wait3 + str a1, [a2, #0] + +#endif /* CONFIG_SUPPORT_CA_RELEASE */ + bx lr +uart_base_addr_L3: + .word UART0_REG_BASE diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/cfg.mk b/hispark_aries/uboot/secureboot_release/ddr_init/cfg.mk new file mode 100755 index 00000000..49aaca02 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/cfg.mk @@ -0,0 +1,2 @@ +TEXT_BASE = 0x00000000 +RAM_BASE = 0x04010000 diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/Makefile b/hispark_aries/uboot/secureboot_release/ddr_init/drv/Makefile new file mode 100755 index 00000000..62b12abd --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/Makefile @@ -0,0 +1,20 @@ +CSRC = $(wildcard *.c) +OBJS := $(patsubst %.c,%.o,$(CSRC) ) + +#.SILENT: + +default: libdrv.a + +libdrv.a: $(OBJS) + echo " AR libdrv.a" + $(AR) r libdrv.a $(OBJS) + echo " RL $@" + $(RANLIB) $@ + +.c.o: + echo " CC $<" + $(CC) $(CFLAGS) $< + +clean: + rm *.o *.a -f + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_cmd_loc.S b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_cmd_loc.S new file mode 100755 index 00000000..67559bfa --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_cmd_loc.S @@ -0,0 +1,9 @@ +/* DDR Training command codes location. Copy from DDR to SRAM to train DDR. */ + +.section .image,#alloc + +.globl ddr_training_cmd_start +ddr_training_cmd_start: +.incbin "drivers/ddr/hisilicon/default/cmd_bin/ddr_cmd.bin" +.globl ddr_training_cmd_end +ddr_training_cmd_end: diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v500.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v500.h new file mode 100755 index 00000000..0c21cfa7 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v500.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrc_v500.h + * + * DDRC V500 register define. + */ + + +/******** DMC **************************/ +/* base address: DDR_REG_BASE_DMC0 DDR_REG_BASE_DMC1 */ +/* register offset address */ +#define DDR_DMC_CTRL_SREF 0X0 /* DDRC self-refresh control. */ +#define DDR_DMC_CFG_PD 0x28 /* PowerDown */ +#define DDR_DMC_CFG_DDRMODE 0x50 +#define DDR_DMC_CFG_RNKVOL(n) (0x60 + ((n) << 2)) +#define DDR_DMC_CFG_EMRS01 0x70 +#define DDR_DMC_TIMING2 0x88 +#define DDR_DMC_SFCREQ 0xc +#define DDR_DMC_SFCCMD 0x210 +#define DDR_DMC_SFCADDR 0x214 /* read col and row */ +#define DDR_DMC_SFCBANK 0x218 +#define DDR_DMC_CURR_FUNC 0x294 +#ifndef DDR_DMC_SFC_RDATA0 +#define DDR_DMC_SFC_RDATA0 0x4A8 /* SFC read data[127:96] */ +#endif +#ifndef DDR_DMC_SFC_RDATA1 +#define DDR_DMC_SFC_RDATA1 0x4AC /* SFC read data[95:64] */ +#endif +#ifndef DDR_DMC_SFC_RDATA2 +#define DDR_DMC_SFC_RDATA2 0x4B0 /* SFC read data[63:32] */ +#endif +#ifndef DDR_DMC_SFC_RDATA3 +#define DDR_DMC_SFC_RDATA3 0x4B4 /* SFC read data[31:0] */ +#endif + +/* register mask */ +#define DMC_CMD_MRS_MASK 0xffff +/* storing data bus width. [00]8bit, [01]16bit, [10]32bit, [11]64bit */ +#define DMC_MEM_WIDTH_MASK 0x3 +#define DMC_MRS_MASK 0xffff /* [15:0] Mode Register mask */ +#define DMC_MR0_BL_MASK 0x3 +#define DMC_CFG_DRAM_TYPE_MASK 0x7 /* [2:0]101:DDR2, 110:DDR3, 111:DDR4 */ +#define DMC_CFG_MEM_BG_MASK 0x3 /* [11:10]0:1, 1:2, 2:4 Bank Group */ +#define DMC_CURR_FUNC_IN_SREF_MASK 0x1 +#define DMC_RNKVOL_MEM_BANK_MASK 0x3 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_MASK 0x7 /* [6:4] */ +#define DMC_RNKVOL_MEM_COL_MASK 0x7 /* [2:0] */ + +/* register bit */ +#define DMC_MEM_WIDTH_BIT 4 /* storing data bus width */ +#define DMC_SFC_PRE_DIS_BIT 0 /* ddrcv500 not use */ +/* [CUSTOM] [31:16]config MR when LMR command */ +#define DMC_SFC_CMD_MRS_BIT 16 +#define DMC_SFC_RANK_BIT 4 /* [CUSTOM] [7:4]cmd_rank */ +#define DMC_CFG_MEM_BG_BIT 10 /* [11:10] mem_bankgroup */ +#define DMC_RNKVOL_MEM_BANK_BIT 8 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_BIT 4 /* [6:4] */ + +/* register value */ +#define DMC_BANK_MR1 1 +#define DMC_BANK_MR3 0x3 +#define DMC_CMD_TYPE_LMR 0x2 +#define DMC_CMD_TYPE_READ 0x5 /* read */ +#define DMC_CMD_TYPE_PRECHARGE_ALL 0x6 /* precharge all */ +#define DMC_CMD_MRS_MR3 0x4 /* MR3 = 0x4 */ +#define DMC_CMD_MRS_A7 0x80 +/* value 1 means exexute command. cmd_rank[0] control DDR RANK0 */ +#define DMC_CMD_RANK0 0x1 +#define DMC_MR0_BL_BUST8 0x0 /* BC8 (fixed) */ +#define DMC_MR0_BL_BUST4 0x2 /* BC4 (fixed) */ +#define DMC_AUTO_TIMING_DIS 0xfffff000 /* auto refresh disable */ +#define DMC_POWER_DOWN_DIS 0xfffffffe /* powerDown disable */ +#define DMC_SCRAMB_DIS 0xffffffff /* v500 no scramb */ +#define DMC_CFG_DRAM_TYPE_DDR4 0x7 /* DDR4 */ +#define DMC_CTRL_SREF_ENTER 0x1 /* 1 Enter Auto-self refresh */ +#define DMC_CTRL_SREF_EXIT 0x2 /* 2 Exit Auto-self refresh */ +#define DMC_CFG_MEM_2BG 0x1 /* 2 Bank Group */ + +#ifndef DDR_PHY_NUM +#define DDR_PHY_NUM 1 /* phy number */ +#endif + +#ifndef DDR_DMC_PER_PHY_MAX +#define DDR_DMC_PER_PHY_MAX 1 +#endif + +#ifndef DDR_RANK_NUM +#define DDR_RANK_NUM 1 /* rank number */ +#endif + +#define DMC_SFC_CMD_WRITE(sfc_cmd, addr) \ + ddr_write(sfc_cmd | (DMC_CMD_RANK0 << DMC_SFC_RANK_BIT), addr) +#define DMC_SFC_BANK_WRITE(sfc_bank, addr) ddr_write(sfc_bank, addr) + +#define DMC_MPR_CHECK_BIT_0_127(cfg) \ + ddr_mpr_extract(cfg, \ + DDR_DMC_SFC_RDATA0, DDR_DMC_SFC_RDATA1, \ + DDR_DMC_SFC_RDATA2, DDR_DMC_SFC_RDATA3) +/* ddrcv500 not have [128, 255] */ +#define DMC_MPR_CHECK_BIT_128_255(base_dmc, byte_index, dq_index) 0 + +/* ddrcv500 0x50 not support scramb */ +#define DMC_SAVE_SCRAMB(relate_reg, i, base_dmc) +#define DMC_DISABLE_SCRAMB(relate_reg, i, base_dmc) +#define DMC_RESTORE_SCRAMB(relate_reg, i, base_dmc) +/******** AXI **************************/ +/** + * DMC -- PHY + * / + * DDRT -- AXI + * \ + * DMC -- PHY + */ +/* base address: DDR_REG_BASE_AXI */ +/* register offset address */ +#define DDR_AXI_REGION_ATTRIB0 0x104 /* region 0 */ +#define DDR_AXI_REGION_ATTRIB1 0x114 /* region 1 */ + +/* register mask */ +#define AXI_REGION_ATTRIB_CH_MASK 0xfffffff0 /* channel mask */ + +/* register value */ +/* Map to the single channel, independent address */ +#define AXI_RNG_ATTR_CH_MODE 0x4 +#define AXI_RNG_ATTR_CH_START_0 0x0 +#define AXI_RNG_ATTR_CH_START_1 0x1 + +/********data define************************************/ +struct ddr_ddrc_data { +}; +#define DDR_AXI_SAVE_FUNC(relate_reg) +#define DDR_AXI_RESTORE_FUNC(relate_reg) +#define DDR_AXI_SWITCH_FUNC(cfg) +#define DDR_RNKVOL_SET_FUNC(cfg) +/* ddrc v500 not support two rank */ +#define DDR_RNKVOL_SAVE_FUNC(relate_reg, base_dmc) +#define DDR_RNKVOL_RESTORE_FUNC(relate_reg, base_dmc) + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v510.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v510.h new file mode 100755 index 00000000..177179a6 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v510.h @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrc_v510.h + * + * DDRC V500 register define. + */ + + +/******** DMC **************************/ +/* base address: DDR_REG_BASE_DMC0 DDR_REG_BASE_DMC1 */ +/* register offset address */ +#define DDR_DMC_CTRL_SREF 0X0 /* DDRC self-refresh control. */ +#define DDR_DMC_CFG_SREF 0x20 /* DDRC self-refresh config. */ +#define DDR_DMC_CFG_PD 0x28 /* PowerDown */ +#define DDR_DMC_CFG_DDRMODE 0x50 +#define DDR_DMC_CFG_SCRAMB 0x58 /* DDR scramb config */ +#define DDR_DMC_CFG_RNKVOL(n) (0x60 + ((n) << 2)) +#define DDR_DMC_CFG_EMRS01 0xf0 +#define DDR_DMC_TIMING2 0x108 +#define DDR_DMC_SFCREQ 0xc +#define DDR_DMC_SFCCMD 0x210 +#define DDR_DMC_SFCADDR 0x214 /* read col and row */ +#define DDR_DMC_SFCBANK 0x218 +#define DDR_DMC_CURR_FUNC 0x294 +#ifndef DDR_DMC_SFC_RDATA0 +#define DDR_DMC_SFC_RDATA0 0x4A8 /* SFC read data[31:0] */ +#endif +#ifndef DDR_DMC_SFC_RDATA1 +#define DDR_DMC_SFC_RDATA1 0x4AC /* SFC read data[63:32] */ +#endif +#ifndef DDR_DMC_SFC_RDATA2 +#define DDR_DMC_SFC_RDATA2 0x4B0 /* SFC read data[95:64] */ +#endif +#ifndef DDR_DMC_SFC_RDATA3 +#define DDR_DMC_SFC_RDATA3 0x4B4 /* SFC read data[127:96] */ +#endif +#ifndef DDR_DMC_SFC_RDATA4 +#define DDR_DMC_SFC_RDATA4 0x4B8 /* SFC read data[159:128] */ +#endif +#ifndef DDR_DMC_SFC_RDATA5 +#define DDR_DMC_SFC_RDATA5 0x4BC /* SFC read data[191:160] */ +#endif +#ifndef DDR_DMC_SFC_RDATA6 +#define DDR_DMC_SFC_RDATA6 0x4C0 /* SFC read data[223:192] */ +#endif +#ifndef DDR_DMC_SFC_RDATA7 +#define DDR_DMC_SFC_RDATA7 0x4C4 /* SFC read data[255:224] */ +#endif + +/* register mask */ +#define DMC_CMD_MRS_MASK 0xffff +/* storing data bus width. [00]8bit, [01]16bit, [10]32bit, [11]64bit */ +#define DMC_MEM_WIDTH_MASK 0x3 +#define DMC_MRS_MASK 0xffff /* [15:0] Mode Register mask */ +#define DMC_MR0_BL_MASK 0x3 +#define DMC_CFG_DRAM_TYPE_MASK 0xf /* [3:0]101:DDR2, 110:DDR3, 111:DDR4 */ +#define DMC_CFG_MEM_BG_MASK 0x3 /* [11:10]0:1, 1:2, 2:4 Bank Group */ +#define DMC_CURR_FUNC_IN_SREF_MASK 0x1 +#define DMC_RNKVOL_MEM_BANK_MASK 0x3 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_MASK 0x7 /* [6:4] */ +#define DMC_RNKVOL_MEM_COL_MASK 0x7 /* [2:0] */ + +/* register bit */ +#define DMC_MEM_WIDTH_BIT 4 /* storing data bus width */ +/* [CUSTOM] precharge disable/enable bit */ +#define DMC_SFC_PRE_DIS_BIT 30 +/* [CUSTOM] [29:12]config MR when LMR command */ +#define DMC_SFC_CMD_MRS_BIT 12 +#define DMC_SFC_RANK_BIT 16 /* [CUSTOM] [31:16]sfc_rank */ +#define DMC_CFG_MEM_BG_BIT 10 /* [11:10] mem_bankgroup */ +#define DMC_RNKVOL_MEM_BANK_BIT 8 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_BIT 4 /* [6:4] */ + +/* register value */ +#define DMC_BANK_MR1 1 +#define DMC_BANK_MR3 0x3 +#define DMC_CMD_TYPE_LMR 0x2 +#define DMC_CMD_TYPE_READ 0x5 /* read */ +#define DMC_CMD_TYPE_PRECHARGE_ALL 0x6 /* precharge all */ +#define DMC_CMD_MRS_MR3 0x4 /* MR3 = 0x4 */ +#define DMC_CMD_MRS_A7 0x80 +/* value 1 means exexute command. cmd_rank[0] control DDR RANK0 */ +#define DMC_CMD_RANK0 0x1 +#define DMC_MR0_BL_BUST8 0x0 /* BC8 (fixed) */ +#define DMC_MR0_BL_BUST4 0x2 /* BC4 (fixed) */ +#define DMC_AUTO_TIMING_DIS 0xfffff000 /* auto refresh disable */ +#define DMC_POWER_DOWN_DIS 0xfffffffe /* powerDown disable */ +#define DMC_SCRAMB_DIS 0xffffbfff /* [14] scramb disable */ +/* [4] scramb_seed_type, [2:0] scramb_seed_sort */ +#define DMC_SCRAMB_CFG 0xffffffe8 +#define DMC_CFG_DRAM_TYPE_DDR4 0x7 /* DDR4 */ +#define DMC_CFG_DRAM_TYPE_LPDDR4 0x8 /* LPDDR4 */ +#define DMC_CFG_MEM_2BG 0x1 /* 2 Bank Group */ +#define DMC_CTRL_SREF_ENTER 0x1 /* 1 Enter Auto-self refresh */ +#define DMC_CTRL_SREF_EXIT 0x2 /* 2 Exit Auto-self refresh */ + +#ifndef DDR_PHY_NUM +#define DDR_PHY_NUM 2 /* phy number */ +#endif + +#ifndef DDR_DMC_PER_PHY_MAX +#define DDR_DMC_PER_PHY_MAX 1 +#endif + +#ifndef DDR_RANK_NUM +#define DDR_RANK_NUM 1 /* rank number */ +#endif + +#define DMC_SFC_CMD_WRITE(sfc_cmd, addr) \ + ddr_write(sfc_cmd | (1 << DMC_SFC_PRE_DIS_BIT), addr) +#define DMC_SFC_BANK_WRITE(sfc_bank, addr) \ + ddr_write(sfc_bank | (DMC_CMD_RANK0 << DMC_SFC_RANK_BIT), addr) + +#define DMC_MPR_CHECK_BIT_0_127(cfg) \ + ddr_mpr_extract(cfg, \ + DDR_DMC_SFC_RDATA3, DDR_DMC_SFC_RDATA2, \ + DDR_DMC_SFC_RDATA1, DDR_DMC_SFC_RDATA0) +#define DMC_MPR_CHECK_BIT_128_255(cfg) \ + ddr_mpr_extract(cfg, \ + DDR_DMC_SFC_RDATA7, DDR_DMC_SFC_RDATA6, \ + DDR_DMC_SFC_RDATA5, DDR_DMC_SFC_RDATA4) + +/* dmc scramb */ +#define DMC_SAVE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + relate_reg->dmc_scramb[i] = \ + ddr_read(base_dmc + DDR_DMC_CFG_DDRMODE); \ + relate_reg->dmc_scramb_cfg[i] = \ + ddr_read(base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +#define DMC_DISABLE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + ddr_write(relate_reg->dmc_scramb[i] & DMC_SCRAMB_DIS, \ + base_dmc + DDR_DMC_CFG_DDRMODE); \ + ddr_write(relate_reg->dmc_scramb_cfg[i] & DMC_SCRAMB_CFG, \ + base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +#define DMC_RESTORE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + ddr_write(relate_reg->dmc_scramb[i], \ + base_dmc + DDR_DMC_CFG_DDRMODE); \ + ddr_write(relate_reg->dmc_scramb_cfg[i], \ + base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +/******** AXI **************************/ +/** + * DMC -- PHY + * / + * DDRT -- AXI + * \ + * DMC -- PHY + */ +/* base address: DDR_REG_BASE_AXI */ +/* register offset address */ +#define DDR_AXI_REGION_ATTRIB0 0x104 /* region 0 */ +#define DDR_AXI_REGION_ATTRIB1 0x114 /* region 1 */ + +/* register mask */ +#define AXI_REGION_ATTRIB_CH_MASK 0xfffffff0 /* channel mask */ + +/* register value */ +/* Map to the single channel, independent address */ +#define AXI_RNG_ATTR_CH_MODE 0x4 +#define AXI_RNG_ATTR_CH_START_0 0x0 +#define AXI_RNG_ATTR_CH_START_1 0x1 +#define AXI_RNG_NUM 2 /* region number */ + +/********data define************************************/ +struct ddr_ddrc_data { + unsigned int region_attrib[AXI_RNG_NUM]; +}; + +#define DDR_AXI_SAVE_FUNC(relate_reg) \ + do { \ + relate_reg->ddrc.region_attrib[0] = \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + relate_reg->ddrc.region_attrib[1] = \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + } while (0) + +#define DDR_AXI_RESTORE_FUNC(relate_reg) \ + do { \ + ddr_write(relate_reg->ddrc.region_attrib[0], \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + ddr_write(relate_reg->ddrc.region_attrib[1], \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + } while (0) + +#define DDR_AXI_SWITCH_FUNC(cfg) \ + do { \ + unsigned int ch_start = (cfg->phy_idx == 0 ? \ + AXI_RNG_ATTR_CH_START_0 : AXI_RNG_ATTR_CH_START_1); \ + ddr_write((ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0) \ + & AXI_REGION_ATTRIB_CH_MASK) \ + | AXI_RNG_ATTR_CH_MODE | ch_start, \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + ddr_write((ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1) \ + & AXI_REGION_ATTRIB_CH_MASK) \ + | AXI_RNG_ATTR_CH_MODE | ch_start, \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + } while (0) + +#define DDR_RNKVOL_SET_FUNC(cfg) + +/* ddrc v510 not support two rank */ +#define DDR_RNKVOL_SAVE_FUNC(relate_reg, base_dmc) +#define DDR_RNKVOL_RESTORE_FUNC(relate_reg, base_dmc) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v520.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v520.h new file mode 100755 index 00000000..d4b077e1 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrc_v520.h @@ -0,0 +1,246 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrc_v520.h + * + * DDRC V500 register define. + */ + + +/******** DMC **************************/ +/* base address: DDR_REG_BASE_DMC0 DDR_REG_BASE_DMC1 */ +/* register offset address */ +#define DDR_DMC_CTRL_SREF 0X0 /* DDRC self-refresh control. */ +#define DDR_DMC_CFG_SREF 0x20 /* DDRC self-refresh config. */ +#define DDR_DMC_CFG_PD 0x28 /* PowerDown */ +#define DDR_DMC_CFG_DDRMODE 0x50 +#define DDR_DMC_CFG_SCRAMB 0x58 /* DDR scramb config */ +#define DDR_DMC_CFG_RNKVOL(n) (0x60 + ((n) << 2)) +#define DDR_DMC_CFG_EMRS01 0xf0 +#define DDR_DMC_TIMING2 0x108 +#define DDR_DMC_SFCREQ 0xc +#define DDR_DMC_SFCCMD 0x210 +#define DDR_DMC_SFCADDR 0x214 /* read col and row */ +#define DDR_DMC_SFCBANK 0x218 +#define DDR_DMC_CURR_FUNC 0x294 +#ifndef DDR_DMC_SFC_RDATA0 +#define DDR_DMC_SFC_RDATA0 0x4A8 /* SFC read data[31:0] */ +#endif +#ifndef DDR_DMC_SFC_RDATA1 +#define DDR_DMC_SFC_RDATA1 0x4AC /* SFC read data[63:32] */ +#endif +#ifndef DDR_DMC_SFC_RDATA2 +#define DDR_DMC_SFC_RDATA2 0x4B0 /* SFC read data[95:64] */ +#endif +#ifndef DDR_DMC_SFC_RDATA3 +#define DDR_DMC_SFC_RDATA3 0x4B4 /* SFC read data[127:96] */ +#endif +#ifndef DDR_DMC_SFC_RDATA4 +#define DDR_DMC_SFC_RDATA4 0x4B8 /* SFC read data[159:128] */ +#endif +#ifndef DDR_DMC_SFC_RDATA5 +#define DDR_DMC_SFC_RDATA5 0x4BC /* SFC read data[191:160] */ +#endif +#ifndef DDR_DMC_SFC_RDATA6 +#define DDR_DMC_SFC_RDATA6 0x4C0 /* SFC read data[223:192] */ +#endif +#ifndef DDR_DMC_SFC_RDATA7 +#define DDR_DMC_SFC_RDATA7 0x4C4 /* SFC read data[255:224] */ +#endif + +/* register mask */ +#define DMC_CMD_MRS_MASK 0xffff +/* storing data bus width. [00]8bit, [01]16bit, [10]32bit, [11]64bit */ +#define DMC_MEM_WIDTH_MASK 0x3 +#define DMC_MRS_MASK 0xffff /* [15:0] Mode Register mask */ +#define DMC_MR0_BL_MASK 0x3 +#define DMC_CFG_DRAM_TYPE_MASK 0xf /* [3:0]101:DDR2, 110:DDR3, 111:DDR4 */ +#define DMC_CFG_MEM_BG_MASK 0x3 /* [11:10]0:1, 1:2, 2:4 Bank Group */ +#define DMC_CURR_FUNC_IN_SREF_MASK 0x1 +#define DMC_RNKVOL_MEM_BANK_MASK 0x3 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_MASK 0x7 /* [6:4] */ +#define DMC_RNKVOL_MEM_COL_MASK 0x7 /* [2:0] */ +#define DMC_CFG_INIT_XSREF_PD_MASK 0xc /* [3:2] */ + +/* register bit */ +#define DMC_MEM_WIDTH_BIT 4 /* storing data bus width */ +/* [CUSTOM] precharge disable/enable bit */ +#define DMC_SFC_PRE_DIS_BIT 30 +/* [CUSTOM] [29:12]config MR when LMR command */ +#define DMC_SFC_CMD_MRS_BIT 12 +#define DMC_SFC_RANK_BIT 16 /* [CUSTOM] [31:16]sfc_rank */ +#define DMC_CFG_MEM_BG_BIT 10 /* [11:10] mem_bankgroup */ +#define DMC_RNKVOL_MEM_BANK_BIT 8 /* [9:8] */ +#define DMC_RNKVOL_MEM_ROW_BIT 4 /* [6:4] */ + + +/* register value */ +#define DMC_BANK_MR1 1 +#define DMC_BANK_MR3 0x3 +#define DMC_CMD_TYPE_LMR 0x2 +#define DMC_CMD_TYPE_READ 0x5 /* read */ +#define DMC_CMD_TYPE_PRECHARGE_ALL 0x6 /* precharge all */ +#define DMC_CMD_MRS_MR3 0x4 /* MR3 = 0x4 */ +#define DMC_CMD_MRS_A7 0x80 +/* value 1 means exexute command. cmd_rank[0] control DDR RANK0 */ +#define DMC_CMD_RANK0 0x1 +#define DMC_MR0_BL_BUST8 0x0 /* BC8 (fixed) */ +#define DMC_MR0_BL_BUST4 0x2 /* BC4 (fixed) */ +#define DMC_AUTO_TIMING_DIS 0xfffff000 /* auto refresh disable */ +#define DMC_POWER_DOWN_DIS 0xfffffffe /* powerDown disable */ +#define DMC_SCRAMB_DIS 0xffffbfff /* [14] scramb disable */ +/* [4] scramb_seed_type, [2:0] scramb_seed_sort */ +#define DMC_SCRAMB_CFG 0xffffffe8 +#define DMC_CFG_DRAM_TYPE_DDR4 0x7 /* DDR4 */ +#define DMC_CFG_DRAM_TYPE_LPDDR4 0x8 /* LPDDR4 */ +#define DMC_CFG_MEM_2BG 0x1 /* 2 Bank Group */ +#define DMC_CFG_INIT_XSREF_PD 0xc /* LPDDR4:Exit Auto-self refresh enter powerdown */ +#define DMC_CTRL_SREF_ENTER 0x1 /* 1 Enter Auto-self refresh */ +#define DMC_CTRL_SREF_EXIT 0x2 /* 2 Exit Auto-self refresh */ +#define DMC_RNKVOL_MEM_ROW_11 0x0 /* 000: 11 bit */ + +#ifndef DDR_PHY_NUM +#define DDR_PHY_NUM 2 /* phy number */ +#endif + +#ifndef DDR_DMC_PER_PHY_MAX +#define DDR_DMC_PER_PHY_MAX 2 +#endif + +#ifndef DDR_AXI_SWITCH_NUM +#define DDR_AXI_SWITCH_NUM 4 /* ddr training axi switch number */ +#endif + +#ifndef DDR_RANK_NUM +#define DDR_RANK_NUM 2 /* rank number */ +#endif + +#define DMC_SFC_CMD_WRITE(sfc_cmd, addr) \ + ddr_write(sfc_cmd | (1 << DMC_SFC_PRE_DIS_BIT), addr) +#define DMC_SFC_BANK_WRITE(sfc_bank, addr) \ + ddr_write(sfc_bank | (DMC_CMD_RANK0 << DMC_SFC_RANK_BIT), addr) + +#define DMC_MPR_CHECK_BIT_0_127(cfg) \ + ddr_mpr_extract(cfg, \ + DDR_DMC_SFC_RDATA3, DDR_DMC_SFC_RDATA2, \ + DDR_DMC_SFC_RDATA1, DDR_DMC_SFC_RDATA0) +#define DMC_MPR_CHECK_BIT_128_255(cfg) \ + ddr_mpr_extract(cfg, \ + DDR_DMC_SFC_RDATA7, DDR_DMC_SFC_RDATA6, \ + DDR_DMC_SFC_RDATA5, DDR_DMC_SFC_RDATA4) + +/* dmc scramb */ +#define DMC_SAVE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + relate_reg->dmc_scramb[i] = \ + ddr_read(base_dmc + DDR_DMC_CFG_DDRMODE); \ + relate_reg->dmc_scramb_cfg[i] = \ + ddr_read(base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +#define DMC_DISABLE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + ddr_write(relate_reg->dmc_scramb[i] & DMC_SCRAMB_DIS, \ + base_dmc + DDR_DMC_CFG_DDRMODE); \ + ddr_write(relate_reg->dmc_scramb_cfg[i] & DMC_SCRAMB_CFG, \ + base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +#define DMC_RESTORE_SCRAMB(relate_reg, i, base_dmc) \ + do { \ + ddr_write(relate_reg->dmc_scramb[i], \ + base_dmc + DDR_DMC_CFG_DDRMODE); \ + ddr_write(relate_reg->dmc_scramb_cfg[i], \ + base_dmc + DDR_DMC_CFG_SCRAMB); \ + } while (0) + +/******** AXI **************************/ +/** + * DMC -- PHY + * / + * DDRT -- AXI + * \ + * DMC -- PHY + */ +/* base address: DDR_REG_BASE_AXI */ +/* register offset address */ +#define DDR_AXI_REGION_ATTRIB0 0x104 /* region 0 */ +#define DDR_AXI_REGION_ATTRIB1 0x114 /* region 1 */ + +/* register mask */ +#define AXI_REGION_ATTRIB_CH_MASK 0xfffffff0 /* channel mask */ + +/* register value */ +/* Map to the single channel, independent address */ +#define AXI_RNG_ATTR_CH_MODE 0x4 +#define AXI_RNG_ATTR_CH_START_0 0x0 +#define AXI_RNG_ATTR_CH_START_1 0x1 +#define AXI_RNG_ATTR_CH_START_2 0x2 +#define AXI_RNG_ATTR_CH_START_3 0x3 +#define AXI_RNG_NUM 2 /* region number */ + +/********data define************************************/ +struct ddr_ddrc_data { + unsigned int region_attrib[AXI_RNG_NUM]; + unsigned int rnkvol; +}; + +#define DDR_AXI_SAVE_FUNC(relate_reg) \ + do { \ + relate_reg->ddrc.region_attrib[0] = \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + relate_reg->ddrc.region_attrib[1] = \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + } while (0) + +#define DDR_AXI_RESTORE_FUNC(relate_reg) \ + do { \ + ddr_write(relate_reg->ddrc.region_attrib[0], \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + ddr_write(relate_reg->ddrc.region_attrib[1], \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + } while (0) + +/* +ch_start value: +#define AXI_RNG_ATTR_CH_START_0 0x0 +#define AXI_RNG_ATTR_CH_START_1 0x1 +#define AXI_RNG_ATTR_CH_START_2 0x2 +#define AXI_RNG_ATTR_CH_START_3 0x3 + */ +#define DDR_AXI_SWITCH_FUNC(cfg) \ + do { \ + unsigned int ch_start = cfg->phy_idx; \ + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) \ + ch_start = (cfg->phy_idx << 1) + cfg->dmc_idx; \ + ddr_write((ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0) \ + & AXI_REGION_ATTRIB_CH_MASK) \ + | AXI_RNG_ATTR_CH_MODE | ch_start, \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0); \ + ddr_write((ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1) \ + & AXI_REGION_ATTRIB_CH_MASK) \ + | AXI_RNG_ATTR_CH_MODE | ch_start, \ + DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1); \ + DDR_DEBUG("AXI region0[%x = %x]", \ + (DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0), \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB0)); \ + DDR_DEBUG("AXI region1[%x = %x]", \ + (DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1), \ + ddr_read(DDR_REG_BASE_AXI + DDR_AXI_REGION_ATTRIB1)); \ + } while (0) + +/* save rank0 for ddrt address */ +#define DDR_RNKVOL_SAVE_FUNC(relate_reg, base_dmc) \ + relate_reg->ddrc.rnkvol = ddr_read(base_dmc + DDR_DMC_CFG_RNKVOL(0)); + +#define DDR_RNKVOL_RESTORE_FUNC(relate_reg, base_dmc) \ + ddr_write(relate_reg->ddrc.rnkvol, base_dmc + DDR_DMC_CFG_RNKVOL(0)); + +/* set mem_row to 0 */ +#define DDR_RNKVOL_SET_FUNC(cfg) \ + do { \ + if (1 == cfg->rank_idx) { \ + ddr_write(ddr_read(cfg->cur_dmc + DDR_DMC_CFG_RNKVOL(0)) & (~DMC_RNKVOL_MEM_ROW_MASK), cfg->cur_dmc + DDR_DMC_CFG_RNKVOL(0)); \ + } \ + } while (0) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_s40.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_s40.h new file mode 100755 index 00000000..754544d6 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_s40.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_s40.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0xf /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) (addr) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t12_v100.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t12_v100.h new file mode 100755 index 00000000..408dbf93 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t12_v100.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_t12_v100.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0x7f /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) ((addr)>>2) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t16.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t16.h new file mode 100755 index 00000000..0075fc30 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t16.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_t16.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0xf /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) ((addr)>>2) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t28.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t28.h new file mode 100755 index 00000000..5437d4a2 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_t28.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_t28.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0xf /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) (addr) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf0.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf0.h new file mode 100755 index 00000000..254da0bb --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf0.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_v2_0_shf0.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0x7f /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) (addr) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf1.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf1.h new file mode 100755 index 00000000..60d2b4a2 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf1.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_v2_0_shf1.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0x7f /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) ((addr)>>1) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf2.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf2.h new file mode 100755 index 00000000..9a4e0304 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_ddrt_v2_0_shf2.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_ddrt_v2_0_shf2.h + * + * DDRT register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_DDRT */ +#define DDRT_OP 0x0 /* DDRT operation config */ +#define DDRT_STATUS 0x4 /* DDRT status indicating */ +#define DDRT_BURST_CONFIG 0x8 /* DDRT burst transfer config */ +#define DDRT_MEM_CONFIG 0xc /* DDRT SDRAM config */ +#define DDRT_BURST_NUM 0x10 /* DDRT burst number config */ +/* DDRT burst number config register while testing address */ +#define DDRT_ADDR_NUM 0x14 +#define DDRT_LOOP_NUM 0x18 /* DDRT loop number config */ +/* This register specified the system DDR starting address */ +#define DDRT_DDR_BASE_ADDR 0x1c +#define DDRT_ADDR 0x20 /* DDRT test start address config */ +#define DDRT_REVERSED_DQ 0x30 /* DDRT reversed DQ indicating */ +#define DDRT_SEED 0x38 /* DDRT starting random seed */ +#define DDRT_KDATA 0x3c /* DDRT kdata config */ +#define DDRT_DATA0 0x40 /* DDRT PRBS7 data config register0 */ +#define DDRT_DATA1 0x44 /* DDRT PRBS7 data config register1 */ +#define DDRT_DATA2 0x48 /* DDRT PRBS7 data config register2 */ +#define DDRT_DATA3 0x4c /* DDRT PRBS7 data config register3 */ + +/* DQ3~DQ0 error number indicator, every 8bit for each DQ */ +#define DDRT_DQ_ERR_CNT(n) (0x60 + ((n) << 2)) +/* DQ31~DQ0 error number overflow indicator, every bit for each DQ. */ +#define DDRT_DQ_ERR_OVFL 0x80 + +/* register mask */ +#define DDRT_TEST_MODE_MASK 0x300 /* DDRT Test Mode */ +#define DDRT_TEST_DONE_MASK 0x1 /* [0] DDRT operation finish signal.*/ +/* [1] DDRT Test result indicator. No error occurred, test pass. */ +#define DDRT_TEST_PASS_MASK 0x2 + +/* register bit */ +#define DDRT_DDR_MEM_WIDTH 12 /* SDRAM total width */ + +/* register value */ +#define DDRT_CFG_START 0x1 +#define DDRT_CFG_BURST_CFG_DATAEYE 0x4f +#define DDRT_CFG_BURST_CFG_GATE 0x43 +#ifdef CFG_EDA_VERIFY +#define DDRT_CFG_BURST_NUM 0x5 /* ddrt test number */ +#else +#define DDRT_CFG_BURST_NUM 0x7f /* ddrt test number */ +#endif +#define DDRT_CFG_SEED 0x6d6d6d6d +#define DDRT_CFG_REVERSED 0x55aa55aa +#ifndef DDRT_CFG_BASE_ADDR +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x0 +#endif +/* [CUSTOM] DDRT test address. 0x800000 = 8M */ +#define DDRT_CFG_TEST_ADDR_CMD (DDRT_CFG_BASE_ADDR + 0x800000) +/* [CUSTOM] DDRT test start address. */ +#define DDRT_CFG_TEST_ADDR_BOOT DDRT_CFG_BASE_ADDR +#define DDRT_CFG_ADDR_NUM 0xffffffff +#define DDRT_CFG_LOOP_NUM 0x0 + +/* [2:0]000:8 bit; 001:9 bit; 010:10 bit; 011:11 bit; 100:12 bit. +single SDRAM column number.*/ +#define DDRT_DDR_COL_WIDTH 0x2 +/* [6:4]000:11 bit; 001:12 bit; 010:13 bit; 011:14 bit; 100:15 bit; 101:16 bit. +single SDRAM row number */ +#define DDRT_DDR_ROW_WIDTH 0x50 +/* [8]0:4 Bank; 1:8 Bank. single SDRAM bank number */ +#define DDRT_DDR_BANK_WIDTH 0x100 + + +#define DDRT_WR_COMPRARE_MODE (0<<8) /* Write read & compare mode */ +#define DDRT_WRITE_ONLY_MODE (1<<8) /* Write only mode */ +#define DDRT_READ_ONLY_MODE (2<<8) /* Read only mode */ +#define DDRT_RANDOM_WR_MODE (3<<8) /* Random write & read mode */ + +#define DDRT_PATTERM_PRBS9 (0<<12) +#define DDRT_PATTERM_PRBS7 (1<<12) +#define DDRT_PATTERM_PRBS11 (2<<12) +#define DDRT_PATTERM_K28_5 (3<<12) + +/* other */ +#define DDRT_WAIT_TIMEOUT (1000000) +#define DDRT_READ_TIMEOUT (20) +#define DDRT_PCODE_WAIT_TIMEOUT (100000) + +/* DDRT test DDR using space */ +#define DDRT_GET_TEST_ADDR(addr) ((addr)>>2) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_interface.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_interface.h new file mode 100755 index 00000000..2bd04e36 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_interface.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#ifndef DDR_INTERFACE_H +#define DDR_INTERFACE_H + +#define DDR_PHY_BYTE_MAX 4 +#define DDR_PHY_BIT_NUM 8 +/* support max bit 32*/ +#define DDR_PHY_BIT_MAX (DDR_PHY_BYTE_MAX * DDR_PHY_BIT_NUM) + +#define DDR_REG_NAME_MAX 32 /* register name */ +#define DDR_CA_ADDR_MAX 10 + +#define DDR_SUPPORT_PHY_MAX 2 /* support max phy number */ +#define DDR_SUPPORT_RANK_MAX 2 /* support max rank number */ +#define DDR_SUPPORT_DMC_MAX 4 /* support max dmc number */ +#define DDR_CK_RESULT_MAX 2 /* DCC CK result number */ + + +/** + * DDR training register number: + * WDQS 4 + * WDQ Phase 4 + * WDQ BDL 8 + * WDM 4 + * Write DQ/DQS OE 4 + * RDQS 4 + * RDQ BDL 8 + * Gate 4 + * CS 1 + * CLK 1 + * Host Vref 4 + * DRAM Vref 4 + * CA Phase 1 + * CA BDL 5 + * ------------------- + * 60 + */ +#define DDR_TRAINING_REG_NUM 60 +/* register max. */ +#define DDR_TRAINING_REG_MAX (DDR_TRAINING_REG_NUM * DDR_SUPPORT_PHY_MAX) + +#define DDR_TRAINING_CMD_SW (1 << 0) +#define DDR_TRAINING_CMD_HW (1 << 1) +#define DDR_TRAINING_CMD_MPR (1 << 2) +#define DDR_TRAINING_CMD_WL (1 << 3) +#define DDR_TRAINING_CMD_GATE (1 << 4) +#define DDR_TRAINING_CMD_DATAEYE (1 << 5) +#define DDR_TRAINING_CMD_VREF (1 << 6) +#define DDR_TRAINING_CMD_AC (1 << 7) +#define DDR_TRAINING_CMD_LPCA (1 << 8) +#define DDR_TRAINING_CMD_SW_NO_WL (1 << 9) +#define DDR_TRAINING_CMD_CONSOLE (1 << 10) +#define DDR_TRAINING_CMD_DCC (1 << 11) +#define DDR_TRAINING_CMD_PCODE (1 << 12) + +/*******log level ********************/ +#define DDR_LOG_INFO_STR "info" +#define DDR_LOG_DEBUG_STR "debug" +#define DDR_LOG_WARNING_STR "warning" +#define DDR_LOG_ERROR_STR "error" +#define DDR_LOG_FATAL_STR "fatal" + +#define DDR_LOG_INFO (1 << 0) +#define DDR_LOG_DEBUG (1 << 1) +#define DDR_LOG_WARNING (1 << 2) +#define DDR_LOG_ERROR (1 << 3) +#define DDR_LOG_FATAL (1 << 4) + +#define DDR_TRAINING_BOOT_RESULT_ADDR (TEXT_BASE + 0x1000000) /* boot + 16M */ + +#define DDR_TRAINING_VER "V2.1.6 20181228" +#define DDR_VERSION 0x216 +struct training_data { + unsigned int ddr_bit_result[DDR_PHY_BIT_MAX]; + unsigned int ddr_bit_best[DDR_PHY_BIT_MAX]; + unsigned int ddr_win_sum; +}; + +struct ddr_training_data_st { + unsigned int base_phy; + unsigned int byte_num; + unsigned int rank_idx; + struct training_data read; + struct training_data write; + unsigned int ca_addr[DDR_CA_ADDR_MAX]; +}; + +struct rank_data_st { + unsigned int item; + struct ddr_training_data_st ddrtr_data; +}; + +struct phy_data_st { + unsigned int rank_num; + struct rank_data_st rank_st[DDR_SUPPORT_RANK_MAX]; +}; + +struct ddr_training_result_st { + unsigned int phy_num; + struct phy_data_st phy_st[DDR_SUPPORT_PHY_MAX]; +}; + +struct ddr_reg_val_st { + unsigned int rank_index; + unsigned int byte_index; + unsigned int offset; + unsigned int val; + char name[DDR_REG_NAME_MAX]; +}; + +struct ddr_cmd_st { + unsigned int cmd; + unsigned int level; + unsigned int start; + unsigned int length; +}; + +typedef struct ddr_training_result_st * (*ddr_cmd_entry_func) + (struct ddr_cmd_st *cmd_st); + +/* DDR training interface before boot */ +int ddr_pcode_training_if(void *ddrtr_result); +int ddr_sw_training_if(void *ddrtr_result); +int ddr_hw_training_if(void *ddr_hw); +int ddr_training_console_if(void *args); + +/* DDR training check interface when boot */ +struct ddr_training_result_st *ddr_cmd_training_if(struct ddr_cmd_st *cmd_st); +int check_ddr_training(void); + +/* DDR training command interface after boot */ +void ddr_reg_result_display(struct ddr_training_result_st *ddrtr_result); +void ddr_cmd_result_display(struct ddr_training_result_st *ddrtr_result, + unsigned int cmd); +void *ddr_cmd_get_entry(void); +void ddr_cmd_prepare_copy(void); +void ddr_cmd_site_save(void); +void ddr_cmd_site_restore(void); + +#endif /* DDR_INTERFACE_H */ + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_s40.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_s40.h new file mode 100755 index 00000000..6855dcdd --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_s40.h @@ -0,0 +1,303 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +/* register offset address */ +/* base address: DDR_REG_BASE_PHY0 DDR_REG_BASE_PHY1 */ +/* control the initialization of the PHY */ +#define DDR_PHY_PHYINITCTRL 0x4 +#define DDR_PHY_PHYINITSTATUS 0x8 /* Read Data Eye Calibration Error*/ +#define DDR_PHY_IMPSTATUS 0x28 /* This register specify the ZQ calibration result. */ +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define DDR_PHY_MODEREG01 0x64 /* Extend Mode Register 01 */ +#define DDR_PHY_MODEREG23 0x68 /* Extend Mode Register 23 */ +/* update delay setting in registers to PHY */ +#define DDR_PHY_MISC 0x70 +#define DDR_PHY_SWTMODE 0xa0 /* S/W training mode */ +/* issue one DQS pulse from PHY to DRAM */ +#define DDR_PHY_SWTWLDQS 0xa4 +#define DDR_PHY_SWTRLT 0xa8 /* S/W training result*/ +/* Host vref. [5:0]range [17:12]refsel */ +#define DDR_PHY_IOCTL2 0xB4 +#define DDR_PHY_VREFTCTRL 0xc0 /* VREF Training Control Register. */ +#define DDR_PHY_DVRFTCTRL 0xC4 /* DRAM VREF Training */ +/* AC command bit delay line setting */ +#define DDR_PHY_ACCMDBDL2 0x128 +#define DDR_PHY_IMP_CTRL1 0x170 /* AC/DX ZQ selection */ +#define DDR_PHY_IMP_STATUS1 0x174 /* AC ZCAL status */ +#define DDR_PHY_ACPHYCTL4 0x180 /* AC block PHY control register*/ +/* AC block PHY control register */ +#define DDR_PHY_ACPHYCTL7 0x18C + +/* WR DQ0-DQ3 [4:0] [12:8] [20:16] [28:24] delay value of the bit delay line + on write path */ +#define DDR_PHY_DXNWDQNBDL0(m, n) (0x210 + ((m) << 10) + ((n) << 7)) +/* WR DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] */ +#define DDR_PHY_DXNWDQNBDL1(m, n) (0x214 + ((m) << 10) + ((n) << 7)) +/* WR DM [6:0] the delay value of the bit delay line on DQM */ +#define DDR_PHY_DXNWDQNBDL2(m, n) (0x218 + ((m) << 10) + ((n) << 7)) +/* RD DQ0-DQ3 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL0(m, n) (0x21C + ((m) << 10) + ((n) << 7)) +/* RD DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL1(m, n) (0x220 + ((m) << 10) + ((n) << 7)) +/* [6:0]RD DM*/ +#define DDR_PHY_DXNRDQNBDL2(m, n) (0x224 + ((m) << 10) + ((n) << 7)) + + +/* [CUSTOM] */ +#define DDR_PHY_DXNOEBDL(m, n) (0x228 + ((m) << 10) + ((n) << 7)) +/* [8:0] rdqs_bdl [24:16]rdqs_cyc. +phase shift of the Read DQS to create 90 degree delays*/ +#define DDR_PHY_DXNRDQSDLY(n) (0x22C + ((n) << 7)) +/* [6:0] the delay value of delay applied on WDQS for write leveling */ +#define DDR_PHY_DXWDQSDLY(m, n) (0x230 + ((m) << 10) + ((n) << 7)) +/* WR DQ phase BIT 12:8 */ +#define DDR_PHY_DXNWDQDLY(m, n) (0x234 + ((m) << 10) + ((n) << 7)) +/* [CUSTOM] rddqs gating*/ +#define DDR_PHY_DXNRDQSGDLY(m, n) (0x240 + ((m) << 10) + ((n) << 7)) +/* read boundary right 8:0 left 24:16 */ +#define DDR_PHY_DXNRDBOUND(n) (0x250 + ((n) << 7)) +/* write boundary right 4:0 left 20:16 */ +#define DDR_PHY_DXNWDBOUND(n) (0x254 + ((n) << 7)) + +#define DDR_PHY_CORNER_DETECTOR 0x104C /* cfg of corner detector */ + +#define DDR_VREF_HOST_VAL_MAX (0x1f) /* 78.75%*VDDIO */ +#define DDR_VREF_HOST_VAL_MIN (0x0) /* 40.00%*VDDIO */ + +/* register mask */ +#define PHY_BDL_MASK 0x1f /* [4:0] */ +#define PHY_WDQS_PHASE_MASK 0xf /* [11:8] */ +#define PHY_RDQS_BDL_MASK 0x7f /* [CUSTOM] [6:0] rdqsbdl*/ +#define PHY_RDQSG_PHASE_MASK 0x3f /* [14:9] rdqsgtxbdl */ +#define PHY_RDM_BDL_MASK 0x7f /* [6:0] */ +/* hardware gate training result */ +#define PHY_INITSTATUS_GT_MASK 0x20 +#define PHY_SWTRLT_WL_MASK 0xf +#define PHY_SWTRLT_GATE_MASK 0xf +#define PHY_WDQ_PHASE_MASK 0x1f +#define PHY_PHYINITCTRL_MASK 0xffff /* [15:0] all stat */ +/* Read Data Eye Calibration Error */ +#define PHY_PHYINITSTATUS_RDET_ERR 0x100 +#define PHY_ACPHY_DCLK_MASK 0x7 /* cp1p_dclk0 mask */ +#define PHY_ACPHY_DRAMCLK_MASK 0x1 /* halft_dramclk0 mask */ +#define PHY_VRFTRES_HVREF_MASK 0x1f /* [4:0] */ +#define PHY_VRFTRES_RXDIFFCAL_MASK 0xf /* [24:21] */ +#define PHY_ACADDR_BDL_MASK 0x7f /* [6:0] */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_OSC_START_MASK 0x1 /* [0] */ +#define PHY_OSC_RPT_VLD_MASK 0x1 /* [15] */ +#define PHY_OSC_CNT_RDATA_MASK 0xffff /* [31:16] */ +#define PHY_ZCODE_PDRV_MASK 0x3f /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_MASK 0x3f /* [29:24] */ + +/* register bit */ +#define PHY_MISC_UPDATE_BIT 20 /* [CUSTOM] delay config update bit */ +#define PHY_PHYCONN_RST_BIT 15 /* issue reset signal to PHY counter */ +#define PHY_RDQSG_PHASE_BIT 8 /* [CUSTOM] */ +#define PHY_RDQSG_TX_BDL_BIT 16 /* [22:16] rdqsgtxbdl */ +#define PHY_WDQS_PHASE_BIT 8 +#define PHY_WDQS_BDL_BIT 0 +#define PHY_WDQ_PHASE_BIT 8 +#define PHY_WDM_BDL_BIT 0 +/* [20:16] Write DQS Output Enable Delay Control */ +#define PHY_WDQSOE_BDL_BIT 16 +#define PHY_OEN_BDL_BIT 0 +/* Mode Register 1. Defines the MR3/MR9 of the mode register */ +#define PHY_MODEREG01_MR1_BIT 16 +#define PHY_ACADDRBDL_ADDR1_BIT 16 /* [16] ADDR1 delay line */ +/* Bit delay line setting of CS1 */ +#define PHY_ACCMD_CS0_BIT 0 +#define PHY_ACCMD_CS1_BIT 16 +#define PHY_ACPHY_DCLK0_BIT 6 /* [8:6] cp1p_dclk0 */ +#define PHY_ACPHY_DCLK1_BIT 9 /* [11:9] ck2p_dclk1 */ +#define PHY_ACPHY_DRAMCLK0_BIT 25 /* [25] halft_dramclk0 */ +#define PHY_ACPHY_DRAMCLK1_BIT 24 /* [24] halft_dramclk1 */ +#define PHY_ACPHY_DRAMCLK_EXT_BIT 3 /* [3] halft_dramclk0 */ +#define PHY_SWTMODE_SW_GTMODE_BIT 1 /* [1] SW gate training */ +#define PHY_VREFS_MRS_ENTER_BIT 31 /* [31] */ +#define PHY_OSC_RPT_VLD 15 /* [15] */ +#define PHY_OSC_CNT_RDATA_BIT 16 /* [31:16] */ +#define PHY_ZCODE_PDRV_BIT 16 /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_BIT 24 /* [29:24] */ +#define PHY_AC_VDDQ_CAL_EN_BIT 8 /* [8] AC ZQ calibration enable */ + +/* BDL register bit */ +#define PHY_BDL_DQ_BIT 0 +#define PHY_BDL_DQ0_BIT 0 +#define PHY_BDL_DQ1_BIT 8 +#define PHY_BDL_DQ2_BIT 16 +#define PHY_BDL_DQ3_BIT 24 +#define PHY_RDM_BDL_BIT 0 +#define PHY_RDQS_BDL_BIT 0 + +/* value */ +#define PHY_PHYINITCTRL_DVREFT_SYNC 0x40000 /* DRAM VREF Synchronize */ +/* hw training item defined in PHYINITCTRL */ +#define PHY_PHYINITCTRL_CTL_CKE_BYPASS (1 << 31) /* PACK's CKE bypass function enable. */ +#define PHY_PHYINITCTRL_PIC_PHYUPD_REQ (1 << 30) /* PACK's DFI PHY UPDATAE request by SW. */ +#define PHY_PHYINITCTRL_PIC_TDQSST (1 << 29) /* TDQSS training Enable. */ +#define PHY_PHYINITCTRL_LP4_CHB_DIS (1 << 28) /* LPDDR4 channel-B disable. */ +#define PHY_PHYINITCTRL_LP4_CHA_DIS (1 << 27) /* LPDDR4 channel-A disable. */ +#define PHY_PHYINITCTRL_PIC_REFRET_SFT (1 << 26) /* Update delay line(switch op_sel) during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_WR (1 << 25) /* Retraining with MPC write during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_RD (1 << 24) /* Retraining with MPC read during tRFC. */ +#define PHY_PHYINITCTRL_JTMT_EN (1 << 23) /* PLL Jitter Meter Enable. */ +#define PHY_PHYINITCTRL_CST_EN (1 << 22) /* HW CS Traninig Enable. */ +#define PHY_PHYINITCTRL_ACDVREFS_EN (1 << 21) /* DRAM VREF(AC) Synchronize Operations. */ +#define PHY_PHYINITCTRL_ACHVREFT_EN (1 << 20) /* Host VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_ACDVREFT_EN (1 << 19) /* DRAM VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_DXDVREFS_EN (1 << 18) /* DRAM VREF(DQ) Synchronize Operations. */ +#define PHY_PHYINITCTRL_HVREFT_EN (1 << 17) /* Host VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_DVREFT_EN (1 << 16) /* DRAM VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_PHYCONN_RST (1 << 15) /* PHY Counter Reset. */ +#define PHY_PHYINITCTRL_PACK_RST (1 << 14) /* PACK Reset. */ +#define PHY_PHYINITCTRL_PHY_RST (1 << 13) /* PHY Reset. */ +#define PHY_PHYINITCTRL_DRAM_RST (1 << 12) /* DRAM Reset. */ +#define PHY_PHYINITCTRL_CAT_EN (1 << 11) /* HW CA Traninig Enable. */ +#define PHY_PHYINITCTRL_DRAM_INIT_EN (1 << 10) /* DRAM Initialization Enable. */ +#define PHY_PHYINITCTRL_WDET_EN (1 << 9) /* Write Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_RDET_EN (1 << 8) /* Read Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_WL2_EN (1 << 7) /* Second Write Leveling Enable. */ +#define PHY_PHYINITCTRL_GDST_EN (1 << 6) /* PHY Read Data Latch Train Enable. */ +#define PHY_PHYINITCTRL_GT_EN (1 << 5) /* Gate Training Enable. */ +#define PHY_PHYINITCTRL_WL_EN (1 << 4) /* Write Leveling Enable. */ +#define PHY_PHYINITCTRL_ZCAL_EN (1 << 3) /* Impedance Calibration Enable. */ +#define PHY_PHYINITCTRL_DLYMEAS_EN (1 << 2) /* Delay Measurement Enable. */ +#define PHY_PHYINITCTRL_PLL_INIT_EN (1 << 1) /* PLL Initialization Enable. */ +#define PHY_PHYINITCTRL_INIT_EN (1 << 0) /* PHY Initialization Enable. */ + +#define PHY_HW_GP_PHY_RESET (PHY_PHYINITCTRL_PHY_RST) +#define PHY_HW_GP_CNT_RESET_START (PHY_PHYINITCTRL_PHYCONN_RST) +#define PHY_HW_GP_PLL (PHY_PHYINITCTRL_PLL_INIT_EN | PHY_PHYINITCTRL_ZCAL_EN | PHY_PHYINITCTRL_DLYMEAS_EN) +#define PHY_HW_GP_DRAM_RESET (PHY_PHYINITCTRL_DRAM_RST | PHY_PHYINITCTRL_DRAM_INIT_EN) +#define PHY_HW_GP_VREF_AC (PHY_PHYINITCTRL_ACDVREFS_EN) +#define PHY_HW_GP_CS (PHY_PHYINITCTRL_CST_EN) +#define PHY_HW_GP_VREF_DQ (PHY_PHYINITCTRL_DVREFT_SYNC) +#define PHY_HW_GP_NORMAL (PHY_PHYINITCTRL_WL_EN \ + | PHY_PHYINITCTRL_GT_EN \ + | PHY_PHYINITCTRL_GDST_EN \ + | PHY_PHYINITCTRL_WL2_EN \ + | PHY_PHYINITCTRL_RDET_EN \ + | PHY_PHYINITCTRL_WDET_EN \ + | PHY_PHYINITCTRL_DVREFT_EN \ + | PHY_PHYINITCTRL_HVREFT_EN \ + | PHY_PHYINITCTRL_PIC_TDQSST) +#define PHY_HW_GP_CNT_RESET_END (PHY_PHYINITCTRL_PHYCONN_RST) + +/* RDQS range[0, 0x1f], middle value is 0x10 */ +#define PHY_RDQS_MIDDLE_VAL 0x10 +/* DQ range[0, 0x1f], middle value is 0x10 */ +#define PHY_DQ_MIDDLE_VAL 0x10101010 +#define PHY_MISC_SCRAMB_DIS 0xfffeffff /* scrambler disable */ +/* NOTE: rdqsg_bdl is [5:0] in register manual, actual use [4:0] */ +#define PHY_GATE_BDL_MAX 0x40 /* [4:0]rdqsg_bdl + [20:16]rdqsgtxbdl */ +#define PHY_DVRFTCTRL_PDAEN_EN 0x80000000 /* pda enable */ +/* [5] two cycle on address or command.(2T timing) */ +#define PHY_DRAMCFG_MA2T 0x20 + +#define PHY_DRAMCFG_TYPE_DDR1 0x0 /* [2:0] 000 DDR1 */ +#define PHY_DRAMCFG_TYPE_DDR2 0x1 /* [2:0] 001 DDR2 */ +#define PHY_DRAMCFG_TYPE_DDR3 0x2 /* [2:0] 010 DDR3 */ +#define PHY_DRAMCFG_TYPE_DDR3L 0x3 /* [2:0] 011 DDR3L */ +#define PHY_DRAMCFG_TYPE_LPDDR1 0x4 /* [2:0] 100 LPDDR1 */ +#define PHY_DRAMCFG_TYPE_LPDDR2 0x5 /* [2:0] 101 LPDDR2 */ +#define PHY_DRAMCFG_TYPE_LPDDR3 0x5 /* [2:0] 101 LPDDR3 */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ +#define PHY_DRAMCFG_TYPE_DDR4 0xa /* [3] 1010 DDR4 */ + +/* other */ +#define PHY_RDQSG_PHASE_STEP 4 /* gate training phase step. */ +#define PHY_GATE_PHASE_MARGIN 8 /* gate phase margin */ +#define PHY_DQ_BDL_LEVEL 32 /* [CUSTOM] DQ BDL range */ +#define PHY_DQ_BDL_MIDDLE 15 /* middle DQ BDL value */ +#define PHY_RDQSG_PHASE_MAX 0x3c /* RDQSG phase max value */ +#define PHY_ACPHY_CLK_MAX 0xf /* halft_dramclk0 + cp1p_dclk0 */ +#define PHY_PCODE_MIN 0x14 +#define PHY_PCODE_MAX 0x24 +/** + * DDR_BDL_PHASE_REL Calculation Method: + * 1. Calculation How many picosecond to one phase. + * PICOSECOND : 1 second is (1000 * 1000 * 1000) picosecond + * WAVE : 1 cycle is 2 + * RATE : DDR rate is 1600 Mbps, is (1600 * 1000) bps + * PHASE : 1 wave is 16 phase + * phase = (((PICOSECOND * WAVE) / RATE) / PHASE) + * = (((1000 * 1000 * 1000 * 2) / (1600 * 1000)) / 16) + * = 78.125 ps. + * 2. Calculation How many bdl to one phase. + * one BDL is 20 ps. + * result = phase/bdl = 78.125 / 20 = 3.9 approximately equal to 4 + * 3. 4 = 1 << 2, so the relation is 2. + */ +#ifndef DDR_BDL_PHASE_TRANSFORM +/* [CUSTOM] one Phase equal how much BDL. 1 phase = 4 bdl */ +#define DDR_BDL_PHASE_TRANSFORM 4 +#endif +#ifndef DDR_BDL_PHASE_REL +/* [CUSTOM] relation between BDL and Phase. 1 phase = 4 bdl, 4 = 1 << 2 */ +#define DDR_BDL_PHASE_REL 2 +#endif + +#define DDR_VARIABLE_DECLARE(var) + +#define DDR_VREF_GET_HOST_MAX(rank, val) \ + do { \ + if (0 == rank) \ + val = PHY_VRFTRES_HVREF_MASK; \ + else \ + val = PHY_VRFTRES_RXDIFFCAL_MASK; \ + } while (0) + +#define DDR_PHY_VREF_HOST_SET(base_phy, rank, bytenum, byte_index, val) \ + ddr_write(((val & 0x7) << 12) | ((val >> 3) & 0x3), \ + base_phy + DDR_PHY_IOCTL2) + +#define DDR_PHY_VREF_HOST_GET(base_phy, rank, byte_index, val) \ + do { \ + unsigned int ref_range; \ + unsigned int ref_sel; \ + val = ddr_read(base_phy + DDR_PHY_IOCTL2); \ + ref_range = val & 0x3; \ + ref_sel = (val >> 12) & 0x7; \ + val = (ref_range << 3) | ref_sel; \ + } while (0) + +#define DDR_PHY_VREF_HOST_DISPLAY \ + {0, 0, DDR_PHY_IOCTL2, 0, "Host Vref"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_RANK1 + +#define DDR_PHY_VREF_HOST_DISPLAY_CMD(base_phy, rank, byte_num) \ + DDR_INFO("[%x = %x] Host Vref", \ + base_phy + DDR_PHY_IOCTL2, \ + ddr_read(base_phy + DDR_PHY_IOCTL2)); + +/* phy s40 not support DRAM vref */ +#define DDR_PHY_VREF_DRAM_SET(base_phy, val, byte_index) +#define DDR_PHY_VREF_DRAM_GET(base_phy, val, byte_index) +#define DDR_PHY_VREF_DRAM_DISPLAY +#define DDR_PHY_VREF_DRAM_DISPLAY_CMD(base_phy, byte_num) + +/* phy s40 not support Lowpower ddr ca */ +#define DDR_PHY_ADDRPH_DISPLAY +#define DDR_PHY_ADDRBDL_DISPLAY +#define DDR_PHY_ADDRPH_DISPLAY_CMD(base_phy) +#define DDR_PHY_ADDRBDL_DISPLAY_CMD(base_phy) + +/* phy s40 not support DDR4 */ +#define DDR_PHY_RDQS_SYNC_RDM(cfg, val) + +/* phy s40 not support dqs swap */ +#define DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy) +#define DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy) + +/* phy s40 not support rank switch */ +#define DDR_PHY_SWITCH_RANK(base_phy, val) + +/* phy s40 not support DCC training */ +#define DDR_PHY_DCC_DISPLAY +#define DDR_PHY_DCC_DISPLAY_CMD(base_phy) diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v100.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v100.h new file mode 100755 index 00000000..d0c7f352 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v100.h @@ -0,0 +1,495 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ddr_phy_t12_v100.h + * + * DDR PHY register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_PHY0 DDR_REG_BASE_PHY1 */ +/* control the initialization of the PHY */ +#define DDR_PHY_PHYINITCTRL 0x4 +#define DDR_PHY_PHYINITSTATUS 0x8 /* Read Data Eye Calibration Error*/ +#define DDR_PHY_IMPSTATUS 0x28 /* This register specify the ZQ calibration result. */ +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define DDR_PHY_TRAINCTRL0 0x48 /* hw training control */ +#define DDR_PHY_MODEREG01 0x64 /* Extend Mode Register 01 */ +#define DDR_PHY_MODEREG23 0x68 /* Extend Mode Register 23 */ +/* update delay setting in registers to PHY */ +#define DDR_PHY_MISC 0x70 +#define DDR_PHY_DMSEL 0x84 /* DM Swap Selection */ +#define DDR_PHY_SWTMODE 0xa0 /* S/W training mode */ +/* issue one DQS pulse from PHY to DRAM */ +#define DDR_PHY_SWTWLDQS 0xa4 +#define DDR_PHY_SWTRLT 0xa8 /* S/W training result*/ +/* Host vref. [5:0]range [17:12]refsel */ +#define DDR_PHY_IOCTL2 0xB4 +#define DDR_PHY_VREFTCTRL 0xc0 /* VREF Training Control Register. */ +#define DDR_PHY_HVRFTCTRL 0xc8 /* Host VREF Training Control Regiser. */ +#define DDR_PHY_DVRFTCTRL 0xC4 /* DRAM VREF Training */ +#define DDR_PHY_ACADDRBDL(n) (0x140 + ((n) << 2)) +#define DDR_PHY_IMP_CTRL1 0x170 /* AC/DX ZQ selection */ +#define DDR_PHY_IMP_STATUS1 0x174 /* AC ZCAL status */ +#define DDR_PHY_CATSWAPINDEX 0x01B8 /* CA SWAP index register */ +#define DDR_PHY_CATSWAPSEL 0x01BC /* CA SWAP select register*/ +#define DDR_PHY_CATCONFIG 0x1C8 /* CA Training Configuration */ +#define DDR_PHY_PHYDQRESULT 0x1D0 /* SW CA Training DQ result from PHY */ +#define DDR_PHY_ADDRPHBOUND 0x1D4 /* CA Training addr phase boundary */ +#define DDR_PHY_SWCATPATTERN_P 0x1D8 /* pattern for positive CK edge */ +#define DDR_PHY_SWCATPATTERN_N 0x1DC /* pattern for negative CK edge */ +/* AC command bit delay line setting */ +#define DDR_PHY_ACCMDBDL2 0x128 + +#define DDR_PHY_DXNWDQNBDL0(m, n) (0x210 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQNBDL1(m, n) (0x214 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQNBDL2(m, n) (0x218 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL0(m, n) (0x21C + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL1(m, n) (0x220 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL2(m, n) (0x224 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNOEBDL(m, n) (0x228 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQSDLY(n) (0x22C + ((n) << 7)) +#define DDR_PHY_DXWDQSDLY(m, n) (0x230 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQDLY(m, n) (0x234 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQSGDLY(m, n) (0x240 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDBOUND(n) (0x250 + ((n) << 7)) +#define DDR_PHY_DXNWDBOUND(n) (0x254 + ((n) << 7)) +#define DDR_PHY_DVREFT_STATUS(n) (0x270 + ((n) << 7)) +#define DDR_PHY_HVREFT_STATUS(m, n) (0x274 + ((m) << 10) + ((n) << 7)) + +/* DDRPHY AC static register */ +#define DDR_PHY_CORNER_DETECTOR 0x104C /* cfg of corner detector */ +#define DDR_PHY_ACPHYCTL4 0x1064 /* AC block PHY control register*/ +#define DDR_PHY_ACPHYCTL7 0x1070 +#define DDR_PHY_ACIOCTL21 0x10F4 +#define DDR_PHY_AC_GATED_BYPASS 0x10FC /* bypass clock gated function */ + +/* register mask */ +#define PHY_BDL_MASK 0x7f /* [7:1] */ +#define PHY_WDQS_PHASE_MASK 0x1f /* [13:9] */ +#define PHY_RDQS_BDL_MASK 0x1ff /* [CUSTOM] [9:1] rdqsbdl*/ +#define PHY_RDQSG_PHASE_MASK 0x1ff /* [18:10] rdqsgphase */ +#define PHY_RDM_BDL_MASK 0x7f /* [7:1] */ + +/* hardware gate training result */ +#define PHY_INITSTATUS_GT_MASK 0x20 +#define PHY_SWTRLT_WL_MASK 0xf +#define PHY_SWTRLT_GATE_MASK 0xf +#define PHY_WDQ_PHASE_MASK 0x7f +#define PHY_PHYINITCTRL_MASK 0x1 +/* Read Data Eye Calibration Error */ +#define PHY_PHYINITSTATUS_RDET_ERR 0x100 +#define PHY_ACPHY_DCLK_MASK 0x7 /* cp1p_dclk0 mask */ +#define PHY_ACPHY_DRAMCLK_MASK 0x1 /* halft_dramclk0 mask */ +#define PHY_VRFTRES_DVREF_MASK 0x3f /* [5:0] */ +#define PHY_VRFTRES_HVREF_MASK 0x7f /* [6:0] */ +#define PHY_VRFTRES_RXDIFFCAL_MASK 0xf /* [24:21] */ + +#define PHY_ADDRPH_MASK 0x1f /* [20:16] */ +#define PHY_ACADDR_BDL_MASK 0x7f /* [6:0] */ +#define PHY_CATSWAPSEL_BIT_MASK 0xff +#define PHY_CAT_PATTERN_MASK 0x3ff +#define PHY_TRAINCTRL0_MASK 0xf /* [3:0] */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_ACIOCTL21_MASK 0x7 /* [30:28],[14:12] */ +#define PHY_DXNRDBOUND_MASK 0x1ff /* [25:17],[9:1] */ +#define PHY_OSC_START_MASK 0x1 /* [0] */ +#define PHY_OSC_RPT_VLD_MASK 0x1 /* [15] */ +#define PHY_OSC_CNT_RDATA_MASK 0xffff /* [31:16] */ +#define PHY_ZCODE_PDRV_MASK 0x3f /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_MASK 0x3f /* [29:24] */ + +/* register bit */ +#define PHY_MISC_UPDATE_BIT 19 /* [CUSTOM] delay config update bit */ +#define PHY_PHYCONN_RST_BIT 15 /* issue reset signal to PHY counter */ +#define PHY_RDQSG_PHASE_BIT 10 /* [CUSTOM] */ +#define PHY_RDQSG_TX_BDL_BIT 16 /* [22:16] rdqsgtxbdl */ +#define PHY_WDQS_PHASE_BIT 9 +#define PHY_WDQS_BDL_BIT 1 +#define PHY_WDQ_PHASE_BIT 9 +#define PHY_WDM_BDL_BIT 1 +/* [22:16] Write DQS Output Enable Delay Control */ +#define PHY_WDQSOE_BDL_BIT 17 +#define PHY_OEN_BDL_BIT 1 +/* Mode Register 1. Defines the MR3/MR9 of the mode register */ +#define PHY_MODEREG01_MR1_BIT 16 +/* Bit delay line setting of CS1 */ +#define PHY_ACCMD_CS0_BIT 1 +#define PHY_ACCMD_CS1_BIT 17 +#define PHY_ACPHY_DCLK0_BIT 6 /* [8:6] cp1p_dclk0 */ +#define PHY_ACPHY_DCLK1_BIT 9 /* [11:9] ck2p_dclk1 */ +#define PHY_ACPHY_DRAMCLK0_BIT 25 /* [25] halft_dramclk0 */ +#define PHY_ACPHY_DRAMCLK1_BIT 24 /* [24] halft_dramclk1 */ +#define PHY_ACPHY_DRAMCLK_EXT_BIT 3 /* [3] halft_dramclk0 */ +#define PHY_SWTMODE_SW_GTMODE_BIT 1 /* [1] SW gate training */ +#define PHY_ACADDRBDL_ADDR1_BIT 17 /* [17] ADDR1 delay line */ +#define PHY_VRFTRES_RXDIFFCAL_BIT 21 /* [24:21] */ +#define PHY_BYPASS_CK0_BIT 2 /* [2]ck_ioctl_DUTY_EN */ +#define PHY_BYPASS_CK1_BIT 3 /* [3]ck1_ioctl_DUTY_EN */ +#define PHY_ACIOCTL21_CK0_BIT 12 /* [14:12] */ +#define PHY_ACIOCTL21_CK1_BIT 28 /* [30:28] */ +#define PHY_ACIOCTL21_CTL0_BIT 15 /* [15] */ +#define PHY_ACIOCTL21_CTL1_BIT 31 /* [31] */ +#define PHY_DXNRDBOUND_RIGHT_BIT 1 /* [9:1] */ +#define PHY_DXNRDBOUND_LEFT_BIT 17 /* [25:17] */ +#define PHY_VREFS_MRS_ENTER_BIT 31 /* [31] */ +#define PHY_HRXDIFFCAL_EN_BIT 31 /* [31] */ +#define PHY_OSC_RPT_VLD 15 /* [15] */ +#define PHY_OSC_CNT_RDATA_BIT 16 /* [31:16] */ +#define PHY_ZCODE_PDRV_BIT 16 /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_BIT 24 /* [29:24] */ +#define PHY_AC_VDDQ_CAL_EN_BIT 8 /* [8] AC ZQ calibration enable */ + +/* BDL register bit */ +#define PHY_BDL_DQ_BIT 1 +#define PHY_BDL_DQ0_BIT 1 +#define PHY_BDL_DQ1_BIT 9 +#define PHY_BDL_DQ2_BIT 17 +#define PHY_BDL_DQ3_BIT 25 +#define PHY_RDM_BDL_BIT 1 +#define PHY_RDQS_BDL_BIT 1 + +/* value */ +#define PHY_PHYINITCTRL_DVREFT_SYNC 0x40000 /* DRAM VREF Synchronize */ +#define PHY_TRAINCTRL0_DTR_RANK0 0x0 /* Training Rank0. */ +#define PHY_TRAINCTRL0_DTR_RANK1 0x1 /* Training Rank1. */ +/* hw training item defined in PHYINITCTRL */ +#define PHY_PHYINITCTRL_CTL_CKE_BYPASS (1 << 31) /* PACK's CKE bypass function enable. */ +#define PHY_PHYINITCTRL_PIC_PHYUPD_REQ (1 << 30) /* PACK's DFI PHY UPDATAE request by SW. */ +#define PHY_PHYINITCTRL_PIC_TDQSST (1 << 29) /* TDQSS training Enable. */ +#define PHY_PHYINITCTRL_LP4_CHB_DIS (1 << 28) /* LPDDR4 channel-B disable. */ +#define PHY_PHYINITCTRL_LP4_CHA_DIS (1 << 27) /* LPDDR4 channel-A disable. */ +#define PHY_PHYINITCTRL_PIC_REFRET_SFT (1 << 26) /* Update delay line(switch op_sel) during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_WR (1 << 25) /* Retraining with MPC write during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_RD (1 << 24) /* Retraining with MPC read during tRFC. */ +#define PHY_PHYINITCTRL_JTMT_EN (1 << 23) /* PLL Jitter Meter Enable. */ +#define PHY_PHYINITCTRL_CST_EN (1 << 22) /* HW CS Traninig Enable. */ +#define PHY_PHYINITCTRL_ACDVREFS_EN (1 << 21) /* DRAM VREF(AC) Synchronize Operations. */ +#define PHY_PHYINITCTRL_ACHVREFT_EN (1 << 20) /* Host VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_ACDVREFT_EN (1 << 19) /* DRAM VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_DXDVREFS_EN (1 << 18) /* DRAM VREF(DQ) Synchronize Operations. */ +#define PHY_PHYINITCTRL_HVREFT_EN (1 << 17) /* Host VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_DVREFT_EN (1 << 16) /* DRAM VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_PHYCONN_RST (1 << 15) /* PHY Counter Reset. */ +#define PHY_PHYINITCTRL_PACK_RST (1 << 14) /* PACK Reset. */ +#define PHY_PHYINITCTRL_PHY_RST (1 << 13) /* PHY Reset. */ +#define PHY_PHYINITCTRL_DRAM_RST (1 << 12) /* DRAM Reset. */ +#define PHY_PHYINITCTRL_CAT_EN (1 << 11) /* HW CA Traninig Enable. */ +#define PHY_PHYINITCTRL_DRAM_INIT_EN (1 << 10) /* DRAM Initialization Enable. */ +#define PHY_PHYINITCTRL_WDET_EN (1 << 9) /* Write Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_RDET_EN (1 << 8) /* Read Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_WL2_EN (1 << 7) /* Second Write Leveling Enable. */ +#define PHY_PHYINITCTRL_GDST_EN (1 << 6) /* PHY Read Data Latch Train Enable. */ +#define PHY_PHYINITCTRL_GT_EN (1 << 5) /* Gate Training Enable. */ +#define PHY_PHYINITCTRL_WL_EN (1 << 4) /* Write Leveling Enable. */ +#define PHY_PHYINITCTRL_ZCAL_EN (1 << 3) /* Impedance Calibration Enable. */ +#define PHY_PHYINITCTRL_DLYMEAS_EN (1 << 2) /* Delay Measurement Enable. */ +#define PHY_PHYINITCTRL_PLL_INIT_EN (1 << 1) /* PLL Initialization Enable. */ +#define PHY_PHYINITCTRL_INIT_EN (1 << 0) /* PHY Initialization Enable. */ + +#define PHY_HW_GP_PHY_RESET (PHY_PHYINITCTRL_PHY_RST) +#define PHY_HW_GP_CNT_RESET_START (PHY_PHYINITCTRL_PHYCONN_RST) +#define PHY_HW_GP_PLL (PHY_PHYINITCTRL_PLL_INIT_EN | PHY_PHYINITCTRL_ZCAL_EN | PHY_PHYINITCTRL_DLYMEAS_EN) +#define PHY_HW_GP_DRAM_RESET (PHY_PHYINITCTRL_DRAM_RST | PHY_PHYINITCTRL_DRAM_INIT_EN) +#define PHY_HW_GP_VREF_AC (PHY_PHYINITCTRL_ACDVREFS_EN) +#define PHY_HW_GP_CS (PHY_PHYINITCTRL_CST_EN) +#define PHY_HW_GP_VREF_DQ (PHY_PHYINITCTRL_DVREFT_SYNC) +#define PHY_HW_GP_NORMAL (PHY_PHYINITCTRL_WL_EN \ + | PHY_PHYINITCTRL_GT_EN \ + | PHY_PHYINITCTRL_GDST_EN \ + | PHY_PHYINITCTRL_WL2_EN \ + | PHY_PHYINITCTRL_RDET_EN \ + | PHY_PHYINITCTRL_WDET_EN \ + | PHY_PHYINITCTRL_DVREFT_EN \ + | PHY_PHYINITCTRL_HVREFT_EN \ + | PHY_PHYINITCTRL_PIC_TDQSST) +#define PHY_HW_GP_CNT_RESET_END (PHY_PHYINITCTRL_PHYCONN_RST) + +/* RDQS range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_RDQS_MIDDLE_VAL 0x30 +/* DQ range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_DQ_MIDDLE_VAL 0x30303030 +#define PHY_MISC_SCRAMB_DIS 0xfffeffff /* scrambler disable */ +#define PHY_GATE_BDL_MAX 0xfe /* [6:0]rdqsg_bdl + [22:16]rdqsgtxbdl */ +#define PHY_DVRFTCTRL_PDAEN_EN 0x80000000 /* pda enable */ +/* [5] two cycle on address or command.(2T timing) */ +#define PHY_DRAMCFG_MA2T 0x20 + +#define PHY_DRAMCFG_TYPE_DDR1 0x0 /* [2:0] 000 DDR1 */ +#define PHY_DRAMCFG_TYPE_DDR2 0x1 /* [2:0] 001 DDR2 */ +#define PHY_DRAMCFG_TYPE_DDR3 0x2 /* [2:0] 010 DDR3 */ +#define PHY_DRAMCFG_TYPE_DDR3L 0x3 /* [2:0] 011 DDR3L */ +#define PHY_DRAMCFG_TYPE_LPDDR1 0x4 /* [2:0] 100 LPDDR1 */ +#define PHY_DRAMCFG_TYPE_LPDDR2 0x5 /* [2:0] 101 LPDDR2 */ +#define PHY_DRAMCFG_TYPE_LPDDR3 0x5 /* [2:0] 101 LPDDR3 */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ +#define PHY_DRAMCFG_TYPE_DDR4 0xa /* [3] 1010 DDR4 */ + +#define PHY_DMSEL_SWAPDFIBYTE 0xf8ffffff /* [24:26] No Swap */ + +/* AC_DDRPHY_GATED_BYPASS */ +#define PHY_CK_IOCTL_DUTY_EN 0x4 /* enable ck_ioctl_DUTY_EN_v */ +#define PHY_CK1_IOCTL_DUTY_EN 0x8 /* enable ck1_ioctl_DUTY_EN_v */ +/* CK AC_IOCTL22 */ +#ifndef DDR_DUTY_NUM +#define DDR_DUTY_NUM 8 /* CK duty number */ +#endif +#ifndef DDR_CK_NUM +#define DDR_CK_NUM 2 /* DDR CK number */ +#endif +#ifndef DDR_DUTY_CTL_NUM +#define DDR_DUTY_CTL_NUM 2 /* CK duty has two control direction */ +#endif +/* CK duty step. */ +#ifndef PHY_AC_IOCTL21_STEP +#define PHY_AC_IOCTL21_STEP 1 +#endif + +/* other */ +#define PHY_RDQSG_PHASE_STEP 2 /* gate training phase step. */ +#define PHY_GATE_PHASE_MARGIN 8 /* gate phase margin */ +#define PHY_DQ_BDL_LEVEL 128 /* [CUSTOM] DQ BDL range */ +#define PHY_DQ_BDL_MIDDLE 64 /* special middle DQ BDL value */ +#define PHY_RDQSG_PHASE_MAX 0x3c /* RDQSG phase max value */ +#define PHY_ACPHY_CLK_MAX 0xf /* halft_dramclk0 + cp1p_dclk0 */ +#define PHY_PCODE_MIN 0x14 +#define PHY_PCODE_MAX 0x24 +/** + * DDR_BDL_PHASE_REL Calculation Method: + * 1. Calculation How many picosecond to one phase. + * PICOSECOND : 1 second is (1000 * 1000 * 1000) picosecond + * WAVE : 1 cycle is 2 + * RATE : DDR rate is 1600 Mbps, is (1600 * 1000) bps + * PHASE : 1 wave is 12 phase + * phase = (((PICOSECOND * WAVE) / RATE) / PHASE) + * = (((1000 * 1000 * 1000 * 2) / (1600 * 1000)) / 12) + * = 104.17 ps. + * 2. Calculation How many bdl to one phase. + * one BDL is 6 ps. + * result = phase/bdl = 104.17 / 6 = 17.36 approximately equal to 17 ~= 16 + * 3. 16 = 1 << 4, so the relation is 4. + */ +#ifndef DDR_BDL_PHASE_TRANSFORM +/* [CUSTOM] one Phase equal how much BDL. 1 phase = 16 bdl */ +#define DDR_BDL_PHASE_TRANSFORM 16 +#endif +#ifndef DDR_BDL_PHASE_REL +/* [CUSTOM] relation between BDL and Phase. 1 phase = 16 bdl, 16 = 1 << 4 */ +#define DDR_BDL_PHASE_REL 4 +#endif + +#define DDR_VARIABLE_DECLARE(var) \ + unsigned int var; + + +#define DDR_VREF_GET_HOST_MAX(rank, val) \ + do { \ + if (0 == rank) \ + val = PHY_VRFTRES_HVREF_MASK; \ + else \ + val = PHY_VRFTRES_RXDIFFCAL_MASK; \ + } while (0) + +/* PHY t28 all byte use a same value */ +#define DDR_PHY_VREF_HOST_SET(base_phy, rank, bytenum, byte_index, val) \ + do { \ + unsigned int hvreft; \ + if (0 == rank) { \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & (~PHY_VRFTRES_HVREF_MASK); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index + 1)); \ + } else { \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & (~(PHY_VRFTRES_RXDIFFCAL_MASK << PHY_VRFTRES_RXDIFFCAL_BIT)); \ + ddr_write(hvreft | (val << PHY_VRFTRES_RXDIFFCAL_BIT), base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)); \ + ddr_write(hvreft | (val << PHY_VRFTRES_RXDIFFCAL_BIT), base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index + 1)); \ + } \ + } while (0) + +#define DDR_PHY_VREF_HOST_GET(base_phy, rank, byte_index, val) \ + do { \ + if (0 == rank) { \ + val = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & PHY_VRFTRES_HVREF_MASK; \ + } else { \ + val = (ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) >> PHY_VRFTRES_RXDIFFCAL_BIT) \ + & PHY_VRFTRES_RXDIFFCAL_MASK; \ + } \ + } while (0) + +#define DDR_PHY_VREF_HOST_DISPLAY \ + {0, 0, DDR_PHY_HVREFT_STATUS(0, 0), 0, "Host Vref Byte0"}, \ + {0, 1, DDR_PHY_HVREFT_STATUS(0, 1), 0, "Host Vref Byte1"}, \ + {0, 2, DDR_PHY_HVREFT_STATUS(0, 2), 0, "Host Vref Byte2"}, \ + {0, 3, DDR_PHY_HVREFT_STATUS(0, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_RANK1 \ + {1, 0, DDR_PHY_HVREFT_STATUS(1, 0), 0, "Host Vref Byte0"}, \ + {1, 1, DDR_PHY_HVREFT_STATUS(1, 1), 0, "Host Vref Byte1"}, \ + {1, 2, DDR_PHY_HVREFT_STATUS(1, 2), 0, "Host Vref Byte2"}, \ + {1, 3, DDR_PHY_HVREFT_STATUS(1, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_CMD(base_phy, rank, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] Host Vref Byte(%x)", \ + base_phy + DDR_PHY_HVREFT_STATUS(rank, _i), \ + ddr_read(base_phy \ + + DDR_PHY_HVREFT_STATUS(rank, _i)), _i); \ + } \ + } while (0) + +/* DRAM vref operations */ +#define DDR_PHY_VREF_DRAM_SET(base_phy, val, byte_index) \ + do { \ + unsigned int dvrftctrl = \ + ddr_read(base_phy + DDR_PHY_DVRFTCTRL); \ + unsigned int dvreft = ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & (~PHY_VRFTRES_DVREF_MASK); \ + ddr_write(dvrftctrl | PHY_DVRFTCTRL_PDAEN_EN, \ + base_phy + DDR_PHY_DVRFTCTRL); \ + ddr_write(dvreft | val, \ + base_phy + DDR_PHY_DVREFT_STATUS(byte_index)); \ + ddr_write(PHY_PHYINITCTRL_DVREFT_SYNC \ + | PHY_PHYINITCTRL_INIT_EN, \ + base_phy + DDR_PHY_PHYINITCTRL); \ + while (1) { \ + if (!(ddr_read(base_phy + DDR_PHY_PHYINITCTRL) \ + & PHY_PHYINITCTRL_INIT_EN)) \ + break; \ + } \ + ddr_write(dvrftctrl & (~PHY_DVRFTCTRL_PDAEN_EN), \ + base_phy + DDR_PHY_DVRFTCTRL); \ + } while (0) + +#define DDR_PHY_VREF_DRAM_GET(base_phy, val, byte_index) \ + { \ + val = ddr_read(base_phy + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & PHY_VRFTRES_DVREF_MASK; \ + } + +#define DDR_PHY_VREF_DRAM_DISPLAY \ + {0, 0, DDR_PHY_DVREFT_STATUS(0), 0, "DRAM Vref Byte0"}, \ + {0, 1, DDR_PHY_DVREFT_STATUS(1), 0, "DRAM Vref Byte1"}, \ + {0, 2, DDR_PHY_DVREFT_STATUS(2), 0, "DRAM Vref Byte2"}, \ + {0, 3, DDR_PHY_DVREFT_STATUS(3), 0, "DRAM Vref Byte3"}, + +#define DDR_PHY_VREF_DRAM_DISPLAY_CMD(base_phy, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] DRAM Vref Byte(%x)", \ + base_phy + DDR_PHY_DVREFT_STATUS(_i), \ + ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(_i)), _i); \ + } \ + } while (0) + +#define DDR_PHY_DCC_DISPLAY \ + {0, 0, DDR_PHY_ACIOCTL21, 0, "CK DUTY"}, + +#define DDR_PHY_DCC_DISPLAY_CMD(base_phy) \ + do { \ + unsigned int val; \ + val = ddr_read(base_phy + DDR_PHY_ACIOCTL21); \ + val = ddr_read(base_phy + DDR_PHY_ACIOCTL21); \ + DDR_INFO("[%x = %x] DCC duty", \ + base_phy + DDR_PHY_ACIOCTL21, val); \ + } while (0) + +#define DDR_PHY_ADDRPH_DISPLAY \ + {0, 0, DDR_PHY_ADDRPHBOUND, 0, "CA Phase"}, + +#define DDR_PHY_ADDRBDL_DISPLAY \ + {0, 0, DDR_PHY_ACADDRBDL(0), 0, "CA BDL(0)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(1), 0, "CA BDL(1)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(2), 0, "CA BDL(2)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(3), 0, "CA BDL(3)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(4), 0, "CA BDL(4)"}, + +#define DDR_PHY_ADDRPH_DISPLAY_CMD(base_phy) \ + DDR_INFO("[%x = %x] CA Phase", \ + base_phy + DDR_PHY_ADDRPHBOUND, \ + ddr_read(base_phy + DDR_PHY_ADDRPHBOUND)); + +#define DDR_PHY_ADDRBDL_DISPLAY_CMD(base_phy) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < DDR_PHY_CA_REG_MAX; _i++) { \ + DDR_INFO("[%x = %x] ACADDRBDL(%x)", \ + base_phy + DDR_PHY_ACADDRBDL(_i), \ + ddr_read(base_phy \ + + DDR_PHY_ACADDRBDL(_i)), _i); \ + } \ + } while (0) + +/* PHY t28 DDR4 RDQS synchronize to RDM */ +#define DDR_PHY_RDQS_SYNC_RDM(cfg, val) \ + ddr_rdqs_sync(cfg, val) + +/* dqs swap */ +#define DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy) \ + do { \ + swapdfibyte_en = \ + ddr_read(base_phy + DDR_PHY_DMSEL); \ + ddr_write(swapdfibyte_en & PHY_DMSEL_SWAPDFIBYTE, \ + base_phy + DDR_PHY_DMSEL); \ + } while (0) + +#define DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy) \ + ddr_write(swapdfibyte_en, base_phy + DDR_PHY_DMSEL); + +#define DDR_PHY_SWITCH_RANK(base_phy, val) \ + do { \ + ddr_write((ddr_read(base_phy + DDR_PHY_TRAINCTRL0) & (~PHY_TRAINCTRL0_MASK)) | val, base_phy + DDR_PHY_TRAINCTRL0); \ + ddr_write((ddr_read(base_phy + DDR_PHY_HVRFTCTRL) & (~(0x1 << PHY_HRXDIFFCAL_EN_BIT))) | (val << PHY_HRXDIFFCAL_EN_BIT), base_phy + DDR_PHY_HVRFTCTRL); \ + } while (0) + +/* Define the union U_PHY_CATCONFIG */ +union U_PHY_CATCONFIG { + /* Define the struct bits */ + struct { + unsigned int ca_samp_num_bdl:4; /* [3:0] */ + unsigned int ca_samp_num_ph:4; /* [7:4] */ + unsigned int ca_trysamp_num:4; /* [11:8] */ + unsigned int cat_rb_backtap:4; /* [15:12] */ + unsigned int reserved:1; /* [16] */ + unsigned int cat_openeye_en:1; /* [17] */ + unsigned int cat_cat_phydq_sel:1; /* [18] */ + unsigned int cat_restore_en:1; /* [19] */ + unsigned int cat_lb_backtap:4; /* [23:20] */ + unsigned int sw_cat_mrw42:1; /* [24] */ + unsigned int sw_cat_mrw48:1; /* [25] */ + unsigned int sw_cat_mrw41:1; /* [26] */ + unsigned int sw_cat_strobe:1; /* [27] */ + unsigned int sw_cat_cke_high:1; /* [28] */ + unsigned int sw_cat_cke_low:1; /* [29] */ + unsigned int sw_cat_dqvalid:1; /* [30] */ + unsigned int sw_cat_en:1; /* [31] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; + +/* Define the union U_PHY_ADDRPHBOUND */ +union U_PHY_ADDRPHBOUND { + /* Define the struct bits */ + struct { + unsigned int addrph_a_right:5; /* [4:0] */ + unsigned int reserved0:3; /* [7:5] */ + unsigned int addrph_a_left:5; /* [12:8] */ + unsigned int reserved1:3; /* [15:13] */ + unsigned int addrph_a:5; /* [20:16] */ + unsigned int reserved2:3; /* [23:21] */ + unsigned int addrph_a_ori:5; /* [28:24] */ + unsigned int reserved3:3; /* [31:29] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v101.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v101.h new file mode 100755 index 00000000..a118d55b --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t12_v101.h @@ -0,0 +1,496 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_phy_t12_v101.h + * + * DDR PHY register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_PHY0 DDR_REG_BASE_PHY1 */ +/* control the initialization of the PHY */ +#define DDR_PHY_PHYINITCTRL 0x4 +#define DDR_PHY_PHYINITSTATUS 0x8 /* Read Data Eye Calibration Error*/ +#define DDR_PHY_IMPSTATUS 0x28 /* This register specify the ZQ calibration result. */ +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define DDR_PHY_TRAINCTRL0 0x48 /* hw training control */ +#define DDR_PHY_MODEREG01 0x64 /* Extend Mode Register 01 */ +#define DDR_PHY_MODEREG23 0x68 /* Extend Mode Register 23 */ +/* update delay setting in registers to PHY */ +#define DDR_PHY_MISC 0x70 +#define DDR_PHY_DMSEL 0x84 /* DM Swap Selection */ +#define DDR_PHY_SWTMODE 0xa0 /* S/W training mode */ +/* issue one DQS pulse from PHY to DRAM */ +#define DDR_PHY_SWTWLDQS 0xa4 +#define DDR_PHY_SWTRLT 0xa8 /* S/W training result*/ +/* Host vref. [5:0]range [17:12]refsel */ +#define DDR_PHY_IOCTL2 0xB4 +#define DDR_PHY_VREFTCTRL 0xc0 /* VREF Training Control Register. */ +#define DDR_PHY_HVRFTCTRL 0xc8 /* Host VREF Training Control Regiser. */ +#define DDR_PHY_DVRFTCTRL 0xC4 /* DRAM VREF Training */ +#define DDR_PHY_ACADDRBDL(n) (0x140 + ((n) << 2)) +#define DDR_PHY_IMP_CTRL1 0x170 /* AC/DX ZQ selection */ +#define DDR_PHY_IMP_STATUS1 0x174 /* AC ZCAL status */ +#define DDR_PHY_CATSWAPINDEX 0x01B8 /* CA SWAP index register */ +#define DDR_PHY_CATSWAPSEL 0x01BC /* CA SWAP select register*/ +#define DDR_PHY_CATCONFIG 0x1C8 /* CA Training Configuration */ +#define DDR_PHY_PHYDQRESULT 0x1D0 /* SW CA Training DQ result from PHY */ +#define DDR_PHY_ADDRPHBOUND 0x1D4 /* CA Training addr phase boundary */ +#define DDR_PHY_SWCATPATTERN_P 0x1D8 /* pattern for positive CK edge */ +#define DDR_PHY_SWCATPATTERN_N 0x1DC /* pattern for negative CK edge */ +/* AC command bit delay line setting */ +#define DDR_PHY_ACCMDBDL2 0x128 + +#define DDR_PHY_DXNWDQNBDL0(m, n) (0x210 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQNBDL1(m, n) (0x214 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQNBDL2(m, n) (0x218 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL0(m, n) (0x21C + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL1(m, n) (0x220 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQNBDL2(m, n) (0x224 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNOEBDL(m, n) (0x228 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQSDLY(n) (0x22C + ((n) << 7)) +#define DDR_PHY_DXWDQSDLY(m, n) (0x230 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNWDQDLY(m, n) (0x234 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDQSGDLY(m, n) (0x240 + ((m) << 10) + ((n) << 7)) +#define DDR_PHY_DXNRDBOUND(n) (0x250 + ((n) << 7)) +#define DDR_PHY_DXNWDBOUND(n) (0x254 + ((n) << 7)) +#define DDR_PHY_DVREFT_STATUS(n) (0x270 + ((n) << 7)) +#define DDR_PHY_HVREFT_STATUS(m, n) (0x274 + ((m) << 10) + ((n) << 7)) + +/* DDRPHY AC static register */ +#define DDR_PHY_CORNER_DETECTOR 0x104C /* cfg of corner detector */ +#define DDR_PHY_ACPHYCTL4 0x1064 /* AC block PHY control register*/ +#define DDR_PHY_ACPHYCTL7 0x1070 +#define DDR_PHY_ACIOCTL21 0x10F4 +#define DDR_PHY_AC_GATED_BYPASS 0x10FC /* bypass clock gated function */ + +/* register mask */ +#define PHY_BDL_MASK 0x7f /* [7:1] */ +#define PHY_WDQS_PHASE_MASK 0x1f /* [13:9] */ +#define PHY_RDQS_BDL_MASK 0x1ff /* [CUSTOM] [9:1] rdqsbdl*/ +#define PHY_RDQSG_PHASE_MASK 0x1ff /* [18:10] rdqsgphase */ +#define PHY_RDM_BDL_MASK 0x7f /* [7:1] */ +/* hardware gate training result */ +#define PHY_INITSTATUS_GT_MASK 0x20 +#define PHY_SWTRLT_WL_MASK 0xf +#define PHY_SWTRLT_GATE_MASK 0xf +#define PHY_WDQ_PHASE_MASK 0x7f +#define PHY_PHYINITCTRL_MASK 0x1 +/* Read Data Eye Calibration Error */ +#define PHY_PHYINITSTATUS_RDET_ERR 0x100 +#define PHY_ACPHY_DCLK_MASK 0x7 /* cp1p_dclk0 mask */ +#define PHY_ACPHY_DRAMCLK_MASK 0x1 /* halft_dramclk0 mask */ +#define PHY_VRFTRES_DVREF_MASK 0x3f /* [5:0] */ +#define PHY_VRFTRES_HVREF_MASK 0x7f /* [6:0] */ +#define PHY_VRFTRES_RXDIFFCAL_MASK 0xf /* [24:21] */ + +#define PHY_ADDRPH_MASK 0x1f /* [20:16] */ +#define PHY_ACADDR_BDL_MASK 0x7f /* [6:0] */ +#define PHY_CATSWAPSEL_BIT_MASK 0xff +#define PHY_CAT_PATTERN_MASK 0x3ff +#define PHY_TRAINCTRL0_MASK 0xf /* [3:0] */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_ACIOCTL21_MASK 0xf /* [31:28],[15:12] */ +#define PHY_DXNRDBOUND_MASK 0x1ff /* [25:17],[9:1] */ +#define PHY_OSC_START_MASK 0x1 /* [0] */ +#define PHY_OSC_RPT_VLD_MASK 0x1 /* [15] */ +#define PHY_OSC_CNT_RDATA_MASK 0xffff /* [31:16] */ +#define PHY_ZCODE_PDRV_MASK 0x3f /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_MASK 0x3f /* [29:24] */ + +/* register bit */ +#define PHY_MISC_UPDATE_BIT 19 /* [CUSTOM] delay config update bit */ +#define PHY_PHYCONN_RST_BIT 15 /* issue reset signal to PHY counter */ +#define PHY_RDQSG_PHASE_BIT 10 /* [CUSTOM] */ +#define PHY_RDQSG_TX_BDL_BIT 16 /* [22:16] rdqsgtxbdl */ +#define PHY_WDQS_PHASE_BIT 9 +#define PHY_WDQS_BDL_BIT 1 +#define PHY_WDQ_PHASE_BIT 9 +#define PHY_WDM_BDL_BIT 1 +/* [22:16] Write DQS Output Enable Delay Control */ +#define PHY_WDQSOE_BDL_BIT 17 +#define PHY_OEN_BDL_BIT 1 +/* Mode Register 1. Defines the MR3/MR9 of the mode register */ +#define PHY_MODEREG01_MR1_BIT 16 +/* Bit delay line setting of CS1 */ +#define PHY_ACCMD_CS0_BIT 1 +#define PHY_ACCMD_CS1_BIT 17 +#define PHY_ACPHY_DCLK0_BIT 6 /* [8:6] cp1p_dclk0 */ +#define PHY_ACPHY_DCLK1_BIT 9 /* [11:9] ck2p_dclk1 */ +#define PHY_ACPHY_DRAMCLK0_BIT 25 /* [25] halft_dramclk0 */ +#define PHY_ACPHY_DRAMCLK1_BIT 24 /* [24] halft_dramclk1 */ +#define PHY_ACPHY_DRAMCLK_EXT_BIT 3 /* [3] halft_dramclk0 */ +#define PHY_SWTMODE_SW_GTMODE_BIT 1 /* [1] SW gate training */ +#define PHY_ACADDRBDL_ADDR1_BIT 17 /* [17] ADDR1 delay line */ +#define PHY_VRFTRES_RXDIFFCAL_BIT 21 /* [24:21] */ +#define PHY_BYPASS_CK0_BIT 2 /* [2]ck_ioctl_DUTY_EN */ +#define PHY_BYPASS_CK1_BIT 3 /* [3]ck1_ioctl_DUTY_EN */ +#define PHY_ACIOCTL21_CK0_BIT 12 /* [15:12] */ +#define PHY_ACIOCTL21_CK1_BIT 28 /* [31:28] */ +#define PHY_ACIOCTL21_CTL0_BIT 10 /* [10] */ +#define PHY_ACIOCTL21_CTL1_BIT 26 /* [26] */ +#define PHY_DXNRDBOUND_RIGHT_BIT 1 /* [9:1] */ +#define PHY_DXNRDBOUND_LEFT_BIT 17 /* [25:17] */ +#define PHY_VREFS_MRS_ENTER_BIT 31 /* [31] */ +#define PHY_HRXDIFFCAL_EN_BIT 31 /* [31] */ +#define PHY_OSC_RPT_VLD 15 /* [15] */ +#define PHY_OSC_CNT_RDATA_BIT 16 /* [31:16] */ +#define PHY_ZCODE_PDRV_BIT 16 /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_BIT 24 /* [29:24] */ +#define PHY_AC_VDDQ_CAL_EN_BIT 8 /* [8] AC ZQ calibration enable */ + +/* BDL register bit */ +#define PHY_BDL_DQ_BIT 1 +#define PHY_BDL_DQ0_BIT 1 +#define PHY_BDL_DQ1_BIT 9 +#define PHY_BDL_DQ2_BIT 17 +#define PHY_BDL_DQ3_BIT 25 +#define PHY_RDM_BDL_BIT 1 +#define PHY_RDQS_BDL_BIT 1 + +/* value */ +#define PHY_PHYINITCTRL_DVREFT_SYNC 0x40000 /* DRAM VREF Synchronize */ +#define PHY_TRAINCTRL0_DTR_RANK0 0x0 /* Training Rank0. */ +#define PHY_TRAINCTRL0_DTR_RANK1 0x1 /* Training Rank1. */ +/* hw training item defined in PHYINITCTRL */ +#define PHY_PHYINITCTRL_CTL_CKE_BYPASS (1 << 31) /* PACK's CKE bypass function enable. */ +#define PHY_PHYINITCTRL_PIC_PHYUPD_REQ (1 << 30) /* PACK's DFI PHY UPDATAE request by SW. */ +#define PHY_PHYINITCTRL_PIC_TDQSST (1 << 29) /* TDQSS training Enable. */ +#define PHY_PHYINITCTRL_LP4_CHB_DIS (1 << 28) /* LPDDR4 channel-B disable. */ +#define PHY_PHYINITCTRL_LP4_CHA_DIS (1 << 27) /* LPDDR4 channel-A disable. */ +#define PHY_PHYINITCTRL_PIC_REFRET_SFT (1 << 26) /* Update delay line(switch op_sel) during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_WR (1 << 25) /* Retraining with MPC write during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_RD (1 << 24) /* Retraining with MPC read during tRFC. */ +#define PHY_PHYINITCTRL_JTMT_EN (1 << 23) /* PLL Jitter Meter Enable. */ +#define PHY_PHYINITCTRL_CST_EN (1 << 22) /* HW CS Traninig Enable. */ +#define PHY_PHYINITCTRL_ACDVREFS_EN (1 << 21) /* DRAM VREF(AC) Synchronize Operations. */ +#define PHY_PHYINITCTRL_ACHVREFT_EN (1 << 20) /* Host VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_ACDVREFT_EN (1 << 19) /* DRAM VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_DXDVREFS_EN (1 << 18) /* DRAM VREF(DQ) Synchronize Operations. */ +#define PHY_PHYINITCTRL_HVREFT_EN (1 << 17) /* Host VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_DVREFT_EN (1 << 16) /* DRAM VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_PHYCONN_RST (1 << 15) /* PHY Counter Reset. */ +#define PHY_PHYINITCTRL_PACK_RST (1 << 14) /* PACK Reset. */ +#define PHY_PHYINITCTRL_PHY_RST (1 << 13) /* PHY Reset. */ +#define PHY_PHYINITCTRL_DRAM_RST (1 << 12) /* DRAM Reset. */ +#define PHY_PHYINITCTRL_CAT_EN (1 << 11) /* HW CA Traninig Enable. */ +#define PHY_PHYINITCTRL_DRAM_INIT_EN (1 << 10) /* DRAM Initialization Enable. */ +#define PHY_PHYINITCTRL_WDET_EN (1 << 9) /* Write Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_RDET_EN (1 << 8) /* Read Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_WL2_EN (1 << 7) /* Second Write Leveling Enable. */ +#define PHY_PHYINITCTRL_GDST_EN (1 << 6) /* PHY Read Data Latch Train Enable. */ +#define PHY_PHYINITCTRL_GT_EN (1 << 5) /* Gate Training Enable. */ +#define PHY_PHYINITCTRL_WL_EN (1 << 4) /* Write Leveling Enable. */ +#define PHY_PHYINITCTRL_ZCAL_EN (1 << 3) /* Impedance Calibration Enable. */ +#define PHY_PHYINITCTRL_DLYMEAS_EN (1 << 2) /* Delay Measurement Enable. */ +#define PHY_PHYINITCTRL_PLL_INIT_EN (1 << 1) /* PLL Initialization Enable. */ +#define PHY_PHYINITCTRL_INIT_EN (1 << 0) /* PHY Initialization Enable. */ + +#define PHY_HW_GP_PHY_RESET (PHY_PHYINITCTRL_PHY_RST) +#define PHY_HW_GP_CNT_RESET_START (PHY_PHYINITCTRL_PHYCONN_RST) +#define PHY_HW_GP_PLL (PHY_PHYINITCTRL_PLL_INIT_EN | PHY_PHYINITCTRL_ZCAL_EN | PHY_PHYINITCTRL_DLYMEAS_EN) +#define PHY_HW_GP_DRAM_RESET (PHY_PHYINITCTRL_DRAM_RST | PHY_PHYINITCTRL_DRAM_INIT_EN) +#define PHY_HW_GP_VREF_AC (PHY_PHYINITCTRL_ACDVREFS_EN) +#define PHY_HW_GP_CS (PHY_PHYINITCTRL_CST_EN) +#define PHY_HW_GP_VREF_DQ (PHY_PHYINITCTRL_DVREFT_SYNC) +#define PHY_HW_GP_NORMAL (PHY_PHYINITCTRL_WL_EN \ + | PHY_PHYINITCTRL_GT_EN \ + | PHY_PHYINITCTRL_GDST_EN \ + | PHY_PHYINITCTRL_WL2_EN \ + | PHY_PHYINITCTRL_RDET_EN \ + | PHY_PHYINITCTRL_WDET_EN \ + | PHY_PHYINITCTRL_DVREFT_EN \ + | PHY_PHYINITCTRL_HVREFT_EN \ + | PHY_PHYINITCTRL_PIC_TDQSST) +#define PHY_HW_GP_CNT_RESET_END (PHY_PHYINITCTRL_PHYCONN_RST) + +/* RDQS range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_RDQS_MIDDLE_VAL 0x30 +/* DQ range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_DQ_MIDDLE_VAL 0x30303030 +#define PHY_MISC_SCRAMB_DIS 0xfffeffff /* scrambler disable */ +#define PHY_GATE_BDL_MAX 0xfe /* [6:0]rdqsg_bdl + [22:16]rdqsgtxbdl */ +#define PHY_DVRFTCTRL_PDAEN_EN 0x80000000 /* pda enable */ +/* [5] two cycle on address or command.(2T timing) */ +#define PHY_DRAMCFG_MA2T 0x20 + +#define PHY_DRAMCFG_TYPE_DDR1 0x0 /* [2:0] 000 DDR1 */ +#define PHY_DRAMCFG_TYPE_DDR2 0x1 /* [2:0] 001 DDR2 */ +#define PHY_DRAMCFG_TYPE_DDR3 0x2 /* [2:0] 010 DDR3 */ +#define PHY_DRAMCFG_TYPE_DDR3L 0x3 /* [2:0] 011 DDR3L */ +#define PHY_DRAMCFG_TYPE_LPDDR1 0x4 /* [2:0] 100 LPDDR1 */ +#define PHY_DRAMCFG_TYPE_LPDDR2 0x5 /* [2:0] 101 LPDDR2 */ +#define PHY_DRAMCFG_TYPE_LPDDR3 0x5 /* [2:0] 101 LPDDR3 */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ +#define PHY_DRAMCFG_TYPE_DDR4 0xa /* [3] 1010 DDR4 */ + +#define PHY_DMSEL_SWAPDFIBYTE 0xf8ffffff /* [24:26] No Swap */ + +/* AC_DDRPHY_GATED_BYPASS */ +#define PHY_CK_IOCTL_DUTY_EN 0x4 /* enable ck_ioctl_DUTY_EN_v */ +#define PHY_CK1_IOCTL_DUTY_EN 0x8 /* enable ck1_ioctl_DUTY_EN_v */ +/* CK AC_IOCTL22 */ +#ifndef DDR_DUTY_NUM +#define DDR_DUTY_NUM 13 /* CK duty number */ +#endif +#ifndef DDR_CK_NUM +#define DDR_CK_NUM 2 /* DDR CK number */ +#endif +#ifndef DDR_DUTY_CTL_NUM +#define DDR_DUTY_CTL_NUM 2 /* CK duty has two control direction */ +#endif +/* CK duty step. */ +#ifndef PHY_AC_IOCTL21_STEP +#define PHY_AC_IOCTL21_STEP 1 +#endif + +/* other */ +#define PHY_RDQSG_PHASE_STEP 2 /* gate training phase step. */ +#define PHY_GATE_PHASE_MARGIN 8 /* gate phase margin */ +#define PHY_DQ_BDL_LEVEL 128 /* [CUSTOM] DQ BDL range */ +#define PHY_DQ_BDL_MIDDLE 64 /* special middle DQ BDL value */ +#define PHY_RDQSG_PHASE_MAX 0x3c /* RDQSG phase max value */ +#define PHY_ACPHY_CLK_MAX 0xf /* halft_dramclk0 + cp1p_dclk0 */ +#define PHY_PCODE_MIN 0x14 +#define PHY_PCODE_MAX 0x24 +/** + * DDR_BDL_PHASE_REL Calculation Method: + * 1. Calculation How many picosecond to one phase. + * PICOSECOND : 1 second is (1000 * 1000 * 1000) picosecond + * WAVE : 1 cycle is 2 + * RATE : DDR rate is 1600 Mbps, is (1600 * 1000) bps + * PHASE : 1 wave is 12 phase + * phase = (((PICOSECOND * WAVE) / RATE) / PHASE) + * = (((1000 * 1000 * 1000 * 2) / (1600 * 1000)) / 12) + * = 104.17 ps. + * 2. Calculation How many bdl to one phase. + * one BDL is 6 ps. + * result = phase/bdl = 104.17 / 6 = 17.36 approximately equal to 17 ~= 16 + * 3. 16 = 1 << 4, so the relation is 4. + */ +#ifndef DDR_BDL_PHASE_TRANSFORM +/* [CUSTOM] one Phase equal how much BDL. 1 phase = 16 bdl */ +#define DDR_BDL_PHASE_TRANSFORM 16 +#endif +#ifndef DDR_BDL_PHASE_REL +/* [CUSTOM] relation between BDL and Phase. 1 phase = 16 bdl, 16 = 1 << 4 */ +#define DDR_BDL_PHASE_REL 4 +#endif + +#define DDR_VARIABLE_DECLARE(var) \ + unsigned int var; + + +#define DDR_VREF_GET_HOST_MAX(rank, val) \ + do { \ + if (0 == rank) \ + val = PHY_VRFTRES_HVREF_MASK; \ + else \ + val = PHY_VRFTRES_RXDIFFCAL_MASK; \ + } while (0) + +/* PHY t28 all byte use a same value */ +#define DDR_PHY_VREF_HOST_SET(base_phy, rank, bytenum, byte_index, val) \ + do { \ + unsigned int hvreft; \ + if (0 == rank) { \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & (~PHY_VRFTRES_HVREF_MASK); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index + 1)); \ + } else { \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & (~(PHY_VRFTRES_RXDIFFCAL_MASK << PHY_VRFTRES_RXDIFFCAL_BIT)); \ + ddr_write(hvreft | (val << PHY_VRFTRES_RXDIFFCAL_BIT), base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)); \ + ddr_write(hvreft | (val << PHY_VRFTRES_RXDIFFCAL_BIT), base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index + 1)); \ + } \ + } while (0) + +#define DDR_PHY_VREF_HOST_GET(base_phy, rank, byte_index, val) \ + do { \ + if (0 == rank) { \ + val = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & PHY_VRFTRES_HVREF_MASK; \ + } else { \ + val = (ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) >> PHY_VRFTRES_RXDIFFCAL_BIT) \ + & PHY_VRFTRES_RXDIFFCAL_MASK; \ + } \ + } while (0) + +#define DDR_PHY_VREF_HOST_DISPLAY \ + {0, 0, DDR_PHY_HVREFT_STATUS(0, 0), 0, "Host Vref Byte0"}, \ + {0, 1, DDR_PHY_HVREFT_STATUS(0, 1), 0, "Host Vref Byte1"}, \ + {0, 2, DDR_PHY_HVREFT_STATUS(0, 2), 0, "Host Vref Byte2"}, \ + {0, 3, DDR_PHY_HVREFT_STATUS(0, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_RANK1 \ + {1, 0, DDR_PHY_HVREFT_STATUS(1, 0), 0, "Host Vref Byte0"}, \ + {1, 1, DDR_PHY_HVREFT_STATUS(1, 1), 0, "Host Vref Byte1"}, \ + {1, 2, DDR_PHY_HVREFT_STATUS(1, 2), 0, "Host Vref Byte2"}, \ + {1, 3, DDR_PHY_HVREFT_STATUS(1, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_CMD(base_phy, rank, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] Host Vref Byte(%x)", \ + base_phy + DDR_PHY_HVREFT_STATUS(rank, _i), \ + ddr_read(base_phy \ + + DDR_PHY_HVREFT_STATUS(rank, _i)), _i); \ + } \ + } while (0) + +/* DRAM vref operations */ +#define DDR_PHY_VREF_DRAM_SET(base_phy, val, byte_index) \ + do { \ + unsigned int dvrftctrl = \ + ddr_read(base_phy + DDR_PHY_DVRFTCTRL); \ + unsigned int dvreft = ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & (~PHY_VRFTRES_DVREF_MASK); \ + ddr_write(dvrftctrl | PHY_DVRFTCTRL_PDAEN_EN, \ + base_phy + DDR_PHY_DVRFTCTRL); \ + ddr_write(dvreft | val, \ + base_phy + DDR_PHY_DVREFT_STATUS(byte_index)); \ + ddr_write(PHY_PHYINITCTRL_DVREFT_SYNC \ + | PHY_PHYINITCTRL_INIT_EN, \ + base_phy + DDR_PHY_PHYINITCTRL); \ + while (1) { \ + if (!(ddr_read(base_phy + DDR_PHY_PHYINITCTRL) \ + & PHY_PHYINITCTRL_INIT_EN)) \ + break; \ + } \ + ddr_write(dvrftctrl & (~PHY_DVRFTCTRL_PDAEN_EN), \ + base_phy + DDR_PHY_DVRFTCTRL); \ + } while (0) + +#define DDR_PHY_VREF_DRAM_GET(base_phy, val, byte_index) \ + { \ + val = ddr_read(base_phy + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & PHY_VRFTRES_DVREF_MASK; \ + } + +#define DDR_PHY_VREF_DRAM_DISPLAY \ + {0, 0, DDR_PHY_DVREFT_STATUS(0), 0, "DRAM Vref Byte0"}, \ + {0, 1, DDR_PHY_DVREFT_STATUS(1), 0, "DRAM Vref Byte1"}, \ + {0, 2, DDR_PHY_DVREFT_STATUS(2), 0, "DRAM Vref Byte2"}, \ + {0, 3, DDR_PHY_DVREFT_STATUS(3), 0, "DRAM Vref Byte3"}, + +#define DDR_PHY_VREF_DRAM_DISPLAY_CMD(base_phy, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] DRAM Vref Byte(%x)", \ + base_phy + DDR_PHY_DVREFT_STATUS(_i), \ + ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(_i)), _i); \ + } \ + } while (0) + +#define DDR_PHY_DCC_DISPLAY \ + {0, 0, DDR_PHY_ACIOCTL21, 0, "CK DUTY"}, + +#define DDR_PHY_DCC_DISPLAY_CMD(base_phy) \ + do { \ + unsigned int val; \ + val = ddr_read(base_phy + DDR_PHY_ACIOCTL21); \ + val = ddr_read(base_phy + DDR_PHY_ACIOCTL21); \ + DDR_INFO("[%x = %x] DCC duty", \ + base_phy + DDR_PHY_ACIOCTL21, val); \ + } while (0) + +#define DDR_PHY_ADDRPH_DISPLAY \ + {0, 0, DDR_PHY_ADDRPHBOUND, 0, "CA Phase"}, + +#define DDR_PHY_ADDRBDL_DISPLAY \ + {0, 0, DDR_PHY_ACADDRBDL(0), 0, "CA BDL(0)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(1), 0, "CA BDL(1)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(2), 0, "CA BDL(2)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(3), 0, "CA BDL(3)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(4), 0, "CA BDL(4)"}, + +#define DDR_PHY_ADDRPH_DISPLAY_CMD(base_phy) \ + DDR_INFO("[%x = %x] CA Phase", \ + base_phy + DDR_PHY_ADDRPHBOUND, \ + ddr_read(base_phy + DDR_PHY_ADDRPHBOUND)); + +#define DDR_PHY_ADDRBDL_DISPLAY_CMD(base_phy) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < DDR_PHY_CA_REG_MAX; _i++) { \ + DDR_INFO("[%x = %x] ACADDRBDL(%x)", \ + base_phy + DDR_PHY_ACADDRBDL(_i), \ + ddr_read(base_phy \ + + DDR_PHY_ACADDRBDL(_i)), _i); \ + } \ + } while (0) + +/* PHY t28 DDR4 RDQS synchronize to RDM */ +#define DDR_PHY_RDQS_SYNC_RDM(cfg, val) \ + ddr_rdqs_sync(cfg, val) + +/* dqs swap */ +#define DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy) \ + do { \ + swapdfibyte_en = \ + ddr_read(base_phy + DDR_PHY_DMSEL); \ + ddr_write(swapdfibyte_en & PHY_DMSEL_SWAPDFIBYTE, \ + base_phy + DDR_PHY_DMSEL); \ + } while (0) + +#define DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy) \ + ddr_write(swapdfibyte_en, base_phy + DDR_PHY_DMSEL); + +#define DDR_PHY_SWITCH_RANK(base_phy, val) \ + do { \ + ddr_write((ddr_read(base_phy + DDR_PHY_TRAINCTRL0) & (~PHY_TRAINCTRL0_MASK)) | val, base_phy + DDR_PHY_TRAINCTRL0); \ + ddr_write((ddr_read(base_phy + DDR_PHY_HVRFTCTRL) & (~(0x1 << PHY_HRXDIFFCAL_EN_BIT))) | (val << PHY_HRXDIFFCAL_EN_BIT), base_phy + DDR_PHY_HVRFTCTRL); \ + } while (0) + +/* Define the union U_PHY_CATCONFIG */ +union U_PHY_CATCONFIG { + /* Define the struct bits */ + struct { + unsigned int ca_samp_num_bdl:4; /* [3:0] */ + unsigned int ca_samp_num_ph:4; /* [7:4] */ + unsigned int ca_trysamp_num:4; /* [11:8] */ + unsigned int cat_rb_backtap:4; /* [15:12] */ + unsigned int reserved:1; /* [16] */ + unsigned int cat_openeye_en:1; /* [17] */ + unsigned int cat_cat_phydq_sel:1; /* [18] */ + unsigned int cat_restore_en:1; /* [19] */ + unsigned int cat_lb_backtap:4; /* [23:20] */ + unsigned int sw_cat_mrw42:1; /* [24] */ + unsigned int sw_cat_mrw48:1; /* [25] */ + unsigned int sw_cat_mrw41:1; /* [26] */ + unsigned int sw_cat_strobe:1; /* [27] */ + unsigned int sw_cat_cke_high:1; /* [28] */ + unsigned int sw_cat_cke_low:1; /* [29] */ + unsigned int sw_cat_dqvalid:1; /* [30] */ + unsigned int sw_cat_en:1; /* [31] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; + +/* Define the union U_PHY_ADDRPHBOUND */ +union U_PHY_ADDRPHBOUND { + /* Define the struct bits */ + struct { + unsigned int addrph_a_right:5; /* [4:0] */ + unsigned int reserved0:3; /* [7:5] */ + unsigned int addrph_a_left:5; /* [12:8] */ + unsigned int reserved1:3; /* [15:13] */ + unsigned int addrph_a:5; /* [20:16] */ + unsigned int reserved2:3; /* [23:21] */ + unsigned int addrph_a_ori:5; /* [28:24] */ + unsigned int reserved3:3; /* [31:29] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t16.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t16.h new file mode 100755 index 00000000..0b331cc9 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t16.h @@ -0,0 +1,458 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_phy_t16.h + * + * DDR PHY register offset address, mask, bit. + */ + +/* register offset address */ +/* base address: DDR_REG_BASE_PHY0 DDR_REG_BASE_PHY1 */ +/* control the initialization of the PHY */ +#define DDR_PHY_PHYINITCTRL 0x4 +#define DDR_PHY_PHYINITSTATUS 0x8 /* Read Data Eye Calibration Error*/ +#define DDR_PHY_IMPSTATUS 0x28 /* This register specify the ZQ calibration result. */ +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define DDR_PHY_TRAINCTRL0 0x48 /* hw training control */ +#define DDR_PHY_MODEREG01 0x64 /* Extend Mode Register 01 */ +#define DDR_PHY_MODEREG23 0x68 /* Extend Mode Register 23 */ +/* update delay setting in registers to PHY */ +#define DDR_PHY_MISC 0x70 +#define DDR_PHY_DMSEL 0x84 /* DM Swap Selection */ +#define DDR_PHY_SWTMODE 0xa0 /* S/W training mode */ +/* issue one DQS pulse from PHY to DRAM */ +#define DDR_PHY_SWTWLDQS 0xa4 +#define DDR_PHY_SWTRLT 0xa8 /* S/W training result*/ +/* Host vref. [5:0]range [17:12]refsel */ +#define DDR_PHY_IOCTL2 0xB4 +#define DDR_PHY_VREFTCTRL 0xc0 /* VREF Training Control Register. */ +#define DDR_PHY_DVRFTCTRL 0xC4 /* DRAM VREF Training */ +#define DDR_PHY_ACADDRBDL(n) (0x140 + ((n) << 2)) +#define DDR_PHY_IMP_CTRL1 0x170 /* AC/DX ZQ selection */ +#define DDR_PHY_IMP_STATUS1 0x174 /* AC ZCAL status */ +#define DDR_PHY_CATSWAPINDEX 0x01B8 /* CA SWAP index register */ +#define DDR_PHY_CATSWAPSEL 0x01BC /* CA SWAP select register*/ +#define DDR_PHY_CATCONFIG 0x1C8 /* CA Training Configuration */ +#define DDR_PHY_PHYDQRESULT 0x1D0 /* SW CA Training DQ result from PHY */ +#define DDR_PHY_ADDRPHBOUND 0x1D4 /* CA Training addr phase boundary */ +#define DDR_PHY_SWCATPATTERN_P 0x1D8 /* pattern for positive CK edge */ +#define DDR_PHY_SWCATPATTERN_N 0x1DC /* pattern for negative CK edge */ +/* AC command bit delay line setting */ +#define DDR_PHY_ACCMDBDL2 0x128 + +/* WR DQ0-DQ3 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line +on write path */ +#define DDR_PHY_DXNWDQNBDL0(m, n) (0x210 + ((m) << 10) + ((n) << 7)) +/* WR DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] */ +#define DDR_PHY_DXNWDQNBDL1(m, n) (0x214 + ((m) << 10) + ((n) << 7)) +/* WR DM [6:0] the delay value of the bit delay line on DQM */ +#define DDR_PHY_DXNWDQNBDL2(m, n) (0x218 + ((m) << 10) + ((n) << 7)) +/* RD DQ0-DQ3 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL0(m, n) (0x21C + ((m) << 10) + ((n) << 7)) +/* RD DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL1(m, n) (0x220 + ((m) << 10) + ((n) << 7)) +/* [6:0]RD DM*/ +#define DDR_PHY_DXNRDQNBDL2(m, n) (0x224 + ((m) << 10) + ((n) << 7)) + +/* [CUSTOM] */ +#define DDR_PHY_DXNOEBDL(m, n) (0x228 + ((m) << 10) + ((n) << 7)) +/* [8:0] rdqs_bdl [24:16]rdqs_cyc. +phase shift of the Read DQS to create 90 degree delays*/ +#define DDR_PHY_DXNRDQSDLY(n) (0x22C + ((n) << 7)) +/* [6:0] the delay value of delay applied on WDQS for write leveling */ +#define DDR_PHY_DXWDQSDLY(m, n) (0x230 + ((m) << 10) + ((n) << 7)) +/* WR DQ phase BIT 12:8 */ +#define DDR_PHY_DXNWDQDLY(m, n) (0x234 + ((m) << 10) + ((n) << 7)) +/* [CUSTOM] rddqs gating*/ +#define DDR_PHY_DXNRDQSGDLY(m, n) (0x240 + ((m) << 10) + ((n) << 7)) +/* read boundary right 8:0 left 24:16 */ +#define DDR_PHY_DXNRDBOUND(n) (0x250 + ((n) << 7)) +/* write boundary right 4:0 left 20:16 */ +#define DDR_PHY_DXNWDBOUND(n) (0x254 + ((n) << 7)) +/* [5:0] DRAM VREF(DQ) training result */ +#define DDR_PHY_DVREFT_STATUS(n) (0x270 + ((n) << 7)) +/* [4:0] Host PHY VREF(DQ) training result */ +#define DDR_PHY_HVREFT_STATUS(n) (0x274 + ((n) << 7)) + +/* DDRPHY AC static register */ +#define DDR_PHY_CORNER_DETECTOR 0x104C /* cfg of corner detector */ +#define DDR_PHY_ACPHYCTL4 0x1064 /* AC block PHY control register*/ +#define DDR_PHY_ACPHYCTL7 0x1070 + +#define DDR_VREF_HOST_VAL_MAX (0x3f) /* 78.75%*VDDIO */ +#define DDR_VREF_HOST_VAL_MIN (0x0) /* 40.00%*VDDIO */ + +/* register mask */ +#define PHY_BDL_MASK 0x7f /* [6:0] */ +#define PHY_WDQS_PHASE_MASK 0xf /* [11:8] */ +#define PHY_RDQS_BDL_MASK 0x1ff /* [CUSTOM] [8:0] rdqsbdl*/ +#define PHY_RDQSG_PHASE_MASK 0x3f /* [14:9] rdqsgtxbdl */ +#define PHY_RDM_BDL_MASK 0x7f /* [6:0] */ +/* hardware gate training result */ +#define PHY_INITSTATUS_GT_MASK 0x20 +#define PHY_SWTRLT_WL_MASK 0xf +#define PHY_SWTRLT_GATE_MASK 0xf +#define PHY_WDQ_PHASE_MASK 0x1f +#define PHY_PHYINITCTRL_MASK 0xffff /* [15:0] all stat */ +/* Read Data Eye Calibration Error */ +#define PHY_PHYINITSTATUS_RDET_ERR 0x100 +#define PHY_ACPHY_DCLK_MASK 0x7 /* cp1p_dclk0 mask */ +#define PHY_ACPHY_DRAMCLK_MASK 0x1 /* halft_dramclk0 mask */ +#define PHY_VRFTRES_DVREF_MASK 0x3f /* [5:0] */ +#define PHY_VRFTRES_HVREF_MASK 0x3f /* [4:0] */ +#define PHY_VRFTRES_RXDIFFCAL_MASK 0xf /* [24:21] */ +#define PHY_ADDRPH_MASK 0x1f /* [20:16] */ +#define PHY_ACADDR_BDL_MASK 0x7f /* [6:0] */ +#define PHY_CATSWAPSEL_BIT_MASK 0xff +#define PHY_CAT_PATTERN_MASK 0x3ff +#define PHY_TRAINCTRL0_MASK 0xf /* [3:0] */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_OSC_START_MASK 0x1 /* [0] */ +#define PHY_OSC_RPT_VLD_MASK 0x1 /* [15] */ +#define PHY_OSC_CNT_RDATA_MASK 0xffff /* [31:16] */ +#define PHY_ZCODE_PDRV_MASK 0x3f /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_MASK 0x3f /* [29:24] */ + +/* register bit */ +#define PHY_MISC_UPDATE_BIT 19 /* [CUSTOM] delay config update bit */ +#define PHY_PHYCONN_RST_BIT 15 /* issue reset signal to PHY counter */ +#define PHY_RDQSG_PHASE_BIT 9 /* [CUSTOM] */ +#define PHY_RDQSG_TX_BDL_BIT 16 /* [22:16] rdqsgtxbdl */ +#define PHY_WDQS_PHASE_BIT 8 +#define PHY_WDQS_BDL_BIT 0 +#define PHY_WDQ_PHASE_BIT 8 +#define PHY_WDM_BDL_BIT 0 +/* [22:16] Write DQS Output Enable Delay Control */ +#define PHY_WDQSOE_BDL_BIT 16 +#define PHY_OEN_BDL_BIT 0 +/* Mode Register 1. Defines the MR3/MR9 of the mode register */ +#define PHY_MODEREG01_MR1_BIT 16 +/* Bit delay line setting of CS1 */ +#define PHY_ACCMD_CS0_BIT 0 +#define PHY_ACCMD_CS1_BIT 16 +#define PHY_ACPHY_DCLK0_BIT 6 /* [8:6] cp1p_dclk0 */ +#define PHY_ACPHY_DCLK1_BIT 9 /* [11:9] ck2p_dclk1 */ +#define PHY_ACPHY_DRAMCLK0_BIT 25 /* [25] halft_dramclk0 */ +#define PHY_ACPHY_DRAMCLK1_BIT 24 /* [24] halft_dramclk1 */ +#define PHY_ACPHY_DRAMCLK_EXT_BIT 3 /* [3] halft_dramclk0 */ +#define PHY_SWTMODE_SW_GTMODE_BIT 1 /* [1] SW gate training */ +#define PHY_ACADDRBDL_ADDR1_BIT 16 /* [16] ADDR1 delay line */ +#define PHY_VREFS_MRS_ENTER_BIT 31 /* [31] */ +#define PHY_OSC_RPT_VLD 15 /* [15] */ +#define PHY_OSC_CNT_RDATA_BIT 16 /* [31:16] */ +#define PHY_ZCODE_PDRV_BIT 16 /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_BIT 24 /* [29:24] */ +#define PHY_AC_VDDQ_CAL_EN_BIT 8 /* [8] AC ZQ calibration enable */ + +/* BDL register bit */ +#define PHY_BDL_DQ_BIT 0 +#define PHY_BDL_DQ0_BIT 0 +#define PHY_BDL_DQ1_BIT 8 +#define PHY_BDL_DQ2_BIT 16 +#define PHY_BDL_DQ3_BIT 24 +#define PHY_RDM_BDL_BIT 0 +#define PHY_RDQS_BDL_BIT 0 + +/* value */ +#define PHY_PHYINITCTRL_DVREFT_SYNC 0x40000 /* DRAM VREF Synchronize */ +#define PHY_TRAINCTRL0_DTR_RANK0 0x0 /* Training Rank0. */ +#define PHY_TRAINCTRL0_DTR_RANK1 0x1 /* Training Rank1. */ +/* hw training item defined in PHYINITCTRL */ +#define PHY_PHYINITCTRL_CTL_CKE_BYPASS (1 << 31) /* PACK's CKE bypass function enable. */ +#define PHY_PHYINITCTRL_PIC_PHYUPD_REQ (1 << 30) /* PACK's DFI PHY UPDATAE request by SW. */ +#define PHY_PHYINITCTRL_PIC_TDQSST (1 << 29) /* TDQSS training Enable. */ +#define PHY_PHYINITCTRL_LP4_CHB_DIS (1 << 28) /* LPDDR4 channel-B disable. */ +#define PHY_PHYINITCTRL_LP4_CHA_DIS (1 << 27) /* LPDDR4 channel-A disable. */ +#define PHY_PHYINITCTRL_PIC_REFRET_SFT (1 << 26) /* Update delay line(switch op_sel) during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_WR (1 << 25) /* Retraining with MPC write during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_RD (1 << 24) /* Retraining with MPC read during tRFC. */ +#define PHY_PHYINITCTRL_JTMT_EN (1 << 23) /* PLL Jitter Meter Enable. */ +#define PHY_PHYINITCTRL_CST_EN (1 << 22) /* HW CS Traninig Enable. */ +#define PHY_PHYINITCTRL_ACDVREFS_EN (1 << 21) /* DRAM VREF(AC) Synchronize Operations. */ +#define PHY_PHYINITCTRL_ACHVREFT_EN (1 << 20) /* Host VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_ACDVREFT_EN (1 << 19) /* DRAM VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_DXDVREFS_EN (1 << 18) /* DRAM VREF(DQ) Synchronize Operations. */ +#define PHY_PHYINITCTRL_HVREFT_EN (1 << 17) /* Host VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_DVREFT_EN (1 << 16) /* DRAM VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_PHYCONN_RST (1 << 15) /* PHY Counter Reset. */ +#define PHY_PHYINITCTRL_PACK_RST (1 << 14) /* PACK Reset. */ +#define PHY_PHYINITCTRL_PHY_RST (1 << 13) /* PHY Reset. */ +#define PHY_PHYINITCTRL_DRAM_RST (1 << 12) /* DRAM Reset. */ +#define PHY_PHYINITCTRL_CAT_EN (1 << 11) /* HW CA Traninig Enable. */ +#define PHY_PHYINITCTRL_DRAM_INIT_EN (1 << 10) /* DRAM Initialization Enable. */ +#define PHY_PHYINITCTRL_WDET_EN (1 << 9) /* Write Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_RDET_EN (1 << 8) /* Read Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_WL2_EN (1 << 7) /* Second Write Leveling Enable. */ +#define PHY_PHYINITCTRL_GDST_EN (1 << 6) /* PHY Read Data Latch Train Enable. */ +#define PHY_PHYINITCTRL_GT_EN (1 << 5) /* Gate Training Enable. */ +#define PHY_PHYINITCTRL_WL_EN (1 << 4) /* Write Leveling Enable. */ +#define PHY_PHYINITCTRL_ZCAL_EN (1 << 3) /* Impedance Calibration Enable. */ +#define PHY_PHYINITCTRL_DLYMEAS_EN (1 << 2) /* Delay Measurement Enable. */ +#define PHY_PHYINITCTRL_PLL_INIT_EN (1 << 1) /* PLL Initialization Enable. */ +#define PHY_PHYINITCTRL_INIT_EN (1 << 0) /* PHY Initialization Enable. */ + +#define PHY_HW_GP_PHY_RESET (PHY_PHYINITCTRL_PHY_RST) +#define PHY_HW_GP_CNT_RESET_START (PHY_PHYINITCTRL_PHYCONN_RST) +#define PHY_HW_GP_PLL (PHY_PHYINITCTRL_PLL_INIT_EN | PHY_PHYINITCTRL_ZCAL_EN | PHY_PHYINITCTRL_DLYMEAS_EN) +#define PHY_HW_GP_DRAM_RESET (PHY_PHYINITCTRL_DRAM_RST | PHY_PHYINITCTRL_DRAM_INIT_EN) +#define PHY_HW_GP_VREF_AC (PHY_PHYINITCTRL_ACDVREFS_EN) +#define PHY_HW_GP_CS (PHY_PHYINITCTRL_CST_EN) +#define PHY_HW_GP_VREF_DQ (PHY_PHYINITCTRL_DVREFT_SYNC) +#define PHY_HW_GP_NORMAL (PHY_PHYINITCTRL_WL_EN \ + | PHY_PHYINITCTRL_GT_EN \ + | PHY_PHYINITCTRL_GDST_EN \ + | PHY_PHYINITCTRL_WL2_EN \ + | PHY_PHYINITCTRL_RDET_EN \ + | PHY_PHYINITCTRL_WDET_EN \ + | PHY_PHYINITCTRL_DVREFT_EN \ + | PHY_PHYINITCTRL_HVREFT_EN \ + | PHY_PHYINITCTRL_PIC_TDQSST) +#define PHY_HW_GP_CNT_RESET_END (PHY_PHYINITCTRL_PHYCONN_RST) + +/* RDQS range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_RDQS_MIDDLE_VAL 0x30 +/* DQ range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_DQ_MIDDLE_VAL 0x30303030 +#define PHY_MISC_SCRAMB_DIS 0xfffeffff /* scrambler disable */ +#define PHY_GATE_BDL_MAX 0xfe /* [6:0]rdqsg_bdl + [22:16]rdqsgtxbdl */ +#define PHY_DVRFTCTRL_PDAEN_EN 0x80000000 /* pda enable */ +/* [5] two cycle on address or command.(2T timing) */ +#define PHY_DRAMCFG_MA2T 0x20 + +#define PHY_DRAMCFG_TYPE_DDR1 0x0 /* [2:0] 000 DDR1 */ +#define PHY_DRAMCFG_TYPE_DDR2 0x1 /* [2:0] 001 DDR2 */ +#define PHY_DRAMCFG_TYPE_DDR3 0x2 /* [2:0] 010 DDR3 */ +#define PHY_DRAMCFG_TYPE_DDR3L 0x3 /* [2:0] 011 DDR3L */ +#define PHY_DRAMCFG_TYPE_LPDDR1 0x4 /* [2:0] 100 LPDDR1 */ +#define PHY_DRAMCFG_TYPE_LPDDR2 0x5 /* [2:0] 101 LPDDR2 */ +#define PHY_DRAMCFG_TYPE_LPDDR3 0x5 /* [2:0] 101 LPDDR3 */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ +#define PHY_DRAMCFG_TYPE_DDR4 0xa /* [3] 1010 DDR4 */ + +#define PHY_DMSEL_SWAPDFIBYTE 0xf8ffffff /* [24:26] No Swap */ + +/* other */ +#define PHY_RDQSG_PHASE_STEP 2 /* gate training phase step. */ +#define PHY_GATE_PHASE_MARGIN 8 /* gate phase margin */ +#define PHY_DQ_BDL_LEVEL 128 /* [CUSTOM] DQ BDL range */ +#define PHY_DQ_BDL_MIDDLE 48 /* special middle DQ BDL value */ +#define PHY_RDQSG_PHASE_MAX 0x3c /* RDQSG phase max value */ +#define PHY_ACPHY_CLK_MAX 0xf /* halft_dramclk0 + cp1p_dclk0 */ +#define PHY_PCODE_MIN 0x14 +#define PHY_PCODE_MAX 0x24 +/** + * DDR_BDL_PHASE_REL Calculation Method: + * 1. Calculation How many picosecond to one phase. + * PICOSECOND : 1 second is (1000 * 1000 * 1000) picosecond + * WAVE : 1 cycle is 2 + * RATE : DDR rate is 1600 Mbps, is (1600 * 1000) bps + * PHASE : 1 wave is 12 phase + * phase = (((PICOSECOND * WAVE) / RATE) / PHASE) + * = (((1000 * 1000 * 1000 * 2) / (1600 * 1000)) / 12) + * = 104.17 ps. + * 2. Calculation How many bdl to one phase. + * one BDL is 6 ps. + * result = phase/bdl = 104.17 / 6 = 17.36 approximately equal to 17 ~= 16 + * 3. 16 = 1 << 4, so the relation is 4. + */ +#ifndef DDR_BDL_PHASE_TRANSFORM +/* [CUSTOM] one Phase equal how much BDL. 1 phase = 16 bdl */ +#define DDR_BDL_PHASE_TRANSFORM 16 +#endif +#ifndef DDR_BDL_PHASE_REL +/* [CUSTOM] relation between BDL and Phase. 1 phase = 16 bdl, 16 = 1 << 4 */ +#define DDR_BDL_PHASE_REL 4 +#endif + +#define DDR_VARIABLE_DECLARE(var) \ + unsigned int var; + +#define DDR_VREF_GET_HOST_MAX(rank, val) \ + do { \ + if (0 == rank) \ + val = PHY_VRFTRES_HVREF_MASK; \ + else \ + val = PHY_VRFTRES_RXDIFFCAL_MASK; \ + } while (0) + +/* PHY t28 all byte use a same value */ +#define DDR_PHY_VREF_HOST_SET(base_phy, rank, bytenum, byte_index, val) \ + do { \ + int i = 0; \ + unsigned int hvreft; \ + for (i = 0; i < bytenum; i++) { \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(i)) \ + & (~PHY_VRFTRES_HVREF_MASK); \ + ddr_write(hvreft | val, \ + base_phy + DDR_PHY_HVREFT_STATUS(i)); \ + } \ + } while (0) + +#define DDR_PHY_VREF_HOST_GET(base_phy, rank, byte_index, val) \ + { \ + val = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(0)) \ + & PHY_VRFTRES_HVREF_MASK; \ + } + +#define DDR_PHY_VREF_HOST_DISPLAY \ + {0, 0, DDR_PHY_HVREFT_STATUS(0), 0, "Host Vref Byte0"}, \ + {0, 1, DDR_PHY_HVREFT_STATUS(1), 0, "Host Vref Byte1"}, \ + {0, 2, DDR_PHY_HVREFT_STATUS(2), 0, "Host Vref Byte2"}, \ + {0, 3, DDR_PHY_HVREFT_STATUS(3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_RANK1 + +#define DDR_PHY_VREF_HOST_DISPLAY_CMD(base_phy, rank, byte_num) \ + do { \ + for (i = 0; i < byte_num; i++) { \ + DDR_INFO("[%x = %x] Host Vref Byte(%x)", \ + base_phy + DDR_PHY_HVREFT_STATUS(i), \ + ddr_read(base_phy \ + + DDR_PHY_HVREFT_STATUS(i)), i); \ + } \ + } while (0) + +/* DRAM vref operations */ +#define DDR_PHY_VREF_DRAM_SET(base_phy, val, byte_index) \ + do { \ + unsigned int dvrftctrl = \ + ddr_read(base_phy + DDR_PHY_DVRFTCTRL); \ + unsigned int dvreft = ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & (~PHY_VRFTRES_DVREF_MASK); \ + ddr_write(dvrftctrl | PHY_DVRFTCTRL_PDAEN_EN, \ + base_phy + DDR_PHY_DVRFTCTRL); \ + ddr_write(dvreft | val, \ + base_phy + DDR_PHY_DVREFT_STATUS(byte_index)); \ + ddr_write(PHY_PHYINITCTRL_DVREFT_SYNC \ + | PHY_PHYINITCTRL_INIT_EN, \ + base_phy + DDR_PHY_PHYINITCTRL); \ + while (1) { \ + if (!(ddr_read(base_phy + DDR_PHY_PHYINITCTRL) \ + & PHY_PHYINITCTRL_INIT_EN)) \ + break; \ + } \ + ddr_write(dvrftctrl & (~PHY_DVRFTCTRL_PDAEN_EN), \ + base_phy + DDR_PHY_DVRFTCTRL); \ + } while (0) + +#define DDR_PHY_VREF_DRAM_GET(base_phy, val, byte_index) \ + { \ + val = ddr_read(base_phy + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & PHY_VRFTRES_DVREF_MASK; \ + } + +#define DDR_PHY_VREF_DRAM_DISPLAY \ + {0, 0, DDR_PHY_DVREFT_STATUS(0), 0, "DRAM Vref Byte0"}, \ + {0, 1, DDR_PHY_DVREFT_STATUS(1), 0, "DRAM Vref Byte1"}, \ + {0, 2, DDR_PHY_DVREFT_STATUS(2), 0, "DRAM Vref Byte2"}, \ + {0, 3, DDR_PHY_DVREFT_STATUS(3), 0, "DRAM Vref Byte3"}, + +#define DDR_PHY_VREF_DRAM_DISPLAY_CMD(base_phy, byte_num) \ + do { \ + for (i = 0; i < byte_num; i++) { \ + DDR_INFO("[%x = %x] DRAM Vref Byte(%x)", \ + base_phy + DDR_PHY_DVREFT_STATUS(i), \ + ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(i)), i); \ + } \ + } while (0) + +/* phy t16 not support DCC training */ +#define DDR_PHY_DCC_DISPLAY +#define DDR_PHY_DCC_DISPLAY_CMD(base_phy) + +/* lowpower ddr ca operations */ +#define DDR_PHY_ADDRPH_DISPLAY \ + {0, 0, DDR_PHY_ADDRPHBOUND, 0, "CA Phase"}, + +#define DDR_PHY_ADDRBDL_DISPLAY \ + {0, 0, DDR_PHY_ACADDRBDL(0), 0, "CA BDL(0)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(1), 0, "CA BDL(1)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(2), 0, "CA BDL(2)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(3), 0, "CA BDL(3)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(4), 0, "CA BDL(4)"}, + +#define DDR_PHY_ADDRPH_DISPLAY_CMD(base_phy) \ + DDR_INFO("[%x = %x] CA Phase", \ + base_phy + DDR_PHY_ADDRPHBOUND, \ + ddr_read(base_phy + DDR_PHY_ADDRPHBOUND)); + +#define DDR_PHY_ADDRBDL_DISPLAY_CMD(base_phy) \ + do { \ + for (i = 0; i < DDR_PHY_CA_REG_MAX; i++) { \ + DDR_INFO("[%x = %x] ACADDRBDL(%x)", \ + base_phy + DDR_PHY_ACADDRBDL(i), \ + ddr_read(base_phy \ + + DDR_PHY_ACADDRBDL(i)), i); \ + } \ + } while (0) + +/* PHY t28 DDR4 RDQS synchronize to RDM */ +#define DDR_PHY_RDQS_SYNC_RDM(cfg, val) \ + ddr_rdqs_sync(cfg, val) + +/* dqs swap */ +#define DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy) \ + do { \ + swapdfibyte_en = \ + ddr_read(base_phy + DDR_PHY_DMSEL); \ + ddr_write(swapdfibyte_en & PHY_DMSEL_SWAPDFIBYTE, \ + base_phy + DDR_PHY_DMSEL); \ + } while (0) + +#define DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy) \ + ddr_write(swapdfibyte_en, base_phy + DDR_PHY_DMSEL); + +/* phy t16 not support rank switch */ +#define DDR_PHY_SWITCH_RANK(base_phy, val) + +/* Define the union U_PHY_CATCONFIG */ +union U_PHY_CATCONFIG { + /* Define the struct bits */ + struct { + unsigned int ca_samp_num_bdl:4; /* [3:0] */ + unsigned int ca_samp_num_ph:4; /* [7:4] */ + unsigned int ca_trysamp_num:4; /* [11:8] */ + unsigned int cat_rb_backtap:4; /* [15:12] */ + unsigned int reserved:1; /* [16] */ + unsigned int cat_openeye_en:1; /* [17] */ + unsigned int cat_cat_phydq_sel:1; /* [18] */ + unsigned int cat_restore_en:1; /* [19] */ + unsigned int cat_lb_backtap:4; /* [23:20] */ + unsigned int sw_cat_mrw42:1; /* [24] */ + unsigned int sw_cat_mrw48:1; /* [25] */ + unsigned int sw_cat_mrw41:1; /* [26] */ + unsigned int sw_cat_strobe:1; /* [27] */ + unsigned int sw_cat_cke_high:1; /* [28] */ + unsigned int sw_cat_cke_low:1; /* [29] */ + unsigned int sw_cat_dqvalid:1; /* [30] */ + unsigned int sw_cat_en:1; /* [31] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; + +/* Define the union U_PHY_ADDRPHBOUND */ +union U_PHY_ADDRPHBOUND { + /* Define the struct bits */ + struct { + unsigned int addrph_a_right:5; /* [4:0] */ + unsigned int reserved0:3; /* [7:5] */ + unsigned int addrph_a_left:5; /* [12:8] */ + unsigned int reserved1:3; /* [15:13] */ + unsigned int addrph_a:5; /* [20:16] */ + unsigned int reserved2:3; /* [23:21] */ + unsigned int addrph_a_ori:5; /* [28:24] */ + unsigned int reserved3:3; /* [31:29] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t28.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t28.h new file mode 100755 index 00000000..a4e13b82 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_phy_t28.h @@ -0,0 +1,459 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +/* register offset address */ +/* base address: DDR_REG_BASE_PHY0 DDR_REG_BASE_PHY1 */ +/* control the initialization of the PHY */ +#define DDR_PHY_PHYINITCTRL 0x4 +#define DDR_PHY_PHYINITSTATUS 0x8 /* Read Data Eye Calibration Error*/ +#define DDR_PHY_IMPSTATUS 0x28 /* This register specify the ZQ calibration result. */ +#define DDR_PHY_DRAMCFG 0x2c /* DRAM config register */ +#define DDR_PHY_TRAINCTRL0 0x48 /* hw training control */ +#define DDR_PHY_MODEREG01 0x64 /* Extend Mode Register 01 */ +#define DDR_PHY_MODEREG23 0x68 /* Extend Mode Register 23 */ +/* update delay setting in registers to PHY */ +#define DDR_PHY_MISC 0x70 +#define DDR_PHY_DMSEL 0x84 /* DM Swap Selection */ +#define DDR_PHY_SWTMODE 0xa0 /* S/W training mode */ +/* issue one DQS pulse from PHY to DRAM */ +#define DDR_PHY_SWTWLDQS 0xa4 +#define DDR_PHY_SWTRLT 0xa8 /* S/W training result*/ +/* Host vref. [5:0]range [17:12]refsel */ +#define DDR_PHY_PHYRSCTRL 0xB0 /* PHY Register Slice Contrl */ +#define DDR_PHY_IOCTL2 0xB4 +#define DDR_PHY_VREFTCTRL 0xc0 /* VREF Training Control Register. */ +#define DDR_PHY_DVRFTCTRL 0xC4 /* DRAM VREF Training */ +#define DDR_PHY_ACADDRBDL(n) (0x140 + ((n) << 2)) +#define DDR_PHY_IMP_CTRL1 0x170 /* AC/DX ZQ selection */ +#define DDR_PHY_IMP_STATUS1 0x174 /* AC ZCAL status */ +#define DDR_PHY_CATSWAPINDEX 0x01B8 /* CA SWAP index register */ +#define DDR_PHY_CATSWAPSEL 0x01BC /* CA SWAP select register*/ +#define DDR_PHY_CATCONFIG 0x1C8 /* CA Training Configuration */ +#define DDR_PHY_PHYDQRESULT 0x1D0 /* SW CA Training DQ result from PHY */ +#define DDR_PHY_ADDRPHBOUND 0x1D4 /* CA Training addr phase boundary */ +#define DDR_PHY_SWCATPATTERN_P 0x1D8 /* pattern for positive CK edge */ +#define DDR_PHY_SWCATPATTERN_N 0x1DC /* pattern for negative CK edge */ +/* AC command bit delay line setting */ +#define DDR_PHY_ACCMDBDL2 0x128 + +/* WR DQ0-DQ3 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line +on write path */ +#define DDR_PHY_DXNWDQNBDL0(m, n) (0x210 + ((m) << 10) + ((n) << 7)) +/* WR DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] */ +#define DDR_PHY_DXNWDQNBDL1(m, n) (0x214 + ((m) << 10) + ((n) << 7)) +/* WR DM [6:0] the delay value of the bit delay line on DQM */ +#define DDR_PHY_DXNWDQNBDL2(m, n) (0x218 + ((m) << 10) + ((n) << 7)) +/* RD DQ0-DQ3 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL0(m, n) (0x21C + ((m) << 10) + ((n) << 7)) +/* RD DQ4-DQ7 [6:0] [14:8] [22:16] [30:24] delay value of the bit delay line + on read path */ +#define DDR_PHY_DXNRDQNBDL1(m, n) (0x220 + ((m) << 10) + ((n) << 7)) +/* [6:0]RD DM*/ +#define DDR_PHY_DXNRDQNBDL2(m, n) (0x224 + ((m) << 10) + ((n) << 7)) + + +/* [CUSTOM] */ +#define DDR_PHY_DXNOEBDL(m, n) (0x228 + ((m) << 10) + ((n) << 7)) +/* [8:0] rdqs_bdl [24:16]rdqs_cyc. +phase shift of the Read DQS to create 90 degree delays*/ +#define DDR_PHY_DXNRDQSDLY(n) (0x22C + ((n) << 7)) +/* [6:0] the delay value of delay applied on WDQS for write leveling */ +#define DDR_PHY_DXWDQSDLY(m, n) (0x230 + ((m) << 10) + ((n) << 7)) +/* WR DQ phase BIT 12:8 */ +#define DDR_PHY_DXNWDQDLY(m, n) (0x234 + ((m) << 10) + ((n) << 7)) +/* [CUSTOM] rddqs gating*/ +#define DDR_PHY_DXNRDQSGDLY(m, n) (0x240 + ((m) << 10) + ((n) << 7)) +/* read boundary right 8:0 left 24:16 */ +#define DDR_PHY_DXNRDBOUND(n) (0x250 + ((n) << 7)) +/* write boundary right 4:0 left 20:16 */ +#define DDR_PHY_DXNWDBOUND(n) (0x254 + ((n) << 7)) +/* [5:0] DRAM VREF(DQ) training result */ +#define DDR_PHY_DVREFT_STATUS(n) (0x270 + ((n) << 7)) +/* [4:0] Host PHY VREF(DQ) training result */ +#define DDR_PHY_HVREFT_STATUS(m, n) (0x274 + ((m) << 10) + ((n) << 7)) + +/* DDRPHY AC static register */ +#define DDR_PHY_CORNER_DETECTOR 0x104C /* cfg of corner detector */ +#define DDR_PHY_ACPHYCTL4 0x1064 /* AC block PHY control register*/ +#define DDR_PHY_ACPHYCTL7 0x1070 + +#define DDR_VREF_HOST_VAL_MAX (0x1f) /* 78.75%*VDDIO */ +#define DDR_VREF_HOST_VAL_MIN (0x0) /* 40.00%*VDDIO */ + +/* register mask */ +#define PHY_BDL_MASK 0x7f /* [6:0] */ +#define PHY_WDQS_PHASE_MASK 0xf /* [11:8] */ +#define PHY_RDQS_BDL_MASK 0x1ff /* [CUSTOM] [8:0] rdqsbdl*/ +#define PHY_RDQSG_PHASE_MASK 0x3f /* [14:9] rdqsgphase */ +#define PHY_RDM_BDL_MASK 0x7f /* [6:0] */ +/* hardware gate training result */ +#define PHY_INITSTATUS_GT_MASK 0x20 +#define PHY_SWTRLT_WL_MASK 0xf +#define PHY_SWTRLT_GATE_MASK 0xf +#define PHY_WDQ_PHASE_MASK 0x1f +#define PHY_PHYINITCTRL_MASK 0x1 /* [15:0] all stat */ +/* Read Data Eye Calibration Error */ +#define PHY_PHYINITSTATUS_RDET_ERR 0x100 +#define PHY_ACPHY_DCLK_MASK 0x7 /* cp1p_dclk0 mask */ +#define PHY_ACPHY_DRAMCLK_MASK 0x1 /* halft_dramclk0 mask */ +#define PHY_VRFTRES_DVREF_MASK 0x3f /* [5:0] */ +#define PHY_VRFTRES_HVREF_MASK 0x1f /* [4:0] */ +#define PHY_VRFTRES_RXDIFFCAL_MASK 0xf /* [24:21] */ +#define PHY_ADDRPH_MASK 0x1f /* [20:16] */ +#define PHY_ACADDR_BDL_MASK 0x7f /* [6:0] */ +#define PHY_CATSWAPSEL_BIT_MASK 0xff +#define PHY_CAT_PATTERN_MASK 0x3ff +#define PHY_TRAINCTRL0_MASK 0xf /* [3:0] */ +#define PHY_DRAMCFG_TYPE_MASK 0xf /* [3:0] */ +#define PHY_OSC_START_MASK 0x1 /* [0] */ +#define PHY_OSC_RPT_VLD_MASK 0x1 /* [15] */ +#define PHY_OSC_CNT_RDATA_MASK 0xffff /* [31:16] */ +#define PHY_ZCODE_PDRV_MASK 0x3f /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_MASK 0x3f /* [29:24] */ + +/* register bit */ +#define PHY_MISC_UPDATE_BIT 19 /* [CUSTOM] delay config update bit */ +#define PHY_PHYCONN_RST_BIT 15 /* issue reset signal to PHY counter */ +#define PHY_RDQSG_PHASE_BIT 9 /* [CUSTOM] */ +#define PHY_RDQSG_TX_BDL_BIT 16 /* [22:16] rdqsgtxbdl */ +#define PHY_WDQS_PHASE_BIT 8 +#define PHY_WDQS_BDL_BIT 0 +#define PHY_WDQ_PHASE_BIT 8 +#define PHY_WDM_BDL_BIT 0 +/* [22:16] Write DQS Output Enable Delay Control */ +#define PHY_WDQSOE_BDL_BIT 16 +#define PHY_OEN_BDL_BIT 0 +/* Mode Register 1. Defines the MR3/MR9 of the mode register */ +#define PHY_MODEREG01_MR1_BIT 16 +/* Bit delay line setting of CS1 */ +#define PHY_ACCMD_CS0_BIT 0 +#define PHY_ACCMD_CS1_BIT 16 +#define PHY_ACPHY_DCLK0_BIT 6 /* [8:6] cp1p_dclk0 */ +#define PHY_ACPHY_DCLK1_BIT 9 /* [11:9] ck2p_dclk1 */ +#define PHY_ACPHY_DRAMCLK0_BIT 25 /* [25] halft_dramclk0 */ +#define PHY_ACPHY_DRAMCLK1_BIT 24 /* [24] halft_dramclk1 */ +#define PHY_ACPHY_DRAMCLK_EXT_BIT 3 /* [3] halft_dramclk0 */ +#define PHY_SWTMODE_SW_GTMODE_BIT 1 /* [1] SW gate training */ +#define PHY_ACADDRBDL_ADDR1_BIT 16 /* [16] ADDR1 delay line */ +#define PHY_VREFS_MRS_ENTER_BIT 31 /* [31] */ +#define PHY_OSC_RPT_VLD 15 /* [15] */ +#define PHY_OSC_CNT_RDATA_BIT 16 /* [31:16] */ +#define PHY_ZCODE_PDRV_BIT 16 /* [21:16] */ +#define PHY_ACCTL_PDRV_LATCH_BIT 24 /* [29:24] */ +#define PHY_AC_VDDQ_CAL_EN_BIT 8 /* [8] AC ZQ calibration enable */ + +/* BDL register bit */ +#define PHY_BDL_DQ_BIT 0 +#define PHY_BDL_DQ0_BIT 0 +#define PHY_BDL_DQ1_BIT 8 +#define PHY_BDL_DQ2_BIT 16 +#define PHY_BDL_DQ3_BIT 24 +#define PHY_RDM_BDL_BIT 0 +#define PHY_RDQS_BDL_BIT 0 + +/* value */ +#define PHY_PHYINITCTRL_DVREFT_SYNC 0x40000 /* DRAM VREF Synchronize */ +/* hw training item defined in PHYINITCTRL */ +#define PHY_PHYINITCTRL_CTL_CKE_BYPASS (1 << 31) /* PACK's CKE bypass function enable. */ +#define PHY_PHYINITCTRL_PIC_PHYUPD_REQ (1 << 30) /* PACK's DFI PHY UPDATAE request by SW. */ +#define PHY_PHYINITCTRL_PIC_TDQSST (1 << 28) /* TDQSS training Enable. */ +#define PHY_PHYINITCTRL_CFG_LPBK_COMPST_EN (1 << 27) /* RDQS/CK loopback delay compensate enable. */ +#define PHY_PHYINITCTRL_PIC_REFRET_SFT (1 << 26) /* Update delay line(switch op_sel) during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_WR (1 << 25) /* Retraining with MPC write during tRFC. */ +#define PHY_PHYINITCTRL_PIC_REFRET_RD (1 << 24) /* Retraining with MPC read during tRFC. */ +#define PHY_PHYINITCTRL_JTMT_EN (1 << 23) /* PLL Jitter Meter Enable. */ +#define PHY_PHYINITCTRL_CST_EN (1 << 22) /* HW CS Traninig Enable. */ +#define PHY_PHYINITCTRL_ACDVREFS_EN (1 << 21) /* DRAM VREF(AC) Synchronize Operations. */ +#define PHY_PHYINITCTRL_ACHVREFT_EN (1 << 20) /* Host VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_ACDVREFT_EN (1 << 19) /* DRAM VREF(AC) Training Enable. */ +#define PHY_PHYINITCTRL_DXDVREFS_EN (1 << 18) /* DRAM VREF(DQ) Synchronize Operations. */ +#define PHY_PHYINITCTRL_HVREFT_EN (1 << 17) /* Host VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_DVREFT_EN (1 << 16) /* DRAM VREF(DQ) Training Enable. */ +#define PHY_PHYINITCTRL_PHYCONN_RST (1 << 15) /* PHY Counter Reset. */ +#define PHY_PHYINITCTRL_PACK_RST (1 << 14) /* PACK Reset. */ +#define PHY_PHYINITCTRL_PHY_RST (1 << 13) /* PHY Reset. */ +#define PHY_PHYINITCTRL_DRAM_RST (1 << 12) /* DRAM Reset. */ +#define PHY_PHYINITCTRL_CAT_EN (1 << 11) /* HW CA Traninig Enable. */ +#define PHY_PHYINITCTRL_DRAM_INIT_EN (1 << 10) /* DRAM Initialization Enable. */ +#define PHY_PHYINITCTRL_WDET_EN (1 << 9) /* Write Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_RDET_EN (1 << 8) /* Read Data Eye Training Enable. */ +#define PHY_PHYINITCTRL_WL2_EN (1 << 7) /* Second Write Leveling Enable. */ +#define PHY_PHYINITCTRL_GDST_EN (1 << 6) /* PHY Read Data Latch Train Enable. */ +#define PHY_PHYINITCTRL_GT_EN (1 << 5) /* Gate Training Enable. */ +#define PHY_PHYINITCTRL_WL_EN (1 << 4) /* Write Leveling Enable. */ +#define PHY_PHYINITCTRL_ZCAL_EN (1 << 3) /* Impedance Calibration Enable. */ +#define PHY_PHYINITCTRL_DLYMEAS_EN (1 << 2) /* Delay Measurement Enable. */ +#define PHY_PHYINITCTRL_PLL_INIT_EN (1 << 1) /* PLL Initialization Enable. */ +#define PHY_PHYINITCTRL_INIT_EN (1 << 0) /* PHY Initialization Enable. */ + +#define PHY_HW_GP_PHY_RESET (PHY_PHYINITCTRL_PHY_RST) +#define PHY_HW_GP_CNT_RESET_START (PHY_PHYINITCTRL_PHYCONN_RST) +#define PHY_HW_GP_PLL (PHY_PHYINITCTRL_PLL_INIT_EN | PHY_PHYINITCTRL_ZCAL_EN | PHY_PHYINITCTRL_DLYMEAS_EN) +#define PHY_HW_GP_DRAM_RESET (PHY_PHYINITCTRL_DRAM_RST | PHY_PHYINITCTRL_DRAM_INIT_EN) +#define PHY_HW_GP_VREF_AC (PHY_PHYINITCTRL_ACDVREFS_EN) +#define PHY_HW_GP_CS (PHY_PHYINITCTRL_CST_EN) +#define PHY_HW_GP_VREF_DQ (PHY_PHYINITCTRL_DVREFT_SYNC) +#define PHY_HW_GP_NORMAL (PHY_PHYINITCTRL_WL_EN \ + | PHY_PHYINITCTRL_GT_EN \ + | PHY_PHYINITCTRL_GDST_EN \ + | PHY_PHYINITCTRL_WL2_EN \ + | PHY_PHYINITCTRL_RDET_EN \ + | PHY_PHYINITCTRL_WDET_EN \ + | PHY_PHYINITCTRL_DVREFT_EN \ + | PHY_PHYINITCTRL_HVREFT_EN \ + | PHY_PHYINITCTRL_PIC_TDQSST) +#define PHY_HW_GP_CNT_RESET_END (PHY_PHYINITCTRL_PHYCONN_RST) + +/* RDQS range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_RDQS_MIDDLE_VAL 0x30 +/* DQ range[0, 0x7f], middle value is 0x40, but it affected by + temperature, so middle value change to 0x30 */ +#define PHY_DQ_MIDDLE_VAL 0x30303030 +#define PHY_MISC_SCRAMB_DIS 0xfffeffff /* scrambler disable */ +#define PHY_GATE_BDL_MAX 0xfe /* [6:0]rdqsg_bdl + [22:16]rdqsgtxbdl */ +#define PHY_DVRFTCTRL_PDAEN_EN 0x80000000 /* pda enable */ +/* [5] two cycle on address or command.(2T timing) */ +#define PHY_DRAMCFG_MA2T 0x20 + +#define PHY_DRAMCFG_TYPE_DDR1 0x0 /* [2:0] 000 DDR1 */ +#define PHY_DRAMCFG_TYPE_DDR2 0x1 /* [2:0] 001 DDR2 */ +#define PHY_DRAMCFG_TYPE_DDR3 0x2 /* [2:0] 010 DDR3 */ +#define PHY_DRAMCFG_TYPE_DDR3L 0x3 /* [2:0] 011 DDR3L */ +#define PHY_DRAMCFG_TYPE_LPDDR1 0x4 /* [2:0] 100 LPDDR1 */ +#define PHY_DRAMCFG_TYPE_LPDDR2 0x5 /* [2:0] 101 LPDDR2 */ +#define PHY_DRAMCFG_TYPE_LPDDR3 0x5 /* [2:0] 101 LPDDR3 */ +#define PHY_DRAMCFG_TYPE_LPDDR4 0x6 /* [2:0] 110 LPDDR4 */ +#define PHY_DRAMCFG_TYPE_DDR4 0xa /* [3] 1010 DDR4 */ + +#define PHY_DMSEL_SWAPDFIBYTE 0xf8ffffff /* [24:26] No Swap */ +/* other */ +#define PHY_RDQSG_PHASE_STEP 2 /* gate training phase step. */ +#define PHY_GATE_PHASE_MARGIN 8 /* gate phase margin */ +#define PHY_DQ_BDL_LEVEL 128 /* [CUSTOM] DQ BDL range */ +#define PHY_DQ_BDL_MIDDLE 64 /* special middle DQ BDL value */ +#define PHY_RDQSG_PHASE_MAX 0x3c /* RDQSG phase max value */ +#define PHY_ACPHY_CLK_MAX 0xf /* halft_dramclk0 + cp1p_dclk0 */ +#define PHY_PCODE_MIN 0x14 +#define PHY_PCODE_MAX 0x24 +/** + * DDR_BDL_PHASE_REL Calculation Method: + * 1. Calculation How many picosecond to one phase. + * PICOSECOND : 1 second is (1000 * 1000 * 1000) picosecond + * WAVE : 1 cycle is 2 + * RATE : DDR rate is 1600 Mbps, is (1600 * 1000) bps + * PHASE : 1 wave is 12 phase + * phase = (((PICOSECOND * WAVE) / RATE) / PHASE) + * = (((1000 * 1000 * 1000 * 2) / (1600 * 1000)) / 12) + * = 104.17 ps. + * 2. Calculation How many bdl to one phase. + * one BDL is 6 ps. + * result = phase/bdl = 104.17 / 6 = 17.36 approximately equal to 17 ~= 16 + * 3. 16 = 1 << 4, so the relation is 4. + */ +#ifndef DDR_BDL_PHASE_TRANSFORM +/* [CUSTOM] one Phase equal how much BDL. 1 phase = 16 bdl */ +#define DDR_BDL_PHASE_TRANSFORM 16 +#endif +#ifndef DDR_BDL_PHASE_REL +/* [CUSTOM] relation between BDL and Phase. 1 phase = 16 bdl, 16 = 1 << 4 */ +#define DDR_BDL_PHASE_REL 4 +#endif + +#define DDR_VARIABLE_DECLARE(var) \ + unsigned int var; + +#define DDR_VREF_GET_HOST_MAX(rank, val) \ + do { \ + if (0 == rank) \ + val = PHY_VRFTRES_HVREF_MASK; \ + else \ + val = PHY_VRFTRES_RXDIFFCAL_MASK; \ + } while (0) + +/* PHY t28 all byte use a same value */ +#define DDR_PHY_VREF_HOST_SET(base_phy, rank, bytenum, byte_index, val) \ + do { \ + unsigned int hvreft; \ + hvreft = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & (~PHY_VRFTRES_HVREF_MASK); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)); \ + ddr_write(hvreft | val, base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index + 1)); \ + } while (0) + +#define DDR_PHY_VREF_HOST_GET(base_phy, rank, byte_index, val) \ + do { \ + val = ddr_read(base_phy + DDR_PHY_HVREFT_STATUS(rank, byte_index)) \ + & PHY_VRFTRES_HVREF_MASK; \ + } while (0) + +#define DDR_PHY_VREF_HOST_DISPLAY \ + {0, 0, DDR_PHY_HVREFT_STATUS(0, 0), 0, "Host Vref Byte0"}, \ + {0, 1, DDR_PHY_HVREFT_STATUS(0, 1), 0, "Host Vref Byte1"}, \ + {0, 2, DDR_PHY_HVREFT_STATUS(0, 2), 0, "Host Vref Byte2"}, \ + {0, 3, DDR_PHY_HVREFT_STATUS(0, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_RANK1 \ + {1, 0, DDR_PHY_HVREFT_STATUS(1, 0), 0, "Host Vref Byte0"}, \ + {1, 1, DDR_PHY_HVREFT_STATUS(1, 1), 0, "Host Vref Byte1"}, \ + {1, 2, DDR_PHY_HVREFT_STATUS(1, 2), 0, "Host Vref Byte2"}, \ + {1, 3, DDR_PHY_HVREFT_STATUS(1, 3), 0, "Host Vref Byte3"}, + +#define DDR_PHY_VREF_HOST_DISPLAY_CMD(base_phy, rank, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] Host Vref Byte(%x)", \ + base_phy + DDR_PHY_HVREFT_STATUS(rank, _i), \ + ddr_read(base_phy \ + + DDR_PHY_HVREFT_STATUS(rank, _i)), _i); \ + } \ + } while (0) + +/* DRAM vref operations */ +#define DDR_PHY_VREF_DRAM_SET(base_phy, val, byte_index) \ + do { \ + unsigned int dvrftctrl = \ + ddr_read(base_phy + DDR_PHY_DVRFTCTRL); \ + unsigned int dvreft = ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & (~PHY_VRFTRES_DVREF_MASK); \ + ddr_write(dvrftctrl | PHY_DVRFTCTRL_PDAEN_EN, \ + base_phy + DDR_PHY_DVRFTCTRL); \ + ddr_write(dvreft | val, \ + base_phy + DDR_PHY_DVREFT_STATUS(byte_index)); \ + ddr_write(PHY_PHYINITCTRL_DVREFT_SYNC \ + | PHY_PHYINITCTRL_INIT_EN, \ + base_phy + DDR_PHY_PHYINITCTRL); \ + while (1) { \ + if (!(ddr_read(base_phy + DDR_PHY_PHYINITCTRL) \ + & PHY_PHYINITCTRL_INIT_EN)) \ + break; \ + } \ + ddr_write(dvrftctrl & (~PHY_DVRFTCTRL_PDAEN_EN), \ + base_phy + DDR_PHY_DVRFTCTRL); \ + } while (0) + +#define DDR_PHY_VREF_DRAM_GET(base_phy, val, byte_index) \ + { \ + val = ddr_read(base_phy + DDR_PHY_DVREFT_STATUS(byte_index)) \ + & PHY_VRFTRES_DVREF_MASK; \ + } + +#define DDR_PHY_VREF_DRAM_DISPLAY \ + {0, 0, DDR_PHY_DVREFT_STATUS(0), 0, "DRAM Vref Byte0"}, \ + {0, 1, DDR_PHY_DVREFT_STATUS(1), 0, "DRAM Vref Byte1"}, \ + {0, 2, DDR_PHY_DVREFT_STATUS(2), 0, "DRAM Vref Byte2"}, \ + {0, 3, DDR_PHY_DVREFT_STATUS(3), 0, "DRAM Vref Byte3"}, + +#define DDR_PHY_VREF_DRAM_DISPLAY_CMD(base_phy, byte_num) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < byte_num; _i++) { \ + DDR_INFO("[%x = %x] DRAM Vref Byte(%x)", \ + base_phy + DDR_PHY_DVREFT_STATUS(_i), \ + ddr_read(base_phy \ + + DDR_PHY_DVREFT_STATUS(_i)), _i); \ + } \ + } while (0) + +/* phy t28 not support DCC training */ +#define DDR_PHY_DCC_DISPLAY +#define DDR_PHY_DCC_DISPLAY_CMD(base_phy) + +/* lowpower ddr ca operations */ +#define DDR_PHY_ADDRPH_DISPLAY \ + {0, 0, DDR_PHY_ADDRPHBOUND, 0, "CA Phase"}, + +#define DDR_PHY_ADDRBDL_DISPLAY \ + {0, 0, DDR_PHY_ACADDRBDL(0), 0, "CA BDL(0)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(1), 0, "CA BDL(1)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(2), 0, "CA BDL(2)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(3), 0, "CA BDL(3)"}, \ + {0, 0, DDR_PHY_ACADDRBDL(4), 0, "CA BDL(4)"}, + +#define DDR_PHY_ADDRPH_DISPLAY_CMD(base_phy) \ + DDR_INFO("[%x = %x] CA Phase", \ + base_phy + DDR_PHY_ADDRPHBOUND, \ + ddr_read(base_phy + DDR_PHY_ADDRPHBOUND)); + +#define DDR_PHY_ADDRBDL_DISPLAY_CMD(base_phy) \ + do { \ + unsigned int _i; \ + for (_i = 0; _i < DDR_PHY_CA_REG_MAX; _i++) { \ + DDR_INFO("[%x = %x] ACADDRBDL(%x)", \ + base_phy + DDR_PHY_ACADDRBDL(_i), \ + ddr_read(base_phy \ + + DDR_PHY_ACADDRBDL(_i)), _i); \ + } \ + } while (0) + +/* PHY t28 DDR4 RDQS synchronize to RDM */ +#define DDR_PHY_RDQS_SYNC_RDM(cfg, val) \ + ddr_rdqs_sync(cfg, val) + +/* dqs swap */ +#define DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy) \ + do { \ + swapdfibyte_en = \ + ddr_read(base_phy + DDR_PHY_DMSEL); \ + ddr_write(swapdfibyte_en & PHY_DMSEL_SWAPDFIBYTE, \ + base_phy + DDR_PHY_DMSEL); \ + } while (0) + +#define DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy) \ + ddr_write(swapdfibyte_en, base_phy + DDR_PHY_DMSEL); + + +#define DDR_PHY_SWITCH_RANK(base_phy, val) \ + do { \ + ddr_write((ddr_read(base_phy + DDR_PHY_TRAINCTRL0) & (~PHY_TRAINCTRL0_MASK)) | val, base_phy + DDR_PHY_TRAINCTRL0); \ + } while (0) + +/* Define the union U_PHY_CATCONFIG */ +union U_PHY_CATCONFIG { + /* Define the struct bits */ + struct { + unsigned int ca_samp_num_bdl:4; /* [3:0] */ + unsigned int ca_samp_num_ph:4; /* [7:4] */ + unsigned int ca_trysamp_num:4; /* [11:8] */ + unsigned int cat_rb_backtap:4; /* [15:12] */ + unsigned int reserved:1; /* [16] */ + unsigned int cat_openeye_en:1; /* [17] */ + unsigned int cat_cat_phydq_sel:1; /* [18] */ + unsigned int cat_restore_en:1; /* [19] */ + unsigned int cat_lb_backtap:4; /* [23:20] */ + unsigned int sw_cat_mrw42:1; /* [24] */ + unsigned int sw_cat_mrw48:1; /* [25] */ + unsigned int sw_cat_mrw41:1; /* [26] */ + unsigned int sw_cat_strobe:1; /* [27] */ + unsigned int sw_cat_cke_high:1; /* [28] */ + unsigned int sw_cat_cke_low:1; /* [29] */ + unsigned int sw_cat_dqvalid:1; /* [30] */ + unsigned int sw_cat_en:1; /* [31] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; + +/* Define the union U_PHY_ADDRPHBOUND */ +union U_PHY_ADDRPHBOUND { + /* Define the struct bits */ + struct { + unsigned int addrph_a_right:5; /* [4:0] */ + unsigned int reserved0:3; /* [7:5] */ + unsigned int addrph_a_left:5; /* [12:8] */ + unsigned int reserved1:3; /* [15:13] */ + unsigned int addrph_a:5; /* [20:16] */ + unsigned int reserved2:3; /* [23:21] */ + unsigned int addrph_a_ori:5; /* [28:24] */ + unsigned int reserved3:3; /* [31:29] */ + } bits; + + /* Define an unsigned member */ + unsigned int u32; +}; diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_boot.c b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_boot.c new file mode 100755 index 00000000..c8d25f53 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_boot.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * Description:Special function for ddr training when power up. + */ + +#include "ddr_training_impl.h" +#include "ddr_interface.h" + +#ifdef DDR_TRAINING_UART_CONFIG +extern void uart_early_put_hex(int hex); +extern void uart_early_putc(int chr); +#endif + +/* Save DDR tarining result */ +void ddr_result_data_save(struct ddr_cfg_st *cfg, struct training_data *training) +{ + /* nothing to do when ddr training on power up */ +} + +void ddr_lpca_data_save(struct ca_data_st *data) +{ + /* nothing to do when ddr training on power up */ +} + +/* Get DDRT test address */ +unsigned int ddr_ddrt_get_test_addr(void) +{ + return DDRT_CFG_TEST_ADDR_BOOT; +} + +#ifdef DDR_TRAINING_UART_CONFIG +#ifdef DDR_TRAINING_MINI_LOG_CONFIG +/* Display DDR training error when boot */ +void ddr_training_error(unsigned int mask, unsigned int phy, int byte, int dq) +{ + uart_early_putc('E'); + uart_early_put_hex(mask); + uart_early_putc('P'); + uart_early_put_hex(phy); + uart_early_putc('B'); + uart_early_put_hex(byte); + uart_early_putc('D'); + uart_early_put_hex(dq); +} +void ddr_training_start(void) +{ + uart_early_putc('D'); + uart_early_putc('D'); + uart_early_putc('R'); +} +void ddr_training_suc(void) +{ + uart_early_putc('S'); +} +#else +/* Define string to print */ +void ddr_training_local_str(void) +{ + asm volatile( + "str_wl:\n\t" + ".asciz \"WL\"\n\t" + ".align 2\n\t" + + "str_hwg:\n\t" + ".asciz \"HWG\"\n\t" + ".align 2\n\t" + + "str_gate:\n\t" + ".asciz \"Gate\"\n\t" + ".align 2\n\t" + + "str_ddrt:\n\t" + ".asciz \"DDRT\"\n\t" + ".align 2\n\t" + + "str_hwrd:\n\t" + ".asciz \"HWRD\"\n\t" + ".align 2\n\t" + + "str_mpr:\n\t" + ".asciz \"MPR\"\n\t" + ".align 2\n\t" + + "str_dataeye:\n\t" + ".asciz \"Dataeye\"\n\t" + ".align 2\n\t" + + "str_lpca:\n\t" + ".asciz \"LPCA\"\n\t" + ".align 2\n\t" + + "str_err:\n\t" + ".asciz \" Err:\"\n\t" + ".align 2\n\t" + + "str_phy:\n\t" + ".asciz \"Phy\"\n\t" + ".align 2\n\t" + + "str_byte:\n\t" + ".asciz \"Byte\"\n\t" + ".align 2\n\t" + + "str_dq:\n\t" + ".asciz \"DQ\"\n\t" + ".align 2\n\t" + + "str_ddrtr_start:\n\t" + ".asciz \"\r\\nDDRTR \"\n\t" + ".align 2\n\t" + + "str_ddrtr_suc:\n\t" + ".asciz \"Suc\"\n\t" + ".align 2\n\t" + ); +} + +/* Display DDR training error when boot */ +void ddr_training_error(unsigned int mask, unsigned int phy, int byte, int dq) +{ + uart_early_putc('\r'); + uart_early_putc('\n'); + /* error type */ + switch (mask) { + case DDR_ERR_WL: + asm volatile( + "adr r0, str_wl\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_HW_GATING: + asm volatile( + "adr r0, str_hwg\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_GATING: + asm volatile( + "adr r0, str_gate\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_DDRT_TIME_OUT: + asm volatile( + "adr r0, str_ddrt\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_HW_RD_DATAEYE: + asm volatile( + "adr r0, str_hwrd\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_MPR: + asm volatile( + "adr r0, str_mpr\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_DATAEYE: + asm volatile( + "adr r0, str_dataeye\n\t" + "bl uart_early_puts" + ); + break; + case DDR_ERR_LPCA: + asm volatile( + "adr r0, str_lpca\n\t" + "bl uart_early_puts" + ); + break; + default: + break; + } + + /* error string */ + asm volatile( + "adr r0, str_err\n\t" + "bl uart_early_puts" + ); + + /* error phy */ + if (0 != phy) { + asm volatile( + "adr r0, str_phy\n\t" + "bl uart_early_puts" + ); + uart_early_put_hex(phy); + } + + /* error byte */ + if (-1 != byte) { + asm volatile( + "adr r0, str_byte\n\t" + "bl uart_early_puts" + ); + uart_early_put_hex(byte); + } + + /* error dq */ + if (-1 != dq) { + asm volatile( + "adr r0, str_dq\n\t" + "bl uart_early_puts" + ); + uart_early_put_hex(dq); + } +} + +/* Display DDR training start when boot */ +void ddr_training_start(void) +{ + asm volatile( + "push {lr}\n\t" + "adr r0, str_ddrtr_start\n\t" + "bl uart_early_puts\n\t" + "pop {lr}" + ); +} + +/* Display DDR training result when boot */ +void ddr_training_suc(void) +{ + asm volatile( + "push {lr}\n\t" + "adr r0, str_ddrtr_suc\n\t" + "bl uart_early_puts\n\t" + "pop {lr}" + ); +} +#endif /* DDR_TRAINING_CUT_CODE_CONFIG */ +#else +void ddr_training_error(unsigned int mask, unsigned int phy, int byte, int dq) +{ + return; +} +void ddr_training_suc(void) +{ + return; +} +void ddr_training_start(void) +{ + return; +} +#endif /* DDR_TRAINING_UART_CONFIG */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_console.c b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_console.c new file mode 100755 index 00000000..e8ed82de --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_console.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * Description:DDR training console + */ + +#include "ddr_interface.h" +#include "ddr_training_impl.h" + +#define __ddr_training_console__ +#ifdef DDR_TRAINING_CONSOLE_CONFIG + +#define DDR_UART_BASE_REG 0x12090000 +#define UART_PL01x_FR 0x18 /* Flag register (Read only). */ +#define UART_PL01x_FR_RXFE 0x10 +#define UART_PL01x_DR 0x00 /* Data read or written from the interface. */ +#define UART_PL01x_ECR 0x04 /* Error clear register (Write). */ + +#define isprint(c) ((c) >= ' ' && (c) <= '~') +#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define isxdigit(c) (isdigit(c) \ + || ((c) >= 'A' && (c) <= 'F') \ + || ((c) >= 'a' && (c) <= 'f')) +#define CMD(_p, _c0, _c1, _do_cmd) \ + if (_p[0] == _c0 && _p[1] == _c1) { \ + if (!_do_cmd(_p + 2)) \ + continue; \ + } + +/* DDR console get char */ +static int ddr_console_getc(void) +{ + unsigned int data; + + /* Wait until there is data in the FIFO */ + while (ddr_read(DDR_UART_BASE_REG + UART_PL01x_FR) & UART_PL01x_FR_RXFE) { + } + + data = ddr_read(DDR_UART_BASE_REG + UART_PL01x_DR); + + /* Check for an error flag */ + if (data & 0xFFFFFF00) { + /* Clear the error */ + ddr_write(0xFFFFFFFF, DDR_UART_BASE_REG + UART_PL01x_ECR); + return -1; + } + return (int) data; +} + +/* DDR read line */ +static char *ddr_readline(char *str, int len) +{ + unsigned int c; + char *p = str; + while (len > 0) { + c = ddr_console_getc(); + switch (c) { + case '\r': + case '\n': + *p = '\0'; + DDR_PUTC('\r'); + DDR_PUTC('\n'); + return str; + case 0x08: + case 0x7F: + if (p > str) { + p--; + len++; + DDR_PUTC('\b'); + DDR_PUTC(' '); + DDR_PUTC('\b'); + } + break; + default: + if (isprint(c)) { + (*p++) = (char)c; + len--; + DDR_PUTC(c); + } + break; + } + } + (*--p) = '\0'; + return str; +} + +/* HEX to INT */ +static int hex2int(char **ss, unsigned int *n) +{ + unsigned char *s = (unsigned char *)(*ss); + + while (isspace(*s)) s++; + + if (!(*s)) + return -1; + + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + s += 2; + + for ((*n) = 0; isxdigit(*s); s++) { + (*n) = ((*n) << 4); + if ((*s) >= '0' && (*s) <= '9') + (*n) |= ((*s) - '0'); + else if ((*s) >= 'a' && (*s) <= 'f') + (*n) |= ((*s) + 10 - 'a'); + else if ((*s) >= 'A' && (*s) <= 'F') + (*n) |= ((*s) + 10 - 'A'); + } + + if (isspace(*s) || !(*s)) { + while (isspace(*s)) s++; + (*ss) = (char *)s; + return 0; + } + + return -2; +} +/** + * DDR do memory write. + * mw address value [count] + */ +static int ddr_do_memory_write(char *cmd) +{ + unsigned int address; + unsigned int value; + unsigned int count = 4; + + if (hex2int(&cmd, &address)) + return -1; + + if (hex2int(&cmd, &value)) + return -1; + + if ((*cmd) && hex2int(&cmd, &count)) + return -1; + + if (address & 0x03 || count & 0x03) { + DDR_INFO("parameter should align with 4 bytes.\n"); + return -1; + } + for (;count > 0; count -= 4, address += 4) + ddr_write(value, address); + return 0; +} +/** + * DDR do memory display. + * md address [count] + */ +static int ddr_do_memory_display(char *cmd) +{ + unsigned int ix; + unsigned int loop; + unsigned int address; + unsigned int count = 64; + + if (hex2int(&cmd, &address)) + return -1; + + if ((*cmd) && hex2int(&cmd, &count)) + return -1; + + if (count < 4) + count = 4; + + address &= ~0x03; + loop = (count & ~0x03); + + while (loop > 0) { + + DDR_PUTC('0'); + DDR_PUTC('x'); + DDR_PUT_HEX(address); + DDR_PUTC(':'); + + for (ix = 0; + ix < 4 && loop > 0; + ix++, loop -= 4, address += 4) { + + DDR_PUTC(' '); DDR_PUT_HEX(ddr_read(address)); + } + DDR_PUTC('\r'); + DDR_PUTC('\n'); + } + return 0; +} + +#ifdef DDR_TRAINING_CMD +extern struct ddr_training_result_st ddrt_result_sram; +#endif +static int ddr_do_sw_training(char *cmd) +{ + int result; + struct ddr_cfg_st ddr_cfg; + struct ddr_cfg_st *cfg = &ddr_cfg; + + ddr_training_cfg_init(cfg); +#ifdef DDR_TRAINING_CMD + cfg->res_st = (void *)&ddrt_result_sram; +#endif + result = ddr_training_all(cfg); + + result += ddr_dcc_training_func(cfg); + + return 0; +} + +static int ddr_do_hw_training(char *cmd) +{ + int result; + + result = ddr_hw_training_func(0); + + return 0; +} + +/* Do DDR training console if sw training or hw training fail */ +static int ddr_training_console(void *args) +{ + char str[256]; + char *p = NULL; + unsigned int cmd=0; + + while (1) { + DDR_PUTC('d'); + DDR_PUTC('d'); + DDR_PUTC('r'); + DDR_PUTC('#'); + + p = ddr_readline(str, sizeof(str)); + + while (isspace(*p)) p++; + if (p[0] == 'q') + break; + CMD(p, 'm', 'w', ddr_do_memory_write) else + CMD(p, 'm', 'd', ddr_do_memory_display) else + CMD(p, 's', 'w', ddr_do_sw_training) else + CMD(p, 'h', 'w', ddr_do_hw_training) + + } + + return 0; +} +#else +static int ddr_training_console(void *args) +{ + DDR_WARNING("Not support DDR training console."); + return 0; +} +#endif /* DDR_TRAINING_CONSOLE_CONFIG */ + +int ddr_training_console_if(void *args) +{ + return DDR_TRAINING_CONSOLE(args); +} diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_ctl.c b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_ctl.c new file mode 100755 index 00000000..53d7eb9a --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_ctl.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * Description:DDR training control + */ + +#include "ddr_interface.h" +#include "ddr_training_impl.h" + +#ifdef DDR_SW_TRAINING_FUNC_PUBLIC +#ifdef DDR_TRAINING_CUT_CODE_CONFIG +/** + * Cut ddr training control code for less SRAM. + * Support DDRC500. + * Support DDRC510 with one PHY. + */ +int ddr_sw_training_func(void *ddrtr_result) +{ + struct ddr_cfg_st ddr_cfg; + struct ddr_cfg_st *cfg = &ddr_cfg; + + unsigned int base_dmc = DDR_REG_BASE_DMC0; + unsigned int base_phy = DDR_REG_BASE_PHY0; + int result = 0; + unsigned int auto_ref_timing = ddr_read(base_dmc + DDR_DMC_TIMING2); + unsigned int misc_scramb = ddr_read(base_phy + DDR_PHY_MISC); + unsigned int dramcfg_ma2t = ddr_read(base_phy + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_MA2T; + unsigned int acphyctl; + + /* Static register have to read two times to get the right value. */ + acphyctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL4); + acphyctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL4); + + DDR_VARIABLE_DECLARE(swapdfibyte_en); + + /* check sw ddr training enable */ + if (DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL + + SYSCTRL_DDR_TRAINING_CFG)) + return 0; + + ddr_training_start(); + ddr_training_cfg_init(cfg); + +#ifdef DDR_TRAINING_STAT_CONFIG + /* clear stat register */ + ddr_write(0x0, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT); +#endif + + /* disable scramb */ + ddr_write(misc_scramb & PHY_MISC_SCRAMB_DIS, + base_phy + DDR_PHY_MISC); + + /* disable rdqs swap */ + DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy); + + /* check hardware gating */ + if (ddr_read(base_phy + DDR_PHY_PHYINITSTATUS) + & PHY_INITSTATUS_GT_MASK) { + DDR_FATAL("PHY[%x] hw gating fail.", base_phy); + ddr_training_stat(DDR_ERR_HW_GATING, + base_phy, -1, -1); + } + +#ifdef DDR_LPCA_TRAINING_CONFIG + /* lpca */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_LPCA_MASK) + && (PHY_DRAMCFG_TYPE_LPDDR3 == + (ddr_read(base_phy + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_LPDDR3))) { + /* disable auto refresh */ + ddr_training_set_timing(base_dmc, + auto_ref_timing & DMC_AUTO_TIMING_DIS); + + result += ddr_lpca_training(cfg); + + /* enable auto refresh */ + ddr_training_set_timing(base_dmc, auto_ref_timing); + } +#endif + +#ifdef DDR_WL_TRAINING_CONFIG + /* write leveling */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_WL_MASK)) { + /* disable auto refresh */ + ddr_training_set_timing(base_dmc, + auto_ref_timing & DMC_AUTO_TIMING_DIS); + result += ddr_write_leveling(cfg); + /* enable auto refresh */ + ddr_training_set_timing(base_dmc, auto_ref_timing); + } +#endif + +#ifdef DDR_DATAEYE_TRAINING_CONFIG + /* dataeye */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_DATAEYE_MASK)) { + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE); + result += ddr_dataeye_training(cfg); + } +#endif + +#ifdef DDR_HW_TRAINING_CONFIG + /* hardware read */ + if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_HW_MASK)) { + if (!dramcfg_ma2t) /* set 1T */ + ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4); + + result = ddr_hw_dataeye_read(cfg); + if (!dramcfg_ma2t) /* restore */ + ddr_write(acphyctl, base_phy + DDR_PHY_ACPHYCTL4); + + result += ddr_dataeye_training(cfg); + } +#endif + +#ifdef DDR_MPR_TRAINING_CONFIG + /* mpr */ + if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_MPR_MASK)) { + result = ddr_mpr_training(cfg); + result += ddr_dataeye_training(cfg); + } +#endif + +#ifdef DDR_GATE_TRAINING_CONFIG + /* gate */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_GATE_MASK)) { + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_GATE); + /* disable auto refresh */ + ddr_training_set_timing(base_dmc, + auto_ref_timing & DMC_AUTO_TIMING_DIS); + + if (!dramcfg_ma2t) /* set 1T */ + ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4); + + result += ddr_gate_training(cfg); + + /* enable auto refresh */ + ddr_training_set_timing(base_dmc, auto_ref_timing); + + if (!dramcfg_ma2t) /* restore */ + ddr_write(acphyctl, base_phy + DDR_PHY_ACPHYCTL4); + } +#endif + +#ifdef DDR_VREF_TRAINING_CONFIG + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_VREF_MASK)) { + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE); + result += ddr_vref_training(cfg); + } +#endif + + /* restore scramb */ + ddr_write(misc_scramb, base_phy + DDR_PHY_MISC); + + /* restore rdqs swap */ + DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy); + + if (!result) + ddr_training_suc(); + return result; +} +#else +int ddr_training_boot_func(struct ddr_cfg_st *cfg) +{ + int result = 0; + + /* check hardware gating */ + if (ddr_read(cfg->cur_phy + DDR_PHY_PHYINITSTATUS) + & PHY_INITSTATUS_GT_MASK) { + DDR_FATAL("PHY[%x] hw gating fail.", cfg->cur_phy); + ddr_training_stat(DDR_ERR_HW_GATING, + cfg->cur_phy, -1, -1); + } + + /* lpca */ + result = ddr_lpca_training_func(cfg); + /* write leveling */ + result += ddr_wl_func(cfg); + /* dataeye/gate/vref need switch axi */ + /* dataeye */ + result += ddr_dataeye_training_func(cfg); +#ifdef DDR_HW_TRAINING_CONFIG + /* hardware read */ + if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_HW_MASK)) { + struct tr_relate_reg relate_reg_ac; + ddr_training_save_reg(cfg, &relate_reg_ac, + DDR_BYPASS_HW_MASK); + result = ddr_hw_dataeye_read(cfg); + ddr_training_restore_reg(cfg, &relate_reg_ac); + cfg->adjust = DDR_DATAEYE_ABNORMAL_ADJUST; + result += ddr_dataeye_training(cfg); + } +#endif + /* mpr */ + result += ddr_mpr_training_func(cfg); + /* gate */ + result += ddr_gating_func(cfg); + /* vref */ + result += ddr_vref_training_func(cfg); + + return result; +} + +/* Support DDRC510 with two PHY */ +int ddr_sw_training_func(void *ddrtr_result) +{ + struct ddr_cfg_st ddr_cfg; + struct ddr_cfg_st *cfg = &ddr_cfg; + int result = 0; + +#ifdef SYSCTRL_DDR_TRAINING_VERSION_FLAG + /* DDR training version flag */ + unsigned int tmp_reg = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_VERSION_FLAG); + tmp_reg = (tmp_reg & 0xffff0000) | DDR_VERSION; + ddr_write(tmp_reg, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_VERSION_FLAG); +#endif + + /* check sw ddr training enable */ + if (DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG) +#ifdef SYSCTRL_DDR_TRAINING_CFG_SEC + && DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG_SEC) +#endif + ) + return 0; + + ddr_training_start(); + +#ifdef DDR_TRAINING_STAT_CONFIG + /* clear stat register */ + ddr_write(0x0, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT); +#endif + + ddr_training_cfg_init(cfg); + cfg->cmd_st = 0; + + result = ddr_training_all(cfg); + result += ddr_dcc_training_func(cfg); + + if (!result) + ddr_training_suc(); + else + ddr_training_console_if(0); + return result; +} +#endif /* DDR_TRAINING_CUT_CODE_CONFIG */ +#endif /* DDR_SW_TRAINING_FUNC_PUBLIC */ + +#ifdef DDR_PCODE_TRAINING_CONFIG +int ddr_pcode_training_func(void *ddrtr_result) +{ + struct ddr_cfg_st ddr_cfg; + struct ddr_cfg_st *cfg = &ddr_cfg; + + ddr_training_cfg_init(cfg); + return ddr_pcode_training(cfg); +} +#else +int ddr_pcode_training_func(void *ddrtr_result) +{ + DDR_WARNING("Not support DDR pcode training."); + return 0; +} +#endif + +#ifdef DDR_HW_TRAINING_CONFIG +int ddr_hw_training_func(void *ddr_hw) +{ + struct ddr_cfg_st ddr_cfg; + struct ddr_cfg_st *cfg = &ddr_cfg; + + ddr_training_cfg_init(cfg); + return ddr_hw_training(cfg); +} +#else +int ddr_hw_training_func(void *ddr_hw) +{ + DDR_WARNING("Not support DDR HW training."); + return 0; +} +#endif /* DDR_HW_TRAINING_CONFIG */ + +int ddr_sw_training_if(void *ddrtr_result) +{ + return DDR_SW_TRAINING_FUNC(ddrtr_result); +} + +int ddr_hw_training_if(void *ddr_hw) +{ + return DDR_HW_TRAINING_FUNC(ddr_hw); +} + +int ddr_pcode_training_if(void *ddrtr_result) +{ + return DDR_PCODE_TRAINING_FUNC(ddrtr_result); +} + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.c b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.c new file mode 100755 index 00000000..920dbf5a --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#include "ddr_interface.h" +#include "ddr_training_impl.h" + +#define CRG_REG_BASE 0x12010000U +#define PERI_CRG_DDRT 0x198U +#define PERI_CRG_DDRCKSEL 0x80U +/* [SYSCTRL]RAM Retention control register 0 */ +#define SYSCTRL_MISC_CTRL4 0x8010U + +static struct tr_relate_reg relate_reg; +static struct tr_relate_reg *reg = &relate_reg; + +/** + * Do some prepare before copy code from DDR to SRAM. + * Keep empty when nothing to do. + */ +void ddr_cmd_prepare_copy(void) { return; } + +/** + * Save site before DDR training command execute . + * Keep empty when nothing to do. + */ +void ddr_cmd_site_save(void) +{ + /* select ddrt bus path */ + reg->custom.ive_ddrt_mst_sel = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + ddr_write(reg->custom.ive_ddrt_mst_sel & 0xffffffdf, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + + /* turn on ddrt clock */ + reg->custom.ddrt_clk_reg = ddr_read(CRG_REG_BASE + PERI_CRG_DDRT); + /* enable ddrt0 clock */ + ddr_write(reg->custom.ddrt_clk_reg | (1U << 1), CRG_REG_BASE + PERI_CRG_DDRT); + __asm__ __volatile__("nop"); + /* disable ddrt0 soft reset */ + ddr_write(ddr_read(CRG_REG_BASE + PERI_CRG_DDRT) & (~(1U << 0)), CRG_REG_BASE + PERI_CRG_DDRT); + + /* disable rdqs anti-aging */ + reg->custom.phy0_age_compst_en = ddr_read(DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); + ddr_write((reg->custom.phy0_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); +#ifdef DDR_REG_BASE_PHY1 + reg->custom.phy1_age_compst_en = ddr_read(DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); + ddr_write((reg->custom.phy1_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); +#endif +} + +/** + * Restore site after DDR training command execute. + * Keep empty when nothing to do. + */ +void ddr_cmd_site_restore(void) +{ + /* restore ddrt bus path */ + ddr_write(reg->custom.ive_ddrt_mst_sel, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4); + + /* restore ddrt clock */ + ddr_write(reg->custom.ddrt_clk_reg, CRG_REG_BASE + PERI_CRG_DDRT); + + /* restore rdqs anti-aging */ + ddr_write(reg->custom.phy0_age_compst_en, DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL); +#ifdef DDR_REG_BASE_PHY1 + ddr_write(reg->custom.phy1_age_compst_en, DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL); +#endif +} + +void ddr_training_save_reg_custom(void *reg, unsigned int mask) { return; } +void ddr_training_restore_reg_custom(void *reg) { return; } + +/** + * DDR clock select. + * For ddr osc training. + */ +#ifdef DDR_PCODE_TRAINING_CONFIG +int ddr_get_cksel(void) +{ + int freq; + unsigned int ddr_cksel; + ddr_cksel = (ddr_read(CRG_REG_BASE + PERI_CRG_DDRCKSEL) >> 0x3) & 0x7; + switch (ddr_cksel) { + case 0x000: + /* 24MHz */ + freq = 24; + break; + case 0x001: + /* 450MHz */ + freq = 450; + break; + case 0x011: + /* 300MHz */ + freq = 300; + break; + case 0x100: + /* 297MHz */ + freq = 297; + break; + default: + freq = 300; + break; + } + return freq; +} +#endif diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.h new file mode 100755 index 00000000..7538a8d3 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_custom.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#ifndef DDR_TRAINING_CUSTOM_H +#define DDR_TRAINING_CUSTOM_H + +/* config DDRC, PHY, DDRT typte */ +#define DDR_DDRC_V520_CONFIG +#define DDR_PHY_T28_CONFIG +#define DDR_DDRT_V2_0_SHF0_CONFIG + +/* config special item */ +#define DDR_VREF_TRAINING_CONFIG +#define DDR_VREF_WITHOUT_BDL_CONFIG +#define DDR_PCODE_TRAINING_CONFIG + +#define DDR_WL_TRAINING_DISABLE +#define DDR_GATE_TRAINING_DISABLE +#define DDR_TRAINING_UART_DISABLE + +/* Disable write dm +#define DDR_WRITE_DM_DISABLE */ + +#define DDR_PHY_NUM 1 /* phy number */ + +#define DDR_DMC_PER_PHY_MAX 2 /* dmc number per phy max */ + +#define DDR_AXI_SWITCH_NUM 4 /* ddr training axi switch number */ + +/* config DDRC, PHY, DDRT base address */ +/* [CUSTOM] DDR PHY0 base register */ +#define DDR_REG_BASE_PHY0 0x120dc000 +/* [CUSTOM] DDR PHY1 base register +#define DDR_REG_BASE_PHY1 0x120de000 */ +/* [CUSTOM] DDR DMC0 base register */ +#define DDR_REG_BASE_DMC0 0x120d8000 +/* [CUSTOM] DDR DMC1 base register */ +#define DDR_REG_BASE_DMC1 0x120d8000 + +#ifdef DDR_REG_BASE_PHY1 +/* [CUSTOM] DDR DMC2 base register */ +#define DDR_REG_BASE_DMC2 0x120d9000 +/* [CUSTOM] DDR DMC3 base register */ +#define DDR_REG_BASE_DMC3 0x120d9000 +#endif + +/* [CUSTOM] DDR DDRT base register */ +#define DDR_REG_BASE_DDRT 0x11330000 +/* [CUSTOM] DDR training item system control */ +#define DDR_REG_BASE_SYSCTRL 0x12020000 +#define DDR_REG_BASE_AXI 0x120d0000 +/* Serial Configuration */ +#define DDR_REG_BASE_UART0 0x12040000 + +/* config offset address */ +/* Assume sysctrl offset address for DDR training as follows, +if not please define. */ +/* [CUSTOM] ddrt reversed data */ +#define SYSCTRL_DDRT_PATTERN 0xa8 +/* [CUSTOM] PHY2 ddrt reversed data +#define SYSCTRL_DDRT_PATTERN_SEC 0xac */ +/* [CUSTOM] ddr training item */ +#define SYSCTRL_DDR_TRAINING_CFG 0xa0 +#define SYSCTRL_DDR_TRAINING_CFG_SEC 0xa4 +/* [CUSTOM] ddr training version flag */ +#define SYSCTRL_DDR_TRAINING_VERSION_FLAG 0xb4 +/* [CUSTOM] ddr training stat */ +#define SYSCTRL_DDR_TRAINING_STAT 0xb0 + +/* [CUSTOM] ddr hw training item */ +#define SYSCTRL_DDR_HW_PHY0_RANK0 0x90 +#define SYSCTRL_DDR_HW_PHY0_RANK1 0x94 +#if 0 +/* PHY1 hw training item */ +#define SYSCTRL_DDR_HW_PHY1_RANK0 0x98 +#define SYSCTRL_DDR_HW_PHY1_RANK1 0x9c +#endif + +/* config other special */ +/* [CUSTOM] DDR training start address. MEM_BASE_DDR */ +#define DDRT_CFG_BASE_ADDR 0x40000000 +/* [CUSTOM] SRAM start address. +NOTE: Makefile will parse it, plase define it as Hex. eg: 0xFFFF0C00 */ +#define DDR_TRAINING_RUN_STACK 0x04010c00 + +#define DDR_RELATE_REG_DECLARE +#define DDR_TRAINING_SAVE_REG_FUNC(relate_reg, mask) \ + ddr_training_save_reg_custom(relate_reg, mask) + +#define DDR_TRAINING_RESTORE_REG_FUNC(relate_reg) \ + ddr_training_restore_reg_custom(relate_reg) + +struct tr_custom_reg { + unsigned int ive_ddrt_mst_sel; + unsigned int ddrt_clk_reg; + unsigned int phy0_age_compst_en; + unsigned int phy1_age_compst_en; +}; +void ddr_training_save_reg_custom(void *relate_reg, unsigned int mask); +void ddr_training_restore_reg_custom(void *relate_reg); +int ddr_get_cksel(void); +#endif /* DDR_TRAINING_CUSTOM_H */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.c b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.c new file mode 100755 index 00000000..c73aeb4d --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.c @@ -0,0 +1,4372 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * Description: DDR training implement + */ + +#include "ddr_training_impl.h" +#include "ddr_interface.h" + +#define __common__ + +typedef unsigned long int uintptr_t; + +unsigned int ddr_read(unsigned addr) +{ + return (*(volatile unsigned int *)((uintptr_t)(addr))); +} + +void ddr_write(unsigned val, unsigned addr) +{ + (*(volatile unsigned int *)((uintptr_t)(addr))) = (val); +} + +void* ddrtr_memcpy(void *dst, const void *src, unsigned int len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + return dst; +} + +void* ddrtr_memset(void *b, int c, unsigned int len) +{ + char *bp = b; + + while (len--) + *bp++ = (unsigned char)c; + return b; +} + +int ddr_training_by_dmc(struct ddr_cfg_st *cfg) +{ + if (cfg->cmd_st) { +#ifdef DDR_TRAINING_CMD + return ddr_training_cmd_func(cfg); +#endif + } else { + return ddr_training_boot_func(cfg); + } + return 0; +} + +int ddr_training_by_rank(struct ddr_cfg_st *cfg) +{ + int result = 0; + int i; + + DDR_PHY_SWITCH_RANK(cfg->cur_phy, cfg->rank_idx); + + for (i = 0; i < cfg->phy[cfg->phy_idx].dmc_num; i++) { + cfg->dmc_idx = i; + cfg->cur_dmc = cfg->phy[cfg->phy_idx].dmc[i].addr; + cfg->cur_pattern = cfg->phy[cfg->phy_idx].dmc[i].ddrt_pattern; + result += ddr_training_by_dmc(cfg); + } + return result; +} + +int ddr_training_by_phy(struct ddr_cfg_st *cfg) +{ + int result = 0; + int i; + unsigned int phy_mask = 1 << (cfg->phy_idx); + unsigned int rank_num = cfg->phy[cfg->phy_idx].rank_num; + for (i = 0; i < rank_num; i++) { + cfg->rank_idx = i; + cfg->cur_item = cfg->phy[cfg->phy_idx].rank[i].item; + if (ddr_training_check_bypass(cfg, phy_mask)) + continue; + result += ddr_training_by_rank(cfg); + } + return result; +} + +int ddr_training_all(struct ddr_cfg_st *cfg) +{ + int result = 0; + int i; + for (i = 0; i < cfg->phy_num; i++) { + cfg->phy_idx = i; + cfg->cur_phy = cfg->phy[i].addr; + result += ddr_training_by_phy(cfg); + } + return result; +} + +/* DDR training phy/dmc/dram_type config init */ +void ddr_training_cfg_set_dmc(struct ddr_cfg_st *cfg) +{ + unsigned int ddrt_pattern; + + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[0].dram_type) { + cfg->phy[0].dmc_num = 2; + ddrt_pattern = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDRT_PATTERN); + cfg->phy[0].dmc[0].addr = DDR_REG_BASE_DMC0; + cfg->phy[0].dmc[0].ddrt_pattern = ddrt_pattern & 0xffff; + cfg->phy[0].dmc[0].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC0); + cfg->phy[0].dmc[1].addr = DDR_REG_BASE_DMC1; + cfg->phy[0].dmc[1].ddrt_pattern = ddrt_pattern >> 16; + cfg->phy[0].dmc[1].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC1); + cfg->phy[0].total_byte_num = cfg->phy[0].dmc[0].byte_num + cfg->phy[0].dmc[1].byte_num; + } else { + cfg->phy[0].dmc_num = 1; + cfg->phy[0].dmc[0].addr = DDR_REG_BASE_DMC0; + cfg->phy[0].dmc[0].ddrt_pattern = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDRT_PATTERN); + cfg->phy[0].dmc[0].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC0); + cfg->phy[0].total_byte_num = cfg->phy[0].dmc[0].byte_num; + } + DDR_INFO("phy[0] total_byte_num[%x] dram_type[%x]", cfg->phy[0].total_byte_num, cfg->phy[0].dram_type); + +#ifdef DDR_REG_BASE_PHY1 + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[1].dram_type) { + cfg->phy[1].dmc_num = 2; + ddrt_pattern = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDRT_PATTERN_SEC); + cfg->phy[1].dmc[0].addr = DDR_REG_BASE_DMC2; + cfg->phy[1].dmc[0].ddrt_pattern = ddrt_pattern & 0xffff; + cfg->phy[1].dmc[0].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC2); + cfg->phy[1].dmc[1].addr = DDR_REG_BASE_DMC3; + cfg->phy[1].dmc[1].ddrt_pattern = ddrt_pattern >> 16; + cfg->phy[1].dmc[1].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC3); + cfg->phy[1].total_byte_num = cfg->phy[1].dmc[0].byte_num + cfg->phy[1].dmc[1].byte_num; + } else { + cfg->phy[1].dmc_num = 1; + cfg->phy[1].dmc[0].addr = DDR_REG_BASE_DMC1; + cfg->phy[1].dmc[0].ddrt_pattern = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDRT_PATTERN_SEC); + cfg->phy[1].dmc[0].byte_num = ddr_phy_get_byte_num(DDR_REG_BASE_DMC1); + cfg->phy[1].total_byte_num = cfg->phy[1].dmc[0].byte_num; + } + DDR_INFO("phy[1] total_byte_num[%x] dram_type[%x]", cfg->phy[1].total_byte_num, cfg->phy[1].dram_type); +#endif +} +void ddr_training_cfg_set_rank(struct ddr_cfg_st *cfg) +{ + cfg->phy[0].rank_num = 1; + cfg->phy[0].rank[0].item = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG); + cfg->phy[0].rank[0].item_hw = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY0_RANK0); + + cfg->phy[0].rank[1].item = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG_SEC); + cfg->phy[0].rank[1].item_hw = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY0_RANK1); + + if (ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY0_RANK1)) { + cfg->phy[0].rank_num = 2; + } + + DDR_INFO("Rank number PHY0 [%x]", cfg->phy[0].rank_num); + DDR_INFO("HW training item PHY0[%x = %x][%x = %x]", + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY0_RANK0), cfg->phy[0].rank[0].item_hw, + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY0_RANK1), cfg->phy[0].rank[1].item_hw); + +#ifdef DDR_REG_BASE_PHY1 + cfg->phy[1].rank_num = 1; + cfg->phy[1].rank[0].item = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG); + cfg->phy[1].rank[0].item_hw = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY1_RANK0); + + cfg->phy[1].rank[1].item = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG_SEC); + cfg->phy[1].rank[1].item_hw = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY1_RANK1); + + + if (ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY1_RANK1)) { + cfg->phy[1].rank_num = 2; + } + + DDR_INFO("Rank number PHY1[%x]", cfg->phy[1].rank_num); + DDR_INFO("HW training item PHY1[%x = %x][%x = %x]", + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY1_RANK0), cfg->phy[1].rank[0].item_hw, + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_HW_PHY1_RANK1), cfg->phy[1].rank[1].item_hw); +#endif + + DDR_INFO("SW training item Rank0[%x = %x] Rank1[%x = %x]", + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG), cfg->phy[0].rank[0].item, + (DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG_SEC), cfg->phy[0].rank[1].item); +} + +void ddr_training_cfg_set_phy(struct ddr_cfg_st *cfg) +{ + cfg->phy_num = DDR_PHY_NUM; + cfg->phy[0].addr = DDR_REG_BASE_PHY0; + cfg->phy[0].dram_type = ddr_read(DDR_REG_BASE_PHY0 + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_MASK; +#ifdef DDR_REG_BASE_PHY1 + cfg->phy[1].addr = DDR_REG_BASE_PHY1; + cfg->phy[1].dram_type = ddr_read(DDR_REG_BASE_PHY1 + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_MASK; +#endif +} + +void ddr_training_cfg_init(struct ddr_cfg_st *cfg) +{ + ddrtr_memset(cfg, 0, sizeof(struct ddr_cfg_st)); + ddr_training_cfg_set_phy(cfg); + ddr_training_cfg_set_dmc(cfg); + ddr_training_cfg_set_rank(cfg); +} + +/* 2GHz CPU run 2000 "nop" in 1 ns */ +static inline void ddr_training_delay(unsigned int cnt) +{ + while (cnt--) + asm("nop"); +} + +/* set auto refresh */ +void ddr_training_set_timing(unsigned int base_dmc, unsigned int timing) +{ + ddr_training_delay(DDR_AUTO_TIMING_DELAY); + ddr_write(timing, base_dmc + DDR_DMC_TIMING2); + /* need to delay 1 ns */ + ddr_training_delay(DDR_AUTO_TIMING_DELAY); +} + +#ifdef DDR_TRAINING_STAT_CONFIG +/* Save training result in stat register */ +static void ddr_training_save(unsigned int mask, unsigned int phy, + int byte, int dq) +{ + unsigned int stat; + unsigned int phy_index; + + stat = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT); + /* only record the first error */ + if (stat) + return; + + stat = mask; + + if (0 != phy) { + phy_index = (DDR_REG_BASE_PHY0 == phy ? + DDR_ERR_PHY0 : DDR_ERR_PHY1); + stat |= phy_index; + } + + if (-1 != byte) + stat |= ((unsigned int)byte << DDR_ERR_BYTE_BIT); + + if (-1 != dq) + stat |= ((unsigned int)dq << DDR_ERR_DQ_BIT); + + ddr_write(stat, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT); +} +#endif + +/* Record error code in register */ +void ddr_training_stat(unsigned int mask, unsigned int phy, int byte, int dq) +{ + ddr_training_error(mask, phy, byte, dq); +#ifdef DDR_TRAINING_STAT_CONFIG + ddr_training_save(mask, phy, byte, dq); +#endif +} + +/* Check DDR training item whether by pass */ +int ddr_training_check_bypass(struct ddr_cfg_st *cfg, unsigned int mask) +{ + /* training item disable */ + if ((cfg->cur_item) & mask) { + DDR_DEBUG("DDR training [%x] is disable, rank[%x] cfg[%x]", + mask, cfg->rank_idx, cfg->cur_item); + return DDR_TRUE; + } else { + return DDR_FALSE; + } +} + +#if !defined(DDR_TRAINING_CUT_CODE_CONFIG) || defined(DDR_TRAINING_CMD) +/** + * Check PHY whether disable. + * DDR_TRUE: PHY is disable. + * DDR_FALSE: PHY is not disable. + */ +int ddr_training_phy_disable(int index) +{ + return 0; +} + +/* Save register value before training */ +void ddr_training_save_reg(struct ddr_cfg_st *cfg, + struct tr_relate_reg *relate_reg, unsigned int mask) +{ + unsigned int base_dmc = cfg->cur_dmc; + unsigned int base_phy = cfg->cur_phy; + + /* save reg value */ + relate_reg->auto_ref_timing = + ddr_read(base_dmc + DDR_DMC_TIMING2); + relate_reg->power_down = + ddr_read(base_dmc + DDR_DMC_CFG_PD); + relate_reg->misc_scramb = ddr_read(base_phy + DDR_PHY_MISC); + /* Static register have to read two times to get the right value. */ + relate_reg->ac_phy_ctl = + ddr_read(base_phy + DDR_PHY_ACPHYCTL4); + relate_reg->ac_phy_ctl = + ddr_read(base_phy + DDR_PHY_ACPHYCTL4); + + /* set new value */ + switch (mask) { + case DDR_BYPASS_WL_MASK: + case DDR_BYPASS_LPCA_MASK: + /* disable auto refresh */ + ddr_training_set_timing(base_dmc, + relate_reg->auto_ref_timing & DMC_AUTO_TIMING_DIS); + break; + case DDR_BYPASS_GATE_MASK: + /* disable auto refresh */ + ddr_training_set_timing(base_dmc, + relate_reg->auto_ref_timing & DMC_AUTO_TIMING_DIS); + + if (!(ddr_read(base_phy + DDR_PHY_DRAMCFG) & PHY_DRAMCFG_MA2T)) /* set 1T */ + ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4); + break; + case DDR_BYPASS_HW_MASK: + if (!(ddr_read(base_phy + DDR_PHY_DRAMCFG) & PHY_DRAMCFG_MA2T)) /* set 1T */ + ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4); + break; + default: + break; + } + + ddr_write(relate_reg->power_down & DMC_POWER_DOWN_DIS, + base_dmc + DDR_DMC_CFG_PD); + ddr_write(relate_reg->misc_scramb & PHY_MISC_SCRAMB_DIS, + base_phy + DDR_PHY_MISC); + + DDR_DQSSWAP_SAVE_FUNC(relate_reg->swapdfibyte_en, base_phy); + + DDR_AXI_SAVE_FUNC(relate_reg); + + DDR_RNKVOL_SAVE_FUNC(relate_reg, base_dmc); + + /* save customer reg */ + DDR_TRAINING_SAVE_REG_FUNC((void *)relate_reg, mask); + + ddr_phy_cfg_update(base_phy); + + DDR_ASM_DSB(); +} + +/* Restore register value after training */ +void ddr_training_restore_reg(struct ddr_cfg_st *cfg, + struct tr_relate_reg *relate_reg) +{ + unsigned int base_dmc = cfg->cur_dmc; + unsigned int base_phy = cfg->cur_phy; + + /* enable auto refresh */ + ddr_training_set_timing(base_dmc, relate_reg->auto_ref_timing); + ddr_write(relate_reg->power_down, base_dmc + DDR_DMC_CFG_PD); + ddr_write(relate_reg->misc_scramb, base_phy + DDR_PHY_MISC); + if (!(ddr_read(base_phy + DDR_PHY_DRAMCFG) & PHY_DRAMCFG_MA2T)) + ddr_write(relate_reg->ac_phy_ctl, base_phy + DDR_PHY_ACPHYCTL4); + + DDR_DQSSWAP_RESTORE_FUNC(relate_reg->swapdfibyte_en, base_phy); + + DDR_AXI_RESTORE_FUNC(relate_reg); + + DDR_RNKVOL_RESTORE_FUNC(relate_reg, base_dmc); + + /* restore customer reg */ + DDR_TRAINING_RESTORE_REG_FUNC((void *)relate_reg); + + ddr_phy_cfg_update(base_phy); + + DDR_ASM_DSB(); +} + +/* Switch AXI to DMC0/DMC1/DMC2/DMC3 for DDRT test */ +void ddr_training_switch_axi(struct ddr_cfg_st *cfg) +{ + DDR_AXI_SWITCH_FUNC(cfg); + + DDR_RNKVOL_SET_FUNC(cfg); +} +#endif + +#if defined(DDR_WL_TRAINING_CONFIG) || defined(DDR_MPR_TRAINING_CONFIG) + +/* Excute DMC sfc command */ +static void ddr_dmc_sfc_cmd(unsigned int base_dmc, unsigned int sfc_cmd, + unsigned int sfc_addr, unsigned int sfc_bank) +{ + unsigned int count = 0; + + /* set sfc cmd */ + DMC_SFC_CMD_WRITE(sfc_cmd, base_dmc + DDR_DMC_SFCCMD); + /* set col and row */ + ddr_write(sfc_addr, base_dmc + DDR_DMC_SFCADDR); + /* set bank */ + DMC_SFC_BANK_WRITE(sfc_bank, base_dmc + DDR_DMC_SFCBANK); + /* excute cmd */ + ddr_write(0x1, base_dmc + DDR_DMC_SFCREQ); + + DDR_ASM_DSB(); + + while (count < DDR_SFC_WAIT_TIMEOUT) { /* wait command finished */ + if (!(ddr_read(base_dmc + DDR_DMC_SFCREQ) & 0x1)) + break; + + count++; + } + + if (count >= DDR_HWR_WAIT_TIMEOUT) + DDR_ERROR("SFC cmd wait timeout."); +} +#endif + +#if defined(DDR_HW_TRAINING_CONFIG) || defined(DDR_DCC_TRAINING_CONFIG) + +/* Exit or enter auto self-refresh */ +static int ddr_training_easr(unsigned int base_dmc, unsigned int sref_req) +{ + unsigned int count = DDR_HWR_WAIT_TIMEOUT; + if (DDR_EXIT_SREF == sref_req) { + /* Exit Auto-self refresh */ + ddr_write(DMC_CTRL_SREF_EXIT, base_dmc + DDR_DMC_CTRL_SREF); + + while (count--) { + if (!(ddr_read(base_dmc + DDR_DMC_CURR_FUNC) + & DMC_CURR_FUNC_IN_SREF_MASK)) + break; + } + } else if (DDR_ENTER_SREF == sref_req) { + /* Enter Auto-self refresh */ + ddr_write(DMC_CTRL_SREF_ENTER, base_dmc + DDR_DMC_CTRL_SREF); + + while (count--) { + if (ddr_read(base_dmc + DDR_DMC_CURR_FUNC) + & DMC_CURR_FUNC_IN_SREF_MASK) + break; + } + } + + if (count == 0xffffffff) { + DDR_FATAL("SREF wait timeout."); + ddr_training_stat(DDR_ERR_HW_RD_DATAEYE, -1, -1, -1); + return -1; + } + return 0; +} + +/* DDR hw/dcc training exit or enter auto self-refresh */ +static int ddr_training_ctrl_easr(struct ddr_cfg_st *cfg, unsigned int sref_req) +{ + int result = 0; + int i; + struct ddr_phy_st *phy_st = &cfg->phy[cfg->phy_idx]; + + for (i = 0; i < phy_st->dmc_num; i++) { + result += ddr_training_easr(phy_st->dmc[i].addr, sref_req); + } + + return result; +} + +static void ddr_training_save_timing(struct ddr_cfg_st *cfg, struct ddr_timing_st *timing_st) +{ + int i; + struct ddr_phy_st *phy_st = &cfg->phy[cfg->phy_idx]; + + for (i = 0; i < phy_st->dmc_num; i++) { + + timing_st->val[i] = ddr_read(phy_st->dmc[i].addr + DDR_DMC_TIMING2); + /* disable auto refresh */ + ddr_training_set_timing(phy_st->dmc[i].addr, timing_st->val[i] & DMC_AUTO_TIMING_DIS); + } +} + +static void ddr_training_restore_timing(struct ddr_cfg_st *cfg, struct ddr_timing_st *timing_st) +{ + int i; + struct ddr_phy_st *phy_st = &cfg->phy[cfg->phy_idx]; + for (i = 0; i < phy_st->dmc_num; i++) { + ddr_training_set_timing(phy_st->dmc[i].addr, timing_st->val[i]); + } +} +#endif /* DDR_HW_TRAINING_CONFIG || DDR_DCC_TRAINING_CONFIG*/ + +/** + * Update delay setting in registers to PHY immediately. + * Make delay setting take effect. + */ +void ddr_phy_cfg_update(unsigned int base_phy) +{ + unsigned int tmp; + + tmp = ddr_read(base_phy + DDR_PHY_MISC); + tmp |= (1 << PHY_MISC_UPDATE_BIT); + /* update new config to PHY */ + ddr_write(tmp, base_phy + DDR_PHY_MISC); + tmp &= ~(1 << PHY_MISC_UPDATE_BIT); + ddr_write(tmp, base_phy + DDR_PHY_MISC); + tmp = ddr_read(base_phy + DDR_PHY_PHYINITCTRL); + /* set 1 to issue PHY counter reset signal */ + tmp |= (1 << PHY_PHYCONN_RST_BIT); + ddr_write(tmp, base_phy + DDR_PHY_PHYINITCTRL); + /* set 0 to end the reset signal */ + tmp &= ~(1 << PHY_PHYCONN_RST_BIT); + ddr_write(tmp, base_phy + DDR_PHY_PHYINITCTRL); + + DDR_ASM_DSB(); +} + +/* Set delay value of the bit delay line of the DATA block */ +void ddr_phy_set_dq_bdl(struct ddr_cfg_st *cfg, unsigned int value) +{ + unsigned int val; + unsigned int offset; + unsigned int dq; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_index = cfg->cur_byte; + unsigned int rank = cfg->rank_idx; + + dq = cfg->cur_dq & 0x7; + if (DDR_MODE_WRITE == cfg->cur_mode) { + if (dq < 4) + offset = DDR_PHY_DXNWDQNBDL0(rank, byte_index); + else + offset = DDR_PHY_DXNWDQNBDL1(rank, byte_index); + } else { + if (dq < 4) + offset = DDR_PHY_DXNRDQNBDL0(rank, byte_index); + else + offset = DDR_PHY_DXNRDQNBDL1(rank, byte_index); + } + + dq &= 0x3; + val = ddr_read(base_phy + offset); + val &= ~(0xFF << (dq << 3)); + val |= ((PHY_BDL_MASK & value) << ((dq << 3) + PHY_BDL_DQ_BIT)); + ddr_write(val, base_phy + offset); + + ddr_phy_cfg_update(base_phy); +} + +/* Get PHY DQ value */ +unsigned int ddr_phy_get_dq_bdl(struct ddr_cfg_st *cfg) +{ + unsigned int val; + unsigned int offset; + unsigned int dq; + unsigned int byte_index = cfg->cur_byte; + unsigned int rank = cfg->rank_idx; + + dq = cfg->cur_dq & 0x7; + if (DDR_MODE_WRITE == cfg->cur_mode) { + if (dq < 4) + offset = DDR_PHY_DXNWDQNBDL0(rank, byte_index); + else + offset = DDR_PHY_DXNWDQNBDL1(rank, byte_index); + } else { + if (dq < 4) + offset = DDR_PHY_DXNRDQNBDL0(rank, byte_index); + else + offset = DDR_PHY_DXNRDQNBDL1(rank, byte_index); + } + + dq &= 0x3; + val = (ddr_read(cfg->cur_phy + offset) >> ((dq << 3) + PHY_BDL_DQ_BIT)) & PHY_BDL_MASK; + + return val; +} + +/* Get byte number */ +unsigned int ddr_phy_get_byte_num(unsigned int base_dmc) +{ + unsigned int byte_num; + + /* memery width -> byte number */ + byte_num = ((ddr_read(base_dmc + DDR_DMC_CFG_DDRMODE) + >> DMC_MEM_WIDTH_BIT) & DMC_MEM_WIDTH_MASK) << 1; + + /* for codedex */ + if (byte_num > DDR_PHY_BYTE_MAX) { + byte_num = DDR_PHY_BYTE_MAX; + DDR_ERROR("get byte num fail"); + } + + return byte_num; +} + + +static void ddr_rdqs_sync_rdm(struct ddr_cfg_st *cfg, int offset) +{ + unsigned int rdqnbdl; + int rdm; + + rdqnbdl = ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQNBDL2(cfg->rank_idx, cfg->cur_byte)); + rdm = (rdqnbdl >> PHY_RDM_BDL_BIT) & PHY_RDM_BDL_MASK; + rdm += offset; + rdm = (rdm < 0 ? 0 : rdm); + rdm = (rdm > PHY_RDM_BDL_MASK ? PHY_RDM_BDL_MASK : rdm); + rdqnbdl = rdqnbdl & (~(PHY_RDM_BDL_MASK << PHY_RDM_BDL_BIT)); + ddr_write(rdqnbdl | ((unsigned int)rdm << PHY_RDM_BDL_BIT), cfg->cur_phy + DDR_PHY_DXNRDQNBDL2(cfg->rank_idx, cfg->cur_byte)); +} + +static void ddr_rdqs_sync_rank_rdq(struct ddr_cfg_st *cfg, int offset) +{ + int dq_val; + int i; + + /* sync other rank rdm */ + ddr_rdqs_sync_rdm(cfg, offset); + + /* sync other rank rdq */ + DDR_DEBUG("Before sync rank[%x] byte[%x] dq[%x = %x][%x = %x] offset[%x]", + cfg->rank_idx, cfg->cur_byte, + cfg->cur_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, cfg->cur_byte), + ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, cfg->cur_byte)), + cfg->cur_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, cfg->cur_byte), + ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, cfg->cur_byte)), offset); + + for (i = 0; i < DDR_PHY_BIT_NUM; i++) { + cfg->cur_dq = i; + dq_val = (int)ddr_phy_get_dq_bdl(cfg); + dq_val += offset; + dq_val = (dq_val < 0 ? 0 : dq_val); + dq_val = (dq_val > PHY_BDL_MASK ? PHY_BDL_MASK : dq_val); + ddr_phy_set_dq_bdl(cfg, dq_val); + } + + DDR_DEBUG("After sync rank[%x] byte[%x] dq[%x = %x][%x = %x]", + cfg->rank_idx, cfg->cur_byte, + cfg->cur_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, cfg->cur_byte), + ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, cfg->cur_byte)), + cfg->cur_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, cfg->cur_byte), + ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, cfg->cur_byte))); +} + +static void ddr_bdl_adj(struct ddr_cfg_st *cfg) +{ + int i; + int value_num = 10; + unsigned int rank = cfg->rank_idx; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_idx = cfg->cur_byte; + unsigned int bdl[value_num]; + unsigned int min = 0xffffffff; + unsigned int dq03, dq47, rdm, rdqs; + + dq03 = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL0(rank, byte_idx)); + dq47 = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL1(rank, byte_idx)); + rdm = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL2(rank, byte_idx)); + rdqs = ddr_read(base_phy + DDR_PHY_DXNRDQSDLY(byte_idx)); + + bdl[0] = (dq03 >> PHY_BDL_DQ0_BIT) & PHY_BDL_MASK; + bdl[1] = (dq03 >> PHY_BDL_DQ1_BIT) & PHY_BDL_MASK; + bdl[2] = (dq03 >> PHY_BDL_DQ2_BIT) & PHY_BDL_MASK; + bdl[3] = (dq03 >> PHY_BDL_DQ3_BIT) & PHY_BDL_MASK; + bdl[4] = (dq47 >> PHY_BDL_DQ0_BIT) & PHY_BDL_MASK; + bdl[5] = (dq47 >> PHY_BDL_DQ1_BIT) & PHY_BDL_MASK; + bdl[6] = (dq47 >> PHY_BDL_DQ2_BIT) & PHY_BDL_MASK; + bdl[7] = (dq47 >> PHY_BDL_DQ3_BIT) & PHY_BDL_MASK; + bdl[8] = (rdm >> PHY_RDM_BDL_BIT) & PHY_RDM_BDL_MASK; + bdl[9] = (rdqs >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK; + + for (i = 0; i < value_num; i++) { + if (bdl[i] < min) + min = bdl[i]; + } + + dq03 = ((bdl[0] - min) << PHY_BDL_DQ0_BIT) | ((bdl[1] - min) << PHY_BDL_DQ1_BIT) | + ((bdl[2] - min) << PHY_BDL_DQ2_BIT) | ((bdl[3] - min) << PHY_BDL_DQ3_BIT); + dq47 = ((bdl[4] - min) << PHY_BDL_DQ0_BIT) | ((bdl[5] - min) << PHY_BDL_DQ1_BIT) | + ((bdl[6] - min) << PHY_BDL_DQ2_BIT) | ((bdl[7] - min) << PHY_BDL_DQ3_BIT); + rdm = (rdm & (~(PHY_RDM_BDL_MASK << PHY_RDM_BDL_BIT))) | ((bdl[8] - min) << PHY_RDM_BDL_BIT); + rdqs = (rdqs & (~(PHY_RDQS_BDL_MASK << PHY_RDQS_BDL_BIT))) | ((bdl[9] - min) << PHY_RDQS_BDL_BIT); + + ddr_write(dq03, base_phy + DDR_PHY_DXNRDQNBDL0(rank, byte_idx)); + ddr_write(dq47, base_phy + DDR_PHY_DXNRDQNBDL1(rank, byte_idx)); + ddr_write(rdm, base_phy + DDR_PHY_DXNRDQNBDL2(rank, byte_idx)); + ddr_write(rdqs, base_phy + DDR_PHY_DXNRDQSDLY(byte_idx)); +} + +#define __ddrt__ +#ifdef DDR_DDRT_SPECIAL_CONFIG +/* Some special DDRT need read register repeatedly */ +static unsigned int ddr_ddrt_read(unsigned int addr) +{ + int times = 0; + unsigned int data0, data1, data2; + do { + data0 = ddr_read(addr); + data1 = ddr_read(addr); + data2 = ddr_read(addr); + times++; + } while (((data0 != data1) || (data1 != data2)) + && (times < DDRT_READ_TIMEOUT)); + + if (times >= DDRT_READ_TIMEOUT) { + DDR_FATAL("DDRT wait timeout."); + ddr_training_stat(DDR_ERR_DDRT_TIME_OUT, 0, -1, -1); + } + + return data0; +} + +/* Some special DDRT need write twice register */ +static void ddr_ddrt_write(unsigned int data, unsigned int addr) +{ + unsigned int tmp; + tmp = ddr_read(addr); + ddr_write(data, addr); + ddr_write(data, addr); +} +#endif /* DDR_DDRT_SPECIAL_CONFIG */ + +static unsigned int ddr_get_rank_size(struct ddr_cfg_st *cfg) +{ + unsigned int base_dmc = cfg->cur_dmc; + unsigned int rnkvol; + unsigned int mem_bank, mem_row, mem_col, mem_width; + unsigned int size; + + mem_width = (ddr_read(base_dmc + DDR_DMC_CFG_DDRMODE) >> DMC_MEM_WIDTH_BIT) & DMC_MEM_WIDTH_MASK; + rnkvol = ddr_read(base_dmc + DDR_DMC_CFG_RNKVOL(0)); + mem_bank = (rnkvol >> DMC_RNKVOL_MEM_BANK_BIT) & DMC_RNKVOL_MEM_BANK_MASK; + mem_row = (rnkvol >> DMC_RNKVOL_MEM_ROW_BIT) & DMC_RNKVOL_MEM_ROW_MASK; + mem_col = rnkvol & DMC_RNKVOL_MEM_COL_MASK; + + size = 1UL << ((mem_bank + 2) + (mem_row + 11) + (mem_col + 8) + mem_width); + DDR_DEBUG("rank size[%x]", size); + + return size; +} + +/* Init DDRT register before DDRT test */ +void ddr_ddrt_init(struct ddr_cfg_st *cfg, unsigned int mode) +{ + unsigned int mem_width; + unsigned int mem_config; + unsigned int offset = 0; + + if (1 == cfg->rank_idx) + offset = ddr_get_rank_size(cfg); + + DDR_TRAINING_DDRT_PREPARE_FUNC(); + + mem_width = ((ddr_read(cfg->cur_dmc + DDR_DMC_CFG_DDRMODE) + >> DMC_MEM_WIDTH_BIT) & DMC_MEM_WIDTH_MASK); + mem_config = ((mem_width - 1) << DDRT_DDR_MEM_WIDTH) + | DDRT_DDR_COL_WIDTH | DDRT_DDR_ROW_WIDTH + | DDRT_DDR_BANK_WIDTH; + /* DDRT SDRAM config */ + DDRT_REG_WRITE(mem_config, DDR_REG_BASE_DDRT + DDRT_MEM_CONFIG); + /* DDR Address Base */ + DDRT_REG_WRITE(DDRT_GET_TEST_ADDR(DDRT_CFG_BASE_ADDR), + DDR_REG_BASE_DDRT + DDRT_DDR_BASE_ADDR); + /* DDRT test DDR using space */ + DDRT_REG_WRITE(DDRT_GET_TEST_ADDR(ddr_ddrt_get_test_addr() + offset), + DDR_REG_BASE_DDRT + DDRT_ADDR); + DDRT_REG_WRITE(DDRT_CFG_SEED, DDR_REG_BASE_DDRT + DDRT_SEED); + + if (DDR_DDRT_MODE_GATE == mode) { + /* Read or Write Once */ + DDRT_REG_WRITE(DDRT_CFG_BURST_CFG_GATE, + DDR_REG_BASE_DDRT + DDRT_BURST_CONFIG); + DDRT_REG_WRITE(0x0, DDR_REG_BASE_DDRT + DDRT_BURST_NUM); + DDRT_REG_WRITE(0x0, DDR_REG_BASE_DDRT + DDRT_ADDR_NUM); + DDRT_REG_WRITE(0x0, DDR_REG_BASE_DDRT + DDRT_LOOP_NUM); + DDRT_REG_WRITE(DDRT_CFG_REVERSED, + DDR_REG_BASE_DDRT + DDRT_REVERSED_DQ); + } else { + /* reversed data form register init table */ + /* 128bit BURST4 */ + DDRT_REG_WRITE(DDRT_CFG_BURST_CFG_DATAEYE, + DDR_REG_BASE_DDRT + DDRT_BURST_CONFIG); + DDRT_REG_WRITE(cfg->phy[cfg->phy_idx].dmc[cfg->dmc_idx].ddrt_pattern, + DDR_REG_BASE_DDRT + DDRT_REVERSED_DQ); + DDRT_REG_WRITE(DDRT_CFG_BURST_NUM, + DDR_REG_BASE_DDRT + DDRT_BURST_NUM); + DDRT_REG_WRITE(DDRT_CFG_ADDR_NUM, + DDR_REG_BASE_DDRT + DDRT_ADDR_NUM); + DDRT_REG_WRITE(DDRT_CFG_LOOP_NUM, + DDR_REG_BASE_DDRT + DDRT_LOOP_NUM); + } + + DDR_DEBUG("DDRT ADDR[%x = %x]", (DDR_REG_BASE_DDRT + DDRT_ADDR), + ddr_read(DDR_REG_BASE_DDRT + DDRT_ADDR)); +} + +/** + * ddr_ddrt_test + * @mask : DDRT option mask. + * @byte : DDR byte index. + * @dq : DDR dq index. + * + * DDRT test. Support read_only mode and write_read_compare mode. + * Success return 0, fail return -1. + */ +int ddr_ddrt_test(unsigned int mask, int byte, int dq) +{ + unsigned int regval; + unsigned int err_ovfl; + unsigned int err_cnt; + unsigned int dq_num; + unsigned int dq_tmp; + unsigned int times = 0; + + DDRT_REG_WRITE(mask | DDRT_CFG_START, DDR_REG_BASE_DDRT + DDRT_OP); + DDRT_REG_WRITE(0, DDR_REG_BASE_DDRT + DDRT_STATUS); + + DDR_ASM_DSB(); + + do { + regval = DDRT_REG_READ(DDR_REG_BASE_DDRT + DDRT_STATUS); + times++; + } while ((!(regval & DDRT_TEST_DONE_MASK)) + && (times < DDRT_WAIT_TIMEOUT)); + + if (times >= DDRT_WAIT_TIMEOUT) { + DDR_FATAL("DDRT wait timeout."); + ddr_training_stat(DDR_ERR_DDRT_TIME_OUT, 0, -1, -1); + return -1; + } + + /* DDRT_READ_ONLY_MODE */ + if (DDRT_READ_ONLY_MODE == (mask & DDRT_TEST_MODE_MASK)) + return 0; /* return when DDRT finish */ + + /* DDRT_WR_COMPRARE_MODE No error occurred, test pass. */ + if (regval & DDRT_TEST_PASS_MASK) + return 0; + + if (-1 != dq) { /* check for dq */ + dq_num = ((unsigned int)byte << 3) + dq; + err_ovfl = DDRT_REG_READ(DDR_REG_BASE_DDRT + + DDRT_DQ_ERR_OVFL) & (1 << dq_num); + if (err_ovfl) + return -1; + + if (dq > 3) + dq_tmp = (unsigned int)(dq - 4) << 3; + else + dq_tmp = (unsigned int)dq << 3; + err_cnt = DDRT_REG_READ(DDR_REG_BASE_DDRT + + DDRT_DQ_ERR_CNT(((unsigned int)byte << 1) + ((unsigned int)dq >> 2))); + err_cnt = err_cnt & (0xff << dq_tmp); + if (err_cnt) + return -1; + } else if (-1 != byte) { /* check for byte */ + err_ovfl = DDRT_REG_READ(DDR_REG_BASE_DDRT + + DDRT_DQ_ERR_OVFL) & (0xff << ((unsigned int)byte << 3)); + if (err_ovfl) + return -1; + + err_cnt = DDRT_REG_READ(DDR_REG_BASE_DDRT + + DDRT_DQ_ERR_CNT((unsigned int)byte << 1)); + err_cnt += DDRT_REG_READ(DDR_REG_BASE_DDRT + + DDRT_DQ_ERR_CNT(((unsigned int)byte << 1) + 1)); + if (err_cnt) + return -1; + } + + return 0; +} + +/* Check ddrt test result. Success return 0, fail return -1 */ +static int ddr_ddrt_check(struct ddr_cfg_st *cfg) +{ + unsigned int byte_index_to_dmc = cfg->cur_byte; + + /* ddrt test the byte relate to dmc, make sure not overflow */ + if (cfg->cur_byte >= (cfg->dmc_idx << 1)) + byte_index_to_dmc = cfg->cur_byte - (cfg->dmc_idx << 1); + + DDRT_REG_WRITE(0, DDR_REG_BASE_DDRT + DDRT_REVERSED_DQ); + if (ddr_ddrt_test(DDRT_WR_COMPRARE_MODE | DDRT_PATTERM_PRBS9, + byte_index_to_dmc, cfg->cur_dq)) + return -1; + + DDRT_REG_WRITE(cfg->cur_pattern, DDR_REG_BASE_DDRT + DDRT_REVERSED_DQ); + if (ddr_ddrt_test(DDRT_WR_COMPRARE_MODE | DDRT_PATTERM_PRBS11, + byte_index_to_dmc, cfg->cur_dq)) + return -1; + + return 0; +} + +#define __dataeye_adjust__ +#ifdef DDR_TRAINING_ADJUST_CONFIG +static unsigned int ddr_adjust_get_average(struct ddr_cfg_st *cfg) +{ + unsigned int dq0_3, dq4_7, val; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_index = cfg->cur_byte; + unsigned int rank = cfg->rank_idx; + + if (DDR_MODE_WRITE == cfg->cur_mode) + return (ddr_read(base_phy + DDR_PHY_DXNWDQNBDL2(rank, byte_index)) + >> PHY_WDM_BDL_BIT) & PHY_BDL_MASK; + + /* read */ + dq0_3 = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL0(rank, byte_index)); + dq4_7 = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL1(rank, byte_index)); + + val = ((dq0_3 >> PHY_BDL_DQ0_BIT) & PHY_BDL_MASK) + + ((dq0_3 >> PHY_BDL_DQ1_BIT) & PHY_BDL_MASK) + + ((dq0_3 >> PHY_BDL_DQ2_BIT) & PHY_BDL_MASK) + + ((dq0_3 >> PHY_BDL_DQ3_BIT) & PHY_BDL_MASK) + + ((dq4_7 >> PHY_BDL_DQ0_BIT) & PHY_BDL_MASK) + + ((dq4_7 >> PHY_BDL_DQ1_BIT) & PHY_BDL_MASK) + + ((dq4_7 >> PHY_BDL_DQ2_BIT) & PHY_BDL_MASK) + + ((dq4_7 >> PHY_BDL_DQ3_BIT) & PHY_BDL_MASK); + + val = val >> 3; + return val; +} + +/** + * ddr_adjust_trend_check + * @accel : Return a value to adjust quickly. + * + * Check dataeye DQ window on left or right or middle. + */ +static unsigned int ddr_adjust_trend_check(struct ddr_cfg_st *cfg, int *accel) +{ + unsigned int dq_bdl = 0; + unsigned int size; + + /* 32 BDL middle[13, 17]. 128 BDL middle[40, 56] */ + /* 1 Phase = (DDR_BDL_PHASE_TRANSFORM) BDL */ + size = DDR_BDL_PHASE_TRANSFORM >> 1; + + dq_bdl = ddr_adjust_get_average(cfg); + + /* increase adjust step to accelerate */ + if (accel) { + if (dq_bdl > PHY_DQ_BDL_MIDDLE) + *accel = dq_bdl - PHY_DQ_BDL_MIDDLE; + else if (dq_bdl < PHY_DQ_BDL_MIDDLE) + *accel = PHY_DQ_BDL_MIDDLE - dq_bdl; + + DDR_INFO("byte[%x] bdl[%x] middle[%x] accel[%x] rdqs[%x]", + cfg->cur_byte, dq_bdl, PHY_DQ_BDL_MIDDLE, *accel, + (ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQSDLY(cfg->cur_byte)) + >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK); + } + + /* window on left */ + if (dq_bdl < (PHY_DQ_BDL_MIDDLE - size)) + return DDR_WIN_LEFT; + /* on right */ + else if (dq_bdl > (PHY_DQ_BDL_MIDDLE + size)) + return DDR_WIN_RIGHT; + else + return DDR_WIN_MIDDLE; +} + +/* Check adjust value whether valid */ +static int ddr_adjust_check_val(int val, unsigned int mode) +{ + if (DDR_MODE_READ == mode) { + if (val < 0 || val > PHY_RDQS_BDL_MASK) + return DDR_FALSE; + } else { + if (val < 0 || val > PHY_WDQ_PHASE_MASK) + return DDR_FALSE; + } + + return DDR_TRUE; +} + +/* Get value which need to adjust */ +static int ddr_adjust_get_val(struct ddr_cfg_st *cfg) +{ + if (DDR_MODE_READ == cfg->cur_mode) + return (ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQSDLY(cfg->cur_byte)) + >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK; + else + return (ddr_read(cfg->cur_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, cfg->cur_byte)) + >> PHY_WDQ_PHASE_BIT) & PHY_WDQ_PHASE_MASK; +} + +static void ddr_rdqs_sync(struct ddr_cfg_st *cfg, int val) +{ + unsigned int rdqsdly; + unsigned int cur_rank = cfg->rank_idx; + int old, offset; + + rdqsdly = ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQSDLY(cfg->cur_byte)); + old = (rdqsdly >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK; + offset = val - old; + + /* sync rdm */ + ddr_rdqs_sync_rank_rdq(cfg, offset); + + if (1 == cfg->phy[cfg->phy_idx].rank_num) { + DDR_DEBUG("Rank number[%x] not need sync another rank", cfg->phy[cfg->phy_idx].rank_num); + return; + } + + /* sync other rank rdm and rdq */ + cfg->rank_idx = DDR_SUPPORT_RANK_MAX - 1 - cur_rank; /* switch to another rank */ + ddr_rdqs_sync_rank_rdq(cfg, offset); + cfg->rank_idx = cur_rank; /* resotre to cur rank */ +} + +static void ddr_set_rdqs(struct ddr_cfg_st *cfg, int val) +{ + unsigned int delay; + delay = ddr_read(cfg->cur_phy + DDR_PHY_DXNRDQSDLY(cfg->cur_byte)); + + DDR_PHY_RDQS_SYNC_RDM(cfg, val); + + /* clear rdqs bdl */ + delay = delay & (~(PHY_RDQS_BDL_MASK << PHY_RDQS_BDL_BIT)); + + ddr_write(delay | ((unsigned int)val << PHY_RDQS_BDL_BIT), + cfg->cur_phy + DDR_PHY_DXNRDQSDLY(cfg->cur_byte)); +} + +/* Set value which need to adjust */ +static void ddr_adjust_set_val(struct ddr_cfg_st *cfg, int val) +{ + unsigned int delay; + if (DDR_MODE_READ == cfg->cur_mode) { + ddr_set_rdqs(cfg, val); + } else { + delay = ddr_read(cfg->cur_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, cfg->cur_byte)); + /* clear wdq phase */ + delay = delay & (~(PHY_WDQ_PHASE_MASK << PHY_WDQ_PHASE_BIT)); + + ddr_write(delay | ((unsigned int)val << PHY_WDQ_PHASE_BIT), + cfg->cur_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, cfg->cur_byte)); + } + + ddr_phy_cfg_update(cfg->cur_phy); +} + +/* Add or delete value to adjust */ +static void ddr_adjust_change_val(unsigned int dir, int *val, + int step, unsigned int mode) +{ + if (DDR_MODE_READ == mode) { + if (DDR_WIN_RIGHT == dir) + (*val) = (*val) + step; + else + (*val) = (*val) - step; + } else { + /* decrease wdq phase, window move to right */ + if (DDR_WIN_RIGHT == dir) + (*val) = (*val) - step; + else + (*val) = (*val) + step; + } +} + +/** + * ddr_adjust_move_win + * @dir : move direction. DDR_TRUE move to right, DDR_FALSE move to left. + * + * Move window to specified direction until the best DQ bdl beyond the midline. + */ +static void ddr_adjust_move_win(struct ddr_cfg_st *cfg, + struct training_data *training, + int step, unsigned int dir) +{ + int cur_val, def_val; + int i; + int accel; + int trend; + unsigned int max_value; + + max_value = (DDR_MODE_WRITE == cfg->cur_mode ? + PHY_WDQ_PHASE_MASK : PHY_RDQS_BDL_MASK); + + def_val = ddr_adjust_get_val(cfg); + cur_val = def_val; + for (i = 0; i <= max_value; i++) { + accel = step; + /* write mode no need to accelerate */ + if (DDR_MODE_WRITE == cfg->cur_mode) + trend = ddr_adjust_trend_check(cfg, 0); + else + trend = ddr_adjust_trend_check(cfg, &accel); + + if (DDR_WIN_MIDDLE == trend || dir == trend) { + DDR_DEBUG("Move byte[%x] window to middle suc", cfg->cur_byte); + break; + } + + ddr_adjust_change_val(dir, &cur_val, accel, cfg->cur_mode); + if (DDR_FALSE == ddr_adjust_check_val(cur_val, cfg->cur_mode)) { + DDR_WARNING("Move byte[%x] to middle fail. value[%x]", + cfg->cur_byte, cur_val); + break; + } + + DDR_DEBUG("Byte[%x] mode[%x] set value[%x]", + cfg->cur_byte, cfg->cur_mode, cur_val); + ddr_adjust_set_val(cfg, cur_val); + if (ddr_dataeye_deskew(cfg, training)) { + ddr_adjust_set_val(cfg, def_val); + /* MUST deskew dataeye after restore rdqs */ + ddr_dataeye_deskew(cfg, training); + DDR_ERROR("Byte[%x] deskew fail, restore[%x]", + cfg->cur_byte, def_val); + break; + } + } +} + +/* Adjust specified byte winodw to middle */ +static void ddr_adjust_byte(struct ddr_cfg_st *cfg, struct training_data *training) +{ + unsigned int trend = ddr_adjust_trend_check(cfg, 0); + + /* window on left, move to right */ + if (DDR_WIN_LEFT == trend) + ddr_adjust_move_win(cfg, training, DDR_DQS_ADJ_STEP, DDR_WIN_RIGHT); + /* window on right, move to left */ + else if (DDR_WIN_RIGHT == trend) + ddr_adjust_move_win(cfg, training, DDR_DQS_ADJ_STEP, DDR_WIN_LEFT); + /* window on middle, no need to move */ + else + DDR_DEBUG("Byte[%x] mode[%x] win on middle.", + cfg->cur_byte, cfg->cur_mode); +} + +/** + * Adjust PHY dataeye. On normal case, + * read dateeye window on left after read dataeye hardware training, + * write dataeye window on left after write leveling training. + * + */ +void ddr_adjust_dataeye(struct ddr_cfg_st *cfg, struct training_data *training) +{ + int i; + + /* dataeye adjust disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_DATAEYE_ADJ_MASK)) + return; + + DDR_DEBUG("DDR dataeye adjust PHY[%x][%x] DMC[%x][%x] Rank[%x]", + cfg->phy_idx, cfg->cur_phy, cfg->dmc_idx, cfg->cur_dmc, cfg->rank_idx); + + if (DDR_FALSE == cfg->adjust) + return; + + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + cfg->cur_byte = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + ddr_adjust_byte(cfg, training); + } +} +#else +#define ddr_adjust_dataeye(cfg, training) +#endif /* DDR_TRAINING_ADJUST_CONFIG */ + +#define __dataeye_training__ +#ifdef DDR_DATAEYE_TRAINING_CONFIG +/* Check dataeye dq */ +int ddr_dataeye_check_dq(struct ddr_cfg_st *cfg) +{ + if (DDR_CHECK_TYPE_DDRT == cfg->dq_check_type) + return ddr_ddrt_check(cfg); + else if (DDR_CHECK_TYPE_MPR == cfg->dq_check_type) + return ddr_mpr_check(cfg); + else + DDR_ERROR("DDR dataeye dq check type not set."); + + return 0; +} + +/* Check dq whether valid and set mask to reduce search time */ +static int ddr_dataeye_check_dir(unsigned int direction, unsigned int left, + unsigned int right, unsigned int *mask, + struct ddr_cfg_st *cfg) +{ + int result = 0; + + result = ddr_dataeye_check_dq(cfg); + switch (direction) { + case DDR_FIND_DQ_BOTH: + *mask = DDR_FIND_DQ_LEFT | DDR_FIND_DQ_RIGHT; + break; + case DDR_FIND_DQ_LEFT: + if (result) { + /* ddr test error, search opposite side */ + *mask = DDR_FIND_DQ_RIGHT; + } else { /* ddr test ok */ + ddr_phy_set_dq_bdl(cfg, left); + if (!ddr_dataeye_check_dq(cfg)) + /* test ok, go on search this side */ + *mask = DDR_FIND_DQ_LEFT; + } + break; + case DDR_FIND_DQ_RIGHT: + if (result) { /* ddr test error, search opposite side */ + *mask = DDR_FIND_DQ_LEFT; + } else { /* ddr test ok */ + ddr_phy_set_dq_bdl(cfg, right); + if (!ddr_dataeye_check_dq(cfg)) + /* test OK, go on search this side */ + *mask = DDR_FIND_DQ_RIGHT; + } + break; + default: + break; + } + + return result; +} + +/* Binary search the valid dq bdl */ +static void ddr_dataeye_search_dq(unsigned int left, unsigned int right, + int *target, unsigned int direction, + struct ddr_cfg_st *cfg) + +{ + unsigned int middle; + unsigned int mask = 0; + + middle = left + ((right - left) >> 1); + + ddr_phy_set_dq_bdl(cfg, middle); + if (!ddr_dataeye_check_dir(direction, left, right, &mask, cfg)) { /* test ok */ + *target = (int)middle; + return; + } + + if (left == middle || middle == right) /* not found */ + return; + + /* find left side */ + if (DDR_FIND_DQ_LEFT & mask) + ddr_dataeye_search_dq(left, middle, target, direction, cfg); + + /* find right side */ + if (DDR_FIND_DQ_RIGHT & mask) + ddr_dataeye_search_dq(middle, right, target, direction, cfg); + + return; +} + +/* Find DQ valid range */ +static void ddr_dataeye_find_dq(struct ddr_cfg_st *cfg, + struct training_data *training) +{ + int cur_dq, left_dq, right_dq, def_dq; + unsigned int dq_num; + unsigned int win_num; + + dq_num = (cfg->cur_byte << 3) + cfg->cur_dq; + def_dq = (int)ddr_phy_get_dq_bdl(cfg); + cur_dq = def_dq; + + /* check default dq */ + if (ddr_dataeye_check_dq(cfg)) { + /* test error */ + cur_dq = -1; + ddr_dataeye_search_dq(0, PHY_BDL_MASK, &cur_dq, + DDR_FIND_DQ_BOTH, cfg); + DDR_DEBUG("DQ[%x] def[%x] nok, find new value[%x]", + dq_num, def_dq, cur_dq); + if (-1 == cur_dq) { /* no valid dq */ + training->ddr_bit_result[dq_num] = 0; + training->ddr_bit_best[dq_num] = 0; + /* restore default value */ + ddr_phy_set_dq_bdl(cfg, def_dq); + DDR_WARNING("DQ[%x] not found dq. restore[%x]", dq_num, def_dq); + return; + } + } + + /* find the left boundary */ + left_dq = cur_dq; + ddr_dataeye_search_dq(0, cur_dq, &left_dq, + DDR_FIND_DQ_LEFT, cfg); + while (left_dq > 0) { + left_dq--; + ddr_phy_set_dq_bdl(cfg, left_dq); + if (ddr_dataeye_check_dq(cfg)) { + /* test error */ + left_dq++; + break; + } + } + + /* find the right boundary */ + right_dq = cur_dq; + ddr_dataeye_search_dq(cur_dq, PHY_BDL_MASK, &right_dq, + DDR_FIND_DQ_RIGHT, cfg); + while (right_dq < PHY_BDL_MASK) { + right_dq++; + ddr_phy_set_dq_bdl(cfg, right_dq); + if (ddr_dataeye_check_dq(cfg)) { + /* test error */ + right_dq--; + break; + } + } + + /* reset dq */ + ddr_phy_set_dq_bdl(cfg, def_dq); + + /** + * 0 1 2 3 4 5 6 7 8 9 + * x x - - - - - x x x + * | | + * left_dq right_dq + * + * so left_dq = 2, right_dq = 6 + */ + /* set result */ + win_num = right_dq - left_dq + 1; + training->ddr_bit_result[dq_num] = ((unsigned int)left_dq << DDR_DATAEYE_RESULT_BIT + | (unsigned int)right_dq); + training->ddr_bit_best[dq_num] = (win_num << DDR_DATAEYE_RESULT_BIT) + | ((win_num >> 1) + (unsigned int)left_dq); + + DDR_INFO("DQ[%x] range: left[%x] right[%x] best[%x] mode[%x] rank[%x]", dq_num, + left_dq, right_dq, training->ddr_bit_best[dq_num], cfg->cur_mode, cfg->rank_idx); +} + +/* DDR dataeye training one byte */ +int ddr_dataeye_deskew(struct ddr_cfg_st *cfg, struct training_data *training) +{ + unsigned int dq_num; + unsigned int loop_times = 0; + unsigned int win_num, dq_sum; + unsigned int def_dq, best_dq; + int i; + unsigned int byte_index = cfg->cur_byte; + + dq_sum = 0; + training->ddr_win_sum = 0; + for (i = 0; i < DDR_PHY_BIT_NUM; i++) { + cfg->cur_dq = i; + dq_num = (byte_index << 3) + i; + def_dq = ddr_phy_get_dq_bdl(cfg); + ddr_dataeye_find_dq(cfg, training); + win_num = training->ddr_bit_best[dq_num] >> DDR_DATAEYE_RESULT_BIT; + best_dq = training->ddr_bit_best[dq_num] & DDR_DATAEYE_RESULT_MASK; + /* check window number */ + if (win_num < DDR_DATAEYE_WIN_NUM) { + if (loop_times < DDR_LOOP_TIMES_LMT) { + loop_times++; + i--; + continue; + } else { + if (win_num == 0) { + DDR_WARNING("Byte[%x] DQ[%x] no win.", byte_index, dq_num); + /* restore default value */ + ddr_phy_set_dq_bdl(cfg, def_dq); + ddr_training_stat(DDR_ERR_DATAEYE, cfg->cur_phy, byte_index, i); + continue; + } + } + } + + loop_times = 0; + ddr_phy_set_dq_bdl(cfg, best_dq); + dq_sum = dq_sum + best_dq; + training->ddr_win_sum = training->ddr_win_sum + win_num; + } + + dq_sum = dq_sum >> 3; + + /* only DDR_MODE_WRITE need to set */ + if (DDR_MODE_WRITE == cfg->cur_mode) + ddr_write((dq_sum & PHY_BDL_MASK) << PHY_WDM_BDL_BIT, cfg->cur_phy + + DDR_PHY_DXNWDQNBDL2(cfg->rank_idx, byte_index)); + + ddr_phy_cfg_update(cfg->cur_phy); + return 0; +} + +/* DDR write or read dataeye training */ +static int ddr_dataeye_process(struct ddr_cfg_st *cfg, + struct training_data *training) +{ + int result = 0; + int i; + + /* dataeye training */ + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + cfg->cur_byte = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + result += ddr_dataeye_deskew(cfg, training); + } + + if (result) { + result = -1; + DDR_ERROR("PHY[%x] mode[%x] dataeye training fail", cfg->cur_phy, cfg->cur_mode); + } else { + /* dataeye training result adjust */ + ddr_adjust_dataeye(cfg, training); + } + + /* save training result to printf */ + ddr_result_data_save(cfg, training); + + return result; +} + +/* DDR dataeye training */ +int ddr_dataeye_training(struct ddr_cfg_st *cfg) +{ + struct training_data tmp_result; + struct training_data *training = &tmp_result; + int result_read, result_write; + + DDR_DEBUG("DDR dataeye training PHY[%x][%x] DMC[%x][%x] Rank[%x]", + cfg->phy_idx, cfg->cur_phy, cfg->dmc_idx, cfg->cur_dmc, cfg->rank_idx); + + /* write dataeye training */ + cfg->cur_mode = DDR_MODE_WRITE; + ddrtr_memset(training, 0, sizeof(struct training_data)); + result_write = ddr_dataeye_process(cfg, training); + + /* read dataeye training */ + cfg->cur_mode = DDR_MODE_READ; + ddrtr_memset(training, 0, sizeof(struct training_data)); + result_read = ddr_dataeye_process(cfg, training); + + if (result_read || result_write) + return -1; + else + return 0; +} + +int ddr_dataeye_training_func(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result; + + /* dataeye training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_DATAEYE_MASK)) + return 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_DATAEYE_MASK); + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE); + cfg->adjust = DDR_DATAEYE_NORMAL_ADJUST; + cfg->dq_check_type = DDR_CHECK_TYPE_DDRT; + result = ddr_dataeye_training(cfg); + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_dataeye_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR dataeye training."); + return 0; +} +#endif /* DDR_DATAEYE_TRAINING_CONFIG */ + +#define __hardware_training__ +#ifdef DDR_HW_TRAINING_CONFIG +#ifdef DDR_HW_READ_ADJ_CONFIG +/** + * Adjust rdqs and dq after hw read training. + * When define DDR_TRAINING_ADJUST_DISABLE, MUST define DDR_HW_READ_ADJ_CONFIG. + */ +static void ddr_hw_read_adj(struct ddr_cfg_st *cfg) +{ + int i; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + DDR_DEBUG("DDR hw read adjust."); + /* check hw read adjust bypass bit */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_HW_ADJ_MASK)) + return; + + /* assume read dataeye window on left */ + for (i = 0; i < byte_num; i++) { + ddr_write(ddr_read(base_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, i)) + + (PHY_DQ_MIDDLE_VAL << PHY_BDL_DQ_BIT), + base_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, i)); + ddr_write(ddr_read(base_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, i)) + + (PHY_DQ_MIDDLE_VAL << PHY_BDL_DQ_BIT), + base_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, i)); + ddr_write(ddr_read(base_phy + DDR_PHY_DXNRDQSDLY(i)) + + (PHY_RDQS_MIDDLE_VAL << PHY_RDQS_BDL_BIT), + base_phy + DDR_PHY_DXNRDQSDLY(i)); + } +} +#else +static void ddr_hw_read_adj(struct ddr_cfg_st *cfg) {} +#endif /* DDR_HW_READ_ADJ_CONFIG */ + +static void ddr_training_get_rdqs(struct ddr_cfg_st *cfg, struct ddr_bdl_st *rdqs) +{ + unsigned int i; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + unsigned int base_phy = cfg->cur_phy; + + for(i = 0; i < byte_num; i++) { + rdqs->bdl[i] = ddr_read(base_phy + DDR_PHY_DXNRDQSDLY(i)); + } +} + +static void ddr_training_set_rdqs(struct ddr_cfg_st *cfg, struct ddr_bdl_st *rdqs) +{ + unsigned int i; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + unsigned int base_phy = cfg->cur_phy; + + for (i = 0; i < byte_num; i++) { + ddr_write(rdqs->bdl[i], base_phy + DDR_PHY_DXNRDQSDLY(i)); + } +} + +static void ddr_hw_training_adjust_rdqs(struct ddr_cfg_st *cfg, struct rdqs_data_st *rdqs_st) +{ + unsigned int i; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + unsigned int rdqs_rank0, rdqs_rank1; + unsigned int cur_rank = cfg->rank_idx; + int offset; + + for (i = 0; i < byte_num; i++) { + /* struct rdqs_data_st store the whole register value */ + rdqs_rank0 = (rdqs_st->rank[0].bdl[i] >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK; + rdqs_rank1 = (rdqs_st->rank[1].bdl[i] >> PHY_RDQS_BDL_BIT) & PHY_RDQS_BDL_MASK; + + cfg->cur_byte = i; + if (rdqs_rank0 > rdqs_rank1) { + offset = rdqs_rank0 - rdqs_rank1; + ddr_write(rdqs_st->rank[0].bdl[i], cfg->cur_phy+ DDR_PHY_DXNRDQSDLY(i)); + cfg->rank_idx = 1; /* switch to rank1 for sync rank1 rdq */ + } else { + offset = rdqs_rank1 - rdqs_rank0; + ddr_write(rdqs_st->rank[1].bdl[i], cfg->cur_phy+ DDR_PHY_DXNRDQSDLY(i)); + cfg->rank_idx = 0; /* switch to rank0 for sync rank0 rdq */ + } + ddr_rdqs_sync_rank_rdq(cfg, offset); + } + + cfg->rank_idx = cur_rank; /* restore to current rank */ + + ddr_phy_cfg_update(cfg->cur_phy); +} + +/* DDR HW training process */ +static int ddr_hw_training_process(struct ddr_cfg_st *cfg, unsigned int item) +{ + unsigned int count = DDR_HWR_WAIT_TIMEOUT; + unsigned int base_phy = cfg->cur_phy; + unsigned int init_ctrl = ddr_read(base_phy + DDR_PHY_PHYINITCTRL); + + if (!item) + return 0; + + DDR_DEBUG("base_phy[%x] itme[%x]", base_phy, item); + /* hardware training enable */ + ddr_write(item | PHY_PHYINITCTRL_INIT_EN | init_ctrl, base_phy + DDR_PHY_PHYINITCTRL); + + if (item & PHY_PHYINITCTRL_DRAM_RST) { + if (ddr_training_ctrl_easr(cfg, DDR_EXIT_SREF)) + return -1; + } + + count = DDR_HWR_WAIT_TIMEOUT; + /* auto cleared to 0 after training finished */ + while (count--) { + if (!(ddr_read(base_phy + DDR_PHY_PHYINITCTRL) + & PHY_PHYINITCTRL_MASK)) + break; + } + + if (count == 0xffffffff) { + DDR_FATAL("HWR wait timeout."); + ddr_training_stat(DDR_ERR_HW_RD_DATAEYE, base_phy, item, ddr_read(base_phy + DDR_PHY_PHYINITSTATUS)); /* TODO: */ + return -1; + } + + if (ddr_read(base_phy + DDR_PHY_PHYINITSTATUS)) { + DDR_FATAL("Phy[%x] hw[%x] failed[%x]", base_phy, item, ddr_read(base_phy + DDR_PHY_PHYINITSTATUS)); + ddr_training_stat(DDR_ERR_HW_RD_DATAEYE, base_phy, item, ddr_read(base_phy + DDR_PHY_PHYINITSTATUS)); /* TODO: */ + return -1; + } + return 0; +} + +/* Dataeye hardware training */ +int ddr_hw_dataeye_read(struct ddr_cfg_st *cfg) +{ + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + unsigned int i; + int result; + + ddr_training_cfg_init(cfg); + /* clear */ + for (i = 0; i < byte_num; i++) { + ddr_write(0, base_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, i)); + ddr_write(0, base_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, i)); + ddr_write(0, base_phy + DDR_PHY_DXNRDQSDLY(i)); + } + + ddr_phy_cfg_update(base_phy); + + result = ddr_hw_training_process(cfg, PHY_PHYINITCTRL_RDET_EN); + + ddr_hw_read_adj(cfg); + + return result; +} + +/* DDR HW training control */ +int ddr_hw_training_ctl(struct ddr_cfg_st *cfg) +{ + int byte_idx; + int result = 0; + unsigned int temp = 0; + unsigned int item = cfg->cur_item; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + unsigned int dvrft_ctrl = ddr_read(base_phy + DDR_PHY_DVRFTCTRL); + struct rdqs_data_st *rdqs_st = (struct rdqs_data_st *)cfg->res_st; + + if (!item || !rdqs_st) + return 0; + + ddr_phy_cfg_update(base_phy); + /* NOTE: not support array when boot */ + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_CNT_RESET_START); + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_PLL); + + /* save rdqs bdl after PHY_PHYINITCTRL_DLYMEAS_EN */ + if (0 == cfg->rank_idx) + ddr_training_get_rdqs(cfg, &rdqs_st->origin); + + for (byte_idx = 0; byte_idx < byte_num; byte_idx++) { + cfg->cur_byte = byte_idx; + ddr_bdl_adj(cfg); + } + + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + temp = ddr_read(base_phy + 0x64); + ddr_write(temp & 0x0fffffff, base_phy + 0x64); /* ca odt disable */ + + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_DRAM_RESET); + ddr_write(temp, base_phy + 0x64); /* restore */ + + temp = ddr_read(base_phy + 0x48); + ddr_write(temp & 0xfffffffe, base_phy + 0x48); /* todo rank0 */ + + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_VREF_AC); + + ddr_write(temp | 0x1, base_phy + 0x48); /* rank1 */ + + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_VREF_AC); + + ddr_write(temp, base_phy + 0x48); /* restore */ + + /* ddr_training_delay(10000); */ + result += ddr_hw_training_process(cfg, item & PHY_PHYINITCTRL_DRAM_INIT_EN); + } else { +#ifdef DDR_WRITE_DM_DISABLE + if (PHY_DRAMCFG_TYPE_DDR4 == cfg->phy[cfg->phy_idx].dram_type) { + temp = ddr_read(base_phy + 0xe0); + ddr_write((temp & 0xFBFFFFFF) | 0x8000000, base_phy + 0xe0); /* write dm disable */ + } +#endif + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_DRAM_RESET); + } + result += ddr_hw_training_process(cfg, item & PHY_PHYINITCTRL_CAT_EN); + + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_CS); + + ddr_write(dvrft_ctrl & (~PHY_DVRFTCTRL_PDAEN_EN), + base_phy + DDR_PHY_DVRFTCTRL); + /* DDR_PHY_VREFTCTRL 31bit:1 do vref dram set twice */ + ddr_write((ddr_read(base_phy + DDR_PHY_VREFTCTRL) + & (~(0x1 << PHY_VREFS_MRS_ENTER_BIT))) + | (0x1 << PHY_VREFS_MRS_ENTER_BIT), + base_phy + DDR_PHY_VREFTCTRL); + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_VREF_DQ); + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_VREF_DQ); + /* DDR_PHY_VREFTCTRL 31bit:0 do vref dram set once */ + ddr_write(ddr_read(base_phy + DDR_PHY_VREFTCTRL) + & (~(0x1 << PHY_VREFS_MRS_ENTER_BIT)), + base_phy + DDR_PHY_VREFTCTRL); + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_VREF_DQ); + ddr_write(dvrft_ctrl, base_phy + DDR_PHY_DVRFTCTRL); + + result += ddr_hw_training_process(cfg, item & PHY_HW_GP_NORMAL); + +#ifdef DDR_WRITE_DM_DISABLE + unsigned int temp1 = 0; + if (PHY_DRAMCFG_TYPE_DDR4 == cfg->phy[cfg->phy_idx].dram_type) { + ddr_write(temp, base_phy + 0xe0); /* restore */ + temp = ddr_read(base_phy + 0x1e0); + temp1 = ddr_read(base_phy + 0x2c); + ddr_write(0x05555555, base_phy + 0x1e0); /* inti MR5 */ + ddr_write(temp1 | 0x00004000 , base_phy + 0x2c); /* write dm disable */ + result += ddr_hw_training_process(cfg, item & PHY_PHYINITCTRL_DRAM_INIT_EN); + ddr_write(temp, base_phy + 0x1e0); /* restore */ + ddr_write(temp1, base_phy + 0x2c); /* restore */ + } +#endif + ddr_phy_cfg_update(base_phy); + + return result; +} + +static int ddr_hw_training_by_rank(struct ddr_cfg_st *cfg) +{ + DDR_DEBUG("PHY[%x][%x] Rank[%x] itme[%x]", + cfg->phy_idx, cfg->cur_phy, cfg->rank_idx, cfg->cur_item); + + /* 0:PHY_TRAINCTRL0_DTR_RANK0, 1:PHY_TRAINCTRL0_DTR_RANK1 */ + DDR_PHY_SWITCH_RANK(cfg->cur_phy, cfg->rank_idx); + return ddr_hw_training_ctl(cfg); +} + +static int ddr_hw_training_by_phy(struct ddr_cfg_st *cfg) +{ + int result = 0; + int i; + struct rdqs_data_st rdqs_st; + struct ddr_timing_st timing_st; + unsigned int rank_num = cfg->phy[cfg->phy_idx].rank_num; + + cfg->res_st = (void *)&rdqs_st; + + /* disable auto refresh */ + ddr_training_save_timing(cfg, &timing_st); + + for (i = 0; i < rank_num; i++) { + cfg->rank_idx = i; + cfg->cur_item = cfg->phy[cfg->phy_idx].rank[i].item_hw; + + result += ddr_hw_training_by_rank(cfg); + + if (DDR_SUPPORT_RANK_MAX != rank_num) + break; + + /* save rank rdqs bdl */ + ddr_training_get_rdqs(cfg, &rdqs_st.rank[i]); + + /* restore PHY_PHYINITCTRL_DLYMEAS_EN rdqs before training next rank */ + if ((rank_num - 1) != i) + ddr_training_set_rdqs(cfg, &rdqs_st.origin); + } + + if (DDR_SUPPORT_RANK_MAX == rank_num) { + ddr_hw_training_adjust_rdqs(cfg, &rdqs_st); + } + + /* restore auto refresh */ + ddr_training_restore_timing(cfg, &timing_st); + + return result; +} + +/* DDR hardware training */ +int ddr_hw_training(struct ddr_cfg_st *cfg) +{ + int result = 0; + int i; + struct tr_relate_reg relate_reg; + struct tr_relate_reg *reg = &relate_reg; + + /* save customer reg */ + DDR_TRAINING_SAVE_REG_FUNC(reg, 0x1); + + for (i = 0; i < cfg->phy_num; i++) { + cfg->phy_idx = i; + cfg->cur_phy = cfg->phy[i].addr; + result += ddr_hw_training_by_phy(cfg); + } + /* restore customer reg */ + DDR_TRAINING_RESTORE_REG_FUNC(reg); + + return result; +} +#endif /* DDR_HW_TRAINING_CONFIG */ + +#define __mpr_training__ +#ifdef DDR_MPR_TRAINING_CONFIG +/* Switch MPR function */ +static void ddr_mpr_switch(unsigned int base_dmc, int val) +{ + unsigned int sfc_cmd; + if (DDR_TRUE == val) + sfc_cmd = (DMC_CMD_MRS_MR3 << DMC_SFC_CMD_MRS_BIT) + | DMC_CMD_TYPE_LMR; + else + sfc_cmd = DMC_CMD_TYPE_LMR; + + ddr_dmc_sfc_cmd(base_dmc, sfc_cmd, 0x0, DMC_BANK_MR3); + + /* clear */ + if (DDR_FALSE == val) { + ddr_write(0x0, base_dmc + DDR_DMC_SFCBANK); + ddr_write(0x0, base_dmc + DDR_DMC_SFCREQ); + } +} + +/* Judge MPR data */ +static int ddr_mpr_judge(unsigned int data1, unsigned int data2, + unsigned int data3, unsigned int data4, + unsigned int dq_index) +{ + /* check byte */ + if (-1 == dq_index) { + if (DDR_MPR_BYTE_MASK == data1 && 0x0 == data2 + && DDR_MPR_BYTE_MASK == data3 && 0x0 == data4) + return 0; + else + return -1; + } else { + /* check DQ */ + data1 = (data1 >> dq_index) & DDR_MPR_BIT_MASK; + data2 = (data2 >> dq_index) & DDR_MPR_BIT_MASK; + data3 = (data3 >> dq_index) & DDR_MPR_BIT_MASK; + data4 = (data4 >> dq_index) & DDR_MPR_BIT_MASK; + if (DDR_MPR_BIT_MASK == data1 && 0x0 == data2 + && DDR_MPR_BIT_MASK == data3 && 0x0 == data4) + return 0; + else + return -1; + } +} + +/* Extract MPR read data to judge */ +static int ddr_mpr_extract(struct ddr_cfg_st *cfg, + unsigned int offset0, unsigned int offset1, + unsigned int offset2, unsigned int offset3) +{ + unsigned int data1, data2, data3, data4; + unsigned int base_dmc = cfg->cur_dmc; + unsigned int byte_index = cfg->cur_byte; + + data1 = ddr_read(base_dmc + offset0); /* [127:96] or [255:224] */ + data2 = ddr_read(base_dmc + offset1); /* [95:64] or [223:192] */ + data3 = ddr_read(base_dmc + offset2); /* [63:32] or [191:160] */ + data4 = ddr_read(base_dmc + offset3); /* [31:0] or [159:128] */ + + DDR_INFO("byte[%x] data[%x=%x][%x=%x][%x=%x][%x=%x]", + byte_index, + base_dmc + offset0, data1, base_dmc + offset1, data2, + base_dmc + offset2, data3, base_dmc + offset3, data4); + + if (DDR_PHY_BYTE_MAX == GET_BYTE_NUM(cfg)) { + /* four byte: data1[0xFFFFFFFF] data2[0x00000000] + data3[0xFFFFFFFF] data4[0x00000000] */ + data1 = (data1 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + data2 = (data2 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + data3 = (data3 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + data4 = (data4 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + } else { + /* two byte: data1[0xFFFF0000] data2[0xFFFF0000] + data3[0xFFFF0000] data4[0xFFFF0000] */ + data1 = ((data1 >> DDR_MPR_BYTE_BIT) >> (byte_index << 3)) + & DDR_MPR_BYTE_MASK; + data2 = (data2 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + data3 = ((data3 >> DDR_MPR_BYTE_BIT) >> (byte_index << 3)) + & DDR_MPR_BYTE_MASK; + data4 = (data4 >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + if (ddr_mpr_judge(data1, data2, data3, data4, cfg->cur_dq)) + return -1; + + /* two byte need to swap data and check again */ + data1 = ((ddr_read(base_dmc + DDR_DMC_SFC_RDATA1) + >> DDR_MPR_BYTE_BIT) >> (byte_index << 3)) + & DDR_MPR_BYTE_MASK; + data2 = (ddr_read(base_dmc + DDR_DMC_SFC_RDATA0) + >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + data3 = ((ddr_read(base_dmc + DDR_DMC_SFC_RDATA3) + >> DDR_MPR_BYTE_BIT) >> (byte_index << 3)) + & DDR_MPR_BYTE_MASK; + data4 = (ddr_read(base_dmc + DDR_DMC_SFC_RDATA2) + >> (byte_index << 3)) & DDR_MPR_BYTE_MASK; + } + + return ddr_mpr_judge(data1, data2, data3, data4, cfg->cur_dq); +} + +/* Check MPR read data */ +int ddr_mpr_check(struct ddr_cfg_st *cfg) +{ + /* read data */ + ddr_dmc_sfc_cmd(cfg->cur_dmc, DMC_CMD_TYPE_READ, 0x0, 0x0); + return DMC_MPR_CHECK_BIT_0_127(cfg); +} + +/* Find RDQ via MPR */ +static int ddr_mpr_find_rdq(struct ddr_cfg_st *cfg) +{ + struct training_data tmp_result; + struct training_data *training = &tmp_result; + unsigned int dq_num; + unsigned int win_num; + unsigned int def_dq, best_dq; + unsigned int byte_index, dq_index; + + /* find rdq via mpr */ + cfg->dq_check_type = DDR_CHECK_TYPE_MPR; + + /* find rdq */ + for (byte_index = 0; + byte_index < GET_BYTE_NUM(cfg); byte_index++) { + for (dq_index = 0; dq_index < DDR_PHY_BIT_NUM; dq_index++) { + dq_num = (byte_index << 3) + dq_index; + def_dq = ddr_phy_get_dq_bdl(cfg); + ddr_dataeye_find_dq(cfg, training); + win_num = training->ddr_bit_best[dq_num] + >> DDR_DATAEYE_RESULT_BIT; + best_dq = training->ddr_bit_best[dq_num] + & DDR_DATAEYE_RESULT_MASK; + if (win_num > 0) + ddr_phy_set_dq_bdl(cfg, best_dq); + else { + /* In normal case, not reach here */ + /* restore default value */ + ddr_phy_set_dq_bdl(cfg, def_dq); + + DDR_FATAL("PHY[%x] Byte[%x] DQ[%x] MPR fail", + cfg->cur_phy, byte_index, dq_index); + ddr_training_stat(DDR_ERR_MPR, cfg->cur_phy, + byte_index, dq_index); + return -1; + } + } + } + + return 0; + +} + +/* Find RDQS via MPR */ +static int ddr_mpr_find_rdqs(struct ddr_cfg_st *cfg) +{ + unsigned int rdqs_start = 0; + unsigned int rdqs_end = PHY_RDQS_BDL_MASK; + unsigned int rdqs_mid; + unsigned int val, delay; + unsigned int count = 0; + int found = DDR_FALSE; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_index = cfg->cur_byte; + + /* set rdq to middle value */ + ddr_write(PHY_DQ_MIDDLE_VAL << PHY_BDL_DQ_BIT, base_phy + DDR_PHY_DXNRDQNBDL0(cfg->rank_idx, byte_index)); + ddr_write(PHY_DQ_MIDDLE_VAL << PHY_BDL_DQ_BIT, base_phy + DDR_PHY_DXNRDQNBDL1(cfg->rank_idx, byte_index)); + + /* clear rdqs */ + delay = ddr_read(base_phy + DDR_PHY_DXNRDQSDLY(byte_index)) >> PHY_RDQS_BDL_BIT; + rdqs_mid = delay; /* if not found, restore default value */ + delay = delay & (~PHY_RDQS_BDL_MASK); + + /* find rdqs */ + for (val = 0; val <= PHY_RDQS_BDL_MASK; val++) { + ddr_write(delay | (val << PHY_RDQS_BDL_BIT), + base_phy + DDR_PHY_DXNRDQSDLY(byte_index)); + ddr_phy_cfg_update(base_phy); + /* check ok */ + if (!ddr_mpr_check(cfg)) { + if (DDR_FALSE == found) { + rdqs_start = val; /* found start value */ + count++; + if (DDR_MPR_RDQS_FIND_TIMES == count) + found = DDR_TRUE; + } + } else { + if (DDR_TRUE == found) { + rdqs_end = val; /* found end value */ + break; + } + } + } + + if (DDR_TRUE == found) { + rdqs_mid = ((rdqs_end - rdqs_start) >> 1) + rdqs_start; + DDR_INFO("PHY[%x] Byte[%x] rdqs_middle[%x]", + base_phy, byte_index, rdqs_mid); + DDR_INFO("rdqs_start[%x] rdqs_end[%x]", + rdqs_start, rdqs_end); + } else { + DDR_FATAL("PHY[%x] Byte[%x] not find RDQS, restore.", + base_phy, byte_index); + ddr_training_stat(DDR_ERR_MPR, base_phy, + byte_index, -1); + } + + ddr_write(delay | (rdqs_mid << PHY_RDQS_BDL_BIT), base_phy + DDR_PHY_DXNRDQSDLY(byte_index)); + ddr_phy_cfg_update(base_phy); + + return ((DDR_TRUE == found) ? 0 : -1); +} + +/* Multi Purpose Register(MPR) */ +int ddr_mpr_training(struct ddr_cfg_st *cfg) +{ + int i; + int result = 0; + unsigned int byte_num = GET_BYTE_NUM(cfg); + unsigned int mr0; + unsigned int sfc_cmd; + unsigned int base_dmc = cfg->cur_dmc; + unsigned int base_phy = cfg->cur_phy; + + DDR_DEBUG("DDR MPR training."); + + /* set DDR bust */ + if (DDR_PHY_BYTE_MAX == byte_num) { + mr0 = (ddr_read(base_phy + DDR_PHY_MODEREG01) + & DMC_MRS_MASK) + & (~DMC_MR0_BL_MASK); + sfc_cmd = ((mr0 | DMC_MR0_BL_BUST4) + << DMC_SFC_CMD_MRS_BIT) + | DMC_CMD_TYPE_LMR; + ddr_dmc_sfc_cmd(base_dmc, sfc_cmd, 0x0, 0x0); + } + + /* precharge all */ + ddr_dmc_sfc_cmd(base_dmc, DMC_CMD_TYPE_PRECHARGE_ALL, 0x0, 0x0); + + /* enable MPR */ + ddr_mpr_switch(base_dmc, DDR_TRUE); + + /* find rdqs */ + for (i = 0; i < byte_num; i++) + result += ddr_mpr_find_rdqs(cfg); + + /* find rdq */ + if (!result) + result = ddr_mpr_find_rdq(cfg); + + /* disable MPR */ + ddr_mpr_switch(base_dmc, DDR_FALSE); + + /* restore DDR bust */ + if (DDR_PHY_BYTE_MAX == byte_num) { + mr0 = (ddr_read(base_phy + DDR_PHY_MODEREG01) + & DMC_MRS_MASK); + sfc_cmd = (mr0 << DMC_SFC_CMD_MRS_BIT) + | DMC_CMD_TYPE_LMR; + ddr_dmc_sfc_cmd(base_dmc, sfc_cmd, 0x0, 0x0); + } + return result; +} + +int ddr_mpr_training_func(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result = 0; + + /* MPR training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_MPR_MASK)) + return 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_MPR_MASK); + result = ddr_mpr_training(cfg); + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#endif /* DDR_MPR_TRAINING_CONFIG */ + +#define __vref_training__ +#ifdef DDR_VREF_TRAINING_CONFIG +#ifdef DDR_VREF_WITHOUT_BDL_CONFIG +/* Save dataeye dq bdl before vref training */ +static void ddr_vref_save_bdl(struct ddr_cfg_st *cfg, struct tr_dq_data *dq_data) +{ + int i; + unsigned int base_phy = cfg->cur_phy; + unsigned int rank = cfg->rank_idx; + unsigned int byte_index; + + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + byte_index = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + if (DDR_MODE_WRITE == cfg->cur_mode) { + dq_data->dq03[i] = ddr_read(base_phy + DDR_PHY_DXNWDQNBDL0(rank, byte_index)); + dq_data->dq47[i] = ddr_read(base_phy + DDR_PHY_DXNWDQNBDL1(rank, byte_index)); + dq_data->wdm[i] = ddr_read(base_phy + DDR_PHY_DXNWDQNBDL2(rank, byte_index)); + } else { + dq_data->dq03[i] = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL0(rank, byte_index)); + dq_data->dq47[i] = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL1(rank, byte_index)); + } + } +} + +/* Restore dataeye dq bdl after vref training */ +static void ddr_vref_restore_bdl(struct ddr_cfg_st *cfg, struct tr_dq_data *dq_data) +{ + int i; + unsigned int base_phy = cfg->cur_phy; + unsigned int rank = cfg->rank_idx; + unsigned int byte_index; + + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + byte_index = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + if (DDR_MODE_WRITE == cfg->cur_mode) { + ddr_write(dq_data->dq03[i], base_phy + DDR_PHY_DXNWDQNBDL0(rank, byte_index)); + ddr_write(dq_data->dq47[i], base_phy + DDR_PHY_DXNWDQNBDL1(rank, byte_index)); + ddr_write(dq_data->wdm[i], base_phy + DDR_PHY_DXNWDQNBDL2(rank, byte_index)); + } else { + ddr_write(dq_data->dq03[i], base_phy + DDR_PHY_DXNRDQNBDL0(rank, byte_index)); + ddr_write(dq_data->dq47[i], base_phy + DDR_PHY_DXNRDQNBDL1(rank, byte_index)); + } + } +} +#else +static void ddr_vref_save_bdl(struct ddr_cfg_st *cfg, struct tr_dq_data *dq_data) +{ +} +static void ddr_vref_restore_bdl(struct ddr_cfg_st *cfg, struct tr_dq_data *dq_data) +{ +} +#endif /* DDR_VREF_WITHOUT_BDL_CONFIG */ + +/* Set DDR Vref value */ +static void ddr_vref_set(struct ddr_cfg_st *cfg, unsigned int val) +{ + if (DDR_MODE_READ == cfg->cur_mode) { /* HOST vref */ + DDR_PHY_VREF_HOST_SET(cfg->cur_phy, cfg->rank_idx, GET_BYTE_NUM(cfg), cfg->cur_byte, val); /* TODO */ + } else { /* DRAM vref */ + unsigned int auto_ref_timing = + ddr_read(cfg->cur_dmc + DDR_DMC_TIMING2); + /* disable auto refresh */ + ddr_training_set_timing(cfg->cur_dmc, + auto_ref_timing & DMC_AUTO_TIMING_DIS); + + /* DDR_PHY_VREFTCTRL 31bit:1 do vref dram set twice */ + ddr_write((ddr_read(cfg->cur_phy + DDR_PHY_VREFTCTRL) + & (~(0x1 << PHY_VREFS_MRS_ENTER_BIT))) + | (0x1 << PHY_VREFS_MRS_ENTER_BIT), + cfg->cur_phy + DDR_PHY_VREFTCTRL); + DDR_PHY_VREF_DRAM_SET(cfg->cur_phy, val, cfg->cur_byte); + DDR_PHY_VREF_DRAM_SET(cfg->cur_phy, val, cfg->cur_byte); + /* DDR_PHY_VREFTCTRL 31bit:0 do vref dram set once */ + ddr_write(ddr_read(cfg->cur_phy + DDR_PHY_VREFTCTRL) + & (~(0x1 << PHY_VREFS_MRS_ENTER_BIT)), + cfg->cur_phy + DDR_PHY_VREFTCTRL); + DDR_PHY_VREF_DRAM_SET(cfg->cur_phy, val, cfg->cur_byte); + + /* enable auto refresh */ + ddr_training_set_timing(cfg->cur_dmc, auto_ref_timing); + } + DDR_INFO("byte[%x] mode[%x] set vref [%x]", cfg->cur_byte, cfg->cur_mode, val); +} + +/* Get DDR Vref value */ +static unsigned int ddr_vref_get(struct ddr_cfg_st *cfg) +{ + unsigned int val = 0; + + if (DDR_MODE_READ == cfg->cur_mode) { /* HOST vref */ + DDR_PHY_VREF_HOST_GET(cfg->cur_phy, cfg->rank_idx, cfg->cur_byte, val); + } else { /* DRAM vref */ + DDR_PHY_VREF_DRAM_GET(cfg->cur_phy, val, cfg->cur_byte); + } + DDR_INFO("byte[%x] mode[%x] get vref [%x]", cfg->cur_byte, cfg->cur_mode, val); + return val; +} + +/* Get totol win number of training result */ +static unsigned int ddr_vref_get_win(struct ddr_cfg_st *cfg, + struct training_data *training, int vref) +{ + unsigned int vref_min = 0; + unsigned int vref_max = DDR_VREF_DRAM_VAL_MAX; + int vref_set; + + training->ddr_win_sum = 0; + + if (DDR_MODE_READ == cfg->cur_mode) { + DDR_VREF_GET_HOST_MAX(cfg->rank_idx, vref_max); + } + + if (vref < vref_min) + vref_set = vref_min; + else if (vref > vref_max) + vref_set = vref_max; + else + vref_set = vref; + + ddr_vref_set(cfg, vref_set); + + ddr_dataeye_deskew(cfg, training); + + return training->ddr_win_sum; +} + +/* Find the best vref which win number is max */ +static unsigned int ddr_vref_find_best(struct ddr_cfg_st *cfg, + struct training_data *training, unsigned int vref, int step) +{ + int cur_vref; + unsigned int best_vref; + unsigned int cur_win; + unsigned int max_win; + unsigned int lower_times = 0; + unsigned int vref_min = 0; + unsigned int vref_max = DDR_VREF_DRAM_VAL_MAX; + + if (DDR_MODE_READ == cfg->cur_mode) { + DDR_VREF_GET_HOST_MAX(cfg->rank_idx, vref_max); + } + + max_win = 0; + cur_vref = vref + step; + + if (vref < vref_min) + best_vref = vref_min; + else if (vref > vref_max) + best_vref = vref_max; + else + best_vref = vref; + + /* find parabola vertex */ + while (cur_vref >= vref_min + && cur_vref <= vref_max) { + cur_win = ddr_vref_get_win(cfg, training, cur_vref); + DDR_DEBUG("byte[%x] vref[%x] win[%x] mode[%x]", + cfg->cur_byte, cur_vref, cur_win, cfg->cur_mode); + if (cur_win < max_win) { + lower_times++; + if (DDR_VREF_COMPARE_TIMES == lower_times) { + /* Continuous decline, mean found vertex */ + break; + } + } else { + lower_times = 0; + max_win = cur_win; + best_vref = cur_vref; + } + cur_vref = cur_vref + step; + } + + return best_vref; +} + +/* DDR Vref calibrate and set the best value */ +static void ddr_vref_cal(struct ddr_cfg_st *cfg, struct training_data *training) +{ + unsigned int def_vref; + unsigned int best_vref; + unsigned int left_win; + unsigned int right_win; + + def_vref = ddr_vref_get(cfg); + left_win = ddr_vref_get_win(cfg, training, def_vref - DDR_VREF_COMPARE_STEP); + right_win = ddr_vref_get_win(cfg, training, def_vref + DDR_VREF_COMPARE_STEP); + + DDR_DEBUG("byte[%x] default vref[%x] win[%x][%x] mode[%x]", + cfg->cur_byte, def_vref, left_win, right_win, cfg->cur_mode); + + /* With vref increments, WIN number is a parabola. + So firstly determine the result on left or right. */ + /* parabola vertex */ + if (left_win < right_win) { /* the result on right */ + best_vref = ddr_vref_find_best(cfg, training, def_vref, 1); + } else if (left_win > right_win) { /* the result on left */ + best_vref = ddr_vref_find_best(cfg, training, def_vref, -1); + } else { + /* when (left_win == right_win), check def_vref */ + unsigned int vref_max = DDR_VREF_DRAM_VAL_MAX; + if (DDR_MODE_READ == cfg->cur_mode) { + DDR_VREF_GET_HOST_MAX(cfg->rank_idx, vref_max); + } + + if (def_vref < (vref_max >> 1)) + best_vref = ddr_vref_find_best(cfg, training, def_vref, 1); + else + best_vref = ddr_vref_find_best(cfg, training, def_vref, -1); + } + + + DDR_DEBUG("byte[%x] best vref[%x] mode[%x]", + cfg->cur_byte, best_vref, cfg->cur_mode); + ddr_vref_set(cfg, best_vref); +} + +int ddr_vref_training(struct ddr_cfg_st *cfg) +{ + struct training_data tmp_result; + struct training_data *training = &tmp_result; + struct tr_dq_data dq_data; + int result = 0; + int i; + + DDR_DEBUG("DDR Vref[%x] training PHY[%x][%x] DMC[%x][%x] Rank[%x]", + cfg->cur_mode, cfg->phy_idx, cfg->cur_phy, cfg->dmc_idx, + cfg->cur_dmc, cfg->rank_idx); + + ddr_vref_save_bdl(cfg, &dq_data); + ddrtr_memset(training, 0, sizeof(struct training_data)); + + /* vref calibrate */ + if (DDR_MODE_READ == cfg->cur_mode) { + /* only training byte0 and byte2 */ + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + cfg->cur_byte = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + if (1 == cfg->cur_byte || 3 == cfg->cur_byte) + continue; + + ddr_vref_cal(cfg, training); + } + } else { + unsigned int dram_type = cfg->phy[cfg->phy_idx].dram_type; + unsigned int bank_group = (ddr_read(cfg->cur_dmc + + DDR_DMC_CFG_RNKVOL(cfg->rank_idx)) >> DMC_CFG_MEM_BG_BIT) + & DMC_CFG_MEM_BG_MASK; + + if (PHY_DRAMCFG_TYPE_LPDDR4 != dram_type + && PHY_DRAMCFG_TYPE_DDR4 != dram_type) + return 0; + + if (PHY_DRAMCFG_TYPE_LPDDR4 == dram_type) + bank_group = DMC_CFG_MEM_2BG; /* lpddr4 not training byte1 byte3 */ + + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + cfg->cur_byte = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + /* byte1 and byte3 bypass when 2 Bank Group */ + if ((DMC_CFG_MEM_2BG == bank_group) + && ((1 == i) || (3 == i))) + continue; + + ddr_vref_cal(cfg, training); + } + } + +#if !defined(DDR_VREF_WITHOUT_BDL_CONFIG) || defined(DDR_TRAINING_CMD) + /* dataeye deskew again on best vref. */ + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + cfg->cur_byte = i + (cfg->dmc_idx << 1); /* byte index accord to phy */ + result += ddr_dataeye_deskew(cfg, training); + } +#endif + + ddr_vref_restore_bdl(cfg, &dq_data); + + ddr_result_data_save(cfg, training); + + return result; +} + +int ddr_vref_training_func(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result = 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_VREF_HOST_MASK); + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE); + cfg->dq_check_type = DDR_CHECK_TYPE_DDRT; + + /* host vref training disable */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_VREF_HOST_MASK)) { + cfg->cur_mode = DDR_MODE_READ; + result += ddr_vref_training(cfg); + } + + /* dram vref training enable && DDR4 */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_VREF_DRAM_MASK)) { + cfg->cur_mode = DDR_MODE_WRITE; + result += ddr_vref_training(cfg); + } + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_vref_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR vref training."); + return 0; +} +#endif /* DDR_VREF_TRAINING_CONFIG */ + +#define __write_leveling__ +#ifdef DDR_WL_TRAINING_CONFIG +static void ddr_bdl_add(unsigned int *raw, unsigned int val) +{ + if (((*raw) + val) > PHY_BDL_MASK) + *raw = PHY_BDL_MASK; + else + *raw += val; +} + +static void ddr_bdl_sub(unsigned int *raw, unsigned int val) +{ + if ((*raw) > val) + *raw -= val; + else + *raw = 0; +} + +/* DDR PHY DQ phase increase */ +static void ddr_phase_inc(unsigned int *raw) +{ +#if defined (DDR_PHY_T28_CONFIG) || defined(DDR_PHY_T16_CONFIG) \ + || defined (DDR_PHY_T12_V100_CONFIG) || defined (DDR_PHY_T12_V101_CONFIG) + if ((*raw) < (PHY_WDQS_PHASE_MASK - 1)) { + if (((*raw) & 0x3) == 0x2) + *raw += 0x2; + else + *raw += 0x1; + } +#else + if ((*raw) < PHY_WDQS_PHASE_MASK) + *raw += 0x1; +#endif +} + +/* DDR PHY DQ phase decrease */ +static void ddr_phase_dec(unsigned int *raw) +{ +#if defined (DDR_PHY_T28_CONFIG) || defined(DDR_PHY_T16_CONFIG) \ + || defined (DDR_PHY_T12_V100_CONFIG) || defined (DDR_PHY_T12_V101_CONFIG) + if ((*raw) > 0x1) { + if (((*raw) & 0x3) == 0x3) + *raw -= 0x2; + else + *raw -= 0x1; + } +#else + if ((*raw) > 0x0) + *raw -= 0x1; +#endif +} + +/* DQ bdl add or sub */ +static void ddr_dq_bdl_operate(unsigned int base_phy, + unsigned int addr_offset, unsigned int val, unsigned int is_add) +{ + unsigned int tmp; + unsigned int dq_bdl[DDR_PHY_REG_DQ_NUM]; + int i; + + tmp = ddr_read(base_phy + addr_offset); + dq_bdl[0] = (tmp >> PHY_BDL_DQ0_BIT) & PHY_BDL_MASK; + dq_bdl[1] = (tmp >> PHY_BDL_DQ1_BIT) & PHY_BDL_MASK; + dq_bdl[2] = (tmp >> PHY_BDL_DQ2_BIT) & PHY_BDL_MASK; + dq_bdl[3] = (tmp >> PHY_BDL_DQ3_BIT) & PHY_BDL_MASK; + + for (i = 0; i < DDR_PHY_REG_DQ_NUM; i++) { + if (is_add) + ddr_bdl_add(&dq_bdl[i], val); + else + ddr_bdl_sub(&dq_bdl[i], val); + } + + tmp = (dq_bdl[3] << PHY_BDL_DQ3_BIT) + (dq_bdl[2] << PHY_BDL_DQ2_BIT) + + (dq_bdl[1] << PHY_BDL_DQ1_BIT) + (dq_bdl[0] << PHY_BDL_DQ0_BIT); + ddr_write(tmp, base_phy + addr_offset); +} + +/* Disable or enable DDR write leveling mode */ +static void ddr_wl_switch(unsigned int base_dmc, unsigned int base_phy, + int val) +{ + unsigned int mr1_raw; + unsigned int sfc_cmd; + unsigned int sfc_bank; + + /* Set Rank = 0, Cmd = MRS, No Precharch CMD */ + mr1_raw = ddr_read(base_phy + DDR_PHY_MODEREG01) + >> PHY_MODEREG01_MR1_BIT; + sfc_cmd = DMC_CMD_TYPE_LMR; + sfc_bank = DMC_BANK_MR1; + + if (DDR_TRUE == val) { /* enable DDR wl */ + /* Set A7 = 1 */ + sfc_cmd += (mr1_raw | DMC_CMD_MRS_A7) << DMC_SFC_CMD_MRS_BIT; + } else { + + /* Set A7 = 0 */ + sfc_cmd += (mr1_raw & ((~DMC_CMD_MRS_A7) & DMC_CMD_MRS_MASK)) + << DMC_SFC_CMD_MRS_BIT; + } + + ddr_dmc_sfc_cmd(base_dmc, sfc_cmd, 0x0, sfc_bank); + + /* clear */ + if (DDR_FALSE == val) { + ddr_write(0x0, base_dmc + DDR_DMC_SFCBANK); + ddr_write(0x0, base_dmc + DDR_DMC_SFCREQ); + } + + /* phy sw write leveling mode */ + ddr_write(val, base_phy + DDR_PHY_SWTMODE); +} + +#ifdef DDR_WL_DATAEYE_ADJUST_CONFIG +/* Adjust dataeye WDQ after Write leveling */ +static void ddr_wl_wdq_adjust(struct ddr_cfg_st *cfg, + struct ddr_delay_st *wdqs_new, struct ddr_delay_st *wdqs_old) +{ + unsigned int val; + int i; + unsigned int phase_adj, bdl_adj = 0; /* for write dataeye */ + unsigned int wdm_bdl; + unsigned int wdq_phase; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + unsigned int rank_index = cfg->rank_idx; + + DDR_DEBUG("DDR WL write adjust."); + + /* check wl write adjust bypass bit */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_WL_ADJ_MASK)) + return; + + /* adjust wdq phase, wdq bdl, wdm bdl */ + for (i = 0; i < byte_num; i++) { + if (wdqs_new->phase[i] == wdqs_old->phase[i] + && wdqs_new->bdl[i] == wdqs_old->bdl[i]) { + continue; + } + + phase_adj = 0; + wdq_phase = (ddr_read(base_phy + DDR_PHY_DXNWDQDLY(rank_index, i)) + >> PHY_WDQ_PHASE_BIT) + & PHY_WDQ_PHASE_MASK; + wdm_bdl = (ddr_read(base_phy + DDR_PHY_DXNWDQNBDL2(rank_index, i)) + >> PHY_WDM_BDL_BIT) + & PHY_BDL_MASK; + + if (wdqs_new->bdl[i] > wdqs_old->bdl[i]) { + val = wdqs_new->bdl[i] - wdqs_old->bdl[i]; + phase_adj = val >> DDR_BDL_PHASE_REL; + wdq_phase = wdq_phase + phase_adj; + + if (wdq_phase > PHY_WDQ_PHASE_MASK) + wdq_phase = PHY_WDQ_PHASE_MASK; + + /* adjust wdq bdl and dm bdl in opposite direction */ + bdl_adj = phase_adj << DDR_BDL_PHASE_REL; + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL0(rank_index, i), + bdl_adj, DDR_FALSE); + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL1(rank_index, i), + bdl_adj, DDR_FALSE); + ddr_bdl_sub(&wdm_bdl, bdl_adj); + + } else if (wdqs_new->bdl[i] < wdqs_old->bdl[i]) { + val = wdqs_old->bdl[i] - wdqs_new->bdl[i]; + phase_adj = val >> DDR_BDL_PHASE_REL; + wdq_phase = (wdq_phase > phase_adj) + ? (wdq_phase - phase_adj) : 0; + + /* adjust wdq bdl and dm bdl in opposite direction */ + bdl_adj = phase_adj << DDR_BDL_PHASE_REL; + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL0(rank_index, i), + bdl_adj, DDR_TRUE); + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL1(rank_index, i), + bdl_adj, DDR_TRUE); + ddr_bdl_add(&wdm_bdl, bdl_adj); + } + + DDR_INFO("Byte[%x] WDQ adjust phase[%x] bdl[%x]", + i, phase_adj, bdl_adj); + + ddr_write(wdq_phase << PHY_WDQ_PHASE_BIT, + base_phy + DDR_PHY_DXNWDQDLY(rank_index, i)); + ddr_write(wdm_bdl << PHY_WDM_BDL_BIT, base_phy + DDR_PHY_DXNWDQNBDL2(rank_index, i)); + } + + ddr_phy_cfg_update(base_phy); +} +#endif /* DDR_WL_DATAEYE_ADJUST_CONFIG */ + +/* Sync WDQ phase, WDQ bdl, WDM bdl, OEN bdl, WDQ SOE bdl by WDQS value */ +static void ddr_wl_bdl_sync(struct ddr_cfg_st *cfg, + struct ddr_delay_st *wdqs_new, struct ddr_delay_st *wdqs_old) +{ + unsigned int tmp; + unsigned int val; + int i; + + unsigned int oen_bdl, wdqsoe_bdl, wdm_bdl; + unsigned int wdq_phase; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + unsigned int rank_index = cfg->rank_idx; + + /* sync wdq phase, wdq bdl, wdm bdl, oen bdl, wdq soe bdl */ + for (i = 0; i < byte_num; i++) { + if (wdqs_new->phase[i] == wdqs_old->phase[i] + && wdqs_new->bdl[i] == wdqs_old->bdl[i]) { + continue; + } + + DDR_DEBUG("Byte[%x] new[%x][%x] old[%x][%x]", i, + wdqs_new->phase[i], wdqs_new->bdl[i], + wdqs_old->phase[i], wdqs_old->bdl[i]); + + /* wdq phase */ + wdq_phase = (ddr_read(base_phy + DDR_PHY_DXNWDQDLY(rank_index, i)) + >> PHY_WDQ_PHASE_BIT) + & PHY_WDQ_PHASE_MASK; + /* always new_phase >= old_phase */ + wdq_phase = wdq_phase + + (wdqs_new->phase[i] - wdqs_old->phase[i]); + + /* bdl */ + tmp = ddr_read(base_phy + DDR_PHY_DXNOEBDL(rank_index, i)); + oen_bdl = (tmp >> PHY_OEN_BDL_BIT) & PHY_BDL_MASK; + wdqsoe_bdl = (tmp >> PHY_WDQSOE_BDL_BIT) & PHY_BDL_MASK; + wdm_bdl = (ddr_read(base_phy + DDR_PHY_DXNWDQNBDL2(rank_index, i)) + >> PHY_WDM_BDL_BIT) & PHY_BDL_MASK; + + if (wdqs_new->bdl[i] > wdqs_old->bdl[i]) { + val = wdqs_new->bdl[i] - wdqs_old->bdl[i]; + ddr_dq_bdl_operate(base_phy, + DDR_PHY_DXNWDQNBDL0(rank_index, i), val, DDR_TRUE); + ddr_dq_bdl_operate(base_phy, + DDR_PHY_DXNWDQNBDL1(rank_index, i), val, DDR_TRUE); + ddr_bdl_add(&oen_bdl, val); + ddr_bdl_add(&wdqsoe_bdl, val); + ddr_bdl_add(&wdm_bdl, val); + } else if (wdqs_new->bdl[i] < wdqs_old->bdl[i]) { + val = wdqs_old->bdl[i] - wdqs_new->bdl[i]; + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL0(rank_index, i), + val, DDR_FALSE); + ddr_dq_bdl_operate(base_phy, DDR_PHY_DXNWDQNBDL1(rank_index, i), + val, DDR_FALSE); + ddr_bdl_sub(&oen_bdl, val); + ddr_bdl_sub(&wdqsoe_bdl, val); + ddr_bdl_sub(&wdm_bdl, val); + } + + if (wdq_phase > PHY_WDQ_PHASE_MASK) + wdq_phase = PHY_WDQ_PHASE_MASK; + + ddr_write(wdq_phase << PHY_WDQ_PHASE_BIT, + base_phy + DDR_PHY_DXNWDQDLY(rank_index, i)); + ddr_write((wdqsoe_bdl << PHY_WDQSOE_BDL_BIT) + (oen_bdl << PHY_OEN_BDL_BIT), + base_phy + DDR_PHY_DXNOEBDL(rank_index, i)); + ddr_write((wdm_bdl << PHY_WDM_BDL_BIT), base_phy + DDR_PHY_DXNWDQNBDL2(rank_index, i)); + } + + ddr_phy_cfg_update(base_phy); +} + +/** + * Write leveling process. + * WL depend default WDQS phase value in register init table. + */ +static int ddr_wl_process(struct ddr_cfg_st *cfg, + unsigned int type, struct ddr_delay_st *wdqs) +{ + int i, j; + unsigned int wl_result = 0; + unsigned int length; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + + if (DDR_DELAY_PHASE == type) + length = PHY_WDQS_PHASE_MASK; + else + length = PHY_BDL_MASK; + + /* find WDQS phase or bdl, assume CLK Delay > DQS Delay */ + for (i = 0; i <= length; i++) { + ddr_phy_cfg_update(base_phy); + ddr_write(0x1, base_phy + DDR_PHY_SWTWLDQS); + DDR_ASM_DSB(); + wl_result = ddr_read(base_phy + DDR_PHY_SWTRLT) + & PHY_SWTRLT_WL_MASK; + ddr_write(0x0, base_phy + DDR_PHY_SWTWLDQS); + + if ((wl_result & ((1 << byte_num) - 1)) == ((1 << byte_num) - 1)) + break; + + for (j = 0; j < byte_num; j++) { + DDR_INFO("type[0x%x] byte[0x%x] phase[0x%x] bdl[0x%x] wl_result[0x%x]", + type, j, wdqs->phase[j], wdqs->bdl[j], wl_result); + if (!(wl_result & (1 << j))) { + if (DDR_DELAY_PHASE == type) + ddr_phase_inc(&wdqs->phase[j]); + else + wdqs->bdl[j] += DDR_WL_BDL_STEP; + + ddr_write((wdqs->phase[j] << PHY_WDQS_PHASE_BIT) + + (wdqs->bdl[j] << PHY_WDQS_BDL_BIT), + base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, j)); + } + } + } + + if (i > length) { /* wl error, not find wdqs delay */ + if (DDR_DELAY_BDL == type) { + DDR_FATAL("PHY[%x] WL fail, result[%x]", + base_phy, wl_result); + for (j = 0; j < byte_num; j++) + if (!(wl_result & (1 << j))) + ddr_training_stat(DDR_ERR_WL, + base_phy, j, -1); + + } else + DDR_DEBUG("PHY[%x] WL not found phase, result[%x]", + base_phy, wl_result); + + return -1; + } else + return 0; +} + +/** + * Find WDQS delay, sync to WDQ delay and OE delay. + * WL depend default WDQS phase value in register init table. + */ +int ddr_write_leveling(struct ddr_cfg_st *cfg) +{ + unsigned int i, tmp; + struct ddr_delay_st wdqs_old; + struct ddr_delay_st wdqs_new; + int result = 0; + + unsigned int base_phy = cfg->cur_phy; + unsigned int base_dmc = cfg->cur_dmc; + unsigned int byte_num = GET_BYTE_NUM(cfg); + unsigned int rank_index = cfg->rank_idx; + + DDR_DEBUG("DDR Write Leveling training."); + + /* init wdqs */ + for (i = 0; i < byte_num; i++) { + tmp = ddr_read(base_phy + DDR_PHY_DXWDQSDLY(rank_index, i)); + + wdqs_old.phase[i] = (tmp >> PHY_WDQS_PHASE_BIT) + & PHY_WDQS_PHASE_MASK; + wdqs_old.bdl[i] = (tmp >> PHY_WDQS_BDL_BIT) & PHY_BDL_MASK; + + wdqs_new.phase[i] = wdqs_old.phase[i]; + wdqs_new.bdl[i] = 0; + + /* clear wdqs bdl */ + ddr_write(wdqs_new.phase[i] << PHY_WDQS_PHASE_BIT, + base_phy + DDR_PHY_DXWDQSDLY(rank_index, i)); + } + + /* enable sw write leveling mode */ + ddr_wl_switch(base_dmc, base_phy, DDR_TRUE); + + /* find first WDQS phase, assume CLK delay > DQS delay. */ + result = ddr_wl_process(cfg, DDR_DELAY_PHASE, &wdqs_new); + + /* check phase result */ + for (i = 0; i < byte_num; i++) { + /* find phase error, keep max value to find bdl. */ + /* find phase ok, decrease to find bdl. */ + if (!result) + ddr_phase_dec(&wdqs_new.phase[i]); + + ddr_write(wdqs_new.phase[i] << PHY_WDQS_PHASE_BIT, + base_phy + DDR_PHY_DXWDQSDLY(rank_index, i)); + } + + /* find WDQS bdl */ + result = ddr_wl_process(cfg, DDR_DELAY_BDL, &wdqs_new); + + /* disable sw write leveling mode */ + ddr_wl_switch(base_dmc, base_phy, DDR_FALSE); + + if (result) { + /* restore default value when find WDQS fail */ + for (i = 0; i < byte_num; i++) { + tmp = (wdqs_old.phase[i] << PHY_WDQS_PHASE_BIT) + + (wdqs_old.bdl[i] << PHY_WDQS_BDL_BIT); + ddr_write(tmp, base_phy + DDR_PHY_DXWDQSDLY(rank_index, i)); + } + ddr_phy_cfg_update(base_phy); + return -1; + } + + /* sync delay */ + ddr_wl_bdl_sync(cfg, &wdqs_new, &wdqs_old); + +#ifdef DDR_WL_DATAEYE_ADJUST_CONFIG + /* adjust WDQ for dataeye */ + ddr_wl_wdq_adjust(cfg, &wdqs_new, &wdqs_old); +#endif + return 0; +} + +int ddr_wl_func(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result = 0; + + /* write leveling disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_WL_MASK)) + return 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_WL_MASK); + + result += ddr_write_leveling(cfg); + + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_wl_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR WL training."); + return 0; +} + #endif /* DDR_WL_TRAINING_CONFIG */ + +#define __gate_training__ +#ifdef DDR_GATE_TRAINING_CONFIG +/* Find gate phase */ +static int ddr_gate_find_phase(struct ddr_cfg_st *cfg, + struct ddr_delay_st *rdqsg) +{ + int i; + unsigned int base_phy = cfg->cur_phy; + + for (i = 0; i < GET_BYTE_NUM(cfg); i++) { + for (rdqsg->phase[i] = PHY_RDQSG_PHASE_MAX; + rdqsg->phase[i] > PHY_GATE_PHASE_MARGIN; + rdqsg->phase[i] -= PHY_RDQSG_PHASE_STEP) { + ddr_write(rdqsg->phase[i] << PHY_RDQSG_PHASE_BIT, + base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + ddr_phy_cfg_update(base_phy); + if (0 == ddr_ddrt_test(DDRT_WR_COMPRARE_MODE, i, -1)) + break; + } + if (rdqsg->phase[i] <= PHY_GATE_PHASE_MARGIN) { + /* find gate phase fail */ + DDR_FATAL("find gate phase[%x] fail.", + rdqsg->phase[i]); + ddr_training_stat(DDR_ERR_GATING, base_phy, -1, -1); + return -1; + } else { + /* decrease one setp to find bdl */ + rdqsg->phase[i] -= PHY_RDQSG_PHASE_STEP; + ddr_write(rdqsg->phase[i] << PHY_RDQSG_PHASE_BIT, + base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + } + } + + ddr_phy_cfg_update(base_phy); + return 0; +} + +static int ddr_gate_find_bdl(struct ddr_cfg_st *cfg, + struct ddr_delay_st *rdqsg) +{ + int i, j; + unsigned int gate_result; + unsigned int tmp; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + + unsigned int swtmode = ddr_read(base_phy + DDR_PHY_SWTMODE); + + for (i = 0; i < byte_num; i++) + rdqsg->bdl[i] = 0; + + /* enable phy sw gate training mode */ + ddr_write(swtmode | (1 << PHY_SWTMODE_SW_GTMODE_BIT), + base_phy + DDR_PHY_SWTMODE); + + for (i = 0; i < PHY_GATE_BDL_MAX; i++) { + ddr_phy_cfg_update(base_phy); + ddr_ddrt_test(DDRT_READ_ONLY_MODE, -1, -1); + gate_result = (ddr_read(base_phy + DDR_PHY_SWTRLT) >> 8) + & PHY_SWTRLT_GATE_MASK; + if (gate_result == ((1 << byte_num) - 1)) + break; + + for (j = 0; j < byte_num; j++) { + if (!(gate_result & (1 << j))) { + rdqsg->bdl[j] += DDR_GATE_BDL_STEP; + if (rdqsg->bdl[j] > PHY_BDL_MASK) { + tmp = ((rdqsg->bdl[j] + - PHY_BDL_MASK - 1) + << PHY_RDQSG_TX_BDL_BIT) + + (rdqsg->phase[j] + << PHY_RDQSG_PHASE_BIT) + + (PHY_BDL_MASK - 1); + } else { + tmp = (rdqsg->phase[j] + << PHY_RDQSG_PHASE_BIT) + + rdqsg->bdl[j]; + } + ddr_write(tmp, + base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, j)); + } + } + } + + /* disable phy sw gate training mode */ + ddr_write(swtmode & (~(1 << PHY_SWTMODE_SW_GTMODE_BIT)), + base_phy + DDR_PHY_SWTMODE); + + if (i == PHY_GATE_BDL_MAX) { /* find gate bdl fail */ + DDR_FATAL("PHY[%x] find gate bdl fail. result[%x]", + base_phy, gate_result); + for (j = 0; j < byte_num; j++) + if (!(gate_result & (1 << j))) + ddr_training_stat(DDR_ERR_GATING, + base_phy, j, -1); + return -1; + } else + return 0; +} + +int ddr_gate_training(struct ddr_cfg_st *cfg) +{ + unsigned int i, tmp; + unsigned int byte_num; + struct ddr_delay_st rdqsg; + unsigned int def_delay[DDR_PHY_BYTE_MAX]; + int result; + unsigned int base_phy = cfg->cur_phy; + + DDR_DEBUG("DDR Gate training."); + + byte_num = GET_BYTE_NUM(cfg); + + for (i = 0; i < byte_num; i++) + def_delay[i] = ddr_read(base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + + /* find phase first */ + result = ddr_gate_find_phase(cfg, &rdqsg); + + /* find bdl */ + if (!result) + result = ddr_gate_find_bdl(cfg, &rdqsg); + + /* set new phase */ + if (!result) { + for (i = 0; i < byte_num; i++) { + rdqsg.phase[i] -= PHY_GATE_PHASE_MARGIN; + tmp = ddr_read(base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + tmp &= ~(PHY_RDQSG_PHASE_MASK << PHY_RDQSG_PHASE_BIT); + tmp |= rdqsg.phase[i] << PHY_RDQSG_PHASE_BIT; + ddr_write(tmp, base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + } + } else { + /* restore default value */ + for (i = 0; i < byte_num; i++) + ddr_write(def_delay[i], + base_phy + DDR_PHY_DXNRDQSGDLY(cfg->rank_idx, i)); + } + + ddr_phy_cfg_update(base_phy); + return 0; /* use default value and not reset */ +} + +int ddr_gating_func(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result = 0; + + /* gate training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_GATE_MASK)) { + /* check hardware gating */ + if (ddr_read(cfg->cur_phy + DDR_PHY_PHYINITSTATUS) + & PHY_INITSTATUS_GT_MASK) { + DDR_FATAL("PHY[%x] hw gating fail.", cfg->cur_phy); + ddr_training_stat(DDR_ERR_HW_GATING, + cfg->cur_phy, -1, -1); + return -1; + } + return 0; + } + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_GATE_MASK); + + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_GATE); + result += ddr_gate_training(cfg); + + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_gating_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR gate training."); + return 0; +} +#endif /* DDR_GATE_TRAINING_CONFIG */ + +#define __ac_training__ +#ifdef DDR_AC_TRAINING_CONFIG +/** + * Get clk value. + * Assume clk0 and clk1 is the same. + */ +static int ddr_ac_get_clk(unsigned int base_phy) +{ + unsigned int val; + unsigned int ac_phy_ctl; + /* Static register have to read two times to get the right value. */ + ac_phy_ctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL7); + ac_phy_ctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL7); + /* halft_dramclk0 */ + val = (ac_phy_ctl >> PHY_ACPHY_DRAMCLK0_BIT) + & PHY_ACPHY_DRAMCLK_MASK; + val = (val << PHY_ACPHY_DRAMCLK_EXT_BIT) + | ((ac_phy_ctl >> PHY_ACPHY_DCLK0_BIT) + & PHY_ACPHY_DCLK_MASK); + return val; +} + +/* Set clk0 and clk1 the same value */ +static void ddr_ac_set_clk(unsigned int base_phy, unsigned int val) +{ + unsigned int ac_phy_ctl, dramclk, dclk; + dclk = val & PHY_ACPHY_DCLK_MASK; + dramclk = (val >> PHY_ACPHY_DRAMCLK_EXT_BIT) + & PHY_ACPHY_DRAMCLK_MASK; + /* Static register have to read two times to get the right value. */ + ac_phy_ctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL7); + ac_phy_ctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL7); + /* clear cp1p_dclk0 */ + ac_phy_ctl &= (~(PHY_ACPHY_DCLK_MASK << PHY_ACPHY_DCLK0_BIT)); + /* clear ck2p_dclk1 */ + ac_phy_ctl &= (~(PHY_ACPHY_DCLK_MASK << PHY_ACPHY_DCLK1_BIT)); + /* clear halft_dramclk0 */ + ac_phy_ctl &= (~(PHY_ACPHY_DRAMCLK_MASK << PHY_ACPHY_DRAMCLK0_BIT)); + /* clear halft_dramclk1 */ + ac_phy_ctl &= (~(PHY_ACPHY_DRAMCLK_MASK << PHY_ACPHY_DRAMCLK1_BIT)); + + ac_phy_ctl |= (dclk << PHY_ACPHY_DCLK0_BIT); /* set cp1p_dclk0 */ + ac_phy_ctl |= (dclk << PHY_ACPHY_DCLK1_BIT); /* set cp2p_dclk1 */ + /* set halft_dramclk0 */ + ac_phy_ctl |= (dramclk << PHY_ACPHY_DRAMCLK0_BIT); + /* set halft_dramclk1 */ + ac_phy_ctl |= (dramclk << PHY_ACPHY_DRAMCLK1_BIT); + ddr_write(ac_phy_ctl, base_phy + DDR_PHY_ACPHYCTL7); +} + +/** + * Get cs bdl value. + * Assume cs0 and cs 1 is the same. + */ +static int ddr_ac_get_cs(unsigned int base_phy) +{ + return (ddr_read(base_phy + DDR_PHY_ACCMDBDL2) >> 1) & PHY_BDL_MASK; +} + +/* Set CS value */ +static void ddr_ac_set_cs(unsigned int base_phy, unsigned int val) +{ + unsigned int ac_cmd_bdl; + ac_cmd_bdl = ddr_read(base_phy + DDR_PHY_ACCMDBDL2); + ac_cmd_bdl &= (~(PHY_BDL_MASK << PHY_ACCMD_CS0_BIT)); /* clear cs0_bdl */ + ac_cmd_bdl &= (~(PHY_BDL_MASK << PHY_ACCMD_CS1_BIT)); /* clear cs1_bdl */ + ac_cmd_bdl |= (val << PHY_ACCMD_CS0_BIT); /* set cs0_bdl */ + ac_cmd_bdl |= (val << PHY_ACCMD_CS1_BIT); /* set cs1_bdl */ + ddr_write(ac_cmd_bdl, base_phy + DDR_PHY_ACCMDBDL2); +} + +static int ddr_ac_ddrt_test(unsigned int mask, unsigned int base_phy) +{ + unsigned int regval; + unsigned int times = 0; + + DDRT_REG_WRITE(mask | DDRT_CFG_START, DDR_REG_BASE_DDRT + DDRT_OP); + DDRT_REG_WRITE(0, DDR_REG_BASE_DDRT + DDRT_STATUS); + + do { + regval = DDRT_REG_READ(DDR_REG_BASE_DDRT + DDRT_STATUS); + times++; + } while ((!(regval & DDRT_TEST_DONE_MASK)) + && (times < DDRT_WAIT_TIMEOUT)); + + if (times >= DDRT_WAIT_TIMEOUT) { + DDR_FATAL("DDRT wait timeout."); + ddr_training_stat(DDR_ERR_DDRT_TIME_OUT, base_phy, -1, -1); + return -1; + } + + /* DDRT_WRITE_ONLY_MODE */ + if (DDRT_WRITE_ONLY_MODE == (mask & DDRT_TEST_MODE_MASK)) + return 0; + + /* DDRT_READ_ONLY_MODE */ + if (regval & DDRT_TEST_PASS_MASK) /* No error occurred, test pass. */ + return 0; + else + return -1; + +} + +/* Check CS value */ +static int ddr_ac_check_cs(unsigned int base_phy, unsigned int def_cs, + unsigned int step) +{ + ddr_ac_set_cs(base_phy, def_cs + step); + ddr_phy_cfg_update(base_phy); + + ddr_ac_ddrt_test(DDRT_WRITE_ONLY_MODE, base_phy); + + ddr_ac_set_cs(base_phy, def_cs); /* restore default to check */ + ddr_phy_cfg_update(base_phy); + + return ddr_ac_ddrt_test(DDRT_READ_ONLY_MODE, base_phy); +} + +/* Check CLK value */ +static int ddr_ac_check_clk(struct ddr_cfg_st *cfg, unsigned int def_clk, + struct ddr_delay_st *def_phase, + unsigned int step) +{ + int i; + unsigned int wdqs_phase_range, wdq_phase_range, phase_range; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + + /* set new value */ + ddr_ac_set_clk(base_phy, def_clk + step); + for (i = 0; i < byte_num; i++) { + wdqs_phase_range = PHY_WDQS_PHASE_MASK + - ((def_phase->phase[i] >> PHY_WDQS_PHASE_BIT) + & PHY_WDQS_PHASE_MASK); + wdq_phase_range = PHY_WDQ_PHASE_MASK + - ((def_phase->bdl[i] >> PHY_WDQ_PHASE_BIT) + & PHY_WDQ_PHASE_MASK); + phase_range = (wdqs_phase_range < wdq_phase_range) + ? wdqs_phase_range : wdq_phase_range; + phase_range = (phase_range < step) ? phase_range : step; + + ddr_write(def_phase->phase[i] + + (phase_range << PHY_WDQS_PHASE_BIT), + base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, i)); + ddr_write(def_phase->bdl[i] + + (phase_range << PHY_WDQ_PHASE_BIT), + base_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, i)); + } + ddr_phy_cfg_update(base_phy); + + ddr_ac_ddrt_test(DDRT_WRITE_ONLY_MODE, base_phy); + + /* restore default to check */ + ddr_ac_set_clk(base_phy, def_clk); + for (i = 0; i < byte_num; i++) { + ddr_write(def_phase->phase[i], + base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, i)); + ddr_write(def_phase->bdl[i], + base_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, i)); + } + ddr_phy_cfg_update(base_phy); + + return ddr_ac_ddrt_test(DDRT_READ_ONLY_MODE, base_phy); +} + +/* Find CS difference */ +static int ddr_ac_find_cs(unsigned int base_phy) +{ + unsigned int def_cs, step; + + def_cs = ddr_ac_get_cs(base_phy); + for (step = 1; step <= (PHY_BDL_MASK - def_cs); step++) { + if (ddr_ac_check_cs(base_phy, def_cs, step)) { + DDR_DEBUG("PHY[%x] default cs[%x], find diff_cs[%x]", + base_phy, def_cs, step); + break; + } + } + + return step; +} + +/* Find CLK difference */ +static int ddr_ac_find_clk(struct ddr_cfg_st *cfg) +{ + int i; + unsigned int def_clk, step; + struct ddr_delay_st def_phase; + unsigned int base_phy = cfg->cur_phy; + unsigned int byte_num = GET_BYTE_NUM(cfg); + + def_clk = ddr_ac_get_clk(base_phy); + for (i = 0; i < byte_num; i++) { + /* WDQS phase */ + def_phase.phase[i] = ddr_read(base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, i)); + /* WDQ phase */ + def_phase.bdl[i] = ddr_read(base_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, i)); + } + + for (step = 1; step <= (PHY_ACPHY_CLK_MAX - def_clk); step++) { + if (ddr_ac_check_clk(cfg, def_clk, &def_phase, step)) { + DDR_DEBUG("PHY[%x] default clk[%x], find diff_clk[%x]", + base_phy, def_clk, step); + break; + } + } + + return step; +} + +/* DDR AC training */ +int ddr_ac_training(struct ddr_cfg_st *cfg) +{ + unsigned int diff_cs, diff_clk; + unsigned int clk_phase, cs_bdl, phase_tmp; + unsigned int byte_num; + unsigned int wdqs_phase, wdq_phase; + unsigned int wdqs_phase_range, wdq_phase_range, phase_range; + unsigned int def_clk, def_cs; + int i; + unsigned int base_phy = cfg->cur_phy; + + DDR_DEBUG("DDR AC training."); + + byte_num = GET_BYTE_NUM(cfg); + + diff_cs = ddr_ac_find_cs(base_phy); /* setup time(bdl) */ + diff_clk = ddr_ac_find_clk(cfg); /* hold time(phase) */ + /* cs bdl transform to clk phase */ + phase_tmp = diff_cs >> DDR_BDL_PHASE_REL; + + if (diff_clk > phase_tmp) { + clk_phase = (diff_clk - phase_tmp) >> 1; + def_clk = ddr_ac_get_clk(base_phy); + + /* set new value */ + ddr_ac_set_clk(base_phy, def_clk + clk_phase); + for (i = 0; i < byte_num; i++) { + wdqs_phase = ddr_read(base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, i)); + wdq_phase = ddr_read(base_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, i)); + + wdqs_phase_range = PHY_WDQS_PHASE_MASK + - ((wdqs_phase >> PHY_WDQS_PHASE_BIT) + & PHY_WDQS_PHASE_MASK); + wdq_phase_range = PHY_WDQ_PHASE_MASK + - ((wdq_phase >> PHY_WDQ_PHASE_BIT) + & PHY_WDQ_PHASE_MASK); + phase_range = (wdqs_phase_range < wdq_phase_range) + ? wdqs_phase_range : wdq_phase_range; + phase_range = (phase_range < clk_phase) + ? phase_range : clk_phase; + ddr_write(wdqs_phase + + (phase_range << PHY_WDQS_PHASE_BIT), + base_phy + DDR_PHY_DXWDQSDLY(cfg->rank_idx, i)); + ddr_write(wdq_phase + + (phase_range << PHY_WDQ_PHASE_BIT), + base_phy + DDR_PHY_DXNWDQDLY(cfg->rank_idx, i)); + } + DDR_DEBUG("PHY[%x] def clk[%x] add phase[%x]", + base_phy, def_clk, clk_phase); + } else { + def_cs = ddr_ac_get_cs(base_phy); + cs_bdl = 0; + if (diff_cs > (diff_clk << DDR_BDL_PHASE_REL)) + cs_bdl = diff_cs - (diff_clk << DDR_BDL_PHASE_REL); + + ddr_ac_set_cs(base_phy, def_cs + cs_bdl); + DDR_DEBUG("PHY[%x] def cs[%x] add bdl[%x]", + base_phy, def_cs, cs_bdl); + } + + ddr_phy_cfg_update(base_phy); + return 0; +} + +int ddr_ac_training_func(struct ddr_cfg_st *cfg) +{ + int result = 0; + struct tr_relate_reg relate_reg; + + /* AC training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_AC_MASK)) + return 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_AC_MASK); + + ddr_training_switch_axi(cfg); + ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE); + result += ddr_ac_training(cfg); + + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_ac_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR AC training."); + return 0; +} +#endif /* DDR_AC_TRAINING_CONFIG */ + +#define __lpca_training__ +#ifdef DDR_LPCA_TRAINING_CONFIG +/* Reset address bdl training data */ +static void ddr_lpca_reset(struct ca_data_st *data) +{ + unsigned int index; + for (index = 0; index < DDR_PHY_CA_MAX; index++) { + data->left[index] = -1; + data->right[index] = -1; + } + + data->min = PHY_ACADDR_BDL_MASK; + data->max = 0; + data->done = 0; +} + +/* Get ca bit relation */ +static void ddr_lpca_get_bit(struct ca_data_st *data) +{ + unsigned int index; + //unsigned int swap_sel; + + /* get ca bit in four register */ + #if 0 + for (index = 0; index < (DDR_PHY_CA_REG_MAX - 1); index++) { + ddr_write(index + 1, data->base_phy + DDR_PHY_CATSWAPINDEX); + swap_sel = ddr_read(data->base_phy + DDR_PHY_CATSWAPSEL); + + data->bits[index * 2].bit_p = + swap_sel & PHY_CATSWAPSEL_BIT_MASK; + data->bits[index * 2].bit_n = + (swap_sel >> 8) & PHY_CATSWAPSEL_BIT_MASK; + data->bits[index * 2 + 1].bit_p = + (swap_sel >> 16) & PHY_CATSWAPSEL_BIT_MASK; + data->bits[index * 2 + 1].bit_n = + (swap_sel >> 24) & PHY_CATSWAPSEL_BIT_MASK; + } + #else /* for HiMVPV200 */ + for (index = 0; index < (DDR_PHY_CA_REG_MAX - 1); index++) { + data->bits[index * 2].bit_p =index*4+ 0; + data->bits[index * 2].bit_n =index*4+ 1; + data->bits[index * 2 + 1].bit_p =index*4+ 2; + data->bits[index * 2 + 1].bit_n =index*4+ 3; + } + #endif + + /** + * set ca bit for ca4 and ca9 + * ca4 = ca0, ca9 = ca5 + */ + for (index = 8; index > 4; index--) { + data->bits[index].bit_p = data->bits[index - 1].bit_p; + data->bits[index].bit_n = data->bits[index - 1].bit_n; + } + + data->bits[4].bit_p = data->bits[0].bit_p; + data->bits[4].bit_n = data->bits[0].bit_n; + data->bits[9].bit_p = data->bits[5].bit_p; + data->bits[9].bit_n = data->bits[5].bit_n; + +#if defined(DDR_TRAINING_CMD) + for (index = 0; index < DDR_PHY_CA_MAX; index++) { + DDR_INFO("CA[%x] bit_p[%x]", index, data->bits[index].bit_p); + DDR_INFO("CA[%x] bit_n[%x]", index, data->bits[index].bit_n); + } +#endif +} + +/* Get address bdl default value */ +static void ddr_lpca_get_def(struct ca_data_st *data) +{ + unsigned int index; + + for (index = 0; index < DDR_PHY_CA_REG_MAX; index++) + data->def[index] = ddr_read(data->base_phy + + DDR_PHY_ACADDRBDL(index)); +} + +/* Restore address bdl default value */ +static void ddr_lpca_restore_def(struct ca_data_st *data) +{ + unsigned int index; + + for (index = 0; index < DDR_PHY_CA_REG_MAX; index++) + ddr_write(data->def[index], data->base_phy + + DDR_PHY_ACADDRBDL(index)); + + ddr_phy_cfg_update(data->base_phy); +} + +/* Set address bdl value */ +static void ddr_lpca_set_bdl(unsigned int base_phy, unsigned int bdl) +{ + unsigned int index; + for (index = 0; index < DDR_PHY_CA_REG_MAX; index++) + ddr_write(bdl | (bdl << PHY_ACADDRBDL_ADDR1_BIT), + base_phy + DDR_PHY_ACADDRBDL(index)); + + ddr_phy_cfg_update(base_phy); +} + +/* Update address bdl value with training result */ +static void ddr_lpca_update_bdl(struct ca_data_st *data) +{ + unsigned int index; + unsigned int addr0, addr1; + + for (index = 0; index < DDR_PHY_CA_REG_MAX; index++) { + addr0 = (data->left[index * 2] + data->right[index * 2]) >> 1; + addr1 = (data->left[index * 2 + 1] + + data->right[index * 2 + 1]) >> 1; + ddr_write(addr0 | (addr1 << PHY_ACADDRBDL_ADDR1_BIT), + data->base_phy + DDR_PHY_ACADDRBDL(index)); + } + + ddr_phy_cfg_update(data->base_phy); +} + +/* Init data before training */ +static void ddr_lpca_init(unsigned int base_dmc, unsigned int base_phy, + struct ca_data_st *data) +{ + data->base_dmc = base_dmc; + data->base_phy = base_phy; + + /* gat ca bit relation */ + ddr_lpca_get_bit(data); + + /* get ac addr bdl default value */ + ddr_lpca_get_def(data); + + /* reset training data */ + ddr_lpca_reset(data); +} + +/* Display training result */ +static void ddr_lpca_display(struct ca_data_st *data) +{ +#if defined(DDR_TRAINING_CMD) + unsigned int index; + + DDR_DEBUG("CA phase[%x = %x]", + data->base_phy + DDR_PHY_ADDRPHBOUND, + ddr_read(data->base_phy + DDR_PHY_ADDRPHBOUND)); + + for (index = 0; index < DDR_PHY_CA_MAX; index++) + DDR_DEBUG("CA[%x] left[%x] right[%x]", + index, data->left[index], data->right[index]); + + DDR_DEBUG("min[%x] max[%x] done[%x]", + data->min, data->max, data->done); +#endif +} + +/* Wait lpca command done */ +static void ddr_lpca_wait(volatile union U_PHY_CATCONFIG *ca) +{ + unsigned int count = 0; + while (count < DDR_LPCA_WAIT_TIMEOUT) { + if (1 == ca->bits.sw_cat_dqvalid) { + ca->bits.sw_cat_dqvalid = 0; /* clear */ + break; + } + + count++; + } + + /* generally, count is 0 */ + if (count >= DDR_LPCA_WAIT_TIMEOUT) + DDR_ERROR("LPCA wait timeout."); +} + +/* Compare dq result and pattern */ +static int ddr_lpca_compare(struct ca_bit_st *ca_bit, + unsigned int dq_result, unsigned int pattern_p, + unsigned int pattern_n, unsigned int index) +{ + if (((dq_result >> ca_bit->bit_p) & 0x1) + != ((pattern_p >> index) & 0x1)) + return -1; + + if (((dq_result >> ca_bit->bit_n) & 0x1) + != ((pattern_n >> index) & 0x1)) + return -1; + + return 0; +} + +/* Check each CA whether pass */ +static void ddr_lpca_check(struct ca_data_st *data, unsigned int bdl, + unsigned int is_ca49) +{ + unsigned int dq_result = ddr_read(data->base_phy + DDR_PHY_PHYDQRESULT); + unsigned int pattern_p = ddr_read(data->base_phy + + DDR_PHY_SWCATPATTERN_P) & PHY_CAT_PATTERN_MASK; + unsigned int pattern_n = ddr_read(data->base_phy + + DDR_PHY_SWCATPATTERN_N) & PHY_CAT_PATTERN_MASK; + unsigned int index; + + for (index = 0; index < DDR_PHY_CA_MAX; index++) { + if (is_ca49) { + if (4 != index && 9 != index) + continue; + } else { + if (4 == index || 9 == index) + continue; + } + + /* compare result and pattern */ + if (!ddr_lpca_compare(&data->bits[index], + dq_result, pattern_p, pattern_n, index)) { + /* pass */ + if (-1 == data->left[index]) { + data->left[index] = bdl; + /* set min left bound */ + if (bdl < data->min) + data->min = bdl; + } + + /* unstable border value or abnormal value */ + if ((-1 != data->right[index]) + && ((bdl - data->right[index]) > 1)) + DDR_WARNING("CA[%x] bdl[%x] right[%x] ph[%x]", + index, bdl, data->right[index], + ddr_read(data->base_phy + + DDR_PHY_ADDRPHBOUND)); + + data->right[index] = bdl; + data->done |= (0x1 << index); + + /* set max right bound */ + if (data->right[index] > data->max) + data->max = data->right[index]; + } + } +} + +/* Excute lpca command and check result */ +static void ddr_lpca_excute(struct ca_data_st *data, unsigned int bdl, + unsigned int is_ca49) +{ + volatile union U_PHY_CATCONFIG *ca = (union U_PHY_CATCONFIG *) + (data->base_phy + DDR_PHY_CATCONFIG); + + if (is_ca49) + ca->bits.sw_cat_mrw48 = 1; + else + ca->bits.sw_cat_mrw41 = 1; + + ddr_lpca_wait(ca); + ca->bits.sw_cat_cke_low = 1; + ddr_lpca_wait(ca); + ca->bits.sw_cat_strobe = 1; + ddr_lpca_wait(ca); + + /* check PHYDQRESULT */ + ddr_lpca_check(data, bdl, is_ca49); + + ca->bits.sw_cat_cke_high = 1; + ddr_lpca_wait(ca); + ca->bits.sw_cat_mrw42 = 1; + ddr_lpca_wait(ca); +} + +/* Find address bdl */ +static int ddr_lpca_find_bdl(struct ca_data_st *data) +{ + unsigned int bdl; + + for (bdl = 0; bdl <= PHY_ACADDR_BDL_MASK; bdl++) { + /* update bdl */ + ddr_lpca_set_bdl(data->base_phy, bdl); + + /* ca0~ca3, ca5~ca8 */ + ddr_lpca_excute(data, bdl, DDR_FALSE); + + /* ca4, ca9 */ + ddr_lpca_excute(data, bdl, DDR_TRUE); + } + + if (PHY_CAT_PATTERN_MASK == data->done) + return 0; + + return -1; +} + +/* Loop phase to find valid bdl and phase */ +static int ddr_lpca_loop_phase(struct ca_data_st *data, int step) +{ + volatile union U_PHY_ADDRPHBOUND *ph = (union U_PHY_ADDRPHBOUND *) + (data->base_phy + DDR_PHY_ADDRPHBOUND); + unsigned int phase; + unsigned int addrph_def = ph->bits.addrph_a; + int addrph = addrph_def; + + for (phase = 0; phase <= PHY_ADDRPH_MASK; phase++) { + /* reset ca training data */ + ddr_lpca_reset(data); + + /* find bdl */ + if (!ddr_lpca_find_bdl(data)) + return 0; + + addrph += step; + if (addrph < 0 || addrph > PHY_ADDRPH_MASK) + break; + + ph->bits.addrph_a = addrph; + ddr_phy_cfg_update(data->base_phy); + } + + /* restore default value */ + DDR_DEBUG("current phase[%x = %x], restore default[%x]", + ph, *ph, addrph_def); + ph->bits.addrph_a = addrph_def; + return -1; +} + +/* Find a valid phase */ +static int ddr_lpca_find_phase(struct ca_data_st *data) +{ + /* increase default value to find */ + if (!ddr_lpca_loop_phase(data, 1)) + return 0; + + /* decrease default value to find */ + if (!ddr_lpca_loop_phase(data, -1)) + return 0; + + return -1; +} + +/* Set step to adjust address window */ +static int ddr_lpca_set_step(struct ca_data_st *data) +{ + /* max window, no need to found */ + if (0 == data->min && PHY_ACADDR_BDL_MASK == data->max) + return 0; + + if (0 == data->min) + return -1; /* window on left, move to right */ + else + return 1; /* window on right, move to left */ +} + +/** + * Adjust address window via change phase. + * Increase phase, window will move to left. + */ +static void ddr_lpca_adjust(struct ca_data_st *data) +{ + int step = 0; + volatile union U_PHY_ADDRPHBOUND *ph = (union U_PHY_ADDRPHBOUND *) + (data->base_phy + DDR_PHY_ADDRPHBOUND); + unsigned int phase; + unsigned int addrph_last = ph->bits.addrph_a; + int addrph_cur = addrph_last; + + /* set step to increase or decrease phase */ + step = ddr_lpca_set_step(data); + + if (!step) + return; + + for (phase = 0; phase <= PHY_ADDRPH_MASK; phase++) { + addrph_cur += step; + if (addrph_cur < 0 || addrph_cur > PHY_ADDRPH_MASK) + return; + + ph->bits.addrph_a = addrph_cur; + ddr_phy_cfg_update(data->base_phy); + + /* reset ca training data */ + ddr_lpca_reset(data); + + if (ddr_lpca_find_bdl(data)) { + /* not find bdl, restore last value */ + addrph_cur -= step; + ddr_lpca_find_bdl(data); + return; + } + + /* max window: ------- */ + if (0 == data->min && PHY_ACADDR_BDL_MASK == data->max) + return; + + /* last window: -----xx */ + if (0 == data->min && 1 == step) { + /* last value is best */ + addrph_cur -= step; + ph->bits.addrph_a = addrph_cur; + ddr_phy_cfg_update(data->base_phy); + ddr_lpca_reset(data); + ddr_lpca_find_bdl(data); + return; + } + + /* best window: x-----x */ + if (0 < data->min && -1 == step) + return; + } +} + +/* Low power DDR CA training */ +int ddr_lpca_training(struct ddr_cfg_st *cfg) +{ + volatile union U_PHY_CATCONFIG *ca = (union U_PHY_CATCONFIG *) + (cfg->cur_phy + DDR_PHY_CATCONFIG); + + struct ca_data_st data; + int ret = -1; + + DDR_DEBUG("DDR LPCA training."); + + /* init data */ + ddr_lpca_init(cfg->cur_dmc, cfg->cur_phy, &data); + + /* enable sw ca training, wait 62.5ns */ + ca->bits.sw_cat_en = 1; + + /* find a valid phase first */ + ret = ddr_lpca_find_phase(&data); + + /* display training result */ + ddr_lpca_display(&data); + + if (ret) { + /* restore default value when fail */ + ddr_lpca_restore_def(&data); + DDR_ERROR("PHY[%x] found phase fail, result[%x].", + cfg->cur_phy, data.done); + ddr_training_stat(DDR_ERR_LPCA, cfg->cur_phy, -1, -1); + } else { + /* adjust window via phase */ + ddr_lpca_adjust(&data); + ddr_lpca_display(&data); + /* set training result */ + ddr_lpca_update_bdl(&data); + } + + /* disable sw ca training */ + ca->bits.sw_cat_en = 0; + + /* save lpca result data to printf */ + ddr_lpca_data_save(&data); + + return ret; +} + +int ddr_lpca_training_func(struct ddr_cfg_st *cfg) +{ + int result = 0; + struct tr_relate_reg relate_reg; + + /* LPCA training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_LPCA_MASK)) + return 0; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_LPCA_MASK); + + /* only lowpower ddr3 support */ + if (PHY_DRAMCFG_TYPE_LPDDR3 == + (ddr_read(cfg->cur_phy + DDR_PHY_DRAMCFG) + & PHY_DRAMCFG_TYPE_LPDDR3)) + result += ddr_lpca_training(cfg); + + ddr_training_restore_reg(cfg, &relate_reg); + + return result; +} +#else +int ddr_lpca_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support LPDDR CA training."); + return 0; +} +#endif /* DDR_LPCA_TRAINING_CONFIG */ + +/* s40/t28/t16 not support dcc training */ +#define __dcc_training__ +#ifdef DDR_DCC_TRAINING_CONFIG +/* Save two rank RDET result */ +static void ddr_save_two_rank_bdl(struct ddr_cfg_st *cfg, struct dcc_data_st *dcc_data) +{ + unsigned int byte_idx; + unsigned int base_phy = cfg->cur_phy; + unsigned int rank_idx = cfg->rank_idx; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + for (byte_idx = 0; byte_idx < byte_num; byte_idx++) { + dcc_data->rank[rank_idx].dq03[byte_idx] = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL0(rank_idx, byte_idx)); + dcc_data->rank[rank_idx].dq47[byte_idx] = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL1(rank_idx, byte_idx)); + dcc_data->rank[rank_idx].rdm[byte_idx] = ddr_read(base_phy + DDR_PHY_DXNRDQNBDL2(rank_idx, byte_idx)); + dcc_data->rank[rank_idx].rdqs[byte_idx] = ddr_read(base_phy + DDR_PHY_DXNRDQSDLY(byte_idx)); + + DDR_DEBUG("rank[%x] dq03[%x] dq47[%x] rdm[%x] rdqs[%x]", rank_idx, + dcc_data->rank[rank_idx].dq03[byte_idx], + dcc_data->rank[rank_idx].dq47[byte_idx], + dcc_data->rank[rank_idx].rdm[byte_idx], + dcc_data->rank[rank_idx].rdqs[byte_idx]); + } +} + +/* Restore two rank RDET result */ +static void ddr_restore_two_rank_bdl(struct ddr_cfg_st *cfg, struct dcc_data_st *dcc_data) +{ + unsigned int byte_idx; + unsigned int base_phy = cfg->cur_phy; + unsigned int rank_idx = cfg->rank_idx; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + for (byte_idx = 0; byte_idx < byte_num; byte_idx++) { + ddr_write(dcc_data->rank[rank_idx].dq03[byte_idx], base_phy + DDR_PHY_DXNRDQNBDL0(rank_idx, byte_idx)); + ddr_write(dcc_data->rank[rank_idx].dq47[byte_idx], base_phy + DDR_PHY_DXNRDQNBDL1(rank_idx, byte_idx)); + ddr_write(dcc_data->rank[rank_idx].rdm[byte_idx], base_phy + DDR_PHY_DXNRDQNBDL2(rank_idx, byte_idx)); + ddr_write(dcc_data->rank[rank_idx].rdqs[byte_idx], base_phy + DDR_PHY_DXNRDQSDLY(byte_idx)); + } +} + +/* DMC_CFG_SREF exit self-refresa enter powerdown */ +static void ddr_exit_sref_enter_pd(struct ddr_cfg_st *cfg, struct dmc_cfg_sref_st *cfg_sref) +{ + int i; + struct ddr_phy_st *phy_st = &cfg->phy[cfg->phy_idx]; + + for (i = 0; i < phy_st->dmc_num; i++) { + cfg_sref->val[i] = ddr_read(phy_st->dmc[i].addr + DDR_DMC_CFG_SREF); + ddr_write((cfg_sref->val[i] & (~DMC_CFG_INIT_XSREF_PD_MASK)) | DMC_CFG_INIT_XSREF_PD, + phy_st->dmc[i].addr + DDR_DMC_CFG_SREF); + } +} + +/* Restore DMC_CFG_SREF config */ +static void ddr_restore_sref_cfg(struct ddr_cfg_st *cfg, struct dmc_cfg_sref_st *cfg_sref) +{ + int i; + struct ddr_phy_st *phy_st = &cfg->phy[cfg->phy_idx]; + + for (i = 0; i < phy_st->dmc_num; i++) { + ddr_write(cfg_sref->val[i], phy_st->dmc[i].addr + DDR_DMC_CFG_SREF); + } +} + +/* DCC RDET training */ +static int ddr_dcc_dataeye_read(struct ddr_cfg_st *cfg) +{ + /* 0:PHY_TRAINCTRL0_DTR_RANK0, 1:PHY_TRAINCTRL0_DTR_RANK1 */ + DDR_PHY_SWITCH_RANK(cfg->cur_phy, cfg->rank_idx); + return ddr_hw_training_process(cfg, PHY_PHYINITCTRL_RDET_EN); +} + +/* Duty direction ctl */ +static int ddr_dcc_ck_ctl(struct ddr_cfg_st *cfg, unsigned int ioctl21_def, unsigned int ctl_index) +{ + unsigned int ioctl21; + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + ioctl21 = (ioctl21_def & (~(1 << PHY_ACIOCTL21_CTL0_BIT)) + & (~(1 << PHY_ACIOCTL21_CTL1_BIT))) + | (ctl_index << PHY_ACIOCTL21_CTL0_BIT) + | (ctl_index << PHY_ACIOCTL21_CTL1_BIT); + ddr_write(ioctl21, cfg->cur_phy + DDR_PHY_ACIOCTL21); + } else { + ioctl21 = (ioctl21_def & (~(1 << PHY_ACIOCTL21_CTL0_BIT))) + | (ctl_index << PHY_ACIOCTL21_CTL0_BIT); + ddr_write(ioctl21, cfg->cur_phy + DDR_PHY_ACIOCTL21); + } + return ioctl21; +} + +/* Duty Correction */ +static int ddr_dcc_correct_duty(struct ddr_cfg_st *cfg, unsigned int cur_duty, unsigned int duty_def) +{ + unsigned int ioctl21; + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + /* Correct CK0 & CK1 duty */ + ioctl21 = (duty_def & (~(PHY_ACIOCTL21_MASK << PHY_ACIOCTL21_CK0_BIT)) + & (~(PHY_ACIOCTL21_MASK << PHY_ACIOCTL21_CK1_BIT))) + | (cur_duty << PHY_ACIOCTL21_CK0_BIT) + | (cur_duty << PHY_ACIOCTL21_CK1_BIT); + ddr_write(ioctl21, cfg->cur_phy + DDR_PHY_ACIOCTL21); + } else { + /* Correct CK0 duty */ + ioctl21 = (duty_def & (~(PHY_ACIOCTL21_MASK << PHY_ACIOCTL21_CK0_BIT))) + | (cur_duty << PHY_ACIOCTL21_CK0_BIT); + ddr_write(ioctl21, cfg->cur_phy + DDR_PHY_ACIOCTL21); + } + + return ioctl21; +} + +/* Duty Correction Control get win data */ +static int ddr_dcc_get_win(struct dcc_data_st *dcc_data, int ck_index, int val_index) +{ + unsigned int win; + unsigned int rdqsbdl_right; + unsigned int rdqsbdl_left; + rdqsbdl_right = dcc_data->ck[ck_index].val[val_index] >> PHY_DXNRDBOUND_RIGHT_BIT & PHY_DXNRDBOUND_MASK; + rdqsbdl_left = dcc_data->ck[ck_index].val[val_index] >> PHY_DXNRDBOUND_LEFT_BIT & PHY_DXNRDBOUND_MASK; + win = rdqsbdl_right - rdqsbdl_left; + return win; +} + +/* Duty Correction Control get the min win of two byte */ +static int ddr_dcc_get_min_win(struct dcc_data_st *dcc_data, int ck_index) +{ + int i; + unsigned int win_min; + unsigned int cur_win; + win_min = ddr_dcc_get_win(dcc_data, ck_index, 0); + for (i = 0; i < DDR_CK_RESULT_MAX; i++) { + cur_win = ddr_dcc_get_win(dcc_data, ck_index, i); + DDR_DEBUG("CK win[%x] = [%x]", i, cur_win); + if (cur_win < win_min) { + win_min = cur_win; + } + } + return win_min; +} + +/* Duty Correction Control get ck0 min win */ +static int ddr_dcc_get_ck0_win(struct ddr_cfg_st *cfg, struct dcc_data_st *dcc_data, + int rank_index, unsigned int ck0_win_min) +{ + int ck_index = 0; + unsigned int byte_index; + unsigned int ck0_win; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + for (byte_index = 0; byte_index < (byte_num/2); byte_index++) { + dcc_data->ck[ck_index].val[byte_index] = ddr_read(cfg->cur_phy + DDR_PHY_DXNRDBOUND(byte_index)); + } + + ck0_win = ddr_dcc_get_min_win(dcc_data, ck_index); + + if (ck0_win < ck0_win_min) + ck0_win_min = ck0_win; + + return ck0_win_min; +} + +/* Duty Correction Control get ck1 min win */ +static int ddr_dcc_get_ck1_win(struct ddr_cfg_st *cfg, struct dcc_data_st *dcc_data, + int rank_index, unsigned int ck1_win_min) +{ + int ck_index = 1; + unsigned int byte_index; + unsigned int ck1_win; + unsigned int byte_num = cfg->phy[cfg->phy_idx].total_byte_num; + + for (byte_index = 2; byte_index < byte_num; byte_index++) { + dcc_data->ck[ck_index].val[byte_index - 2] = ddr_read(cfg->cur_phy + DDR_PHY_DXNRDBOUND(byte_index)); + } + + ck1_win = ddr_dcc_get_min_win(dcc_data, ck_index); + + if (ck1_win < ck1_win_min) + ck1_win_min = ck1_win; + + return ck1_win_min; +} + +static void dcc_data_init(struct dcc_data_st *dcc_data) +{ + dcc_data->ck[0].win_min_ctl = 0xffffffff; + dcc_data->ck[0].win_max_ctl = 0x0; + dcc_data->ck[1].win_min_ctl = 0xffffffff; + dcc_data->ck[1].win_max_ctl = 0x0; + dcc_data->ck[0].idx_duty = 0; + dcc_data->ck[0].idx_duty_ctl = 0; + dcc_data->ck[0].idx_ctl = 0; + dcc_data->ck[1].idx_duty = 0; + dcc_data->ck[1].idx_duty_ctl = 0; + dcc_data->ck[1].idx_ctl = 0; + dcc_data->ck[0].BYPASS_CK_BIT = PHY_BYPASS_CK0_BIT; + dcc_data->ck[0].ACIOCTL21_CTL_BIT = PHY_ACIOCTL21_CTL0_BIT; + dcc_data->ck[0].ACIOCTL21_CK_BIT = PHY_ACIOCTL21_CK0_BIT; + dcc_data->ck[1].BYPASS_CK_BIT = PHY_BYPASS_CK1_BIT; + dcc_data->ck[1].ACIOCTL21_CTL_BIT = PHY_ACIOCTL21_CTL1_BIT; + dcc_data->ck[1].ACIOCTL21_CK_BIT = PHY_ACIOCTL21_CK1_BIT; +} + +/* dcc training get window by rank */ +static int ddr_dcc_get_win_by_rank(struct ddr_cfg_st *cfg, struct dcc_data_st *dcc_data) +{ + int i; + int result = 0; + unsigned int rank_num = cfg->phy[cfg->phy_idx].rank_num; + for (i = 0; i < rank_num; i++) { + DDR_DEBUG("cur_rank = [%x]", i); + cfg->rank_idx = i; + /* RDET */ + result += ddr_dcc_dataeye_read(cfg); + + /* Get win */ + dcc_data->ck[0].win = ddr_dcc_get_ck0_win(cfg, dcc_data, i, dcc_data->ck[0].win); + DDR_DEBUG("ck0 win = [%x]", dcc_data->ck[0].win); + + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + dcc_data->ck[1].win = ddr_dcc_get_ck1_win(cfg, dcc_data, i, dcc_data->ck[1].win); + DDR_DEBUG("ck1 win = [%x]", dcc_data->ck[1].win); + } + + /* Restore two rank bdl */ + ddr_restore_two_rank_bdl(cfg, dcc_data); + } + return result; +} + +/* ddr dcc training compare result */ +static void ddr_dcc_compare_result(struct dcc_data_st *dcc_data, int ck_num, + unsigned int base_phy, unsigned int gated_bypass_def, unsigned int ioctl21_def) +{ + int ck_idx; + + for (ck_idx = 0; ck_idx < ck_num; ck_idx++) { + /* Config ck0 duty */ + if (dcc_data->ck[ck_idx].win_max_ctl - dcc_data->ck[ck_idx].win_min_ctl <= 2) { + dcc_data->ck[ck_idx].def_bp = gated_bypass_def >> dcc_data->ck[ck_idx].BYPASS_CK_BIT & 0x1; + dcc_data->ck[ck_idx].def_ctl = ioctl21_def >> dcc_data->ck[ck_idx].ACIOCTL21_CTL_BIT & 0x1; + dcc_data->ck[ck_idx].def_duty = ioctl21_def >> dcc_data->ck[ck_idx].ACIOCTL21_CK_BIT & PHY_ACIOCTL21_MASK; + + gated_bypass_def = (gated_bypass_def & (~(1 << dcc_data->ck[ck_idx].BYPASS_CK_BIT))) + | (dcc_data->ck[ck_idx].def_bp << dcc_data->ck[ck_idx].BYPASS_CK_BIT); + ddr_write(gated_bypass_def, base_phy + DDR_PHY_AC_GATED_BYPASS); + + ioctl21_def = (ioctl21_def & (~(1 << dcc_data->ck[ck_idx].ACIOCTL21_CTL_BIT)) + & (~(PHY_ACIOCTL21_MASK << dcc_data->ck[ck_idx].ACIOCTL21_CK_BIT))) + | (dcc_data->ck[ck_idx].def_ctl << dcc_data->ck[ck_idx].ACIOCTL21_CTL_BIT) + | (dcc_data->ck[ck_idx].def_duty << dcc_data->ck[ck_idx].ACIOCTL21_CK_BIT); + ddr_write(ioctl21_def, base_phy + DDR_PHY_ACIOCTL21); + + DDR_DEBUG("ck[%x] Final AC_GATED_BYPASS[%x]", ck_idx, gated_bypass_def); + DDR_DEBUG("ck[%x] Final ACIOCTL21[%x]", ck_idx, ioctl21_def); + } else { + ioctl21_def = (ioctl21_def & (~(1 << dcc_data->ck[ck_idx].ACIOCTL21_CTL_BIT)) + & (~(PHY_ACIOCTL21_MASK << dcc_data->ck[ck_idx].ACIOCTL21_CK_BIT))) + | (dcc_data->ck[ck_idx].idx_ctl << dcc_data->ck[ck_idx].ACIOCTL21_CTL_BIT) + | (dcc_data->ck[ck_idx].idx_duty_ctl << dcc_data->ck[ck_idx].ACIOCTL21_CK_BIT); + ddr_write(ioctl21_def, base_phy + DDR_PHY_ACIOCTL21); + + DDR_DEBUG("ck[%x] Final ACIOCTL21[%x]", ck_idx, ioctl21_def); + } + } +} + +static int ddr_dcc_get_best_duty(struct ddr_cfg_st *cfg, + struct dmc_cfg_sref_st *cfg_sref, struct dcc_data_st *dcc_data) +{ + int ck_idx; + int ck_num; + int result = 0; + unsigned int cur_ctl; + unsigned int cur_duty; + unsigned int base_phy = cfg->cur_phy; + unsigned int ioctl21_def; + unsigned int gated_bypass_def, gated_bypass_temp; + + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) + ck_num = 2; + else + ck_num = 1; + + dcc_data_init(dcc_data); + + /* Save ck duty default config. Read two times to get the right static register value. */ + gated_bypass_def = ddr_read(base_phy + DDR_PHY_AC_GATED_BYPASS); + gated_bypass_def = ddr_read(base_phy + DDR_PHY_AC_GATED_BYPASS); + ioctl21_def = ddr_read(base_phy + DDR_PHY_ACIOCTL21); + ioctl21_def = ddr_read(base_phy + DDR_PHY_ACIOCTL21); + + DDR_DEBUG("gated_bypass_def[%x] ioctl21_def[%x]", gated_bypass_def, ioctl21_def); + + /* DCC training exit self-refresa enter powerdown. */ + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) + ddr_exit_sref_enter_pd(cfg, cfg_sref); + + /* DDR dcc training enter auto self-refresh. */ + if (ddr_training_ctrl_easr(cfg, DDR_ENTER_SREF)) + return -1; + + /* Enable ck0 & ck1 duty. */ + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + gated_bypass_temp = gated_bypass_def | PHY_CK1_IOCTL_DUTY_EN | PHY_CK_IOCTL_DUTY_EN; + ddr_write(gated_bypass_temp, base_phy + DDR_PHY_AC_GATED_BYPASS); + } else { + gated_bypass_temp = gated_bypass_def | PHY_CK_IOCTL_DUTY_EN; + ddr_write(gated_bypass_temp, base_phy + DDR_PHY_AC_GATED_BYPASS); + } + DDR_DEBUG("Cur GATED_BYPASS[%x]", gated_bypass_temp); + + if (ddr_training_ctrl_easr(cfg, DDR_EXIT_SREF)) + return -1; + + for (cur_ctl = 0; cur_ctl < DDR_DUTY_CTL_NUM; cur_ctl++) { + dcc_data->ck[0].win_min_duty = 0xffffffff; + dcc_data->ck[0].win_max_duty = 0x0; + dcc_data->ck[1].win_min_duty = 0xffffffff; + dcc_data->ck[1].win_max_duty = 0x0; + + DDR_DEBUG("cur_ctl = [%x]", cur_ctl); + + if (ddr_training_ctrl_easr(cfg, DDR_ENTER_SREF)) + return -1; + + /* Correct CK duty dirrection control */ + dcc_data->ioctl21_tmp = ddr_dcc_ck_ctl(cfg, ioctl21_def, cur_ctl); + + if (ddr_training_ctrl_easr(cfg, DDR_EXIT_SREF)) + return -1; + + for (cur_duty = 0; cur_duty < DDR_DUTY_NUM; cur_duty += PHY_AC_IOCTL21_STEP) { + dcc_data->ck[0].win = 0xffffffff; + dcc_data->ck[1].win = 0xffffffff; + + DDR_DEBUG("cur_duty = [%x]", cur_duty); + /* Correct ck0 and ck1 duty */ + if (ddr_training_ctrl_easr(cfg, DDR_ENTER_SREF)) + return -1; + dcc_data->ioctl21_tmp = ddr_dcc_correct_duty(cfg, cur_duty, dcc_data->ioctl21_tmp); + if (ddr_training_ctrl_easr(cfg, DDR_EXIT_SREF)) + return -1; + DDR_DEBUG("Cur ACIOCTL21[%x]", dcc_data->ioctl21_tmp); + + result = ddr_dcc_get_win_by_rank(cfg, dcc_data); + + /* Get ck0/ck1 duty_win_min/duty_win_max/duty_index */ + for (ck_idx = 0; ck_idx < ck_num; ck_idx++) { + if (dcc_data->ck[ck_idx].win < dcc_data->ck[ck_idx].win_min_duty) + dcc_data->ck[ck_idx].win_min_duty = dcc_data->ck[ck_idx].win; + + if (dcc_data->ck[ck_idx].win > dcc_data->ck[ck_idx].win_max_duty) { + dcc_data->ck[ck_idx].win_max_duty = dcc_data->ck[ck_idx].win; + dcc_data->ck[ck_idx].idx_duty = cur_duty; + } + DDR_DEBUG("ck[%x] duty_win_min[%x] duty_win_max[%x] duty_index[%x]", ck_idx, + dcc_data->ck[ck_idx].win_min_duty, + dcc_data->ck[ck_idx].win_max_duty, + dcc_data->ck[ck_idx].idx_duty); + } + } + + for (ck_idx = 0; ck_idx < ck_num; ck_idx++) { + /* Get ck0/ck1 duty_win_min/duty_win_max/duty_index */ + if (dcc_data->ck[ck_idx].win_min_duty < dcc_data->ck[ck_idx].win_min_ctl) + dcc_data->ck[ck_idx].win_min_ctl = dcc_data->ck[ck_idx].win_min_duty; + + if (dcc_data->ck[ck_idx].win_max_duty > dcc_data->ck[ck_idx].win_max_ctl) { + dcc_data->ck[ck_idx].win_max_ctl = dcc_data->ck[ck_idx].win_max_duty; + dcc_data->ck[ck_idx].idx_duty_ctl = dcc_data->ck[ck_idx].idx_duty; + dcc_data->ck[ck_idx].idx_ctl = cur_ctl; + } + DDR_DEBUG("ck[%x] win_min_ctl[%x] win_max_ctl[%x] ctl_index0[%x] duty_ctl_idx0[%x]", ck_idx, + dcc_data->ck[ck_idx].win_min_ctl, + dcc_data->ck[ck_idx].win_max_ctl, + dcc_data->ck[ck_idx].idx_ctl, + dcc_data->ck[ck_idx].idx_duty_ctl); + } + } + + /* Config ck duty */ + /* DCC training exit self-refresa enter powerdown. */ + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) + ddr_exit_sref_enter_pd(cfg, cfg_sref); + + /* DDR dcc training enter auto self-refresh. */ + if (ddr_training_ctrl_easr(cfg, DDR_ENTER_SREF)) + return -1; + + /* DDR dcc training compare result. */ + ddr_dcc_compare_result(dcc_data, ck_num, base_phy, gated_bypass_def, ioctl21_def); + + /* DDR dcc training exit auto self-refresh. */ + if (ddr_training_ctrl_easr(cfg, DDR_EXIT_SREF)) + return -1; + + return result; +} + +#ifdef DDR_TRAINING_DEBUG +#define DDR_TRINING_BREAK_POINT(name) ddr_training_break_point(name) +#else +#define DDR_TRINING_BREAK_POINT(name) +#endif + +void ddr_training_break_point(const char* name) +{ + DDR_INFO(name); + ddr_training_console_if(0); +} + +int ddr_dcc_training(struct ddr_cfg_st *cfg) +{ + int i; + int result = 0; + unsigned int rank_num = cfg->phy[cfg->phy_idx].rank_num; + + struct dmc_cfg_sref_st cfg_sref; + struct ddr_timing_st timing_st; + struct dcc_data_st dcc_st; + struct dcc_data_st *dcc_data = &dcc_st; + + DDR_DEBUG("dram_type[%x]", cfg->phy[cfg->phy_idx].dram_type); + + DDR_DEBUG("rank num[%x]", rank_num); + + /* Save two rank DERT default result: rdq/rdqs/rdm/ bdl */ + for (i = 0; i < rank_num; i++) { + cfg->rank_idx = i; + ddr_save_two_rank_bdl(cfg, dcc_data); + } + + /* Disable auto refresh */ + ddr_training_save_timing(cfg, &timing_st); + + /* Duty Correction Control training. */ + result += ddr_dcc_get_best_duty(cfg, &cfg_sref, dcc_data); + + /* Do DERT training again */ + for (i = 0; i < rank_num; i++) { + cfg->rank_idx = i; + dcc_data->item[i] = cfg->phy[cfg->phy_idx].rank[i].item_hw; + cfg->phy[cfg->phy_idx].rank[i].item_hw = PHY_PHYINITCTRL_HVREFT_EN; + DDR_DEBUG("item_hw[%x]=[%x]", i, cfg->phy[cfg->phy_idx].rank[i].item_hw); + } + + result += ddr_hw_training_by_phy(cfg); + + for (i = 0; i < rank_num; i++) { + cfg->rank_idx = i; + cfg->phy[cfg->phy_idx].rank[i].item_hw = dcc_data->item[i]; + } + + /* Enable auto refresh */ + ddr_training_restore_timing(cfg, &timing_st); + + if (PHY_DRAMCFG_TYPE_LPDDR4 == cfg->phy[cfg->phy_idx].dram_type) { + /* DCC restore DMC_CFG_SREF config. */ + ddr_restore_sref_cfg(cfg, &cfg_sref); + } + + return result; +} + +int ddr_dcc_training_func(struct ddr_cfg_st *cfg) +{ + int i; + int result = 0; + + for (i = 0; i < cfg->phy_num; i++) { + cfg->phy_idx = i; + cfg->cur_phy = cfg->phy[i].addr; + cfg->cur_item = cfg->phy[i].rank[0].item; + + if (ddr_training_check_bypass(cfg, 1 << (cfg->phy_idx))) + continue; + + /* dpmc training disable */ + if (!ddr_training_check_bypass(cfg, DDR_BYPASS_DCC_MASK)) + result += ddr_dcc_training(cfg); + } + return result; +} + +#else +int ddr_dcc_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DCC training."); + return 0; +} +#endif /* DDR_DCC_TRAINING_CONFIG */ + +#define __pcode_training__ +#ifdef DDR_PCODE_TRAINING_CONFIG +/* Set pcode value to register IMPSTATUS and DDR_PHY_IMP_STATUS1 */ +static void ddr_pcode_set_value(unsigned int base_phy, unsigned int pcode_value) +{ + unsigned int imp_ctrl1; + + ddr_write((ddr_read(base_phy + DDR_PHY_IMPSTATUS) + & (~(PHY_ZCODE_PDRV_MASK << PHY_ZCODE_PDRV_BIT))) + | (pcode_value << PHY_ZCODE_PDRV_BIT), base_phy + DDR_PHY_IMPSTATUS); + DDR_DEBUG("cur IMPSTATUS [%x] = [%x]", + base_phy + DDR_PHY_IMPSTATUS, ddr_read(base_phy + DDR_PHY_IMPSTATUS)); + + imp_ctrl1 = ddr_read(base_phy + DDR_PHY_IMP_CTRL1); + /* ac_vddq_cal_en set 0 */ + ddr_write(imp_ctrl1 & (~(0x1 << PHY_AC_VDDQ_CAL_EN_BIT)), base_phy + DDR_PHY_IMP_CTRL1); + + ddr_write((ddr_read(base_phy + DDR_PHY_IMP_STATUS1) + & (~(PHY_ACCTL_PDRV_LATCH_MASK << PHY_ACCTL_PDRV_LATCH_BIT))) + | (pcode_value << PHY_ACCTL_PDRV_LATCH_BIT), base_phy + DDR_PHY_IMP_STATUS1); + DDR_DEBUG("cur IMP_STATUS1 [%x] = [%x]", + base_phy + DDR_PHY_IMP_STATUS1, ddr_read(base_phy + DDR_PHY_IMP_STATUS1)); + + /* restore ac_vddq_cal_en */ + ddr_write(imp_ctrl1, base_phy + DDR_PHY_IMP_CTRL1); +} + +static int ddr_pcode_trainig_by_phy(struct ddr_cfg_st *cfg) +{ + unsigned int times = 0; + unsigned int base_phy = cfg->cur_phy; + unsigned int pcode_value; + unsigned int osc_rpt_vld; + unsigned int osc_cnt_rdata; + int ddr_freq; + + /* test start */ + ddr_write(ddr_read(base_phy + DDR_PHY_CORNER_DETECTOR) | PHY_OSC_START_MASK, + base_phy + DDR_PHY_CORNER_DETECTOR); + + do { + osc_rpt_vld = (ddr_read(base_phy + DDR_PHY_CORNER_DETECTOR) + >> PHY_OSC_RPT_VLD) & PHY_OSC_RPT_VLD_MASK; + times++; + } while ((!osc_rpt_vld) + && (times < DDRT_PCODE_WAIT_TIMEOUT)); + + if (times >= DDRT_PCODE_WAIT_TIMEOUT) { + DDR_FATAL("IO pcode training wait timeout."); + return -1; + } + + osc_cnt_rdata = (ddr_read(base_phy + DDR_PHY_CORNER_DETECTOR) + >> PHY_OSC_CNT_RDATA_BIT) + & PHY_OSC_CNT_RDATA_MASK; + + /* test stop */ + ddr_write(ddr_read(base_phy + DDR_PHY_CORNER_DETECTOR) + & (~PHY_OSC_START_MASK), base_phy + DDR_PHY_CORNER_DETECTOR); + + ddr_freq = ddr_get_cksel(); + /* get pcode value */ + pcode_value = (490960 - (89 * osc_cnt_rdata * ddr_freq) / 300) / 10000; + + DDR_DEBUG("pcode value[%x]", pcode_value); + if (pcode_value < PHY_PCODE_MIN) { + pcode_value = PHY_PCODE_MIN; + } else if (pcode_value > PHY_PCODE_MAX) { + pcode_value = PHY_PCODE_MAX; + } + + /* set pcode value */ + ddr_pcode_set_value(base_phy, pcode_value); + return 0; +} + +int ddr_pcode_training(struct ddr_cfg_st *cfg) +{ + struct tr_relate_reg relate_reg; + int result = 0; + int i; + + for (i = 0; i < cfg->phy_num; i++) { + cfg->phy_idx = i; + cfg->cur_phy = cfg->phy[i].addr; + cfg->cur_item = cfg->phy[i].rank[0].item; + + if (ddr_training_check_bypass(cfg, 1 << (cfg->phy_idx))) + continue; + + /* pcode training disable */ + if (ddr_training_check_bypass(cfg, DDR_BYPASS_PCODE_MASK)) + continue; + + ddr_training_save_reg(cfg, &relate_reg, DDR_BYPASS_PCODE_MASK); + result += ddr_pcode_trainig_by_phy(cfg); + ddr_training_restore_reg(cfg, &relate_reg); + } + + return result; +} +#else +int ddr_pcode_training(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR pcode training."); + return 0; +} +#endif diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.h new file mode 100755 index 00000000..a7f98e13 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_impl.h @@ -0,0 +1,449 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#ifndef DDR_TRAINING_IMPL_H +#define DDR_TRAINING_IMPL_H + +#ifndef __ASSEMBLY__ + +#include "ddr_training_custom.h" +#include "ddr_training_internal_config.h" +#include "ddr_interface.h" + +/****** special config define*******************************************/ +#ifdef DDR_DATAEYE_NORMAL_NOT_ADJ_CONFIG +/* Adjust dataeye window consume a lot of time, disable it will make boot + * faster. + * NOTE: The WDQ Phase and RDQS MUST be config a good value in the init table + * to avoid window trend to one side. + */ +#define DDR_DATAEYE_NORMAL_ADJUST (DDR_FALSE) +#else +#define DDR_DATAEYE_NORMAL_ADJUST (DDR_TRUE) +#endif +/* MUST adjust dataeye window after HW or MPR training */ +#define DDR_DATAEYE_ABNORMAL_ADJUST (DDR_TRUE) + +/****** ddr training item bypass mask define ****************************/ +#define DDR_BYPASS_PHY0_MASK 0x1 /* [0]PHY0 training */ +#define DDR_BYPASS_PHY1_MASK 0x2 /* [1]PHY1 training */ +#define DDR_BYPASS_WL_MASK 0x10 /* [4]Write leveling */ +#define DDR_BYPASS_GATE_MASK 0x100 /* [8]Gate training */ +#define DDR_BYPASS_DATAEYE_MASK 0x10000 /* [16]Dataeye training */ +#define DDR_BYPASS_PCODE_MASK 0x40000 /* [18]Pcode training */ +#define DDR_BYPASS_HW_MASK 0x100000 /* [20]Hardware read training */ +#define DDR_BYPASS_MPR_MASK 0x200000 /* [21]MPR training */ +#define DDR_BYPASS_AC_MASK 0x400000 /* [22]AC training */ +#define DDR_BYPASS_LPCA_MASK 0x800000 /* [23]LPDDR CA training */ +#define DDR_BYPASS_VREF_HOST_MASK 0x1000000 /* [24]Host Vref training */ +#define DDR_BYPASS_VREF_DRAM_MASK 0x2000000 /* [25]DRAM Vref training */ +#define DDR_BYPASS_DCC_MASK 0x08000000 /* [27]DCC training */ +#define DDR_BYPASS_DATAEYE_ADJ_MASK 0x10000000 /* [28]Dataeye adjust */ +#define DDR_BYPASS_WL_ADJ_MASK 0x20000000 /* [29]WL write adjust */ +#define DDR_BYPASS_HW_ADJ_MASK 0x40000000 /* [30]HW read adjust */ +#define DDR_BYPASS_ALL_MASK 0xffffffff /* all bypass */ + +/****** ddr read/write define **********************************************/ +unsigned int ddr_read(unsigned addr); +void ddr_write(unsigned val, unsigned addr); + +/****** common define **********************************************/ +/* special ddrt need special read and write register */ +#ifdef DDR_DDRT_SPECIAL_CONFIG +#define DDRT_REG_READ(addr) ddr_ddrt_read(addr) +#define DDRT_REG_WRITE(val, addr) ddr_ddrt_write(val, addr) +#else +#define DDRT_REG_READ(addr) ddr_read(addr) +#define DDRT_REG_WRITE(val, addr) ddr_write(val, addr) +#endif + +#define DDR_MODE_READ (1 << 0) +#define DDR_MODE_WRITE (1 << 1) + +#define DDR_ENTER_SREF (1 << 0) +#define DDR_EXIT_SREF (1 << 1) + +/* DSB to make sure the operation is complete */ +#ifndef DDR_ASM_DSB +#if (__LINUX_ARM_ARCH__ >= 8) +#define DDR_ASM_DSB() { __asm__ __volatile__("dsb sy"); } +#else +#define DDR_ASM_DSB() { __asm__ __volatile__("dsb"); } +#endif +#endif + +#define DDR_HWR_WAIT_TIMEOUT 0xffffffff +#define DDR_SFC_WAIT_TIMEOUT (1000) +#define DDR_LPCA_WAIT_TIMEOUT (1000) + +#ifdef CFG_EDA_VERIFY +#define DDR_AUTO_TIMING_DELAY (1) +#else +#define DDR_AUTO_TIMING_DELAY (1000) +#endif + +#define DDR_FIND_DQ_BOTH (1 << 0) /* find a valid value*/ +/* x is valid, (x-1) is invalid*/ +#define DDR_FIND_DQ_LEFT (1 << 1) +/* x is valid, (x+1) is invalid*/ +#define DDR_FIND_DQ_RIGHT (1 << 2) + +#define DDR_VREF_DRAM_VAL_MAX (0x32) /* 92.50%*VDDIO */ +#define DDR_VREF_DRAM_VAL_MIN (0x0) /* 60.00%*VDDIO */ + +#define DDR_PHY_REG_DQ_NUM 4 /* one register has 4 DQ BDL */ + +#define DDR_PHY_CA_MAX 10 +#define DDR_PHY_CA_REG_MAX (DDR_PHY_CA_MAX >> 1) + +#define DDR_TRUE 1 +#define DDR_FALSE 0 + +#define DDR_WIN_MIDDLE (1 << 0) +#define DDR_WIN_LEFT (1 << 1) +#define DDR_WIN_RIGHT (1 << 2) + +#define DDR_DELAY_PHASE 1 +#define DDR_DELAY_BDL 2 + +#ifndef DDR_DATAEYE_WIN_NUM +/* Dateeye window number. More bigger more slower when Vref training. */ +#define DDR_DATAEYE_WIN_NUM 8 +#endif +#ifndef DDR_LOOP_TIMES_LMT +/* Dataeye DQ deskew times for best result. More bigger more slower. */ +#define DDR_LOOP_TIMES_LMT 1 +#endif +#ifndef DDR_VREF_COMPARE_TIMES +/* Compare times when find best vref value. More bigger more slower. */ +#define DDR_VREF_COMPARE_TIMES 3 +#endif +#ifndef DDR_MPR_RDQS_FIND_TIMES +/* MPR Find first start rdqs times. More bigger, start rdqs more bigger. */ +#define DDR_MPR_RDQS_FIND_TIMES 3 +#endif +#ifndef DDR_VREF_COMPARE_STEP +/* Compare step when begin to find. More bigger, more mistake, more stable. */ +#define DDR_VREF_COMPARE_STEP 3 +#endif + +#define DDR_DATAEYE_RESULT_MASK 0xffff +#define DDR_DATAEYE_RESULT_BIT 16 + +#define DDR_WL_BDL_STEP 2 /* wl bdl step */ +#define DDR_GATE_BDL_STEP 2 /* gate bdl step */ +#define DDR_DQS_ADJ_STEP 1 /* WR/RD DQS adjust step */ + +#define DDR_DDRT_MODE_GATE (1 << 0) +#define DDR_DDRT_MODE_DATAEYE (1 << 1) + +#define DDR_CHECK_TYPE_DDRT (1 << 0) +#define DDR_CHECK_TYPE_MPR (1 << 1) + +#define DDR_MPR_BYTE_MASK 0xff +#define DDR_MPR_BIT_MASK 0x1 +#define DDR_MPR_BYTE_BIT 16 /* 16 bit (2 byte) */ + +#define DDR_PHY_AC_TEST_VAL0 0x0 +#define DDR_PHY_AC_TEST_VAL1 0xffffffff +#define DDR_PHY_AC_TEST_VAL2 0x55555555 +#define DDR_PHY_AC_TEST_VAL3 0xaaaaaaaa + +/*******log define ***********************************************/ +#if defined(DDR_TRAINING_CMD) && defined(DDR_TRAINING_LOG_CONFIG) +#define DDR_INFO(fmt...) ddr_training_log(__func__, DDR_LOG_INFO, fmt) +#define DDR_DEBUG(fmt...) ddr_training_log(__func__, DDR_LOG_DEBUG, fmt) +#define DDR_WARNING(fmt...) ddr_training_log(__func__, DDR_LOG_WARNING, fmt) +#define DDR_ERROR(fmt...) ddr_training_log(__func__, DDR_LOG_ERROR, fmt) +#define DDR_FATAL(fmt...) ddr_training_log(__func__, DDR_LOG_FATAL, fmt) +#else +#define DDR_INFO(fmt...) +#define DDR_DEBUG(fmt...) +#define DDR_WARNING(fmt...) +#define DDR_ERROR(fmt...) +#define DDR_FATAL(fmt...) +#endif /* DDR_TRAINING_CMD && DDR_TRAINING_LOG_CONFIG */ + +/* [11:0] Error type */ +/* 0x00000001 Write Leveling error */ +#define DDR_ERR_WL (1 << 0) +/* 0x00000002 Hardware Gatining error */ +#define DDR_ERR_HW_GATING (1 << 1) +/* 0x00000004 Sofeware Gatining error */ +#define DDR_ERR_GATING (1 << 2) +/* 0x00000008 DDRT test time out */ +#define DDR_ERR_DDRT_TIME_OUT (1 << 3) +/* 0x00000010 Hardware read dataeye error */ +#define DDR_ERR_HW_RD_DATAEYE (1 << 4) +/* 0x00000020 MPR error */ +#define DDR_ERR_MPR (1 << 5) +/* 0x00000040 Dataeye error */ +#define DDR_ERR_DATAEYE (1 << 6) +/* 0x00000080 LPDDR CA error */ +#define DDR_ERR_LPCA (1 << 7) + +/* [13:12] Error phy */ +/* 0x00001000 PHY0 training error */ +#define DDR_ERR_PHY0 (1 << 12) +/* 0x00002000 PHY1 training error */ +#define DDR_ERR_PHY1 (1 << 13) + +#define DDR_ERR_BYTE_BIT 24 /* [28:24] Error DQ0-31 */ +#define DDR_ERR_DQ_BIT 20 /* [22:20] Error Byte0-3 */ + +/*******data define*********************************************/ +#define GET_BYTE_NUM(cfg) (cfg->phy[cfg->phy_idx].dmc[cfg->dmc_idx].byte_num) + + +#ifndef DDR_RELATE_REG_DECLARE +struct tr_custom_reg { +}; +#endif + +struct dmc_cfg_sref_st { + unsigned int val[DDR_DMC_PER_PHY_MAX]; +}; + +struct ddr_bdl_st { + unsigned int bdl[DDR_PHY_BYTE_MAX]; +}; + +struct ddr_timing_st { + unsigned int val[DDR_DMC_PER_PHY_MAX]; +}; + +struct rdqs_data_st { + struct ddr_bdl_st origin; + struct ddr_bdl_st rank[DDR_RANK_NUM]; +}; + +struct ddr_delay_st { + unsigned int phase[DDR_PHY_BYTE_MAX]; + unsigned int bdl[DDR_PHY_BYTE_MAX]; +}; + +struct tr_relate_reg { + unsigned int auto_ref_timing; + unsigned int power_down; + unsigned int dmc_scramb; + unsigned int dmc_scramb_cfg; + unsigned int misc_scramb; + unsigned int ac_phy_ctl; + unsigned int swapdfibyte_en; + struct tr_custom_reg custom; + struct ddr_ddrc_data ddrc; +}; + +struct tr_dq_data { + unsigned int dq03[DDR_PHY_BYTE_MAX]; /* DQ0-DQ3 BDL */ + unsigned int dq47[DDR_PHY_BYTE_MAX]; /* DQ4-DQ7 BDL */ + unsigned int rdqs[DDR_PHY_BYTE_MAX]; /* RDQS */ + unsigned int rdm[DDR_PHY_BYTE_MAX]; /* RDM */ + unsigned int wdm[DDR_PHY_BYTE_MAX]; /* WDM */ +}; + +struct ca_bit_st { + unsigned int bit_p; + unsigned int bit_n; +}; + +struct ca_data_st { + unsigned int base_dmc; + unsigned int base_phy; + unsigned int done; /* whether all ca found bdl range */ + unsigned int min; /* min left bound */ + unsigned int max; /* max right bound */ + unsigned def[DDR_PHY_CA_REG_MAX]; + int left[DDR_PHY_CA_MAX]; + int right[DDR_PHY_CA_MAX]; + struct ca_bit_st bits[DDR_PHY_CA_MAX]; +}; + +struct ddr_dmc_st { + unsigned int addr; + unsigned int byte_num; + unsigned int ddrt_pattern; /* ddrt reversed data */ +}; + +struct ddr_rank_st { + unsigned int item; /* software training item */ + unsigned int item_hw; /* hardware training item */ +}; + +struct ddr_phy_st { + unsigned int addr; + unsigned int dram_type; + unsigned int dmc_num; + unsigned int rank_num; + unsigned int total_byte_num; + struct ddr_dmc_st dmc[DDR_DMC_PER_PHY_MAX]; + struct ddr_rank_st rank[DDR_RANK_NUM]; +}; + +struct ddr_cfg_st { + struct ddr_phy_st phy[DDR_PHY_NUM]; + unsigned int phy_num; + unsigned int cur_phy; /* current training phy addr */ + unsigned int cur_dmc; /* current training dmc addr */ + unsigned int cur_item; /* current SW or HW training item */ + unsigned int cur_pattern; /* current ddrt pattern */ + unsigned int cur_mode; /* read or write */ + unsigned int cur_byte; /* current training byte index */ + unsigned int cur_dq; /* current training dq index */ + unsigned int phy_idx; /* current training phy index */ + unsigned int rank_idx; /* current training rank index */ + unsigned int dmc_idx; /* current training dmc index */ + unsigned int adjust; /* whether need to adjust dataeye window */ + unsigned int dq_check_type; /* ddrt or mpr */ + void *cmd_st; /* struct ddr_cmd_st */ + void *res_st; /* SW: struct ddr_training_result_st, HW: struct rdqs_data_st */ +}; + +struct dcc_ck_st { + unsigned int val[DDR_CK_RESULT_MAX]; + unsigned int win; + unsigned int win_min_ctl; + unsigned int win_max_ctl; + unsigned int win_min_duty; + unsigned int win_max_duty; + unsigned int def_bp; + unsigned int def_ctl; + unsigned int def_duty; + unsigned int idx_duty; + unsigned int idx_duty_ctl; + unsigned int idx_ctl; + unsigned int BYPASS_CK_BIT; + unsigned int ACIOCTL21_CTL_BIT; + unsigned int ACIOCTL21_CK_BIT; +}; + +#ifdef DDR_DCC_TRAINING_CONFIG +struct dcc_data_st { + struct tr_dq_data rank[DDR_RANK_NUM]; + struct dcc_ck_st ck[DDR_CK_NUM]; + unsigned int item[DDR_CK_NUM]; + unsigned int ioctl21_tmp; +}; +#endif +/*******Uart early function ***********************************************/ +#ifndef DDR_PUTS +#define DDR_PUTS uart_early_puts +#endif +#ifndef DDR_PUT_HEX +#define DDR_PUT_HEX uart_early_put_hex +#endif +#ifndef DDR_PUTC +#define DDR_PUTC uart_early_putc +#endif + +#if defined(DDR_TRAINING_UART_CONFIG) || defined(DDR_TRAINING_LOG_CONFIG) +extern void uart_early_puts(const char *s); +extern void uart_early_put_hex(int hex); +extern void uart_early_putc(int chr); +#else +#undef DDR_PUTS +#undef DDR_PUT_HEX +#undef DDR_PUTC +#endif +/*******function interface define*********************************************/ +#ifndef DDR_SW_TRAINING_FUNC +#define DDR_SW_TRAINING_FUNC_PUBLIC +#define DDR_SW_TRAINING_FUNC ddr_sw_training_func +#endif + +#ifndef DDR_HW_TRAINING_FUNC +#define DDR_HW_TRAINING_FUNC_PUBLIC +#define DDR_HW_TRAINING_FUNC ddr_hw_training_func +#endif + +#ifndef DDR_PCODE_TRAINING_FUNC +#define DDR_PCODE_TRAINING_FUNC ddr_pcode_training_func +#endif + +#ifndef DDR_TRAINING_CONSOLE +#define DDR_TRAINING_CONSOLE_PUBLIC +#define DDR_TRAINING_CONSOLE ddr_training_console +#endif +/*******Custom function ***********************************************/ +#ifndef DDR_TRAINING_DDRT_PREPARE_FUNC +#define DDR_TRAINING_DDRT_PREPARE_FUNC() +#endif +#ifndef DDR_TRAINING_SAVE_REG_FUNC +#define DDR_TRAINING_SAVE_REG_FUNC(relate_reg, mask) +#endif +#ifndef DDR_TRAINING_RESTORE_REG_FUNC +#define DDR_TRAINING_RESTORE_REG_FUNC(relate_reg) +#endif +/*******function define*********************************************/ +int ddr_sw_training_func(void *ddrtr_result); +int ddr_training_boot_func(struct ddr_cfg_st *cfg); +int ddr_training_cmd_func(struct ddr_cfg_st *cfg); + +void* ddrtr_memset(void *b, int c, unsigned int len); +void* ddrtr_memcpy(void *dst, const void *src, unsigned int len); +void ddr_training_cfg_init(struct ddr_cfg_st *cfg); +int ddr_training_by_dmc(struct ddr_cfg_st *cfg); +int ddr_training_by_rank(struct ddr_cfg_st *cfg); +int ddr_training_by_phy(struct ddr_cfg_st *cfg); +int ddr_training_all(struct ddr_cfg_st *cfg); +int ddr_dataeye_training_func(struct ddr_cfg_st *cfg); +int ddr_vref_training_func(struct ddr_cfg_st *cfg); +int ddr_wl_func(struct ddr_cfg_st *cfg); +int ddr_gating_func(struct ddr_cfg_st *cfg); +int ddr_ac_training_func(struct ddr_cfg_st *cfg); +int ddr_lpca_training_func(struct ddr_cfg_st *cfg); +int ddr_dcc_training_func(struct ddr_cfg_st *cfg); + +void ddr_phy_cfg_update(unsigned int base_phy); +void ddr_phy_set_dq_bdl(struct ddr_cfg_st *cfg, unsigned int value); +int ddr_hw_training(struct ddr_cfg_st *cfg); +int ddr_pcode_training(struct ddr_cfg_st *cfg); + +int ddr_mpr_training(struct ddr_cfg_st *cfg); +int ddr_write_leveling(struct ddr_cfg_st *cfg); +int ddr_gate_training(struct ddr_cfg_st *cfg); +int ddr_dataeye_training(struct ddr_cfg_st *cfg); +int ddr_vref_training(struct ddr_cfg_st *cfg); +int ddr_ac_training(struct ddr_cfg_st *cfg); +int ddr_lpca_training(struct ddr_cfg_st *cfg); +int ddr_dataeye_deskew(struct ddr_cfg_st *cfg, struct training_data *training); +void ddr_adjust_dataeye(struct ddr_cfg_st *cfg, struct training_data *training); +void ddr_result_data_save(struct ddr_cfg_st *cfg, struct training_data *training); +void ddr_lpca_data_save(struct ca_data_st *data); +unsigned int ddr_ddrt_get_test_addr(void); +int ddr_ddrt_test(unsigned int mask, int byte, int dq); +int ddr_dataeye_check_dq(struct ddr_cfg_st *cfg); +void ddr_ddrt_init(struct ddr_cfg_st *cfg, unsigned int mode); +int ddr_training_check_bypass(struct ddr_cfg_st *cfg, unsigned int mask); +int ddr_training_phy_disable(int index); +void ddr_training_save_reg(struct ddr_cfg_st *cfg, struct tr_relate_reg *relate_reg, + unsigned int mask); +void ddr_training_restore_reg(struct ddr_cfg_st *cfg, struct tr_relate_reg *relate_reg); +void ddr_training_get_base(int index, unsigned int *base_dmc, + unsigned int *base_phy); +void ddr_training_switch_axi(struct ddr_cfg_st *cfg); +void ddr_training_log(const char *func, int level, const char *fmt, ...); +void ddr_training_stat(unsigned int mask, unsigned int phy, int byte, int dq); +void ddr_training_error(unsigned int mask, unsigned int phy, int byte, int dq); +void ddr_training_start(void); +void ddr_training_suc(void); +unsigned int ddr_phy_get_byte_num(unsigned int base_dmc); +void ddr_training_set_timing(unsigned int base_dmc, unsigned int timing); +int ddr_hw_dataeye_read(struct ddr_cfg_st *cfg); + +#ifdef DDR_MPR_TRAINING_CONFIG +int ddr_mpr_training_func(struct ddr_cfg_st *cfg); +int ddr_mpr_check(struct ddr_cfg_st *cfg); +#else +static inline int ddr_mpr_training_func(struct ddr_cfg_st *cfg) +{ + DDR_WARNING("Not support DDR MPR training."); + return 0; +} +static inline int ddr_mpr_check(struct ddr_cfg_st *cfg) { return 0;} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* DDR_TRAINING_IMPL_H */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_internal_config.h b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_internal_config.h new file mode 100755 index 00000000..5d30c559 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/drv/ddr_training_internal_config.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * + * ddr_training_internal_config.h + * + */ + +#ifndef DDR_TRAINING_INTERNAL_CONFIG_H +#define DDR_TRAINING_INTERNAL_CONFIG_H + +/****** include ddrc,phy,dmc define files *******************/ +#if defined(DDR_DDRC_V500_CONFIG) +#include "ddr_ddrc_v500.h" +#elif defined(DDR_DDRC_V510_CONFIG) +#include "ddr_ddrc_v510.h" +#elif defined(DDR_DDRC_V520_CONFIG) +#include "ddr_ddrc_v520.h" +#else +# error Unknown DDRC Type +#endif + +#if defined(DDR_PHY_S40_CONFIG) +#include "ddr_phy_s40.h" +#elif defined(DDR_PHY_T28_CONFIG) +#include "ddr_phy_t28.h" +#elif defined(DDR_PHY_T16_CONFIG) +#include "ddr_phy_t16.h" +#elif defined(DDR_PHY_T12_V100_CONFIG) +#include "ddr_phy_t12_v100.h" +#elif defined(DDR_PHY_T12_V101_CONFIG) +#include "ddr_phy_t12_v101.h" +#else +# error Unknown DDR PHY Type +#endif + +#if defined(DDR_DDRT_S40_CONFIG) +#include "ddr_ddrt_s40.h" +#elif defined(DDR_DDRT_T28_CONFIG) +#include "ddr_ddrt_t28.h" +#elif defined(DDR_DDRT_T16_CONFIG) +#include "ddr_ddrt_t16.h" +#elif defined(DDR_DDRT_T12_V100_CONFIG) +#include "ddr_ddrt_t12_v100.h" +#elif defined(DDR_DDRT_V2_0_SHF0_CONFIG) +#include "ddr_ddrt_v2_0_shf0.h" +#elif defined(DDR_DDRT_V2_0_SHF1_CONFIG) +#include "ddr_ddrt_v2_0_shf1.h" +#elif defined(DDR_DDRT_V2_0_SHF2_CONFIG) +#include "ddr_ddrt_v2_0_shf2.h" +#else +# error Unknown DDR PHY Type +#endif + + +/****** training item define *******************/ +/* enable all config by default */ +#define DDR_WL_TRAINING_CONFIG +#define DDR_GATE_TRAINING_CONFIG +#define DDR_DATAEYE_TRAINING_CONFIG +#define DDR_HW_TRAINING_CONFIG +#define DDR_TRAINING_ADJUST_CONFIG +#define DDR_TRAINING_LOG_CONFIG +#define DDR_TRAINING_UART_CONFIG +#define DDR_TRAINING_STAT_CONFIG + +/* defined in ddr_training_custom.h to disable this item */ +#ifdef DDR_VREF_TRAINING_DISABLE +#undef DDR_VREF_TRAINING_CONFIG +#endif + +#ifdef DDR_WL_TRAINING_DISABLE +#undef DDR_WL_TRAINING_CONFIG +#endif + +#ifdef DDR_GATE_TRAINING_DISABLE +#undef DDR_GATE_TRAINING_CONFIG +#endif + +#ifdef DDR_DATAEYE_TRAINING_DISABLE +#undef DDR_DATAEYE_TRAINING_CONFIG +#endif + +#ifdef DDR_HW_TRAINING_DISABLE +#undef DDR_HW_TRAINING_CONFIG +#endif + +#ifdef DDR_MPR_TRAINING_DISABLE +#undef DDR_MPR_TRAINING_CONFIG +#endif + +#ifdef DDR_TRAINING_ADJUST_DISABLE +#undef DDR_TRAINING_ADJUST_CONFIG +#endif + +#ifdef DDR_TRAINING_LOG_DISABLE +#undef DDR_TRAINING_LOG_CONFIG +#endif + +#ifdef DDR_TRAINING_UART_DISABLE +#undef DDR_TRAINING_UART_CONFIG +#endif + +#ifdef DDR_TRAINING_STAT_DISABLE +#undef DDR_TRAINING_STAT_CONFIG +#endif + +/* for training cmd */ +#ifdef DDR_TRAINING_CMD + /* defined in ddr_training_custom.h to disable this item */ + #ifdef DDR_VREF_TRAINING_CMD_DISABLE + #undef DDR_VREF_TRAINING_CONFIG + #endif + + #ifdef DDR_WL_TRAINING_CMD_DISABLE + #undef DDR_WL_TRAINING_CONFIG + #endif + + #ifdef DDR_GATE_TRAINING_CMD_DISABLE + #undef DDR_GATE_TRAINING_CONFIG + #endif + + #ifdef DDR_DATAEYE_TRAINING_CMD_DISABLE + #undef DDR_DATAEYE_TRAINING_CONFIG + #endif + + #ifdef DDR_HW_TRAINING_CMD_DISABLE + #undef DDR_HW_TRAINING_CONFIG + #endif + + #ifdef DDR_MPR_TRAINING_CMD_DISABLE + #undef DDR_MPR_TRAINING_CONFIG + #endif + + #ifdef DDR_TRAINING_ADJUST_CMD_DISABLE + #undef DDR_TRAINING_ADJUST_CONFIG + #endif + + #ifdef DDR_TRAINING_LOG_CMD_DISABLE + #undef DDR_TRAINING_LOG_CONFIG + #endif +#endif /* DDR_TRAINING_CMD */ + +/* check config */ +#if defined(DDR_TRAINING_ADJUST_DISABLE) && defined(DDR_HW_TRAINING_CONFIG) \ + && !defined(DDR_HW_READ_ADJ_CONFIG) +#error when defined DDR_TRAINING_ADJUST_DISABLE, \ + MUST define DDR_HW_READ_ADJ_CONFIG. +#endif + +#if (defined(DDR_HW_TRAINING_CONFIG) || defined(DDR_MPR_TRAINING_CONFIG) \ + || defined(DDR_VREF_TRAINING_CONFIG) \ + || defined(DDR_TRAINING_ADJUST_CONFIG)) \ + && !defined(DDR_DATAEYE_TRAINING_CONFIG) +#error when enable HW/GATE/VREF training or dataeye adjust, \ + MUST define DDR_DATAEYE_TRAINING_CONFIG. +#endif + +/* reserve config */ +/* DDR_WL_DATAEYE_ADJUST_CONFIG: Adjust WDQ phase/bdl after WL training. */ +/* DDR_VREF_TRAINING_CONFIG : DDR Vref training. */ +/* DDR_MPR_TRAINING_CONFIG : DDR MPR training. */ +/* DDR_AC_TRAINING_CONFIG : DDR AC training. */ +/* DDR_LPCA_TRAINING_CONFIG : LPDDR CA training. */ +/* DDR_DDRT_SPECIAL_CONFIG : DDRT read and write special operate. */ +/* DDR_DDR4_CONFIG : DDR4 special operate. */ +/* DDR_TRAINING_CUT_CODE_CONFIG: Cut code for small SRAM. */ +/* DDR_TRAINING_MINI_LOG_CONFIG: Less code to log */ +/* DDR_HW_READ_ADJ_CONFIG : Adjust read dataeye after hw read training */ +/* DDR_VREF_WITHOUT_BDL_CONFIG : Vref not modify DQ bdl */ +/* DDR_DATAEYE_NORMAL_NOT_ADJ_CONFIG : Do not adjust window on normal case */ + +#endif /* DDR_TRAINING_INTERNAL_CONFIG_H */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/asm/sizes.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/asm/sizes.h new file mode 100755 index 00000000..f8d92ca1 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/asm/sizes.h @@ -0,0 +1,52 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* DO NOT EDIT!! - this file automatically generated + * from .s file by awk -f s2h.awk + */ +/* Size defintions + * Copyright (C) ARM Limited 1998. All rights reserved. + */ + +#ifndef __sizes_h +#define __sizes_h 1 + +/* handy sizes */ +#define SZ_1K 0x00000400 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + +#endif + +/* END */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/barriers.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/barriers.h new file mode 100755 index 00000000..04784b7c --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/barriers.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 ARM Ltd. + * + * ARM and ARM64 barrier instructions + * split from armv7.h to allow sharing between ARM and ARM64 + * + * Original copyright in armv7.h was: + * (C) Copyright 2010 Texas Instruments, Aneesh V + * + * Much of the original barrier code was contributed by: + * Valentine Barshak + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef __BARRIERS_H__ +#define __BARRIERS_H__ + +#ifndef __ASSEMBLY__ + +#ifndef CONFIG_ARM64 +/* + * CP15 Barrier instructions + * Please note that we have separate barrier instructions in ARMv7 + * However, we use the CP15 based instructtions because we use + * -march=armv5 in U-Boot + */ +#define CP15ISB asm volatile ("mcr p15, 0, %0, c7, c5, 4" : : "r" (0)) +#define CP15DSB asm volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)) +#define CP15DMB asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0)) + +#endif /* !CONFIG_ARM64 */ + +#if __LINUX_ARM_ARCH__ >= 7 +#define ISB asm volatile ("isb sy" : : : "memory") +#define DSB asm volatile ("dsb sy" : : : "memory") +#define DMB asm volatile ("dmb sy" : : : "memory") +#elif __LINUX_ARM_ARCH__ == 6 +#define ISB CP15ISB +#define DSB CP15DSB +#define DMB CP15DMB +#else +#define ISB asm volatile ("" : : : "memory") +#define DSB CP15DSB +#define DMB asm volatile ("" : : : "memory") +#endif + +#define isb() ISB +#define dsb() DSB +#define dmb() DMB +#endif /* __ASSEMBLY__ */ +#endif /* __BARRIERS_H__ */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/common.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/common.h new file mode 100755 index 00000000..b35f7f32 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/common.h @@ -0,0 +1,51 @@ +#ifndef __COMMON_H_ +#define __COMMON_H_ +#include "types.h" +/*----------------------------------------------------------------- + * set cpu mode interface +------------------------------------------------------------------*/ +void set_mod_normal(); +void set_mod_slow(); + +/*----------------------------------------------------------------- + * serial interface +------------------------------------------------------------------*/ +int serial_init (); +int serial_deinit(); +void serial_putc (const char c); +void serial_putchar (const char c); +void serial_puts (const char *s); +void serial_flush(); +int serial_getc (void); +int serial_tstc (void); + +/*----------------------------------------------------------------- + * mmc interface +------------------------------------------------------------------*/ +int mmc_init(); +void mmc_deinit(); +size_t mmc_read(void *ptr, size_t size); + + +/*----------------------------------------------------------------- + * timer interface +------------------------------------------------------------------*/ +int timer_init(); +void timer_deinit(); +void timer_start(); +unsigned long timer_get_val(); +unsigned long timer_get_divider(); + +/*----------------------------------------------------------------- + * I cache interface +------------------------------------------------------------------*/ +void open_I_cache(); +void close_I_cache(); + +/*----------------------------------------------------------------- + * mem operation interface +------------------------------------------------------------------*/ +void* memset(void * s,int c,size_t count); +void* memcpy(void * dest,const void *src,size_t count); + +#endif /*__COMMON_H_*/ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/io.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/io.h new file mode 100755 index 00000000..461ed7d3 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/io.h @@ -0,0 +1,17 @@ +#ifndef __ASM_ARM_IO_H +#define __ASM_ARM_IO_H + +#include +#include + +#define __arch_getl(a) (*(volatile unsigned int *)(a)) +#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) + +#define mb() dsb() +#define __iormb() dmb() +#define __iowmb() dmb() + +#define writel(v,c) ({ u32 __v = v; __iowmb(); __arch_putl(__v,c); __v; }) +#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; }) + +#endif /* __ASM_ARM_IO_H */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/linux/ctype.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/linux/ctype.h new file mode 100755 index 00000000..afa36392 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/linux/ctype.h @@ -0,0 +1,54 @@ +#ifndef _LINUX_CTYPE_H +#define _LINUX_CTYPE_H + +/* + * NOTE! This ctype does not handle EOF like the standard C + * library is required to. + */ + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +extern unsigned char _ctype[]; + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isdigit(c) ((__ismask(c)&(_D)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char __tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + +#endif diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/platform.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/platform.h new file mode 100755 index 00000000..bacecbf7 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/platform.h @@ -0,0 +1,50 @@ +#ifndef __HI_CHIP_REGS_H__ +#define __HI_CHIP_REGS_H__ + +//#define CONFIG_DDR_TRAINING_V2 + +#define BIT(nr) (1 << (nr)) + +#define RAM_START_ADRS 0x04010500 +#define STACK_TRAINING 0x04018000 + +#define DDR_DDRT_REG_BASE 0x11330000 +#define TIMER0_REG_BASE 0x12000000 +#define TIMER1_REG_BASE 0x12000020 +#define TIMER2_REG_BASE 0x12001000 +#define TIMER3_REG_BASE 0x12001020 +#define REG_TIMER_RELOAD 0x0 +#define REG_TIMER_VALUE 0x4 +#define REG_TIMER_CONTROL 0x8 + +#define CRG_REG_BASE 0x12010000 + +#define SYS_CTRL_REG_BASE 0x12020000 +#define REG_BASE_SCTL SYS_CTRL_REG_BASE +#define REG_SC_CTRL 0 +#define REMAPCLEAR BIT(8) +#define REMAPCLEAR_SHIFT 8 +#define TIME0_CLK_SEL BIT(16) +#define TIME0_CLK_SEL_SHIFT 16 +#define TIME0_CLK_SEL_3M 0x0 +#define TIME0_CLK_SEL_APB 0x1 + +#define REG_SC_SYSRES 0x4 +#define REG_SYSSTAT 0x008C +#define REG_SC_GEN0 0x0138 +#define REG_SC_GEN1 0x013c +#define REG_SC_GEN2 0x0140 +#define REG_SC_GEN3 0x0144 +#define REG_SC_GEN4 0x0148 +#define REG_SC_GEN5 0x014c +#define REG_SC_GEN7 0x0154 + +#define MISC_REG_BASE 0x12028000 +#define DDRC0_REG_BASE 0x11330000 +#define UART0_REG_BASE 0x12040000 +#define FMC_MEM_BASE 0x14000000 +#define DDR_MEM_BASE 0x40000000 + +#define _HI3516EV200 (0x003516e200LL) +#define _HI3516EV200_MASK (0xFFFFFFFFFFLL) +#endif /* End of __HI_CHIP_REGS_H__ */ diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/include/types.h b/hispark_aries/uboot/secureboot_release/ddr_init/include/types.h new file mode 100755 index 00000000..e5ffd355 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/include/types.h @@ -0,0 +1,73 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +typedef unsigned int size_t; +typedef int ptrdiff_t; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ +typedef u32 dma_addr_t; + +#undef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *)0) +#endif + + +typedef s8 INT8; +typedef s16 INT16; +typedef s32 INT32; + +typedef u8 UINT8; +typedef u16 UINT16; +typedef u32 UINT32; + +typedef int BOOL; +typedef int STATUS; + +#define TRUE 1 +#define FALSE 0 + +#define ERROR -1 +#define OK 0 + +#define FOREVER while(1) +#define IN +#define OUT + +#define PRIVATE static + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef long int64_t; +typedef unsigned long uint64_t; + +typedef unsigned char u_char; +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; + +#endif + diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds b/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds new file mode 100755 index 00000000..f122fb2d --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + boot/start.o (.text) + boot/uart.o (.text) + boot/init_regs.o (.text) + boot/lowlevel_init_v300.o (.text) + drv/ddr_training_impl.o (.text) + drv/ddr_training_ctl.o (.text) + drv/ddr_training_boot.o (.text) + drv/ddr_training_custom.o (.text) + *(.text) + } + . = ALIGN(4); + .data : { *(.data) } + + .rodata : + { + *(.rodata) + *(.version) + } + . = 0x04010000; + __bss_start = .; + .bss : { *(.bss) } + + _end = .; +} diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds.mk b/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds.mk new file mode 100755 index 00000000..1ea7754c --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/linker.lds.mk @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + boot/start.o (.text) + boot/uart.o (.text) + boot/init_regs.o (.text) + boot/lowlevel_init_v300.o (.text) + drv/ddr_training_impl.o (.text) + drv/ddr_training_ctl.o (.text) + drv/ddr_training_boot.o (.text) + drv/ddr_training_custom.o (.text) + *(.text) + } + . = ALIGN(4); + .data : { *(.data) } + + .rodata : + { + *(.rodata) + *(.version) + } + . = RAM_BASE; + __bss_start = .; + .bss : { *(.bss) } + + _end = .; +} diff --git a/hispark_aries/uboot/secureboot_release/ddr_init/mkddrinit.sh b/hispark_aries/uboot/secureboot_release/ddr_init/mkddrinit.sh new file mode 100755 index 00000000..e4b893ba --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/ddr_init/mkddrinit.sh @@ -0,0 +1,25 @@ +#! /bin/sh + +[ -n "$1" ] || { + echo ""; + echo "usage:"; + echo " mkddrinit.sh "; + echo " e.g." + echo " mkddrinit.sh u-boot.bin"; + echo ""; + exit 1; +} + +if [ -f ../$1 ]; then + echo "get reginfo.bin from $1..." +else + echo "no $1!!!" + exit +fi +dd if=../$1 of=./fb4 bs=1 count=8192 skip=64 +dd if=./ddr_init.bin of=./fb1 bs=1 count=64 +dd if=./fb4 of=./fb2 bs=8192 conv=sync +dd if=./ddr_init.bin of=./fb3 bs=1 skip=8256 +cat fb1 fb2 fb3 > ddr_init_reg_info.bin +rm -f fb1 fb2 fb3 fb4 + diff --git a/hispark_aries/uboot/secureboot_release/hash_modify.c b/hispark_aries/uboot/secureboot_release/hash_modify.c new file mode 100755 index 00000000..f77af502 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/hash_modify.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int i,j; + char buffer[0x100]; + unsigned int buf[32]; + int *tmp = buf; + FILE *fp1 = NULL; + char *input_file = argv[1]; + + printf("==================================================================================\n"); + if (argc != 2) { + printf("input err!!!!!!!!!!!!!!!! \n"); + printf("usage: %s filename\n",argv[0]); + exit(-1); + } + printf("input_file:%s\n",input_file); + + fp1 = fopen(input_file, "r"); + if (fp1 == NULL) { + printf("open file failed!\n"); + return -1; + } + + sprintf(buffer,"cat %s",input_file); + printf("%s\n",buffer); + printf("==================================================================================\n"); + system(buffer); + printf("==================================================================================\n"); + + fscanf(fp1,"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + tmp + 0, tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5, tmp + 6, tmp + 7, tmp + 8, tmp + 9, tmp + 10, tmp + 11, + tmp + 12, tmp + 13, tmp + 14, tmp + 15); + tmp += 16; + + fscanf(fp1,"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + tmp + 0, tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5, tmp + 6, tmp + 7, tmp + 8, tmp + 9, tmp + 10, tmp + 11, + tmp + 12, tmp + 13, tmp + 14, tmp + 15); + printf("==================================================================================\n"); + printf("SHA256:\n"); + for (i = 0; i < 32; i++) + printf("%02x", buf[i]); + printf("\n"); + printf("==================================================================================\n"); + + printf("==================================================================================\n"); + printf("REG VALUE:\n"); + for (i = 0; i < 8; i++) { + for (j = 3; j >= 0; j--) { + if (j == 3) + printf("rootkey_hash[%0d]=mw 0x100900%02x 0x", i, (i * 4) + 0xc); + printf("%02x", buf[i * 4 + j]); + if (j == 0) + printf("\n"); + } + } + printf("==================================================================================\n"); + + fclose(fp1); + return 0; +} + diff --git a/hispark_aries/uboot/secureboot_release/rsa2048pem.sh b/hispark_aries/uboot/secureboot_release/rsa2048pem.sh new file mode 100755 index 00000000..68f852c0 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/rsa2048pem.sh @@ -0,0 +1,15 @@ +#! /bin/sh + + +echo "======================================================================================" +echo "| rsa2048pem |" +echo "======================================================================================" +# generate rsa pub key and private key +if [ -f rsa2048pem/rsa_pub_2048_sha256.txt ]; then + echo "use old rsa2048pem/rsa_pub.bin rsa2048pem/rsa_pub_2048_sha256.txt" + ./HASH rsa2048pem/rsa_pub_2048_sha256.txt +else + echo "gen new rsa2048pem/rsa_pub.bin rsa2048pem/rsa_pub_2048_sha256.txt" + openssl genrsa -out rsa2048pem/rsa_priv_2048.pem 2048 + openssl rsa -in rsa2048pem/rsa_priv_2048.pem -pubout -out rsa2048pem/rsa_pub_2048.pem +fi diff --git a/hispark_aries/uboot/secureboot_release/rsa2048pem/ReadMe.txt b/hispark_aries/uboot/secureboot_release/rsa2048pem/ReadMe.txt new file mode 100755 index 00000000..baa41438 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/rsa2048pem/ReadMe.txt @@ -0,0 +1 @@ +Temp dir for compile \ No newline at end of file diff --git a/hispark_aries/uboot/secureboot_release/rsa4096pem.sh b/hispark_aries/uboot/secureboot_release/rsa4096pem.sh new file mode 100755 index 00000000..08fc325c --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/rsa4096pem.sh @@ -0,0 +1,15 @@ +#! /bin/sh + + +echo "======================================================================================" +echo "| rsa4096pem |" +echo "======================================================================================" +# generate rsa pub key and private key +if [ -f rsa4096pem/rsa_pub_4096_sha256.txt ]; then + echo "use old rsa4096pem/rsa_pub.bin rsa4096pem/rsa_pub_4096_sha256.txt" + ./HASH rsa4096pem/rsa_pub_4096_sha256.txt +else + echo "gen new rsa4096pem/rsa_pub.bin rsa4096pem/rsa_pub_4096_sha256.txt" + openssl genrsa -out rsa4096pem/rsa_priv_4096.pem 4096 + openssl rsa -in rsa4096pem/rsa_priv_4096.pem -pubout -out rsa4096pem/rsa_pub_4096.pem +fi diff --git a/hispark_aries/uboot/secureboot_release/rsa4096pem/ReadMe.txt b/hispark_aries/uboot/secureboot_release/rsa4096pem/ReadMe.txt new file mode 100755 index 00000000..baa41438 --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/rsa4096pem/ReadMe.txt @@ -0,0 +1 @@ +Temp dir for compile \ No newline at end of file diff --git a/hispark_aries/uboot/secureboot_release/sha256.cfg b/hispark_aries/uboot/secureboot_release/sha256.cfg new file mode 100755 index 00000000..96e040ba --- /dev/null +++ b/hispark_aries/uboot/secureboot_release/sha256.cfg @@ -0,0 +1,2 @@ +#The valid Algorithm is AES, TDES, HiCRC16, SHA1, SHA256, RSA +Algorithm=SHA256 diff --git a/hispark_taurus/liteos_a/BUILD.gn b/hispark_taurus/liteos_a/BUILD.gn index 8de91a3d..1320af2b 100755 --- a/hispark_taurus/liteos_a/BUILD.gn +++ b/hispark_taurus/liteos_a/BUILD.gn @@ -6,7 +6,7 @@ HAVE_PRODUCT_CONFIG = group("liteos_a") { deps = [ - "//device/soc/hisilicon/hi3516dv300/sdk_liteos/board", + "board", "drivers", "//device/soc/hisilicon/hi3516dv300/sdk_liteos/mpp/module_init", ] @@ -19,7 +19,7 @@ group("liteos_a") { config("public") { configs = [ - "//device/soc/hisilicon/hi3516dv300/sdk_liteos/board:public", + "board:public", "drivers:public", ] } diff --git a/hispark_taurus/liteos_a/board/BUILD.gn b/hispark_taurus/liteos_a/board/BUILD.gn new file mode 100755 index 00000000..01500fcd --- /dev/null +++ b/hispark_taurus/liteos_a/board/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//kernel/liteos_a/liteos.gni") + +module_name = "bsp_config" + +kernel_module(module_name) { + if (defined(LOSCFG_DEBUG_VERSION)) { + libs = [ "libs/debug/libbsp_config.a" ] + } else { + libs = [ "libs/release/libbsp_config.a" ] + } + sources = [ + "board.c", + ] +} + +config("public") { + include_dirs = [ "." ] + include_dirs += [ "include" ] +} diff --git a/hispark_taurus/liteos_a/board/LICENSE b/hispark_taurus/liteos_a/board/LICENSE new file mode 100755 index 00000000..4a459866 --- /dev/null +++ b/hispark_taurus/liteos_a/board/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/hispark_taurus/liteos_a/board/Makefile b/hispark_taurus/liteos_a/board/Makefile new file mode 100755 index 00000000..61f39599 --- /dev/null +++ b/hispark_taurus/liteos_a/board/Makefile @@ -0,0 +1,27 @@ +# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(LITEOSTOPDIR)/config.mk + +MODULE_NAME := bsp_config + +ifeq ($(LOSCFG_DEBUG_VERSION),y) + RELEASE_TYPE := debug +else + RELEASE_TYPE := release +endif + +LOCAL_SRCS := board.c +ARFLAGS = r $$(cp libs/$(RELEASE_TYPE)/lib$(MODULE_NAME).a $@) + +include $(MODULE) diff --git a/hispark_taurus/liteos_a/board/board.c b/hispark_taurus/liteos_a/board/board.c new file mode 100755 index 00000000..4af7177c --- /dev/null +++ b/hispark_taurus/liteos_a/board/board.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_config.h" +#include "gic_common.h" +#include "los_printf.h" +#include "los_smp.h" +#include "los_vm_map.h" +#include "los_vm_zone.h" +#include "los_vm_boot.h" +#include "los_mmu_descriptor_v6.h" +#include "los_init.h" + +#ifdef LOSCFG_KERNEL_SMP +#define BOOTROM_PHYS_BASE 0 +#define BOOTROM_VIRT_BASE (PERIPH_UNCACHED_BASE + PERIPH_UNCACHED_SIZE) +#define BOOTROM_MEM_SIZE 0x100000 + +/* The startEntry is physical addr. */ +STATIC VOID bootaddr_setup(UINTPTR startEntry) +{ + UINTPTR *startAddrBae = (UINTPTR *)BOOTROM_VIRT_BASE; + + /* + * 0xe51ff004 = "ldr pc, [pc, #-4]" + * next addr value will be the real booting addr + */ + *startAddrBae = 0xe51ff004; + startAddrBae++; + *startAddrBae = startEntry; + + DCacheInvRange(BOOTROM_VIRT_BASE, BOOTROM_VIRT_BASE + 8); +} + +#ifdef LOSCFG_TEE_ENABLE +#define TSP_CPU_ON 0xb2000011UL +STATIC INT32 raw_smc_send(UINT32 cmd) +{ + register UINT32 smc_id asm("r0") = cmd; + do { + asm volatile ( + "mov r0, %[a0]\n" + "smc #0\n" + : [a0] "+r"(smc_id) + ); + } while (0); + + return (INT32)smc_id; +} + +STATIC VOID trigger_secondary_cpu(VOID) +{ + (VOID)raw_smc_send(TSP_CPU_ON); +} + +LITE_OS_SEC_TEXT_INIT INT32 release_secondary_cores(UINT32 cpuNum, UINTPTR startEntry) +{ + PRINT_RELEASE("releasing %u secondary cores\n", cpuNum); + + bootaddr_setup(startEntry); + + trigger_secondary_cpu(); + + return 0; +} +#else +#define CLEAR_RESET_REG_STATUS(regval) (regval) &= ~(1U << 2) +LITE_OS_SEC_TEXT_INIT INT32 release_secondary_cores(UINT32 cpuNum, UINTPTR startEntry) +{ + UINT32 regval; + + PRINT_RELEASE("releasing %u secondary cores\n", cpuNum); + + bootaddr_setup(startEntry); + + /* clear the second cpu reset status */ + READ_UINT32(regval, PERI_CRG30_BASE); + CLEAR_RESET_REG_STATUS(regval); + WRITE_UINT32(regval, PERI_CRG30_BASE); + + return 0; +} +#endif /* LOSCFG_TEE_ENABLE */ + +STATIC struct SmpOps g_hisiSmpOps = { + .SmpCpuOn = release_secondary_cores, +}; + +STATIC VOID HisiSmpInit(VOID) +{ + LOS_SmpOpsSet(&g_hisiSmpOps); +} + +LOS_MODULE_INIT(HisiSmpInit, LOS_INIT_LEVEL_EARLIEST); +#endif /* LOSCFG_KERNEL_SMP */ + +#ifdef LOSCFG_KERNEL_MMU +LosArchMmuInitMapping g_archMmuInitMapping[] = { + { + .phys = SYS_MEM_BASE, + .virt = KERNEL_VMM_BASE, + .size = KERNEL_VMM_SIZE, + .flags = MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS, + .name = "KernelCached", + }, + { + .phys = SYS_MEM_BASE, + .virt = UNCACHED_VMM_BASE, + .size = UNCACHED_VMM_SIZE, + .flags = MMU_INITIAL_MAP_NORMAL_NOCACHE, + .name = "KernelUncached", + }, + { + .phys = PERIPH_PMM_BASE, + .virt = PERIPH_DEVICE_BASE, + .size = PERIPH_DEVICE_SIZE, + .flags = MMU_INITIAL_MAP_DEVICE, + .name = "PeriphDevice", + }, + { + .phys = PERIPH_PMM_BASE, + .virt = PERIPH_CACHED_BASE, + .size = PERIPH_CACHED_SIZE, + .flags = MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS, + .name = "PeriphCached", + }, + { + .phys = PERIPH_PMM_BASE, + .virt = PERIPH_UNCACHED_BASE, + .size = PERIPH_UNCACHED_SIZE, + .flags = MMU_INITIAL_MAP_STRONGLY_ORDERED, + .name = "PeriphStronglyOrdered", + }, +#ifdef LOSCFG_KERNEL_SMP + { + .phys = BOOTROM_PHYS_BASE, + .virt = BOOTROM_VIRT_BASE, + .size = BOOTROM_MEM_SIZE, + .flags = MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS, + .name = "BootRom", + }, +#endif + {0} +}; +#endif + diff --git a/hispark_taurus/liteos_a/board/include/asm/dma.h b/hispark_taurus/liteos_a/board/include/asm/dma.h new file mode 100755 index 00000000..974c69a5 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/asm/dma.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DMA_H +#define __DMA_H + +#include "los_hw.h" + +#endif /* __DMA_H */ + diff --git a/hispark_taurus/liteos_a/board/include/asm/hal_platform_ints.h b/hispark_taurus/liteos_a/board/include/asm/hal_platform_ints.h new file mode 100755 index 00000000..72515bd9 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/asm/hal_platform_ints.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PLATFORM_HAL_PLATFORM_INTS_H +#define PLATFORM_HAL_PLATFORM_INTS_H + +#include"los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * Maximum number of supported hardware devices that generate hardware interrupts. + * The maximum number of hardware devices that generate hardware interrupts is 128. + */ +#define OS_HWI_MAX_NUM 128 + +/** + * Maximum interrupt number. + */ + +#define OS_HWI_MAX ((OS_HWI_MAX_NUM) - 1) + +/** + * Minimum interrupt number. + */ + +#define OS_HWI_MIN 0 + +/** + * Maximum usable interrupt number. + */ + +#define OS_USER_HWI_MAX OS_HWI_MAX + +/** + * Minimum usable interrupt number. + */ + +#define OS_USER_HWI_MIN OS_HWI_MIN + +#define NUM_HAL_INTERRUPT_CNTPSIRQ 29 +#define NUM_HAL_INTERRUPT_CNTPNSIRQ 30 +#ifdef LOSCFG_TEE_ENABLE +#define OS_TICK_INT_NUM NUM_HAL_INTERRUPT_CNTPNSIRQ // use non-secure physical timer for now +#else +#define OS_TICK_INT_NUM NUM_HAL_INTERRUPT_CNTPSIRQ // use secure physical timer for now +#endif + +#define NUM_HAL_INTERRUPT_TIMER0 33 +#define NUM_HAL_INTERRUPT_TIMER1 33 +#define NUM_HAL_INTERRUPT_TIMER2 34 +#define NUM_HAL_INTERRUPT_TIMER3 34 +#define NUM_HAL_INTERRUPT_TIMER4 35 +#define NUM_HAL_INTERRUPT_TIMER5 35 +#define NUM_HAL_INTERRUPT_TIMER6 36 +#define NUM_HAL_INTERRUPT_TIMER7 36 + +#define NUM_HAL_INTERRUPT_DMAC 60 +#define NUM_HAL_INTERRUPT_UART0 38 +#define NUM_HAL_INTERRUPT_UART1 39 +#define NUM_HAL_INTERRUPT_UART2 40 +#define NUM_HAL_INTERRUPT_UART3 41 +#define NUM_HAL_INTERRUPT_UART4 42 + +#define NUM_HAL_INTERRUPT_SDIO 62 +#define NUM_HAL_INTERRUPT_SDIO1 63 +#define NUM_HAL_INTERRUPT_EMMC 96 +#define NUM_HAL_INTERRUPT_ETH 64 + +#define NUM_HAL_INTERRUPT_TIMER NUM_HAL_INTERRUPT_TIMER4 +#define NUM_HAL_INTERRUPT_HRTIMER NUM_HAL_INTERRUPT_TIMER7 + +#define NUM_HAL_INTERRUPT_GPIO0 48 +#define NUM_HAL_INTERRUPT_GPIO1 49 +#define NUM_HAL_INTERRUPT_GPIO2 50 +#define NUM_HAL_INTERRUPT_GPIO3 51 +#define NUM_HAL_INTERRUPT_GPIO4 52 +#define NUM_HAL_INTERRUPT_GPIO5 53 +#define NUM_HAL_INTERRUPT_GPIO6 54 +#define NUM_HAL_INTERRUPT_GPIO7 55 +#define NUM_HAL_INTERRUPT_GPIO8 56 +#define NUM_HAL_INTERRUPT_GPIO9 57 +#define NUM_HAL_INTERRUPT_GPIO10 58 +#define NUM_HAL_INTERRUPT_USB_XHCI 59 +#define NUM_HAL_INTERRUPT_GPIO11 112 + +#define NUM_HAL_INTERRUPT_TEE_SPI_NOTIFY 105 + +#define NUM_HAL_INTERRUPT_NONE -1 + +#define NUM_HAL_ISR_MIN OS_HWI_MIN +#define NUM_HAL_INTERRUPT_USB_DEV NUM_HAL_INTERRUPT_USB_XHCI + +#define IO_ADDRESS(x) (x) + +#define HAL_READ_UINT8(addr, data) READ_UINT8(data, addr) + +#define HAL_WRITE_UINT8(addr, data) WRITE_UINT8(data, addr) + +#define HAL_READ_UINT32(addr, data) READ_UINT32(data, addr) + +#define HAL_WRITE_UINT32(addr, data) WRITE_UINT32(data, addr) + +#define NUM_HAL_INTERRUPT_PMU_0 80 +#define NUM_HAL_INTERRUPT_PMU_1 86 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif // PLATFORM_HAL_PLATFORM_INTS_H diff --git a/hispark_taurus/liteos_a/board/include/asm/platform.h b/hispark_taurus/liteos_a/board/include/asm/platform.h new file mode 100755 index 00000000..db9a6cb5 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/asm/platform.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ASM_PLATFORM_H__ +#define __ASM_PLATFORM_H__ + +#include "los_bitmap.h" +#include "asm/hal_platform_ints.h" +#include "hisoc/timer.h" +#include "hisoc/uart.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/*------------------------------------------------ + * GIC reg base address + *------------------------------------------------*/ +#define GIC_BASE_ADDR IO_DEVICE_ADDR(0x10300000) +#define GICD_OFFSET 0x1000 /* interrupt distributor offset */ +#define GICC_OFFSET 0x2000 /* CPU interface register offset */ + +#define DDR_MEM_BASE 0x80000000 + +#define FMC_MEM_PBASE 0x14000000 +#define FMC_MEM_OFFSIZE 0x8 + +#define IO_CTL_REG_BASE IO_DEVICE_ADDR(0x10FF0000) + +#define GPIO_REG_ADDR 0x120d0000 +#define GPIO11_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0xb000) +#define GPIO10_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0xa000) +#define GPIO9_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x9000) +#define GPIO8_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x8000) +#define GPIO7_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x7000) +#define GPIO6_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x6000) +#define GPIO5_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x5000) +#define GPIO4_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x4000) +#define GPIO3_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x3000) +#define GPIO2_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x2000) +#define GPIO1_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x1000) +#define GPIO0_REG_BASE IO_DEVICE_ADDR(GPIO_REG_ADDR + 0x0000) + +#define SPI_REG_ADDR IO_DEVICE_ADDR(0x120c0000) +#define SPI2_REG_BASE (SPI_REG_ADDR + 0x2000) +#define SPI1_REG_BASE (SPI_REG_ADDR + 0x1000) +#define SPI0_REG_BASE (SPI_REG_ADDR + 0x0000) + +#define I2C_REG_ADDR 0x120b0000 +#define I2C7_REG_PBASE (I2C_REG_ADDR + 0x7000) +#define I2C6_REG_PBASE (I2C_REG_ADDR + 0x6000) +#define I2C5_REG_PBASE (I2C_REG_ADDR + 0x5000) +#define I2C4_REG_PBASE (I2C_REG_ADDR + 0x4000) +#define I2C3_REG_PBASE (I2C_REG_ADDR + 0x3000) +#define I2C2_REG_PBASE (I2C_REG_ADDR + 0x2000) +#define I2C1_REG_PBASE (I2C_REG_ADDR + 0x1000) +#define I2C0_REG_PBASE (I2C_REG_ADDR + 0x0000) + +#define I2C7_REG_BASE IO_DEVICE_ADDR(I2C7_REG_PBASE) +#define I2C6_REG_BASE IO_DEVICE_ADDR(I2C6_REG_PBASE) +#define I2C5_REG_BASE IO_DEVICE_ADDR(I2C5_REG_PBASE) +#define I2C4_REG_BASE IO_DEVICE_ADDR(I2C4_REG_PBASE) +#define I2C3_REG_BASE IO_DEVICE_ADDR(I2C3_REG_PBASE) +#define I2C2_REG_BASE IO_DEVICE_ADDR(I2C2_REG_PBASE) +#define I2C1_REG_BASE IO_DEVICE_ADDR(I2C1_REG_PBASE) +#define I2C0_REG_BASE IO_DEVICE_ADDR(I2C0_REG_PBASE) + +#define UART_REG_ADDR 0x120a0000 +#define UART4_REG_PBASE (UART_REG_ADDR + 0x4000) +#define UART3_REG_PBASE (UART_REG_ADDR + 0x3000) +#define UART2_REG_PBASE (UART_REG_ADDR + 0x2000) +#define UART1_REG_PBASE (UART_REG_ADDR + 0x1000) +#define UART0_REG_PBASE (UART_REG_ADDR + 0x0000) +#define UART4_REG_BASE IO_DEVICE_ADDR(UART4_REG_PBASE) +#define UART3_REG_BASE IO_DEVICE_ADDR(UART3_REG_PBASE) +#define UART2_REG_BASE IO_DEVICE_ADDR(UART2_REG_PBASE) +#define UART1_REG_BASE IO_DEVICE_ADDR(UART1_REG_PBASE) +#define UART0_REG_BASE IO_DEVICE_ADDR(UART0_REG_PBASE) + +#define MISC_REG_BASE IO_DEVICE_ADDR(0x12030000) +#define SYS_CTRL_REG_BASE IO_DEVICE_ADDR(0x12020000) + +#define CRG_REG_ADDR 0x12010000 +#define CRG_REG_BASE IO_DEVICE_ADDR(CRG_REG_ADDR) +#define PERI_CRG30_BASE IO_DEVICE_ADDR(CRG_REG_ADDR + 0x0078) /* cpu freq-mode & reset CRG */ + +#define GSF_REG_BASE IO_DEVICE_ADDR(0x12050000) +#define SDIO0_REG_PBASE 0x100f0000 +#define SDIO1_REG_PBASE 0x10020000 +#define EMMC_REG_PBASE 0x10100000 +#define MMC_REG_OFFSIZE 0x118 + +#define ETH_REG_BASE IO_DEVICE_ADDR(0x10010000) +#define ETH_REG_OFFSIZE 0x2000 + +#define VIC_REG_BASE IO_DEVICE_ADDR(0x10040000) +#define IRQ_REG_BASE VIC_REG_BASE + +#define DMAC_REG_BASE IO_DEVICE_ADDR(0x10060000) +#define IO_MUX_REG_BASE IO_DEVICE_ADDR(0x12040000) +#define FMC_REG_PBASE 0x10000000 +#define FMC_REG_OFFSIZE 0xdc + +#define TIMER0_ENABLE BIT(16) +#define TIMER1_ENABLE BIT(17) +#define TIMER2_ENABLE BIT(18) +#define TIMER3_ENABLE BIT(19) +#define TIMER4_ENABLE BIT(20) +#define TIMER5_ENABLE BIT(21) +#define TIMER6_ENABLE BIT(22) +#define TIMER7_ENABLE BIT(23) + +#define TIMER7_REG_BASE IO_DEVICE_ADDR(0x12003020) +#define TIMER6_REG_BASE IO_DEVICE_ADDR(0x12003000) +#define TIMER5_REG_BASE IO_DEVICE_ADDR(0x12002020) +#define TIMER4_REG_BASE IO_DEVICE_ADDR(0x12002000) +#define TIMER3_REG_BASE IO_DEVICE_ADDR(0x12001020) +#define TIMER2_REG_BASE IO_DEVICE_ADDR(0x12001000) +#define TIMER1_REG_BASE IO_DEVICE_ADDR(0x12000020) +#define TIMER0_REG_BASE IO_DEVICE_ADDR(0x12000000) + +#define TIMER_TICK_REG_BASE TIMER4_REG_BASE /* timer for tick */ +#define TIMER_TICK_ENABLE TIMER4_ENABLE +#define TIMER_TIME_REG_BASE TIMER5_REG_BASE /* timer for time */ +#define TIMER_TIME_ENABLE TIMER5_ENABLE +#define HRTIMER_TIMER_REG_BASE TIMER7_REG_BASE /* timer for hrtimer */ +#define HRTIMER_TIMER_ENABLE TIMER7_ENABLE + +#define CACHE_ALIGNED_SIZE 64 + +#define ARM_REG_BASE IO_DEVICE_ADDR(0x10300000) + +extern void OsReboot(void); +extern void InitRebootHook(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/board.h b/hispark_taurus/liteos_a/board/include/board.h new file mode 100755 index 00000000..7b4a7e42 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/board.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/* Physical memory address base and size */ +#ifdef LOSCFG_TEE_ENABLE +#define DDR_MEM_ADDR 0x81000000 +#define DDR_MEM_SIZE 0x1f000000 +#else +#define DDR_MEM_ADDR 0x80000000 +#define DDR_MEM_SIZE 0x20000000 +#endif + +/* Peripheral register address base and size */ +#define PERIPH_PMM_BASE 0x10000000 +#define PERIPH_PMM_SIZE 0x10000000 + +#ifdef LOSCFG_TEE_ENABLE +#define KERNEL_VADDR_BASE 0x41000000 +#else +#define KERNEL_VADDR_BASE 0x40000000 +#endif +#define KERNEL_VADDR_SIZE DDR_MEM_SIZE + +#define SYS_MEM_BASE DDR_MEM_ADDR +#define SYS_MEM_SIZE_DEFAULT 0x07f00000 +#define SYS_MEM_END (SYS_MEM_BASE + SYS_MEM_SIZE_DEFAULT) + +#define EXC_INTERACT_MEM_SIZE 0x100000 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/clock.h b/hispark_taurus/liteos_a/board/include/hisoc/clock.h new file mode 100755 index 00000000..eee002fc --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/clock.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_CLOCK_H__ +#define __HISOC_CLOCK_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + +#define PERI_CRG12 (CRG_REG_BASE + 0x30) + +/*----------------------------------------------------------------------- + * cpu_init configuration + * if bit[13:12] = 1b, AXI = 200M + *----------------------------------------------------------------------*/ +/*lint -e160 */ +#define get_bus_clk() 50000000 +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/cpu.h b/hispark_taurus/liteos_a/board/include/hisoc/cpu.h new file mode 100755 index 00000000..9cc027b4 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/cpu.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_CPU_H__ +#define __HISOC_CPU_H__ + +#include "asm/platform.h" +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + + +#define ARM_GIC_CPU_CTRL 0x00 +#define ARM_GIC_CPU_PRIMASK 0x04 +#define ARM_GIC_CPU_BINPOINT 0x08 +#define ARM_GIC_CPU_INTACK 0x0c +#define ARM_GIC_CPU_EOI 0x10 +#define ARM_GIC_CPU_RUNNINGPRI 0x14 +#define ARM_GIC_CPU_HIGHPRI 0x18 + +#define ARM_GIC_DIST_CTRL 0x000 +#define ARM_GIC_DIST_CTR 0x004 +#define ARM_GIC_DIST_ENABLE_SET 0x100 +#define ARM_GIC_DIST_ENABLE_CLEAR 0x180 +#define ARM_GIC_DIST_PENDING_SET 0x200 +#define ARM_GIC_DIST_PENDING_CLEAR 0x280 +#define ARM_GIC_DIST_ACTIVE_BIT 0x300 +#define ARM_GIC_DIST_PRI 0x400 +#define ARM_GIC_DIST_TARGET 0x800 +#define ARM_GIC_DIST_CONFIG 0xc00 +#define ARM_GIC_DIST_SOFTINT 0xf00 + + +#define REG_A7_PERI_GIC_DIST 0x1000 +#define REG_A7_PERI_GIC_CPU 0x2000 +#define REG_BASE_A7_PERI ARM_REG_BASE +#define CFG_ARM_GIC_CPU_BASE (IO_ADDRESS(REG_BASE_A7_PERI) + REG_A7_PERI_GIC_CPU) +#define CFG_ARM_GIC_DIST_BASE (IO_ADDRESS(REG_BASE_A7_PERI) + REG_A7_PERI_GIC_DIST) +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/dmac.h b/hispark_taurus/liteos_a/board/include/hisoc/dmac.h new file mode 100755 index 00000000..c8555edc --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/dmac.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_DMAC_H__ +#define __HISOC_DMAC_H__ +#include "asm/io.h" +#include "asm/platform.h" +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + +#define DDRAM_ADRS DDR_MEM_BASE /* fixed */ +#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ + + +#define DMAC_INTSTATUS (DMAC_REG_BASE + 0X00) +#define DMAC_INTTCSTATUS (DMAC_REG_BASE + 0X04) +#define DMAC_INTTCCLEAR (DMAC_REG_BASE + 0X08) +#define DMAC_INTERRORSTATUS (DMAC_REG_BASE + 0X0C) +#define DMAC_INTERRCLR (DMAC_REG_BASE + 0X10) + +#define DMAC_RAWINTTCSTATUS (DMAC_REG_BASE + 0X14) +#define DMAC_RAWINTERRORSTATUS (DMAC_REG_BASE + 0X18) + +#define DMAC_ENBLDCHNS (DMAC_REG_BASE + 0X1C) +#define DMAC_SOFT_BREQ (DMAC_REG_BASE + 0X20) +#define DMAC_SOFT_SREQ (DMAC_REG_BASE + 0X24) +#define DMAC_SOFT_LBREQ (DMAC_REG_BASE + 0X28) +#define DMAC_SOFT_LSREQ (DMAC_REG_BASE + 0X2C) + +#define DMAC_CONFIG (DMAC_REG_BASE + 0X30) +#define DMAC_SYNC (DMAC_REG_BASE + 0X34) + +/* the definition for DMAC channel register */ +#define DMAC_CxBASE(i) (DMAC_REG_BASE + 0x100+i*0x20) + +#define DMAC_CxSRCADDR(i) (DMAC_CxBASE(i) + 0x00) +#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i) + 0x04) +#define DMAC_CxLLI(i) (DMAC_CxBASE(i) + 0x08) +#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i) + 0x0C) +#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i) + 0x10) + +#define DMAC_MAXTRANSFERSIZE 0x0fff /* the max length is denoted by 0-11bit */ +#define DMAC_CxDISABLE 0x00 +#define DMAC_CxENABLE 0x01 + +/* the means the bit in the channel control register */ +#define DMAC_CxCONTROL_M2M 0x8d489000 /* Dwidth=32,burst size=4 */ +#define DMAC_CxCONTROL_LLIM2M 0x0d489000 /* Dwidth=32,burst size=4 */ +#define DMAC_CxCONTROL_LLIP2M 0x0a000000 // 0x09409000 +#define DMAC_CxCONTROL_LLIM2P 0x86089000 + +#define DMAC_CxCONTROL_INT_EN (0x01 << 31) /* bit:31,enable interrupt */ + +#define DMAC_CxLLI_LM 0x01 +#define DMAC_TRANS_SIZE 0xff0 + +#define DMAC_CHANNEL_ENABLE 1 +#define DMAC_CHANNEL_DISABLE 0xfffffffe + +#define DMAC_CxCONFIG_M2M 0xc000 +#define DMAC_CxCONFIG_LLIM2M 0xc000 + +#define DMAC_CxCONFIG_P2M 0xd000 +#define DMAC_CxCONFIG_M2P 0xc800 + +#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 +#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 + +/* default the config and sync regsiter for DMAC controller */ +/* M1,M2 little endian, enable DMAC */ +#define DMAC_CONFIG_VAL 0x01 +/* enable the sync logic for the 16 peripheral */ +#define DMAC_SYNC_VAL 0x0 + +#define DMAC_MAX_PERIPHERALS 16 // 12 +#define MEM_MAX_NUM 1 +#define CHANNEL_NUM 4 +#define DMAC_MAX_CHANNELS CHANNEL_NUM + +#define PERI_CRG91 (CRG_REG_BASE + 0x16c) +#define DMAC_CLK_EN (1 << 5) +#define DMAC_SRST_REQ (1 << 4) + + +static void hidmac_clk_en(void) +{ + unsigned int tmp; + + tmp = readl(PERI_CRG91); + tmp |= DMAC_CLK_EN; + writel(tmp, PERI_CRG91); +} + +static void hidmac_unreset(void) +{ + unsigned int tmp; + + tmp = readl(PERI_CRG91); + tmp &= ~DMAC_SRST_REQ; + writel(tmp, PERI_CRG91); +} + +#define PERI_8BIT_MODE 0 +#define PERI_16BIT_MODE 1 +#define PERI_32BIT_MODE 2 + + +// hidmac data structure + +/* DMAC peripheral structure */ +typedef struct dmac_peripheral { + /* peripherial ID */ + unsigned int peri_id; + /* peripheral data register address */ + unsigned int peri_addr; + /* default channel control word */ + unsigned int transfer_ctrl; + /* default channel configuration word */ + unsigned int transfer_cfg; + /* default channel configuration word */ + unsigned int transfer_width; +} dmac_peripheral; + +/* + * DMA config array! + * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH + */ +static dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { + /* DREQ, FIFO, CONTROL, CONFIG, WIDTH */ + /* periphal 0: I2C0/I2C1 RX */ + { 0, I2C1_REG_BASE + 0x10, 0, DMAC_CxCONTROL_LLIP2M | (0 << 1), PERI_8BIT_MODE}, + + /* periphal 1: I2C0/I2C1 TX */ + { 1, I2C1_REG_BASE + 0x10, 0, DMAC_CxCONTROL_LLIP2M | (1 << 1), PERI_8BIT_MODE}, + + /* periphal 2: I2C1/I2C2 RX */ + { 2, I2C1_REG_BASE + 0x10, 0x99000000, DMAC_CxCONTROL_LLIP2M | (2 << 1), PERI_8BIT_MODE}, /* 8bit width */ + + /* periphal 3: I2C1/I2C2 TX */ + { 3, I2C1_REG_BASE + 0x10, 0x96000000, DMAC_CxCONTROL_LLIP2M | (3 << 1), PERI_8BIT_MODE}, /* 8bit width */ + + /* periphal 4: UART0 RX */ + { 4, UART0_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (4 << 1), PERI_8BIT_MODE}, + + /* periphal 5: UART0 TX */ + { 5, UART0_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (5 << 1), PERI_8BIT_MODE}, + + /* periphal 6: UART1 RX */ + { 6, UART1_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (6 << 1), PERI_8BIT_MODE}, + + /* periphal 7: UART1 TX */ + { 7, UART1_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (7 << 1), PERI_8BIT_MODE}, + + /* periphal 8: UART2 RX */ + { 8, UART2_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (8 << 1), PERI_8BIT_MODE}, + + /* periphal 9: UART2 TX */ + { 9, UART2_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (9 << 1), PERI_8BIT_MODE}, + + /* periphal 10: UART3 RX */ + { 10, UART3_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (10 << 1), PERI_8BIT_MODE}, + + /* periphal 11: UART0 TX */ + { 11, UART3_REG_BASE + 0x00, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (11 << 1), PERI_8BIT_MODE}, + + /* periphal 12: SSP1 RX */ + { 12, 0, 0, 0, 0}, + + /* periphal 13: SSP1 TX */ + { 13, 0, 0, 0, 0}, + + /* periphal 14: SSP0 RX */ + { 14, 0, 0, 0, 0}, + + /* periphal 15: SSP0 TX */ + { 15, 0, 0, 0, 0}, + +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + + +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/flash.h b/hispark_taurus/liteos_a/board/include/hisoc/flash.h new file mode 100755 index 00000000..0f1e7a91 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/flash.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_FLASH_H__ +#define __HISOC_FLASH_H__ + +#include "asm/platform.h" +#include "hisoc/sys_ctrl.h" +#include "asm/io.h" +#include "linux/delay.h" +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + +/* FMC CRG register offset */ +#define PERI_CRG48 0xc0 +#define REG_FMC_CRG PERI_CRG48 +#define FMC_CLK_SEL(_clk) (((_clk) & 0x7) << 2) +#define FMC_CLK_SEL_MASK (0x7 << 2) +#define GET_CLK_TYPE(_reg) (((_reg) >> 2) & 0x7) +/* SDR/DDR clock */ +#define FMC_CLK_24M 0 +#define FMC_CLK_75M 1 +#define FMC_CLK_125M 2 +#define FMC_CLK_150M 3 +#define FMC_CLK_200M 4 +#define FMC_CLK_250M 5 +/* Only DDR clock */ +#define FMC_CLK_300M 6 +#define FMC_CLK_400M 7 +#define FMC_CLK_ENABLE (0x1 << 1) +#define FMC_SOFT_RST_REQ (0x1 << 0) + +/* bit[9]=0: 3-Byte address mode; bit[9]=1: 4-Byte address mode */ +#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 9) & 0x1) + +/****************************************************************************/ +/* REG_SYSSTAT 0: 3 Bytes address boot mode; 1: 4Bytes address boot mode */ +#define REG_SYSSTAT 0x008C +#define GET_FMC_BOOT_MODE ({ \ + unsigned int regval; \ + unsigned int boot_mode = 0; \ + regval = readl(SYS_CTRL_REG_BASE + REG_SYSSTAT); \ + boot_mode = GET_SPI_NOR_ADDR_MODE(regval); \ + boot_mode; }) + + +/* This define just for Padctrl, PHY and DC configuration + * of nand flash */ +#define MISC_CTRL28 0x28 +#define EMMC_PHY_INIT_CTRL IO_DEVICE_ADDR(0x12160004) +#define PHY_INIT_EN 0x1 +#define PHY_ZCAL_EN (0x1 << 3) + +#define EMMC_PHY_IOCTL_RONSEL_1_0 IO_DEVICE_ADDR(0x12160264) +#define RG_EMMC_RONSEL1 0x7ff +#define RG_EMMC_RONSEL0 0x7ff +#define EMMC_PHY_IOCTL_OD_RONSEL_2 IO_DEVICE_ADDR(0x12160268) +#define EMMC_PHY_IOCTL_IOE IO_DEVICE_ADDR(0x1216026c) +#define NAND_IO_EN 0x00ff00ff + +static inline void nand_io_config(void) +{ + /* Padctrl, PHY and DC configuration */ + unsigned int reg_val = 0; + unsigned int timeout = 20; + + /* set pad ctrl reg for nand */ + writel(0x1a3, IO_MUX_REG_BASE + 0x91c); + writel(0x103, IO_MUX_REG_BASE + 0x920); + writel(0x100, IO_MUX_REG_BASE + 0x924); + writel(0x1a3, IO_MUX_REG_BASE + 0x928); + writel(0x100, IO_MUX_REG_BASE + 0x92c); + writel(0x100, IO_MUX_REG_BASE + 0x930); + + /* disable emmc io isolation mode */ + reg_val = readl(MISC_REG_BASE + MISC_CTRL28); + reg_val &= ~0x1; + writel(reg_val, MISC_REG_BASE + MISC_CTRL28); + + /* enable phy init */ + reg_val = readl(EMMC_PHY_INIT_CTRL); + reg_val |= (PHY_INIT_EN | PHY_ZCAL_EN); + writel(reg_val, EMMC_PHY_INIT_CTRL); + + /* wait phy init and zcal done */ + for(; ; ) { + reg_val = readl(EMMC_PHY_INIT_CTRL); + if (!(reg_val & (PHY_INIT_EN | PHY_ZCAL_EN))) + break; + udelay(100); + if (timeout-- == 0) { + dprintf("ERROR: wait mmc phy cal done time out\n"); + return; + } + } + + /* DRV50 */ + writel((RG_EMMC_RONSEL1 << 16) | RG_EMMC_RONSEL0, + EMMC_PHY_IOCTL_RONSEL_1_0); + /* DRV50, OD = 0 */ + writel(0, EMMC_PHY_IOCTL_OD_RONSEL_2); + + writel(NAND_IO_EN, EMMC_PHY_IOCTL_IOE); + + writel(0x2, IO_MUX_REG_BASE + 69 * 4); + writel(0x2, IO_MUX_REG_BASE + 70 * 4); + writel(0x2, IO_MUX_REG_BASE + 71 * 4); + writel(0x2, IO_MUX_REG_BASE + 72 * 4); + writel(0x2, IO_MUX_REG_BASE + 73 * 4); + writel(0x2, IO_MUX_REG_BASE + 74 * 4); + writel(0x2, IO_MUX_REG_BASE + 75 * 4); + writel(0x2, IO_MUX_REG_BASE + 76 * 4); + writel(0x2, IO_MUX_REG_BASE + 79 * 4); + writel(0x2, IO_MUX_REG_BASE + 80 * 4); + writel(0x2, IO_MUX_REG_BASE + 81 * 4); + writel(0x2, IO_MUX_REG_BASE + 82 * 4); + writel(0x2, IO_MUX_REG_BASE + 83 * 4); + writel(0x2, IO_MUX_REG_BASE + 84 * 4); +} + +static inline void spi_io_config(void) +{ + /* set pad ctrl reg for spi */ + writel(0x1C0, IO_MUX_REG_BASE + 0x91c); + writel(0x130, IO_MUX_REG_BASE + 0x920); + writel(0x130, IO_MUX_REG_BASE + 0x924); + writel(0x130, IO_MUX_REG_BASE + 0x928); + writel(0x130, IO_MUX_REG_BASE + 0x92c); + writel(0x103, IO_MUX_REG_BASE + 0x930); + + /* set mux ctrl reg for spi */ + writel(0x1, IO_MUX_REG_BASE + 0x13c); + writel(0x1, IO_MUX_REG_BASE + 0x140); + writel(0x1, IO_MUX_REG_BASE + 0x144); + writel(0x1, IO_MUX_REG_BASE + 0x148); + writel(0x1, IO_MUX_REG_BASE + 0x14c); + writel(0x1, IO_MUX_REG_BASE + 0x150); +} + +/*---------------------------------------------------------------------------*/ +/* hifmc100_set_fmc_system_clock */ +/*---------------------------------------------------------------------------*/ +static inline void hifmc100_set_system_clock(unsigned clock, int clk_en) +{ + unsigned int old_val, regval; + + old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG); + + regval &= ~FMC_CLK_SEL_MASK; + + if (clock) + regval |= clock & FMC_CLK_SEL_MASK; + else { + regval |= FMC_CLK_SEL(FMC_CLK_24M); /* Default Clock */ + spi_io_config(); + } + + if (clk_en) + regval |= FMC_CLK_ENABLE; + else + regval &= ~FMC_CLK_ENABLE; + + if (regval != old_val) + writel(regval, (CRG_REG_BASE + REG_FMC_CRG)); +} + +/*---------------------------------------------------------------------------*/ +/* hifmc100_get_best_clock */ +/*---------------------------------------------------------------------------*/ +static inline void hifmc100_get_best_clock(unsigned int *clock) +{ + int ix; + int clk_reg, clk_type; + +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sys_2X_clk[] = { + CLK_2X(24), FMC_CLK_SEL(FMC_CLK_24M), + CLK_2X(75), FMC_CLK_SEL(FMC_CLK_75M), + CLK_2X(125), FMC_CLK_SEL(FMC_CLK_125M), + CLK_2X(150), FMC_CLK_SEL(FMC_CLK_150M), + CLK_2X(200), FMC_CLK_SEL(FMC_CLK_200M), + // CLK_2X(250), FMC_CLK_SEL(FMC_CLK_250M), + 0, 0, + }; +#undef CLK_2X + + clk_type = FMC_CLK_24M; + clk_reg = FMC_CLK_SEL(clk_type); + for (ix = 0; sys_2X_clk[ix]; ix += 2) { + if (*clock < sys_2X_clk[ix]) + break; + clk_reg = sys_2X_clk[ix + 1]; + clk_type = GET_CLK_TYPE(clk_reg); + } + + *clock = clk_reg; +} + +static inline void hifmc100_nand_clk_enable(int enable) +{ + unsigned int old_val, regval; + + old_val = regval = readl(CRG_REG_BASE + REG_FMC_CRG); + + regval |= FMC_CLK_SEL(FMC_CLK_200M); + + if (enable) + regval |= FMC_CLK_ENABLE; + else + regval &= ~FMC_CLK_ENABLE; + + regval &= ~FMC_SOFT_RST_REQ; + if (regval != old_val) + writel(regval, (CRG_REG_BASE + REG_FMC_CRG)); + nand_io_config(); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/mmc.h b/hispark_taurus/liteos_a/board/include/hisoc/mmc.h new file mode 100755 index 00000000..a3455d27 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/mmc.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_MMC_H_ +#define __HISOC_MMC_H_ + +/************************************************************************/ + +#include "asm/platform.h" +#include "asm/io.h" +#include "himci_v200/himci_reg.h" +#include "mmc/mmc_caps.h" +#include "hal_timer.h" +#include "los_printf.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/************************************************************************/ +#define EMMC_DDR50 +#define EMMC_HS200 + +#define MMC0 0 +#define MMC1 1 +#define MMC2 2 + +#define MAX_MMC_NUM 3 + + +/** + * MMC HOST usable + * Set to 1: usable + * Set to 0: not usable + * sdio0=1, sdio1=2, EMMC=0 + **/ +#ifdef LOSCFG_DRIVERS_EMMC +#define USE_MMC0 1 +#else +#define USE_MMC0 0 +#endif +#define USE_MMC1 1 +#define USE_MMC2 1 + + +#define MMC_FREQ_150M (150000000) +#define MMC_FREQ_100M (100000000) +#define MMC_FREQ_50M (50000000) +#define MMC_FREQ_25M (25000000) + +#define CONFIG_MMC0_CCLK_MIN 50000 +#define CONFIG_MMC0_CCLK_MAX MMC_FREQ_100M +#define CONFIG_MMC1_CCLK_MIN 50000 +#define CONFIG_MMC1_CCLK_MAX MMC_FREQ_100M +#define CONFIG_MMC2_CCLK_MIN 50000 +#define CONFIG_MMC2_CCLK_MAX MMC_FREQ_100M + + +#define CONFIG_MMC0_CLK MMC_FREQ_50M +#define CONFIG_MMC1_CLK MMC_FREQ_50M +#define CONFIG_MMC2_CLK MMC_FREQ_100M + + +#define CONFIG_MAX_BLK_COUNT 2048 +#define CONFIG_MAX_BLK_SIZE 512 + +#define HIMMC_PAGE_SIZE 4096 + +/* register mapping */ +#define PERI_CRG49 (CRG_REG_BASE + 0xC4) +#define PERI_CRG50 (CRG_REG_BASE + 0xC8) + +#define PERI_CRG82 (CRG_REG_BASE + 0x0148) +#define PERI_CRG83 (CRG_REG_BASE + 0x014C) +#define PERI_CRG84 (CRG_REG_BASE + 0x0150) +#define PERI_CRG85 (CRG_REG_BASE + 0x0154) + +#define PERI_CRG86 (CRG_REG_BASE + 0x0158) +#define PERI_CRG87 (CRG_REG_BASE + 0x015C) +#define PERI_CRG88 (CRG_REG_BASE + 0x0160) +#define PERI_CRG89 (CRG_REG_BASE + 0x0164) +#define PERI_CRG90 (CRG_REG_BASE + 0x0168) + +/* sdio2:eMMC pad ctrl reg */ +#define REG_CTRL_EMMC_CCLK (IO_CTL_REG_BASE + 0) +#define REG_CTRL_EMMC_CCMD (IO_CTL_REG_BASE + 4) +#define REG_CTRL_EMMC_CDATA0 (IO_CTL_REG_BASE + 8) +#define REG_CTRL_EMMC_CDATA1 (IO_CTL_REG_BASE + 0xc) +#define REG_CTRL_EMMC_CDATA2 (IO_CTL_REG_BASE + 0x10) +#define REG_CTRL_EMMC_CDATA3 (IO_CTL_REG_BASE + 0x14) + +#define EMMC_CLK_DS_1V8 0xc0 +#define EMMC_CMD_DS_1V8 0x150 +#define EMMC_DATA0_DS_1V8 0x1d0 +#define EMMC_DATA1_DS_1V8 0x1d0 +#define EMMC_DATA2_DS_1V8 0x1d0 +#define EMMC_DATA3_DS_1V8 0x1d0 + +#define SDIO_CLK_SEL_MASK (3U << 2) +#define SDIO_CLK_SEL_100M (1U << 2) +#define SDIO_CLK_SEL_50M (2U << 2) +#define SDIO_CLK_SEL_25M (3U << 2) +#define SDIO_CKEN (1U << 1) +#define SDIO_RESET (1U << 0) + +#define SDIO1_CLK_OFFSET (2) +#define SDIO0_CLK_OFFSET (10) + +#define PHASE_SHIFT 0x2030000 +#define READ_THRESHOLD_SIZE 0x2000005 +#define DRV_PHASE_SHIFT (0x4) +#define SMPL_PHASE_SHIFT (0x1) + +#define DDR50_DRV_PHASE_CFG (0x2) +#define SDR104_DRV_PHASE_CFG (0x3) + +#define HIMCI_EDGE_TUNING +#define HIMCI_PHASE_SCALE 8 +#define TUNING_START_PHASE 0 +#define TUNING_END_PHASE 7 + +#define PHASE_NOT_FOUND -1 + +#define hi_mci_detect_polarity_cfg(mmc_num) do { } while (0) + +/* EMMC=PERI_CRG82, sdio0=PERI_CRG88, sdio1=PERI_CRG85 */ +#define hi_mci_soft_reset(mmc_num) do { \ + unsigned int regs[] = {PERI_CRG82, PERI_CRG88, PERI_CRG85}; \ + unsigned int val = 0; \ + if ((int)mmc_num >= 0 && mmc_num <= 2) { \ + val = readl((uintptr_t)regs[mmc_num]); \ + PRINT_DEBUG("0x%x:0x%x\n", regs[mmc_num], val); \ + HalDelayUs(1000); \ + writel(val | 1, (uintptr_t)regs[mmc_num]); \ + val &= ~1; \ + writel(val, (uintptr_t)regs[mmc_num]); \ + PRINT_DEBUG("0x%x:0x%x\n", regs[mmc_num], val); \ + } \ +} while (0) + + +/* MCI_FIFOTH(0x4c) details */ +#define BURST_SIZE (0x6 << 28) +#define RX_WMARK (0x7f << 16) +#define TX_WMARK 0x80 +#define MCI_BMOD_VALUE (BURST_INCR | BURST_16) + +void himci_cfg_phase(unsigned int devid, void *base, enum mmc_bus_timing timing); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/mmu_config.h b/hispark_taurus/liteos_a/board/include/hisoc/mmu_config.h new file mode 100755 index 00000000..fdea2c78 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/mmu_config.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @defgroup mmu Memory management unit + * @ingroup mmu +*/ + +#ifndef __MMU_CONFIG_H +#define __MMU_CONFIG_H + +#include "board.h" +#include "los_config.h" +#include "los_memory.h" +#include "mmu.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define MMU_SET_PAGE_TABLE_PLACE \ +__attribute__((aligned(MMU_16K))) __attribute__((section(".bss.prebss.translation_table"))) UINT8 first_page_table[MMU_16K]; \ +__attribute__((aligned(MMU_1K))) UINT8 second_page_table_os[MMU_16K]; \ +__attribute__((aligned(MMU_1K))) UINT8 second_page_table_app[MMZ_MEM_LEN / MMU_1K]; + +/** + * @ingroup mmu + * The liteos cache addr & length + */ +#define LITEOS_CACHE_ADDR SYS_MEM_BASE +#define LITEOS_CACHE_LENGTH (OS_SYS_FUNC_ADDR_END - LITEOS_CACHE_ADDR) + +/** + * @ingroup mmu + * The page table storage addr + * notice: must ensure it has enough free mem for storage page table + */ +extern UINT8 first_page_table[MMU_16K]; +#define FIRST_PAGE_DESCRIPTOR_ADDR ((UINTPTR)first_page_table) +#define stAppPage g_mmuAppPage + +#define X_MMU_SECOND_TABLE_OS_PAGE_SET() do { \ + g_mmuOsPage.page_addr = SYS_MEM_BASE; \ + g_mmuOsPage.page_length = ((((UINTPTR)&__ram_data_start - SYS_MEM_BASE) + MMU_1M - 1)& ~ (MMU_1M - 1)); \ + g_mmuOsPage.page_descriptor_addr = (UINTPTR)second_page_table_os; \ + g_mmuOsPage.page_type = MMU_SECOND_LEVEL_SMALL_PAGE_TABLE_ID; \ + if (g_mmuOsPage.page_length > (sizeof(second_page_table_os) << 10)) { \ + PRINT_ERR("%s,%d\n", __FUNCTION__, __LINE__); \ + PRINT_ERR("the mapping size of os second page is 0x%x, sholud be not bigger than 0x%x\n", \ + g_mmuOsPage.page_length, (sizeof(second_page_table_os) << 10)); \ + return; \ + } \ + LOS_SecPageEnable(&g_mmuOsPage, BUFFER_ENABLE | CACHE_ENABLE | ACCESS_PERM_RW_RW); \ +} while (0) + +#define X_MMU_SECOND_TABLE_APP_PAGE_SET() \ +do { \ + stAppPage.page_addr = MMZ_MEM_BASE; \ + stAppPage.page_length = MMZ_MEM_LEN; \ + stAppPage.page_descriptor_addr = (UINTPTR)second_page_table_app; \ + stAppPage.page_type = MMU_SECOND_LEVEL_SMALL_PAGE_TABLE_ID; \ + LOS_SecPageEnable(&stAppPage, BUFFER_DISABLE | CACHE_DISABLE | ACCESS_PERM_RW_RW); \ +} while (0) + +#define MMU_GET_FIRST_TABLE_ADDR(addr) (((addr) / MMU_1M)*4 + FIRST_PAGE_DESCRIPTOR_ADDR) // table start position + offset = 'addr' table item position +#define MMU_GET_FIRST_TABLE_ITEM(addr) (*(UINT32 *)MMU_GET_FIRST_TABLE_ADDR(addr)) // get item content which storaged by table +#define MMU_GET_SECOND_TABLE_BASE(addr) ((MMU_GET_FIRST_TABLE_ITEM(addr)) & 0xfffffc00) // if the first item ID is MMU_FIRST_LEVEL_PAGE_TABLE_ID, get second table item addr by hi 22bits +#define MMU_GET_SECOND_TABLE_OFFSET(addr) (((addr) % MMU_1M) / MMU_4K * 4) // second table item offset +#define MMU_GET_SECOND_TABLE_ADDR(addr) (MMU_GET_SECOND_TABLE_BASE(addr) + MMU_GET_SECOND_TABLE_OFFSET(addr)) + +#define CODE_PROTECT do { \ + MMU_PARAM mPara; \ + /* note: must confirm that every addr be aglined as 4K(64K) */ \ + mPara.startAddr = (UINTPTR)&__text_start; \ + mPara.endAddr = (UINTPTR)&__ram_data_start; \ + mPara.uwFlag = BUFFER_ENABLE | CACHE_ENABLE | ACCESS_PERM_RO_RO; \ + mPara.stPage = (SENCOND_PAGE *)&g_mmuOsPage; \ + LOS_MMUParamSet(&mPara); \ +} while (0) + +/** + * @ingroup mmu_config + * @brief Memory Management Unit Cache/Buffer/Access Permission Setting. + * + * @par Description: + * This API is used to set the Cache/Buffer/access permission mode of a section that is specified by a starting address and ending address + * @attention + *
    + *
  • The passed-in starting address and ending address must be aligned on a boundary of 4K. The access permission mode can be only set to ACCESS_PERM_RO_RO and ACCESS_PERM_RW_RW.
  • + *
+ * + * @param MMU_PARAM [IN] param for mmu setting, the struct contains below members + * startAddr: Starting address of a section. + * endAddr: Ending address of a section. + * uwFlag: mode set. There are three func could be controlled with three bit. + * bit0: ACCESS_PERM_RW_RW/ACCESS_PERM_RO_RO(1/0) + * bit1: CACHE_ENABLE/CACHE_DISABLE(1/0) + * bit2: BUFFER_ENABLE/BUFFER_DISABLE(1/0) + * bit3: FIRST_SECTION/SECOND_PAGE(1/0) it need comfire your memory type, be descripted + * bit4~7: ignore + * stPage: the goal object of second page, if uwFlag bit3 is FIRST_SECTION, stPage will be ignored, and you can set this member as NULL + * + * @retval None. + * @par Dependency: + *
  • mmu.h: the header file that contains the API declaration.
+ * @see + */ +VOID LOS_MMUParamSet(MMU_PARAM *mPara); +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/nand.h b/hispark_taurus/liteos_a/board/include/hisoc/nand.h new file mode 100755 index 00000000..27cf42a2 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/nand.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_NAND_H__ +#define __HISOC_NAND_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define PERI_CRG52 (CRG_REG_BASE + 0x00D0) +#define PERI_CRG52_CLK_EN (1U << 1) +#define PERI_CRG52_CLK_SEL_198M (1U << 2) + +#define REG_SYSSTAT 0x008C +#define BOOT_FROM_NAND 2 + +static void hinfc620_clk_enable(int enable) +{ + unsigned int reg_val = readl(PERI_CRG52); + + if (enable) + reg_val |= (PERI_CRG52_CLK_EN | PERI_CRG52_CLK_SEL_198M); + else + reg_val &= ~PERI_CRG52_CLK_EN; + + writel(reg_val, (PERI_CRG52)); +} +#define check_boot_type() ((readl(SYS_CTRL_REG_BASE + REG_SYSSTAT) >> 4) & 0x3); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/net.h b/hispark_taurus/liteos_a/board/include/hisoc/net.h new file mode 100755 index 00000000..70e98775 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/net.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_NET_H__ +#define __HISOC_NET_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define HIETH_CRG_IOBASE (CRG_REG_BASE + 0x016c) +#define ETH_CORE_CLK_SELECT_54M (1 << 7) +#define ETH_PHY_RESET (1 << 3) + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/random.h b/hispark_taurus/liteos_a/board/include/hisoc/random.h new file mode 100755 index 00000000..f483883a --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/random.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HISOC_RANDOM_H +#define _HISOC_RANDOM_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +VOID HiRandomHwInit(VOID); +VOID HiRandomHwDeinit(VOID); +INT32 HiRandomHwGetInteger(UINT32 *result); +INT32 HiRandomHwGetNumber(CHAR *buffer, size_t bufLen); + +VOID PlatformRandomOperationsInit(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/spinand.h b/hispark_taurus/liteos_a/board/include/hisoc/spinand.h new file mode 100755 index 00000000..8d6762ad --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/spinand.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SPINAND_H__ +#define __HISOC_SPINAND_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ +/*****************************************************************************/ +#define CRG48 0xc0 +#define CRG48_SPI_NAND_CLK_SEL(_clk) (((_clk) & 0x3) << 6) +#define CRG48_SPI_NAND_CLK_EN (1 << 5) +#define CRG48_SPI_NAND_SOFT_RST_REQ (1 << 4) + +#define SPI_NAND_CLK_SEL_MASK (0x3 << 6) +#define DEVICE_TYPE_SHIFT 1 +#define DEVICE_TYPE_MASK (0x1 << 1) + +#define CLK_24M 0 +#define CLK_75M 1 +#define CLK_125M 2 + +#define SPI_NAND_CLK_SEL_24M CRG48_SPI_NAND_CLK_SEL(CLK_24M) +#define SPI_NAND_CLK_SEL_75M CRG48_SPI_NAND_CLK_SEL(CLK_75M) +#define SPI_NAND_CLK_SEL_125M CRG48_SPI_NAND_CLK_SEL(CLK_125M) + +#define GET_CLK_TYPE(_reg) (((_reg) >> 2) & 0x3) + +/*****************************************************************************/ +static void hisnfc100_set_system_clock(int clock, int clk_en) +{ + unsigned base = CRG_REG_BASE; + unsigned regval = readl(base + CRG48); + + if (!clock) + clock = SPI_NAND_CLK_SEL_75M; + regval = (regval & SPI_NAND_CLK_SEL_MASK) | clock; + + if (clk_en) + regval |= CRG48_SPI_NAND_CLK_EN; + else + regval &= ~CRG48_SPI_NAND_CLK_EN; + + if (readl(base + CRG48) != regval) + writel(regval, (base + CRG48)); +} + +/*****************************************************************************/ +static void hisnfc100_get_best_clock(unsigned int *clock) +{ + int ix; + int clk_reg; +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sysclk[] = { + CLK_2X(24), SPI_NAND_CLK_SEL_24M, + CLK_2X(75), SPI_NAND_CLK_SEL_75M, + CLK_2X(125), SPI_NAND_CLK_SEL_125M, + 0, 0, + }; +#undef CLK_2X + + clk_reg = SPI_NAND_CLK_SEL_24M; + for (ix = 0; sysclk[ix]; ix += 2) { + if (*clock < sysclk[ix]) + break; + clk_reg = sysclk[ix + 1]; + } + *clock = clk_reg; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/spinor.h b/hispark_taurus/liteos_a/board/include/hisoc/spinor.h new file mode 100755 index 00000000..5fb6c9a0 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/spinor.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SPINOR_H__ +#define __HISOC_SPINOR_H__ + +#include "asm/platform.h" +#include "asm/io.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define PERI_CRG48 (CRG_REG_BASE + 0x00C0) +#define PERI_CRG48_RST (1 << 0) +#define PERI_CRG48_CLKEN (1 << 1) +#define PERI_CRG48_CLK_24M (0 << 2) +#define PERI_CRG48_CLK_75M ((0 << 3) | (1 << 2)) +#define PERI_CRG48_CLK_125M ((1 << 2) | (1 << 3)) + +#define SFC_ADDR_MODE_REG (0x8C) +#define SFC_ADDR_MODE_MASK (0x80) +#define SFC_CLSEL_MASK (0xC) +#define SFC_PERI_CLKDIV1_SHIFT (28) +#define SFC_PERI_CLKDIV1_MASK (0xF) + +/*****************************************************************************/ +#undef GET_SFC_ADDR_MODE +#define GET_SFC_ADDR_MODE ({ \ + int start_up_mode = 0; \ + start_up_mode = readl(IO_ADDRESS(SYS_CTRL_REG_BASE + SFC_ADDR_MODE_REG)); \ + start_up_mode &= SFC_ADDR_MODE_MASK; \ + start_up_mode; }) + +/*****************************************************************************/ +static inline void hisfc350_set_system_clock(unsigned clock, int clk_en) +{ + unsigned int regval = readl(PERI_CRG48); + + regval = regval & (~SFC_CLSEL_MASK); + + if (clock) { + regval &= ~SFC_CLSEL_MASK; + regval |= clock & SFC_CLSEL_MASK; + } else { + regval &= ~SFC_CLSEL_MASK; + regval |= PERI_CRG48_CLK_24M; /* Default Clock */ + } + + if (clk_en) + regval |= PERI_CRG48_CLKEN; + + if (regval != readl(PERI_CRG48)) + writel(regval, (PERI_CRG48)); +} + +/*****************************************************************************/ +static inline void hisfc350_get_best_clock(unsigned int *clock) +{ + int ix; + int clk_reg; + +#define CLK_2X(_clk) (((_clk) + 1) >> 1) + unsigned int sysclk[] = { + CLK_2X(24), PERI_CRG48_CLK_24M, + CLK_2X(75), PERI_CRG48_CLK_75M, + CLK_2X(125), PERI_CRG48_CLK_125M, + 0, 0, + }; +#undef CLK_2X + + clk_reg = PERI_CRG48_CLK_24M; + for (ix = 0; sysclk[ix]; ix += 2) { + if (*clock < sysclk[ix]) + break; + clk_reg = sysclk[ix + 1]; + } + + *clock = clk_reg; +} + +/*****************************************************************************/ +#ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING +static inline char * hisfc350_get_clock_str(unsigned int clk_reg) +{ + static char buffer[40]; + + /* calculate reference PERI_CLKDIV1[31:28] */ + SFC_PR(BT_DBG, "clk_reg=0x%0x.\n", clk_reg); + clk_reg = 216 / ((clk_reg >> SFC_PERI_CLKDIV1_SHIFT) + & SFC_PERI_CLKDIV1_MASK); + (VOID)sprintf_s(buffer, sizeof(buffer), "%dM", clk_reg); + + return buffer; +} +#endif /* CONFIG_PERI_SHOW_CYCLE_TIMING */ + + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/sys_ctrl.h b/hispark_taurus/liteos_a/board/include/hisoc/sys_ctrl.h new file mode 100755 index 00000000..220935c2 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/sys_ctrl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_SYS_CTRL_H__ +#define __HISOC_SYS_CTRL_H__ + +#include "asm/platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define REG_SC_CTRL 0 +#define REG_SC_SYSRES 0x4 +#define PERIPHCTRL24 0x94 + +#define REG_SC_GEN0 0x0138 +#define REG_SC_GEN1 0x013c +#define REG_SC_GEN2 0x0140 +#define REG_SC_GEN3 0x0144 +#define REG_SC_GEN4 0x0148 + +#define REG_SC_DDRT0 0x0090 +#define NORMAL_BOOTMODE_OFFSET 9 +#define NORMAL_BOOTMODE_MASK 3 + +/********** Communication Register and flag used by bootrom *************/ +#define REG_START_FLAG (SYS_CTRL_REG_BASE + REG_SC_GEN1) +#define CONFIG_START_MAGIC (0x444f574e) + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/timer.h b/hispark_taurus/liteos_a/board/include/hisoc/timer.h new file mode 100755 index 00000000..264d521a --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/timer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_TIMER_H__ +#define __HISOC_TIMER_H__ + +#include "asm/platform.h" +#include "los_bitmap.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define TIMER_LOAD 0x0 +#define TIMER_VALUE 0x4 +#define TIMER_CONTROL 0x8 +#define TIMER_INT_CLR 0xc +#define TIMER_RIS 0x10 +#define TIMER_MIS 0x14 +#define TIMER_BGLOAD 0x18 + +#define TIMER0_ENABLE BIT(16) +#define TIMER1_ENABLE BIT(17) +#define TIMER2_ENABLE BIT(18) +#define TIMER3_ENABLE BIT(19) +#define TIMER4_ENABLE BIT(20) +#define TIMER5_ENABLE BIT(21) +#define TIMER6_ENABLE BIT(22) +#define TIMER7_ENABLE BIT(23) +#define TIMER8_ENABLE BIT(24) +#define TIMER9_ENABLE BIT(25) +#define TIMER10_ENABLE BIT(26) +#define TIMER11_ENABLE BIT(27) + +unsigned int arch_timer_rollback(void); +VOID LOS_Udelay(UINT32 usecs); +VOID LOS_Mdelay(UINT32 msecs); +VOID reset_timer_masked(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +#endif + diff --git a/hispark_taurus/liteos_a/board/include/hisoc/uart.h b/hispark_taurus/liteos_a/board/include/hisoc/uart.h new file mode 100755 index 00000000..2059387e --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/uart.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_UART_H__ +#define __HISOC_UART_H__ + +#include "asm/platform.h" +#include "los_typedef.h" +#include "los_base.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define CONFIG_UART0_BAUDRATE 115200 +#define CONFIG_UART_CLK_INPUT (24000000) // 24M or 6M + +#define UART0 0 +#define UART1 1 +#define UART2 2 +#define UART3 3 + +#define UART0_ENABLE 1 +#define UART1_ENABLE 1 +#define UART2_ENABLE 1 +#define UART3_ENABLE 1 + +#define UART0_DMA_RX_PERI 16 +#define UART1_DMA_RX_PERI 18 +#define UART2_DMA_RX_PERI 20 +#define UART3_DMA_RX_PERI 22 + +#define uart_pin_mux_cfg(uart_num) ({ \ + if (UART0 == uart_num) {} \ + else if (UART1 == uart_num) { \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x07C); \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x084); \ + } \ + else if (UART2 == uart_num) { \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x088); \ + WRITE_UINT16(0x01, IO_MUX_REG_BASE + 0x08C); \ + } \ + else if (UART3 ==uart_num) { \ + WRITE_UINT16(0x02, IO_MUX_REG_BASE + 0x078); \ + WRITE_UINT16(0x02, IO_MUX_REG_BASE + 0x080); \ + } \ + }) +#define uart_clk_cfg(uart_num, flag) ({ \ + unsigned int tmp = 0; \ + tmp = GET_UINT32(CRG_REG_BASE + 0x01B8); \ + if (flag) \ + tmp |= (1<<(uart_num)); \ + else \ + tmp &= ~(1<<(uart_num)); \ + WRITE_UINT32(tmp, CRG_REG_BASE + 0x01B8); \ + }) +#define get_uart_dma_peri(uart_num) ({ \ + unsigned int peri_num = -1; \ + if (UART0 == uart_num) \ + peri_num = UART0_DMA_RX_PERI; \ + else if (UART1 == uart_num) \ + peri_num = UART1_DMA_RX_PERI; \ + else if (UART2 == uart_num) \ + peri_num = UART2_DMA_RX_PERI; \ + else if (UART3 == uart_num) \ + peri_num = UART3_DMA_RX_PERI; \ + peri_num; \ + }) + + +#define TTYS0 "/dev/ttyS0" + +#define CONSOLE_UART UART0 + +#define CONSOLE_UART_BAUDRATE 115200 +#define UART_NUM 4 +#if (CONSOLE_UART == UART0) +#define TTY_DEVICE "/dev/uartdev-0" +#define UART_REG_BASE UART0_REG_BASE +#define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART0 +#elif (CONSOLE_UART == UART1) +#define TTY_DEVICE "/dev/uartdev-1" +#define UART_REG_BASE UART1_REG_BASE +#define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART1 +#elif (CONSOLE_UART == UART2) +#define TTY_DEVICE "/dev/uartdev-2" +#define UART_REG_BASE UART2_REG_BASE +#define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART2 +#elif (CONSOLE_UART == UART3) +#define TTY_DEVICE "/dev/uartdev-3" +#define UART_REG_BASE UART3_REG_BASE +#define NUM_HAL_INTERRUPT_UART NUM_HAL_INTERRUPT_UART3 +#endif + +#ifdef LOSCFG_PLATFORM_HISI_AMP +#undef TTY_DEVICE +#define TTY_DEVICE "/dev/virt-tty" +#endif + +typedef struct { + UINT32 base; + INT32 msec_timeout; + int isr_vector; +} channel_data_t; + +extern void uart_init(void); +extern void uart_interrupt_unmask(void); +extern int uart_hwiCreate(void); +extern UINT8 uart_getc(void); +extern char uart_fputc(char c, void *f); + +extern UINT32 UartPutsReg(UINTPTR base, const CHAR *s, UINT32 len, BOOL isLock); +extern VOID UartPuts(const CHAR *s, UINT32 len, BOOL isLock); + +#define UART_WITHOUT_LOCK 0 +#define UART_WITH_LOCK 1 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/hisoc/usb3.h b/hispark_taurus/liteos_a/board/include/hisoc/usb3.h new file mode 100755 index 00000000..b2e34884 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/hisoc/usb3.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HISOC_USB3_H__ +#define __HISOC_USB3_H__ + +#include "los_base.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define CONFIG_HIUSB_XHCI_IOBASE 0x100E0000 +#define CONFIG_HIUSB_XHCI_IOSIZE 0x10000 + +#define DWC_USB3_PORT1_BASE_ADDR CONFIG_HIUSB_XHCI_IOBASE +#define DWC_USB3_PORT1_ADDR_OFFSET 0xc000 + +#define USB_CACHE_ALIGN_SIZE 64 +#define ALIGNBYTES 3 +#define SKB_DATA_ALIGN(X) ALIGN(X, USB_CACHE_ALIGN_SIZE) +#define UVC_USE_CTRL_EP 1 + +#define FMASS_DEV_PATH "/dev/mmcblk0p" + +extern VOID HiUsb3StartHcd(VOID); +extern VOID HiUsb3StopHcd(VOID); +extern VOID HiUsb3Host2Device(VOID); +extern BOOL HiUsbIsDeviceMode(VOID); +extern VOID UsbOtgSwSetDeviceState(VOID); +extern VOID UsbOtgSwClearDeviceState(VOID); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/platform_config.h b/hispark_taurus/liteos_a/board/include/platform_config.h new file mode 100755 index 00000000..18ad36f3 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/platform_config.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PLATFORM_CONFIG_H__ +#define __PLATFORM_CONFIG_H__ + +#include "hisoc/clock.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define LOSCFG_PLATFORM_HWI_LIMIT 96 +#define OS_SYS_CLOCK (50000000) + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/reset_shell.h b/hispark_taurus/liteos_a/board/include/reset_shell.h new file mode 100755 index 00000000..38020dae --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/reset_shell.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RESET_SHELL_H +#define _RESET_SHELL_H +#include "los_task.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +typedef VOID* (*STORAGE_HOOK_FUNC)(VOID*); + +typedef struct tagHookFuncNode { + STORAGE_HOOK_FUNC pHandler; + VOID *pParam; + struct tagHookFuncNode *pNext; +}Hook_Func_Node; + +extern Hook_Func_Node *g_hook_func_node; + +UINT32 osReHookFuncAdd(STORAGE_HOOK_FUNC handler, VOID *param); +UINT32 osReHookFuncDel(STORAGE_HOOK_FUNC handler); +VOID osReHookFuncHandle(VOID); +extern void cmd_reset(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/hispark_taurus/liteos_a/board/include/system_config.h b/hispark_taurus/liteos_a/board/include/system_config.h new file mode 100755 index 00000000..1fee5486 --- /dev/null +++ b/hispark_taurus/liteos_a/board/include/system_config.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*************************************************************/ +#ifndef _SYSTEM_CONFIG_H +#define _SYSTEM_CONFIG_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** system source configuration **/ +/** + * @ingroup los_config + * Maximum supported number of tasks except the idle task rather than the number of usable tasks + */ +#define LOSCFG_BASE_CORE_TSK_CONFIG 64 +/** + * @ingroup los_config + * Maximum supported number of semaphores + */ +#define LOSCFG_BASE_IPC_SEM_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of mutexes + */ +#define LOSCFG_BASE_IPC_MUX_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of queues rather than the number of usable queues + */ +#define LOSCFG_BASE_IPC_QUEUE_CONFIG 1024 +/** + * @ingroup los_config + * Maximum supported number of software timers rather than the number of usable software timers + */ +#define LOSCFG_BASE_CORE_SWTMR_CONFIG 1024 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +#endif /* _SYSTEM_CONFIG_H */ +/*************************************************************/ diff --git a/hispark_taurus/liteos_a/board/libs/debug/libbsp_config.a b/hispark_taurus/liteos_a/board/libs/debug/libbsp_config.a new file mode 100755 index 0000000000000000000000000000000000000000..a9569cd35449c76563f9a7ac2ee820a3a2afae6d GIT binary patch literal 72548 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