From b218f865e8a7defdcb2c6d87e8d93f9ea7e4e9f5 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 22 Sep 2021 18:29:07 +0200 Subject: [PATCH 01/17] mtd: cfi_flash: use cfi_flash_num_flash_banks only when supported When CONFIG_SYS_MAX_FLASH_BANKS_DETECT is activated, CONFIG_SYS_MAX_FLASH_BANKS is replaced by cfi_flash_num_flash_banks, but this variable is defined in drivers/mtd/cfi_flash.c, which is compiled only when CONFIG_FLASH_CFI_DRIVER is activated, in U-Boot or in SPL when CONFIG_SPL_MTD_SUPPORT is activated. This patch deactivates this feature CONFIG_SYS_MAX_FLASH_BANKS_DETECT when flash cfi driver is not activated to avoid compilation issue in the next patch, when CONFIG_SYS_MAX_FLASH_BANKS is used in spi_nor_scan(). Signed-off-by: Patrick Delaunay --- include/mtd/cfi_flash.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/mtd/cfi_flash.h b/include/mtd/cfi_flash.h index 4963c89642f2..a1af6fc200fd 100644 --- a/include/mtd/cfi_flash.h +++ b/include/mtd/cfi_flash.h @@ -157,11 +157,17 @@ struct cfi_pri_hdr { * Use CONFIG_SYS_MAX_FLASH_BANKS_DETECT if defined */ #if defined(CONFIG_SYS_MAX_FLASH_BANKS_DETECT) -#define CONFIG_SYS_MAX_FLASH_BANKS (cfi_flash_num_flash_banks) #define CFI_MAX_FLASH_BANKS CONFIG_SYS_MAX_FLASH_BANKS_DETECT +/* map to cfi_flash_num_flash_banks only when supported */ +#if IS_ENABLED(CONFIG_FLASH_CFI_DRIVER) && \ + (!IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_SPL_MTD_SUPPORT)) +#define CONFIG_SYS_MAX_FLASH_BANKS (cfi_flash_num_flash_banks) /* board code can update this variable before CFI detection */ extern int cfi_flash_num_flash_banks; #else +#define CONFIG_SYS_MAX_FLASH_BANKS CONFIG_SYS_MAX_FLASH_BANKS_DETECT +#endif +#else #define CFI_MAX_FLASH_BANKS CONFIG_SYS_MAX_FLASH_BANKS #endif From a4f2d83414557f2ad7b63d537e2c31790d0f184d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 22 Sep 2021 18:29:08 +0200 Subject: [PATCH 02/17] mtd: spi: nor: force mtd name to "nor%d" Force the mtd name of spi-nor to "nor" + the driver sequence number: "nor0", "nor1"... beginning after the existing nor devices. This patch is coherent with existing "nand" and "spi-nand" mtd device names. When CFI MTD NOR device are supported, the spi-nor index is chosen after the last CFI device defined by CONFIG_SYS_MAX_FLASH_BANKS. When CONFIG_SYS_MAX_FLASH_BANKS_DETECT is activated, this config is replaced by to cfi_flash_num_flash_banks in the include file mtd/cfi_flash.h. This generic name "nor%d" can be use to identify the mtd spi-nor device without knowing the real device name or the DT path of the device, used with API get_mtd_device_nm() and is used in mtdparts command. This patch also avoids issue when the same NOR device is present 2 times, for example on STM32MP15F-EV1: STM32MP> mtd list SF: Detected mx66l51235l with page size 256 Bytes, erase size 64 KiB, \ total 64 MiB List of MTD devices: * nand0 - type: NAND flash - block size: 0x40000 bytes - min I/O: 0x1000 bytes - OOB size: 224 bytes - OOB available: 118 bytes - ECC strength: 8 bits - ECC step size: 512 bytes - bitflip threshold: 6 bits - 0x000000000000-0x000040000000 : "nand0" * mx66l51235l - device: mx66l51235l@0 - parent: spi@58003000 - driver: jedec_spi_nor - path: /soc/spi@58003000/mx66l51235l@0 - type: NOR flash - block size: 0x10000 bytes - min I/O: 0x1 bytes - 0x000000000000-0x000004000000 : "mx66l51235l" * mx66l51235l - device: mx66l51235l@1 - parent: spi@58003000 - driver: jedec_spi_nor - path: /soc/spi@58003000/mx66l51235l@1 - type: NOR flash - block size: 0x10000 bytes - min I/O: 0x1 bytes - 0x000000000000-0x000004000000 : "mx66l51235l" The same mtd name "mx66l51235l" identify the 2 instances mx66l51235l@0 and mx66l51235l@1. This patch fixes a ST32CubeProgrammer / stm32prog command issue with nor0 target on STM32MP157C-EV1 board introduced by commit b7f060565e31 ("mtd: spi-nor: allow registering multiple MTDs when DM is enabled"). Fixes: b7f060565e31 ("mtd: spi-nor: allow registering multiple MTDs when DM is enabled") Signed-off-by: Patrick Delaunay [trini: Add to for DM_MAX_SEQ_STR] Signed-off-by: Tom Rini --- drivers/mtd/spi/spi-nor-core.c | 17 ++++++++++++++--- include/dm/device.h | 3 ++- include/linux/mtd/spi-nor.h | 2 ++ include/mtd.h | 5 +++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index d5d905fa5a1a..f1b4e5ea8e38 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include +#include #include #include @@ -3664,6 +3666,11 @@ int spi_nor_scan(struct spi_nor *nor) struct mtd_info *mtd = &nor->mtd; struct spi_slave *spi = nor->spi; int ret; + int cfi_mtd_nb = 0; + +#ifdef CONFIG_SYS_MAX_FLASH_BANKS + cfi_mtd_nb = CONFIG_SYS_MAX_FLASH_BANKS; +#endif /* Reset SPI protocol for all commands. */ nor->reg_proto = SNOR_PROTO_1_1_1; @@ -3715,8 +3722,12 @@ int spi_nor_scan(struct spi_nor *nor) if (ret) return ret; - if (!mtd->name) - mtd->name = info->name; + if (!mtd->name) { + sprintf(nor->mtd_name, "%s%d", + MTD_DEV_TYPE(MTD_DEV_TYPE_NOR), + cfi_mtd_nb + dev_seq(nor->dev)); + mtd->name = nor->mtd_name; + } mtd->dev = nor->dev; mtd->priv = nor; mtd->type = MTD_NORFLASH; @@ -3821,7 +3832,7 @@ int spi_nor_scan(struct spi_nor *nor) nor->rdsr_dummy = params.rdsr_dummy; nor->rdsr_addr_nbytes = params.rdsr_addr_nbytes; - nor->name = mtd->name; + nor->name = info->name; nor->size = mtd->size; nor->erase_size = mtd->erasesize; nor->sector_size = mtd->erasesize; diff --git a/include/dm/device.h b/include/dm/device.h index 0a9718a5b81a..9d0ca6a550e5 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -207,8 +207,9 @@ struct udevice_rt { u32 flags_; }; -/* Maximum sequence number supported */ +/* Maximum sequence number supported and associated string length */ #define DM_MAX_SEQ 999 +#define DM_MAX_SEQ_STR 3 /* Returns the operations for a device */ #define device_get_ops(dev) (dev->driver->ops) diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 7ddc4ba2bf2d..4ceeae623de4 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -7,6 +7,7 @@ #ifndef __LINUX_MTD_SPI_NOR_H #define __LINUX_MTD_SPI_NOR_H +#include #include #include #include @@ -561,6 +562,7 @@ struct spi_nor { int (*ready)(struct spi_nor *nor); void *priv; + char mtd_name[MTD_NAME_SIZE(MTD_DEV_TYPE_NOR)]; /* Compatibility for spi_flash, remove once sf layer is merged with mtd */ const char *name; u32 size; diff --git a/include/mtd.h b/include/mtd.h index b569331edb0f..f9e5082446a0 100644 --- a/include/mtd.h +++ b/include/mtd.h @@ -6,10 +6,15 @@ #ifndef _MTD_H_ #define _MTD_H_ +#include +#include #include int mtd_probe_devices(void); void board_mtdparts_default(const char **mtdids, const char **mtdparts); +/* compute the max size for the string associated to a dev type */ +#define MTD_NAME_SIZE(type) (sizeof(MTD_DEV_TYPE(type)) + DM_MAX_SEQ_STR) + #endif /* _MTD_H_ */ From b81ce79df091834430dce72f0e4d1451f25fc8f7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 14 Sep 2021 20:28:24 +0200 Subject: [PATCH 03/17] mtd: spi: Set CONFIG_SF_DEFAULT_MODE default to 0 Before e2e95e5e254 ("spi: Update speed/mode on change") most systems silently defaulted to SF bus mode 0. Now the mode is always updated, which causes breakage. It seems most SF which are used as boot media operate in bus mode 0, so switch that as the default. This should fix booting at least on Altera SoCFPGA, ST STM32, Xilinx ZynqMP, NXP iMX and Rockchip SoCs, which recently ran into trouble with mode 3. Marvell Kirkwood and Xilinx microblaze need to be checked as those might need mode 3. Signed-off-by: Marek Vasut Cc: Aleksandar Gerasimovski Cc: Andreas Biessmann Cc: Eugen Hristev Cc: Michal Simek Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Peng Fan Cc: Siew Chin Lim Cc: Tom Rini Cc: Valentin Longchamp Cc: Vignesh Raghavendra --- drivers/mtd/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index b2291f729059..f03fe05e333d 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -57,7 +57,7 @@ config SF_DEFAULT_CS config SF_DEFAULT_MODE hex "SPI Flash default mode (see include/spi.h)" depends on SPI_FLASH || DM_SPI_FLASH - default 3 + default 0 help The default mode may be provided by the platform to handle the common case when only a single serial From b8919eaa6835c8a606569ea596dd4ed209bd1d67 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 13 Sep 2021 16:25:53 +0200 Subject: [PATCH 04/17] mtd: nand: raw: convert nand_dt_init() to ofnode_xx() interface nand_dt_init() is still using fdtdec_xx() interface. If OF_LIVE flag is enabled, dt property can't be get anymore. Updating all fdtdec_xx() interface to ofnode_xx() to solve this issue. For doing this, node parameter type must be ofnode. First idea was to convert "node" parameter to ofnode type inside nand_dt_init() using offset_to_ofnode(node). But offset_to_ofnode() is not bijective, in case OF_LIVE flag is enabled, it performs an assert(). So, this leads to update nand_chip struct flash_node field from int to ofnode and to update all nand_dt_init() callers. Signed-off-by: Patrice Chotard --- drivers/mtd/nand/raw/denali.c | 2 +- drivers/mtd/nand/raw/mxs_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 27 +++++++++++--------------- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- include/linux/mtd/rawnand.h | 6 +++--- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index ab91db85467d..c827f80281c1 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1246,7 +1246,7 @@ int denali_init(struct denali_nand_info *denali) denali->active_bank = DENALI_INVALID_BANK; - chip->flash_node = dev_of_offset(denali->dev); + chip->flash_node = dev_ofnode(denali->dev); /* Fallback to the default name if DT did not give "label" property */ if (!mtd->name) mtd->name = "denali-nand"; diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c index e6bbfac4d686..748056a43e6f 100644 --- a/drivers/mtd/nand/raw/mxs_nand.c +++ b/drivers/mtd/nand/raw/mxs_nand.c @@ -1379,7 +1379,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info) nand->options |= NAND_NO_SUBPAGE_WRITE; if (nand_info->dev) - nand->flash_node = dev_of_offset(nand_info->dev); + nand->flash_node = dev_ofnode(nand_info->dev); nand->cmd_ctrl = mxs_nand_cmd_ctrl; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3679ee727e94..b1fd779884fe 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -29,9 +29,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#if CONFIG_IS_ENABLED(OF_CONTROL) -#include -#endif #include #include #include @@ -4576,23 +4573,20 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, EXPORT_SYMBOL(nand_get_flash_type); #if CONFIG_IS_ENABLED(OF_CONTROL) -#include -DECLARE_GLOBAL_DATA_PTR; -static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node) +static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode node) { int ret, ecc_mode = -1, ecc_strength, ecc_step; - const void *blob = gd->fdt_blob; const char *str; - ret = fdtdec_get_int(blob, node, "nand-bus-width", -1); + ret = ofnode_read_s32_default(node, "nand-bus-width", -1); if (ret == 16) chip->options |= NAND_BUSWIDTH_16; - if (fdtdec_get_bool(blob, node, "nand-on-flash-bbt")) + if (ofnode_read_bool(node, "nand-on-flash-bbt")) chip->bbt_options |= NAND_BBT_USE_FLASH; - str = fdt_getprop(blob, node, "nand-ecc-mode", NULL); + str = ofnode_read_string(node, "nand-ecc-mode"); if (str) { if (!strcmp(str, "none")) ecc_mode = NAND_ECC_NONE; @@ -4608,9 +4602,10 @@ static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node) ecc_mode = NAND_ECC_SOFT_BCH; } - - ecc_strength = fdtdec_get_int(blob, node, "nand-ecc-strength", -1); - ecc_step = fdtdec_get_int(blob, node, "nand-ecc-step-size", -1); + ecc_strength = ofnode_read_s32_default(node, + "nand-ecc-strength", -1); + ecc_step = ofnode_read_s32_default(node, + "nand-ecc-step-size", -1); if ((ecc_step >= 0 && !(ecc_strength >= 0)) || (!(ecc_step >= 0) && ecc_strength >= 0)) { @@ -4627,13 +4622,13 @@ static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node) if (ecc_step > 0) chip->ecc.size = ecc_step; - if (fdt_getprop(blob, node, "nand-ecc-maximize", NULL)) + if (ofnode_read_bool(node, "nand-ecc-maximize")) chip->ecc.options |= NAND_ECC_MAXIMIZE; return 0; } #else -static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node) +static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode node) { return 0; } @@ -4657,7 +4652,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *type; int ret; - if (chip->flash_node) { + if (ofnode_valid(chip->flash_node)) { ret = nand_dt_init(mtd, chip, chip->flash_node); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index fd81a9500b8b..e17f1f8975ef 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -823,7 +823,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node) nand->cs_used[i] = cs[i]; } - nand->chip.flash_node = ofnode_to_offset(node); + nand->chip.flash_node = node; return 0; } diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 7bc6ec7beea2..c378f08f6805 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1711,7 +1711,7 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum) * in the DT. */ nand->ecc.mode = NAND_ECC_HW; - nand->flash_node = node; + nand->flash_node = offset_to_ofnode(node); nand->select_chip = sunxi_nfc_select_chip; nand->cmd_ctrl = sunxi_nfc_cmd_ctrl; nand->read_buf = sunxi_nfc_read_buf; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 66febc6b7212..2fba9dc317e3 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -891,7 +891,7 @@ struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - int flash_node; + ofnode flash_node; uint8_t (*read_byte)(struct mtd_info *mtd); u16 (*read_word)(struct mtd_info *mtd); @@ -973,12 +973,12 @@ struct nand_chip { static inline void nand_set_flash_node(struct nand_chip *chip, ofnode node) { - chip->flash_node = ofnode_to_offset(node); + chip->flash_node = node; } static inline ofnode nand_get_flash_node(struct nand_chip *chip) { - return offset_to_ofnode(chip->flash_node); + return chip->flash_node; } static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd) From 24ea366add54b8ca753eb3259bff8b50693dc8ef Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 16 Sep 2021 16:53:14 +0200 Subject: [PATCH 05/17] imx: imx7d-sdb: fix ethernet, sync .dts with linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0d52bab46 (mx7dsabre: Enable DM_ETH) changed these flags from 0 (aka GPIO_ACTIVE_HIGH) to GPIO_ACTIVE_LOW. It claimed to "Also sync device tree with v5.5-rc1", but in the linux tree, these gpios have always been GPIO_ACTIVE_HIGH ever since this node was introduced around v4.13 (linux commit 184f39b5). I'm guessing that the reason for the GPIO_ACTIVE_LOW was to work around the behaviour of the soft-spi driver back then, which effectively defaulted to spi-mode 3 and not 0. That was arguably a bug in the soft-spi driver, which then got fixed in 0e146993bb3 (spi: add support for all spi modes with soft spi), but that commit then broke ethernet on this board. Fix it by setting the gpios as active high, which as a bonus actually brings us in sync with the .dts in the linux source tree. Without this, one gets Net: Could not get PHY for FEC0: addr 0 No ethernet found. With this, ethernet (at least ping and tftp) works as expected from the U-Boot shell. Cc: Fabio Estevam Cc: Joris Offouga Cc: "Christian Bräuner Sørensen" Signed-off-by: Rasmus Villemoes --- arch/arm/dts/imx7d-sdb.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/dts/imx7d-sdb.dts b/arch/arm/dts/imx7d-sdb.dts index 8191ac7c334e..ea2e58dd5aad 100644 --- a/arch/arm/dts/imx7d-sdb.dts +++ b/arch/arm/dts/imx7d-sdb.dts @@ -44,9 +44,9 @@ compatible = "spi-gpio"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi4>; - gpio-sck = <&gpio1 13 GPIO_ACTIVE_LOW>; - gpio-mosi = <&gpio1 9 GPIO_ACTIVE_LOW>; - cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + gpio-sck = <&gpio1 13 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 9 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; num-chipselects = <1>; #address-cells = <1>; #size-cells = <0>; From 65513f3c185557c0690924102386fbd42b2ea351 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 27 Sep 2021 23:03:26 +0200 Subject: [PATCH 06/17] arm: dts: armada8040: Fix CP0 eMMC/SDIO support During the migration to a single DTSI for the CP110-s specific pinctrl compatibles were moved to the SoC DTSI as CP0 and CP1 have some specifics. Namely, CP0 eMMC/SDIO support depends on the mvebu-pinctrl driver setting the BIT(0) in eMMC PHY IO Control 0 Register to 0 in order for the connect the eMMC/SDIO PHY to the controller and not use it as a MPP pin multiplexor. So, the mvebu-pinctrl driver check specifically for the "marvell,armada-8k-cpm-pinctrl" compatible to clear the that bit. Issue is that compatibles in the 8040 DTSI were set to "marvell,8k-cpm-pinctrl" for CP0 and "marvell,8k-cps-pinctrl" for the CP1. This is obviously incorrect as the pinctrl driver does not know about these. So fix the regression by applying correct compatibles to the DTSI. Regression found and tested on the Puzzle M801 board. Fixes: a0ba97e5 ("arm: armada: dts: Use a single dtsi for cp110 die description") Signed-off-by: Robert Marko Reviewed-by: Stefan Roese --- arch/arm/dts/armada-8040.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/armada-8040.dtsi b/arch/arm/dts/armada-8040.dtsi index 5123742b8d51..eec5fa277405 100644 --- a/arch/arm/dts/armada-8040.dtsi +++ b/arch/arm/dts/armada-8040.dtsi @@ -40,7 +40,7 @@ }; &cp0_pinctl { - compatible = "marvell,mvebu-pinctrl", "marvell,8k-cpm-pinctrl"; + compatible = "marvell,mvebu-pinctrl", "marvell,armada-8k-cpm-pinctrl"; bank-name ="cp0-110"; cp0_i2c0_pins: cp0-i2c-pins-0 { @@ -75,7 +75,7 @@ }; &cp1_pinctl { - compatible = "marvell,mvebu-pinctrl", "marvell,8k-cps-pinctrl"; + compatible = "marvell,mvebu-pinctrl", "marvell,armada-8k-cps-pinctrl"; bank-name ="cp1-110"; cp1_ge1_rgmii_pins: cp1-ge-rgmii-pins-0 { From 6f3a9227cc79009e125006890829496ce00726ea Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Thu, 16 Sep 2021 11:55:48 +0200 Subject: [PATCH 07/17] mailmap: Update mail address for Nicolas Saenz julienne The @suse.de address doesn't exist anymore. Update it to something not dependent on my workplace. Signed-off-by: Nicolas Saenz Julienne Signed-off-by: Matthias Brugger --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index b76f02283c57..b09fc321bd61 100644 --- a/.mailmap +++ b/.mailmap @@ -32,6 +32,7 @@ Jagan Teki Igor Opaniuk Igor Opaniuk Markus Klotzbuecher +Nicolas Saenz Julienne Patrice Chotard Patrick Delaunay Paul Burton From 33166054c72716e46d492a0588f00900a9684a97 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 17 Sep 2021 10:19:43 +0200 Subject: [PATCH 08/17] arm: rpi: perform XHCI firmware upload only once XHCI firmware upload must be performed only once after initializing the PCI bridge. This fixes USB stack initialization after calling "usb stop; usb start" on Raspberry Pi 4B. Signed-off-by: Marek Szyprowski Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Matthias Brugger --- arch/arm/mach-bcm283x/msg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c index 347aece3cd8d..345f7fe2b77f 100644 --- a/arch/arm/mach-bcm283x/msg.c +++ b/arch/arm/mach-bcm283x/msg.c @@ -170,6 +170,12 @@ int bcm2711_notify_vl805_reset(void) ALLOC_CACHE_ALIGN_BUFFER(struct msg_notify_vl805_reset, msg_notify_vl805_reset, 1); int ret; + static int done = false; + + if (done) + return 0; + + done = true; BCM2835_MBOX_INIT_HDR(msg_notify_vl805_reset); BCM2835_MBOX_INIT_TAG(&msg_notify_vl805_reset->dev_addr, From c67fecd2125b43cd478d64c741772d11323d7b6d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 27 Aug 2021 12:53:32 +0200 Subject: [PATCH 09/17] ARM: zynq: Enable capsule update for qspi and mmc Generate dfu_alt_info setup at runtime for capsule update. Enabling this feature will help with upgrading boards without remembering what is where. The similar change was done for ZynqMP by commit b86f43de0be0 ("xilinx: zynqmp: Add support for runtime dfu_alt_info setup"). Code needs to be enabled by CONFIG_SET_DFU_ALT_INFO. And also enable capsule on disk for RAW firmware images with efidebug command. Two indexes are supported for SPL flow. Images can be generated like: ./tools/mkeficapsule --raw spl/boot.bin --index 1 capsule1.bin ./tools/mkeficapsule --raw u-boot.img --index 2 capsule2.bin Then place them to SD card and load them: load mmc 0 10000000 capsule1.bin && efidebug capsule update -v 10000000 load mmc 0 10000000 capsule2.bin && efidebug capsule update -v 10000000 FSBL flow will also work where only index 1 capsule is used. There should be enough space for using boot.bin with bitstream too. Zynq also support multiple boot locations in SPI or MMC but it is not wired by this patch. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/bea5fc75a87a5971f118b46bab4aa7ca39a629c6.1630061610.git.michal.simek@xilinx.com --- board/xilinx/zynq/board.c | 35 ++++++++++++++++++++++++++++++ configs/xilinx_zynq_virt_defconfig | 6 +++++ 2 files changed, 41 insertions(+) diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 61e0a90c119b..1111ad6fca9c 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -151,3 +152,37 @@ enum env_location env_get_location(enum env_operation op, int prio) return ENVL_NOWHERE; } } + +#if defined(CONFIG_SET_DFU_ALT_INFO) + +#define DFU_ALT_BUF_LEN SZ_1K + +void set_dfu_alt_info(char *interface, char *devstr) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); + + if (env_get("dfu_alt_info")) + return; + + memset(buf, 0, sizeof(buf)); + + switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) { + case ZYNQ_BM_SD: + snprintf(buf, DFU_ALT_BUF_LEN, + "mmc 0:1=boot.bin fat 0 1;" + "u-boot.img fat 0 1"); + break; + case ZYNQ_BM_QSPI: + snprintf(buf, DFU_ALT_BUF_LEN, + "sf 0:0=boot.bin raw 0 0x1500000;" + "u-boot.img raw 0x%x 0x500000", + CONFIG_SYS_SPI_U_BOOT_OFFS); + break; + default: + return; + } + + env_set("dfu_alt_info", buf); + puts("DFU alt info setting: done\n"); +} +#endif diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig index 66af37ae1857..d1595e2a1af4 100644 --- a/configs/xilinx_zynq_virt_defconfig +++ b/configs/xilinx_zynq_virt_defconfig @@ -49,6 +49,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TFTPPUT=y CONFIG_CMD_CACHE=y +CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_TIME=y CONFIG_CMD_TIMER=y CONFIG_CMD_EXT4_WRITE=y @@ -69,6 +70,8 @@ CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DFU_TIMEOUT=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y +CONFIG_DFU_SF=y +CONFIG_SET_DFU_ALT_INFO=y CONFIG_SYS_DFU_DATA_BUF_SIZE=0x600000 CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQPL=y @@ -122,3 +125,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_FUNCTION_THOR=y CONFIG_DISPLAY=y CONFIG_SPL_GZIP=y +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y From 5d498a12b6416e2d692d720083eb6c57497112c4 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Wed, 15 Sep 2021 08:52:17 +0200 Subject: [PATCH 10/17] xilinx: zynqmp: Set modeboot env variable in eMMC bootmode Set environment variable modeboot to "emmcboot" in case of eMMC boot mode. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/c61231e4b8c6118862dfc82e923211637bf29991.1631688736.git.michal.simek@xilinx.com --- board/xilinx/zynqmp/zynqmp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index ea15e62eb21e..000a7cde8d84 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -672,6 +672,7 @@ int board_late_init(void) mode = "mmc"; bootseq = dev_seq(dev); + env_set("modeboot", "emmcboot"); break; case SD_MODE: puts("SD_MODE\n"); From 1a94d0554d0d8930e8f6e40cf4cd396ca61edd9c Mon Sep 17 00:00:00 2001 From: Amit Kumar Mahapatra Date: Wed, 15 Sep 2021 15:46:36 +0200 Subject: [PATCH 11/17] arm64: zynqmp: Add device tree properties for nand flash Add ecc strength & ecc step size properties for nand flash devices, when operating in software-ecc mode. Signed-off-by: Amit Kumar Mahapatra Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/866f4b888129ff0213df9cdb51b5529b199fb7b7.1631713594.git.michal.simek@xilinx.com --- arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts index 4225a9547c58..f32f87acacb6 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts @@ -140,6 +140,8 @@ nand-ecc-algo = "bch"; nand-rb = <0>; label = "main-storage-0"; + nand-ecc-step-size = <1024>; + nand-ecc-strength = <24>; partition@0 { /* for testing purpose */ label = "nand-fsbl-uboot"; @@ -174,6 +176,8 @@ nand-ecc-algo = "bch"; nand-rb = <0>; label = "main-storage-1"; + nand-ecc-step-size = <1024>; + nand-ecc-strength = <24>; partition@0 { /* for testing purpose */ label = "nand1-fsbl-uboot"; From 3482ed6faf8931af77ef4d548a2894ed75880611 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 15 Sep 2021 16:22:31 +0200 Subject: [PATCH 12/17] arm: zynq: Use s25fl256s1 compatible string on zedboard Use compatible string which is listed in the Linux kernel. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/49bc6b056b0f6f69d4d90351dc875a66b7e37619.1631715748.git.michal.simek@xilinx.com --- arch/arm/dts/zynq-zed.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/dts/zynq-zed.dts b/arch/arm/dts/zynq-zed.dts index 7a540b63f471..cf28167a7f74 100644 --- a/arch/arm/dts/zynq-zed.dts +++ b/arch/arm/dts/zynq-zed.dts @@ -53,7 +53,7 @@ status = "okay"; num-cs = <1>; flash@0 { - compatible = "spansion,s25fl256s", "jedec,spi-nor"; + compatible = "spansion,s25fl256s1", "jedec,spi-nor"; reg = <0>; spi-max-frequency = <30000000>; m25p,fast-read; From 876b854a22701565193a93da6676b2014b6e5117 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 24 Sep 2021 15:04:57 +0200 Subject: [PATCH 13/17] arm64: zynqmp: Define all eeproms for SC on vck190 There are multiple eeproms on vck190 that's why list all of them. FMC eeproms are present only when fmcs are plugged. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/96902661e3ab9e20b59d626e6129ccf6f3317c4d.1632488695.git.michal.simek@xilinx.com --- arch/arm/dts/zynqmp-e-a2197-00-revA.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts index bd0ba557e072..f229880a7021 100644 --- a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts +++ b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts @@ -24,6 +24,9 @@ i2c1 = &i2c1; mmc0 = &sdhci1; nvmem0 = &eeprom; + nvmem1 = &eeprom_ebm; + nvmem2 = &eeprom_fmc1; + nvmem3 = &eeprom_fmc2; rtc0 = &rtc; serial0 = &uart0; serial1 = &dcc; @@ -477,6 +480,10 @@ silabs,skip-recall; }; /* and connector J212D */ + eeprom_ebm: eeprom@52 { /* x-ebm module */ + compatible = "st,24c128", "atmel,24c128"; + reg = <0x52>; + }; }; fmc1: i2c@1 { /* FMCP1_IIC */ #address-cells = <1>; @@ -484,6 +491,10 @@ reg = <1>; /* FIXME connection to Samtec J51C */ /* expected eeprom 0x50 FMC cards */ + eeprom_fmc1: eeprom@50 { + compatible = "st,24c128", "atmel,24c128"; + reg = <0x50>; + }; }; fmc2: i2c@2 { /* FMCP2_IIC */ #address-cells = <1>; @@ -491,6 +502,10 @@ reg = <2>; /* FIXME connection to Samtec J53C */ /* expected eeprom 0x50 FMC cards */ + eeprom_fmc2: eeprom@50 { + compatible = "st,24c128", "atmel,24c128"; + reg = <0x50>; + }; }; i2c@3 { /* DDR4_DIMM1 */ #address-cells = <1>; From 0285d75a930f4b4d535b9d03972bdfa28e973083 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 24 Sep 2021 15:06:18 +0200 Subject: [PATCH 14/17] arm64: zynqmp: Add psu_init_gpl for vck190/vmk180 SC Add psu_init_gpl file for getting SPL to work directly from the tree. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/6675723ad52d29982e62c6ca4832ed18688076cb.1632488774.git.michal.simek@xilinx.com --- .../zynqmp-e-a2197-00-revA/psu_init_gpl.c | 2052 +++++++++++++++++ 1 file changed, 2052 insertions(+) create mode 100644 board/xilinx/zynqmp/zynqmp-e-a2197-00-revA/psu_init_gpl.c diff --git a/board/xilinx/zynqmp/zynqmp-e-a2197-00-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-e-a2197-00-revA/psu_init_gpl.c new file mode 100644 index 000000000000..348f0e7789a7 --- /dev/null +++ b/board/xilinx/zynqmp/zynqmp-e-a2197-00-revA/psu_init_gpl.c @@ -0,0 +1,2052 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (c) Copyright 2015 Xilinx, Inc. All rights reserved. + */ + +#include +#include + +static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate, + u32 lane2_protocol, u32 lane2_rate, + u32 lane1_protocol, u32 lane1_rate, + u32 lane0_protocol, u32 lane0_rate); + +static void dpll_prog(int div2, int ddr_pll_fbdiv, int d_lock_dly, + int d_lock_cnt, int d_lfhf, int d_cp, int d_res); + +static unsigned long psu_pll_init_data(void) +{ + psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U); + psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00014600U); + psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U); + psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U); + psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U); + mask_poll(0xFF5E0040, 0x00000002U); + psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U); + psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U); + psu_mask_write(0xFF5E0038, 0x8000FFFFU, 0x00000000U); + psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U); + psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E672C6CU); + psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00002D00U); + psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U); + psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U); + psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U); + mask_poll(0xFF5E0040, 0x00000001U); + psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U); + psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U); + psu_mask_write(0xFF5E0028, 0x8000FFFFU, 0x00000000U); + psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U); + psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U); + psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U); + psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U); + mask_poll(0xFD1A0044, 0x00000001U); + psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U); + psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U); + psu_mask_write(0xFD1A0028, 0x8000FFFFU, 0x00000000U); + psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U); + psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014000U); + psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U); + psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U); + mask_poll(0xFD1A0044, 0x00000002U); + psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U); + psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000300U); + psu_mask_write(0xFD1A0034, 0x8000FFFFU, 0x00000000U); + psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C62U); + psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014700U); + psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U); + psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U); + mask_poll(0xFD1A0044, 0x00000004U); + psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U); + psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U); + psu_mask_write(0xFD1A0040, 0x8000FFFFU, 0x00000000U); + + return 1; +} + +static unsigned long psu_clock_init_data(void) +{ + psu_mask_write(0xFF5E0050, 0x063F3F07U, 0x06010C00U); + psu_mask_write(0xFF180360, 0x00000003U, 0x00000001U); + psu_mask_write(0xFF180308, 0x00000006U, 0x00000006U); + psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U); + psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U); + psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U); + psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U); + psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U); + psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U); + psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U); + psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U); + psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U); + psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U); + psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U); + psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U); + psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U); + psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U); + psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01040F00U); + psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010500U); + psu_mask_write(0xFF5E00CC, 0x013F3F07U, 0x01010400U); + psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011D02U); + psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U); + psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U); + psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U); + psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U); + psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U); + psu_mask_write(0xFD1A0084, 0x07003F07U, 0x07000100U); + psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U); + psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U); + psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U); + psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U); + psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U); + psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U); + psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U); + psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U); + psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U); + + return 1; +} + +static unsigned long psu_ddr_init_data(void) +{ + psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U); + psu_mask_write(0xFD070000, 0xE30FBE3DU, 0xC1081020U); + psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U); + psu_mask_write(0xFD070020, 0x000003F3U, 0x00000202U); + psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00516120U); + psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U); + psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408410U); + psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U); + psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U); + psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U); + psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x00418096U); + psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U); + psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U); + psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0030051FU); + psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00030413U); + psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x006A0000U); + psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002305U); + psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x00440024U); + psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00310008U); + psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U); + psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x00000000U); + psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U); + psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000077FU); + psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x15161117U); + psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00040422U); + psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x060C1A10U); + psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00F08000U); + psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x0A04060CU); + psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x01040808U); + psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010005U); + psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000401U); + psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040606U); + psu_mask_write(0xFD070124, 0x40070F3FU, 0x0004040DU); + psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x440C011CU); + psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U); + psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x82160010U); + psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x01B65B96U); + psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x0495820AU); + psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U); + psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U); + psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U); + psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x83FF0003U); + psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU); + psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000004U); + psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00001308U); + psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U); + psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU); + psu_mask_write(0xFD070204, 0x001F1F1FU, 0x00070707U); + psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x00000000U); + psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x0F000000U); + psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU); + psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x060F0606U); + psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x06060606U); + psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU); + psu_mask_write(0xFD070220, 0x00001F1FU, 0x00000000U); + psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x06060606U); + psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x06060606U); + psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000006U); + psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x04000400U); + psu_mask_write(0xFD070244, 0x00003333U, 0x00000000U); + psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U); + psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U); + psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U); + psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U); + psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U); + psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U); + psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U); + psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U); + psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU); + psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U); + psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U); + psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U); + psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U); + psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U); + psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU); + psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU); + psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU); + psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU); + psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU); + psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU); + psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U); + psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU); + psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U); + psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U); + psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U); + psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU); + psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U); + psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U); + psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x87001E00U); + psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F07E38U); + psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U); + psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U); + psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x42C21590U); + psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xD05512C0U); + psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U); + psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U); + psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E4U); + psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0000040DU); + psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x0B2E1708U); + psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x282B0711U); + psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0133U); + psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x82000501U); + psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x012B2B0BU); + psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x0044260BU); + psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000C18U); + psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U); + psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U); + psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000044U); + psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000024U); + psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000031U); + psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000008U); + psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000056U); + psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x00000056U); + psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U); + psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x00000019U); + psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000016U); + psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800091C7U); + psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U); + psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U); + psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U); + psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12340800U); + psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x0000000AU); + psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U); + psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000005U); + psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300BD99U); + psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF1032019U); + psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U); + psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008AAC58U); + psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x0001B39BU); + psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U); + psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U); + psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x0001BB9BU); + psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U); + psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU); + psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U); + psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00F50CU); + psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U); + psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU); + psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U); + psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00F50CU); + psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U); + psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU); + psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U); + psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00F504U); + psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U); + psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU); + psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U); + psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00F504U); + psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x80803660U); + psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x55556000U); + psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0xAAAAAAAAU); + psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x0029A4A4U); + psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0C00BD00U); + psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x80803660U); + psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x55556000U); + psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0xAAAAAAAAU); + psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x0029A4A4U); + psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0C00BD00U); + psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x80803660U); + psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x55556000U); + psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0xAAAAAAAAU); + psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x0029A4A4U); + psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0C00BD00U); + psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x80803660U); + psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x55556000U); + psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0xAAAAAAAAU); + psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x0029A4A4U); + psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0C00BD00U); + psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U); + psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U); + psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU); + psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U); + psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00BD00U); + psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09091616U); + psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU); + psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU); + psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U); + psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U); + psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x000C1800U); + psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x71000000U); + psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU); + psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U); + psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U); + psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x000C1800U); + psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x71000000U); + psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x15019FFEU); + psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x21100000U); + psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01266300U); + psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x000C1800U); + psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70400000U); + psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x15019FFEU); + psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x21100000U); + psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01266300U); + psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x000C1800U); + psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70400000U); + psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU); + psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U); + psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U); + psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x000C1800U); + psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U); + psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U); + + return 1; +} + +static unsigned long psu_ddr_qos_init_data(void) +{ + psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U); + psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U); + + return 1; +} + +static unsigned long psu_mio_init_data(void) +{ + psu_mask_write(0xFF180000, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180004, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180008, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180010, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180014, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180018, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18001C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180020, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180024, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180028, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180030, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180038, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180040, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180044, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180048, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18004C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180050, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180054, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180060, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180064, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180070, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180074, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180078, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180080, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180084, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180088, 0x000000FEU, 0x00000040U); + psu_mask_write(0xFF18008C, 0x000000FEU, 0x00000040U); + psu_mask_write(0xFF180090, 0x000000FEU, 0x00000040U); + psu_mask_write(0xFF180094, 0x000000FEU, 0x00000040U); + psu_mask_write(0xFF180098, 0x000000FEU, 0x000000C0U); + psu_mask_write(0xFF18009C, 0x000000FEU, 0x000000C0U); + psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U); + psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180100, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180104, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180108, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180110, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180114, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180118, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180120, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180124, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180128, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000000U); + psu_mask_write(0xFF180130, 0x000000FEU, 0x00000060U); + psu_mask_write(0xFF180134, 0x000000FEU, 0x00000060U); + psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x00000000U); + psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00002040U); + psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000000U); + psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU); + psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U); + psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U); + + return 1; +} + +static unsigned long psu_peripherals_pre_init_data(void) +{ + psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U); + + return 1; +} + +static unsigned long psu_peripherals_init_data(void) +{ + psu_mask_write(0xFD1A0100, 0x0000007CU, 0x00000000U); + psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U); + psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U); + psu_mask_write(0xFF5E0230, 0x00000001U, 0x00000000U); + psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U); + psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U); + psu_mask_write(0xFF180320, 0x33840000U, 0x00800000U); + psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U); + psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U); + psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U); + psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U); + psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U); + psu_mask_write(0xFF000034, 0x000000FFU, 0x00000006U); + psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000007CU); + psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U); + psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U); + psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U); + psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U); + psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U); + psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U); + psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U); + psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U); + return 1; +} + +static unsigned long psu_serdes_init_data(void) +{ + psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000FU); + psu_mask_write(0xFD402860, 0x00000080U, 0x00000080U); + psu_mask_write(0xFD40106C, 0x0000000FU, 0x0000000FU); + psu_mask_write(0xFD4000F4, 0x0000000BU, 0x0000000BU); + psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD40189C, 0x00000080U, 0x00000080U); + psu_mask_write(0xFD4018F8, 0x000000FFU, 0x0000007DU); + psu_mask_write(0xFD4018FC, 0x000000FFU, 0x0000007DU); + psu_mask_write(0xFD401990, 0x000000FFU, 0x00000000U); + psu_mask_write(0xFD401924, 0x000000FFU, 0x00000082U); + psu_mask_write(0xFD401928, 0x000000FFU, 0x00000000U); + psu_mask_write(0xFD401900, 0x000000FFU, 0x00000064U); + psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000000U); + psu_mask_write(0xFD401980, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD401914, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD401918, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD401940, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD401944, 0x00000001U, 0x00000001U); + psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U); + psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U); + psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U); + psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U); + psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U); + psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U); + psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U); + psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U); + psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU); + psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U); + psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U); + psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U); + + serdes_illcalib(0, 0, 0, 0, 0, 0, 5, 0); + psu_mask_write(0xFD410010, 0x00000007U, 0x00000005U); + psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U); + + return 1; +} + +static unsigned long psu_resetout_init_data(void) +{ + psu_mask_write(0xFF5E0230, 0x00000001U, 0x00000000U); + psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U); + mask_poll(0xFD4023E4, 0x00000010U); + + return 1; +} + +static unsigned long psu_resetin_init_data(void) +{ + psu_mask_write(0xFF5E0230, 0x00000001U, 0x00000001U); + + return 1; +} + +static unsigned long psu_afi_config(void) +{ + psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U); + psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U); + psu_mask_write(0xFF419000, 0x00000300U, 0x00000000U); + + return 1; +} + +static unsigned long psu_ddr_phybringup_data(void) +{ + unsigned int regval = 0; + + for (int tp = 0; tp < 20; tp++) + regval = Xil_In32(0xFD070018); + int cur_PLLCR0; + + cur_PLLCR0 = (Xil_In32(0xFD080068U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SL0PLLCR0; + + cur_DX8SL0PLLCR0 = (Xil_In32(0xFD081404U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SL1PLLCR0; + + cur_DX8SL1PLLCR0 = (Xil_In32(0xFD081444U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SL2PLLCR0; + + cur_DX8SL2PLLCR0 = (Xil_In32(0xFD081484U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SL3PLLCR0; + + cur_DX8SL3PLLCR0 = (Xil_In32(0xFD0814C4U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SL4PLLCR0; + + cur_DX8SL4PLLCR0 = (Xil_In32(0xFD081504U) & 0xFFFFFFFFU) >> 0x00000000U; + int cur_DX8SLBPLLCR0; + + cur_DX8SLBPLLCR0 = (Xil_In32(0xFD0817C4U) & 0xFFFFFFFFU) >> 0x00000000U; + Xil_Out32(0xFD080068, 0x02120000); + Xil_Out32(0xFD081404, 0x02120000); + Xil_Out32(0xFD081444, 0x02120000); + Xil_Out32(0xFD081484, 0x02120000); + Xil_Out32(0xFD0814C4, 0x02120000); + Xil_Out32(0xFD081504, 0x02120000); + Xil_Out32(0xFD0817C4, 0x02120000); + int cur_div2; + + cur_div2 = (Xil_In32(0xFD1A002CU) & 0x00010000U) >> 0x00000010U; + int cur_fbdiv; + + cur_fbdiv = (Xil_In32(0xFD1A002CU) & 0x00007F00U) >> 0x00000008U; + dpll_prog(1, 49, 63, 625, 3, 3, 2); + for (int tp = 0; tp < 20; tp++) + regval = Xil_In32(0xFD070018); + unsigned int pll_retry = 10; + unsigned int pll_locked = 0; + + while ((pll_retry > 0) && (!pll_locked)) { + Xil_Out32(0xFD080004, 0x00040010); + Xil_Out32(0xFD080004, 0x00040011); + + while ((Xil_In32(0xFD080030) & 0x1) != 1) + ; + pll_locked = (Xil_In32(0xFD080030) & 0x80000000) + >> 31; + pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000) + >> 16; + pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16; + pll_retry--; + } + Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16)); + if (!pll_locked) + return 0; + + Xil_Out32(0xFD080004U, 0x00040063U); + Xil_Out32(0xFD0800C0U, 0x00000001U); + + while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU) + ; + prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U); + + while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU) + ; + Xil_Out32(0xFD070010U, 0x80000018U); + Xil_Out32(0xFD0701B0U, 0x00000005U); + regval = Xil_In32(0xFD070018); + while ((regval & 0x1) != 0x0) + regval = Xil_In32(0xFD070018); + + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + Xil_Out32(0xFD070014U, 0x00000331U); + Xil_Out32(0xFD070010U, 0x80000018U); + regval = Xil_In32(0xFD070018); + while ((regval & 0x1) != 0x0) + regval = Xil_In32(0xFD070018); + + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + Xil_Out32(0xFD070014U, 0x00000B36U); + Xil_Out32(0xFD070010U, 0x80000018U); + regval = Xil_In32(0xFD070018); + while ((regval & 0x1) != 0x0) + regval = Xil_In32(0xFD070018); + + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + Xil_Out32(0xFD070014U, 0x00000C56U); + Xil_Out32(0xFD070010U, 0x80000018U); + regval = Xil_In32(0xFD070018); + while ((regval & 0x1) != 0x0) + regval = Xil_In32(0xFD070018); + + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + Xil_Out32(0xFD070014U, 0x00000E19U); + Xil_Out32(0xFD070010U, 0x80000018U); + regval = Xil_In32(0xFD070018); + while ((regval & 0x1) != 0x0) + regval = Xil_In32(0xFD070018); + + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + regval = Xil_In32(0xFD070018); + Xil_Out32(0xFD070014U, 0x00001616U); + Xil_Out32(0xFD070010U, 0x80000018U); + Xil_Out32(0xFD070010U, 0x80000010U); + Xil_Out32(0xFD0701B0U, 0x00000005U); + Xil_Out32(0xFD070320U, 0x00000001U); + while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U) + ; + prog_reg(0xFD0701B0U, 0x00000001U, 0x00000000U, 0x00000000U); + prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U); + prog_reg(0xFD080028U, 0x00000001U, 0x00000000U, 0x00000001U); + prog_reg(0xFD080004U, 0x20000000U, 0x0000001DU, 0x00000001U); + prog_reg(0xFD08016CU, 0x00000004U, 0x00000002U, 0x00000001U); + prog_reg(0xFD080168U, 0x000000F0U, 0x00000004U, 0x00000007U); + prog_reg(0xFD080168U, 0x00000F00U, 0x00000008U, 0x00000002U); + prog_reg(0xFD080168U, 0x0000000FU, 0x00000000U, 0x00000001U); + for (int tp = 0; tp < 20; tp++) + regval = Xil_In32(0xFD070018); + + Xil_Out32(0xFD080068, cur_PLLCR0); + Xil_Out32(0xFD081404, cur_DX8SL0PLLCR0); + Xil_Out32(0xFD081444, cur_DX8SL1PLLCR0); + Xil_Out32(0xFD081484, cur_DX8SL2PLLCR0); + Xil_Out32(0xFD0814C4, cur_DX8SL3PLLCR0); + Xil_Out32(0xFD081504, cur_DX8SL4PLLCR0); + Xil_Out32(0xFD0817C4, cur_DX8SLBPLLCR0); + for (int tp = 0; tp < 20; tp++) + regval = Xil_In32(0xFD070018); + + dpll_prog(cur_div2, cur_fbdiv, 63, 625, 3, 3, 2); + for (int tp = 0; tp < 2000; tp++) + regval = Xil_In32(0xFD070018); + + prog_reg(0xFD080004U, 0x20000000U, 0x0000001DU, 0x00000000U); + prog_reg(0xFD080004U, 0x00040000U, 0x00000012U, 0x00000001U); + prog_reg(0xFD080004U, 0x00000040U, 0x00000006U, 0x00000001U); + prog_reg(0xFD080004U, 0x00000020U, 0x00000005U, 0x00000001U); + prog_reg(0xFD080004U, 0x00000010U, 0x00000004U, 0x00000001U); + prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U); + + while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU) + ; + prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U); + + while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU) + ; + for (int tp = 0; tp < 2000; tp++) + regval = Xil_In32(0xFD070018); + + prog_reg(0xFD080028U, 0x00000001U, 0x00000000U, 0x00000000U); + prog_reg(0xFD08016CU, 0x00000004U, 0x00000002U, 0x00000001U); + prog_reg(0xFD080168U, 0x000000F0U, 0x00000004U, 0x00000007U); + prog_reg(0xFD080168U, 0x00000F00U, 0x00000008U, 0x00000003U); + prog_reg(0xFD080168U, 0x0000000FU, 0x00000000U, 0x00000001U); + for (int tp = 0; tp < 2000; tp++) + regval = Xil_In32(0xFD070018); + + prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U); + Xil_Out32(0xFD080004, 0x0014FE01); + + regval = Xil_In32(0xFD080030); + while (regval != 0x8000007E) + regval = Xil_In32(0xFD080030); + + Xil_Out32(0xFD080200U, 0x000091C7U); + regval = Xil_In32(0xFD080030); + while (regval != 0x80008FFF) + regval = Xil_In32(0xFD080030); + + Xil_Out32(0xFD080200U, 0x800091C7U); + regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18); + if (regval != 0) + return 0; + prog_reg(0xFD070320U, 0x00000001U, 0x00000000U, 0x00000000U); + prog_reg(0xFD0701B0U, 0x00000001U, 0x00000000U, 0x00000001U); + prog_reg(0xFD0701A0U, 0x80000000U, 0x0000001FU, 0x00000000U); + prog_reg(0xFD070320U, 0x00000001U, 0x00000000U, 0x00000001U); + Xil_Out32(0xFD070180U, 0x02160010U); + Xil_Out32(0xFD070060U, 0x00000000U); + prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U); + for (int tp = 0; tp < 4000; tp++) + regval = Xil_In32(0xFD070018); + + prog_reg(0xFD080090U, 0x00000FC0U, 0x00000006U, 0x00000007U); + prog_reg(0xFD080090U, 0x00000004U, 0x00000002U, 0x00000001U); + prog_reg(0xFD08070CU, 0x02000000U, 0x00000019U, 0x00000000U); + prog_reg(0xFD08080CU, 0x02000000U, 0x00000019U, 0x00000000U); + prog_reg(0xFD08090CU, 0x02000000U, 0x00000019U, 0x00000000U); + prog_reg(0xFD080A0CU, 0x02000000U, 0x00000019U, 0x00000000U); + prog_reg(0xFD080F0CU, 0x02000000U, 0x00000019U, 0x00000000U); + prog_reg(0xFD080200U, 0x00000010U, 0x00000004U, 0x00000001U); + prog_reg(0xFD080250U, 0x00000002U, 0x00000001U, 0x00000000U); + prog_reg(0xFD080250U, 0x0000000CU, 0x00000002U, 0x00000001U); + prog_reg(0xFD080250U, 0x000000F0U, 0x00000004U, 0x00000000U); + prog_reg(0xFD080250U, 0x00300000U, 0x00000014U, 0x00000001U); + prog_reg(0xFD080250U, 0xF0000000U, 0x0000001CU, 0x00000002U); + prog_reg(0xFD08070CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD08080CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD08090CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080A0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080B0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080C0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080D0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080E0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080F0CU, 0x08000000U, 0x0000001BU, 0x00000000U); + prog_reg(0xFD080254U, 0x000000FFU, 0x00000000U, 0x00000001U); + prog_reg(0xFD080254U, 0x000F0000U, 0x00000010U, 0x0000000AU); + prog_reg(0xFD080250U, 0x00000001U, 0x00000000U, 0x00000001U); + + return 1; +} + +static int serdes_rst_seq(u32 pllsel, u32 lane3_protocol, u32 lane3_rate, + u32 lane2_protocol, u32 lane2_rate, + u32 lane1_protocol, u32 lane1_rate, + u32 lane0_protocol, u32 lane0_rate) +{ + Xil_Out32(0xFD410098, 0x00000000); + Xil_Out32(0xFD401010, 0x00000040); + Xil_Out32(0xFD405010, 0x00000040); + Xil_Out32(0xFD409010, 0x00000040); + Xil_Out32(0xFD40D010, 0x00000040); + Xil_Out32(0xFD402084, 0x00000080); + Xil_Out32(0xFD406084, 0x00000080); + Xil_Out32(0xFD40A084, 0x00000080); + Xil_Out32(0xFD40E084, 0x00000080); + Xil_Out32(0xFD410098, 0x00000004); + mask_delay(50); + if (lane0_rate == 1) + Xil_Out32(0xFD410098, 0x0000000E); + Xil_Out32(0xFD410098, 0x00000006); + if (lane0_rate == 1) { + Xil_Out32(0xFD40000C, 0x00000004); + Xil_Out32(0xFD40400C, 0x00000004); + Xil_Out32(0xFD40800C, 0x00000004); + Xil_Out32(0xFD40C00C, 0x00000004); + Xil_Out32(0xFD410098, 0x00000007); + mask_delay(400); + Xil_Out32(0xFD40000C, 0x0000000C); + Xil_Out32(0xFD40400C, 0x0000000C); + Xil_Out32(0xFD40800C, 0x0000000C); + Xil_Out32(0xFD40C00C, 0x0000000C); + mask_delay(15); + Xil_Out32(0xFD410098, 0x0000000F); + mask_delay(100); + } + if (pllsel == 0) + mask_poll(0xFD4023E4, 0x00000010U); + if (pllsel == 1) + mask_poll(0xFD4063E4, 0x00000010U); + if (pllsel == 2) + mask_poll(0xFD40A3E4, 0x00000010U); + if (pllsel == 3) + mask_poll(0xFD40E3E4, 0x00000010U); + mask_delay(50); + Xil_Out32(0xFD401010, 0x000000C0); + Xil_Out32(0xFD405010, 0x000000C0); + Xil_Out32(0xFD409010, 0x000000C0); + Xil_Out32(0xFD40D010, 0x000000C0); + Xil_Out32(0xFD401010, 0x00000080); + Xil_Out32(0xFD405010, 0x00000080); + Xil_Out32(0xFD409010, 0x00000080); + Xil_Out32(0xFD40D010, 0x00000080); + + Xil_Out32(0xFD402084, 0x000000C0); + Xil_Out32(0xFD406084, 0x000000C0); + Xil_Out32(0xFD40A084, 0x000000C0); + Xil_Out32(0xFD40E084, 0x000000C0); + mask_delay(50); + Xil_Out32(0xFD402084, 0x00000080); + Xil_Out32(0xFD406084, 0x00000080); + Xil_Out32(0xFD40A084, 0x00000080); + Xil_Out32(0xFD40E084, 0x00000080); + mask_delay(50); + Xil_Out32(0xFD401010, 0x00000000); + Xil_Out32(0xFD405010, 0x00000000); + Xil_Out32(0xFD409010, 0x00000000); + Xil_Out32(0xFD40D010, 0x00000000); + Xil_Out32(0xFD402084, 0x00000000); + Xil_Out32(0xFD406084, 0x00000000); + Xil_Out32(0xFD40A084, 0x00000000); + Xil_Out32(0xFD40E084, 0x00000000); + mask_delay(500); + return 1; +} + +static int serdes_bist_static_settings(u32 lane_active) +{ + if (lane_active == 0) { + Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F)); + Xil_Out32(0xFD403068, 0x1); + Xil_Out32(0xFD40306C, 0x1); + Xil_Out32(0xFD4010AC, 0x0020); + Xil_Out32(0xFD403008, 0x0); + Xil_Out32(0xFD40300C, 0xF4); + Xil_Out32(0xFD403010, 0x0); + Xil_Out32(0xFD403014, 0x0); + Xil_Out32(0xFD403018, 0x00); + Xil_Out32(0xFD40301C, 0xFB); + Xil_Out32(0xFD403020, 0xFF); + Xil_Out32(0xFD403024, 0x0); + Xil_Out32(0xFD403028, 0x00); + Xil_Out32(0xFD40302C, 0x00); + Xil_Out32(0xFD403030, 0x4A); + Xil_Out32(0xFD403034, 0x4A); + Xil_Out32(0xFD403038, 0x4A); + Xil_Out32(0xFD40303C, 0x4A); + Xil_Out32(0xFD403040, 0x0); + Xil_Out32(0xFD403044, 0x14); + Xil_Out32(0xFD403048, 0x02); + Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F)); + } + if (lane_active == 1) { + Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F)); + Xil_Out32(0xFD407068, 0x1); + Xil_Out32(0xFD40706C, 0x1); + Xil_Out32(0xFD4050AC, 0x0020); + Xil_Out32(0xFD407008, 0x0); + Xil_Out32(0xFD40700C, 0xF4); + Xil_Out32(0xFD407010, 0x0); + Xil_Out32(0xFD407014, 0x0); + Xil_Out32(0xFD407018, 0x00); + Xil_Out32(0xFD40701C, 0xFB); + Xil_Out32(0xFD407020, 0xFF); + Xil_Out32(0xFD407024, 0x0); + Xil_Out32(0xFD407028, 0x00); + Xil_Out32(0xFD40702C, 0x00); + Xil_Out32(0xFD407030, 0x4A); + Xil_Out32(0xFD407034, 0x4A); + Xil_Out32(0xFD407038, 0x4A); + Xil_Out32(0xFD40703C, 0x4A); + Xil_Out32(0xFD407040, 0x0); + Xil_Out32(0xFD407044, 0x14); + Xil_Out32(0xFD407048, 0x02); + Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F)); + } + + if (lane_active == 2) { + Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F)); + Xil_Out32(0xFD40B068, 0x1); + Xil_Out32(0xFD40B06C, 0x1); + Xil_Out32(0xFD4090AC, 0x0020); + Xil_Out32(0xFD40B008, 0x0); + Xil_Out32(0xFD40B00C, 0xF4); + Xil_Out32(0xFD40B010, 0x0); + Xil_Out32(0xFD40B014, 0x0); + Xil_Out32(0xFD40B018, 0x00); + Xil_Out32(0xFD40B01C, 0xFB); + Xil_Out32(0xFD40B020, 0xFF); + Xil_Out32(0xFD40B024, 0x0); + Xil_Out32(0xFD40B028, 0x00); + Xil_Out32(0xFD40B02C, 0x00); + Xil_Out32(0xFD40B030, 0x4A); + Xil_Out32(0xFD40B034, 0x4A); + Xil_Out32(0xFD40B038, 0x4A); + Xil_Out32(0xFD40B03C, 0x4A); + Xil_Out32(0xFD40B040, 0x0); + Xil_Out32(0xFD40B044, 0x14); + Xil_Out32(0xFD40B048, 0x02); + Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F)); + } + + if (lane_active == 3) { + Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F)); + Xil_Out32(0xFD40F068, 0x1); + Xil_Out32(0xFD40F06C, 0x1); + Xil_Out32(0xFD40D0AC, 0x0020); + Xil_Out32(0xFD40F008, 0x0); + Xil_Out32(0xFD40F00C, 0xF4); + Xil_Out32(0xFD40F010, 0x0); + Xil_Out32(0xFD40F014, 0x0); + Xil_Out32(0xFD40F018, 0x00); + Xil_Out32(0xFD40F01C, 0xFB); + Xil_Out32(0xFD40F020, 0xFF); + Xil_Out32(0xFD40F024, 0x0); + Xil_Out32(0xFD40F028, 0x00); + Xil_Out32(0xFD40F02C, 0x00); + Xil_Out32(0xFD40F030, 0x4A); + Xil_Out32(0xFD40F034, 0x4A); + Xil_Out32(0xFD40F038, 0x4A); + Xil_Out32(0xFD40F03C, 0x4A); + Xil_Out32(0xFD40F040, 0x0); + Xil_Out32(0xFD40F044, 0x14); + Xil_Out32(0xFD40F048, 0x02); + Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F)); + } + return 1; +} + +static int serdes_bist_run(u32 lane_active) +{ + if (lane_active == 0) { + psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U); + psu_mask_write(0xFD410038, 0x00000007U, 0x00000001U); + Xil_Out32(0xFD4010AC, 0x0020); + Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) | 0x1)); + } + if (lane_active == 1) { + psu_mask_write(0xFD410044, 0x0000000CU, 0x00000000U); + psu_mask_write(0xFD410040, 0x0000000CU, 0x00000000U); + psu_mask_write(0xFD410038, 0x00000070U, 0x00000010U); + Xil_Out32(0xFD4050AC, 0x0020); + Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) | 0x1)); + } + if (lane_active == 2) { + psu_mask_write(0xFD410044, 0x00000030U, 0x00000000U); + psu_mask_write(0xFD410040, 0x00000030U, 0x00000000U); + psu_mask_write(0xFD41003C, 0x00000007U, 0x00000001U); + Xil_Out32(0xFD4090AC, 0x0020); + Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) | 0x1)); + } + if (lane_active == 3) { + psu_mask_write(0xFD410040, 0x000000C0U, 0x00000000U); + psu_mask_write(0xFD410044, 0x000000C0U, 0x00000000U); + psu_mask_write(0xFD41003C, 0x00000070U, 0x00000010U); + Xil_Out32(0xFD40D0AC, 0x0020); + Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) | 0x1)); + } + mask_delay(100); + return 1; +} + +static int serdes_bist_result(u32 lane_active) +{ + u32 pkt_cnt_l0, pkt_cnt_h0, err_cnt_l0, err_cnt_h0; + + if (lane_active == 0) { + pkt_cnt_l0 = Xil_In32(0xFD40304C); + pkt_cnt_h0 = Xil_In32(0xFD403050); + err_cnt_l0 = Xil_In32(0xFD403054); + err_cnt_h0 = Xil_In32(0xFD403058); + } + if (lane_active == 1) { + pkt_cnt_l0 = Xil_In32(0xFD40704C); + pkt_cnt_h0 = Xil_In32(0xFD407050); + err_cnt_l0 = Xil_In32(0xFD407054); + err_cnt_h0 = Xil_In32(0xFD407058); + } + if (lane_active == 2) { + pkt_cnt_l0 = Xil_In32(0xFD40B04C); + pkt_cnt_h0 = Xil_In32(0xFD40B050); + err_cnt_l0 = Xil_In32(0xFD40B054); + err_cnt_h0 = Xil_In32(0xFD40B058); + } + if (lane_active == 3) { + pkt_cnt_l0 = Xil_In32(0xFD40F04C); + pkt_cnt_h0 = Xil_In32(0xFD40F050); + err_cnt_l0 = Xil_In32(0xFD40F054); + err_cnt_h0 = Xil_In32(0xFD40F058); + } + if (lane_active == 0) + Xil_Out32(0xFD403004, 0x0); + if (lane_active == 1) + Xil_Out32(0xFD407004, 0x0); + if (lane_active == 2) + Xil_Out32(0xFD40B004, 0x0); + if (lane_active == 3) + Xil_Out32(0xFD40F004, 0x0); + if (err_cnt_l0 > 0 || err_cnt_h0 > 0 || + (pkt_cnt_l0 == 0 && pkt_cnt_h0 == 0)) + return 0; + return 1; +} + +static int serdes_illcalib_pcie_gen1(u32 pllsel, u32 lane3_protocol, + u32 lane3_rate, u32 lane2_protocol, + u32 lane2_rate, u32 lane1_protocol, + u32 lane1_rate, u32 lane0_protocol, + u32 lane0_rate, u32 gen2_calib) +{ + u64 tempbistresult; + u32 currbistresult[4]; + u32 prevbistresult[4]; + u32 itercount = 0; + u32 ill12_val[4], ill1_val[4]; + u32 loop = 0; + u32 iterresult[8]; + u32 meancount[4]; + u32 bistpasscount[4]; + u32 meancountalt[4]; + u32 meancountalt_bistpasscount[4]; + u32 lane0_active; + u32 lane1_active; + u32 lane2_active; + u32 lane3_active; + + lane0_active = (lane0_protocol == 1); + lane1_active = (lane1_protocol == 1); + lane2_active = (lane2_protocol == 1); + lane3_active = (lane3_protocol == 1); + for (loop = 0; loop <= 3; loop++) { + iterresult[loop] = 0; + iterresult[loop + 4] = 0; + meancountalt[loop] = 0; + meancountalt_bistpasscount[loop] = 0; + meancount[loop] = 0; + prevbistresult[loop] = 0; + bistpasscount[loop] = 0; + } + itercount = 0; + if (lane0_active) + serdes_bist_static_settings(0); + if (lane1_active) + serdes_bist_static_settings(1); + if (lane2_active) + serdes_bist_static_settings(2); + if (lane3_active) + serdes_bist_static_settings(3); + do { + if (gen2_calib != 1) { + if (lane0_active == 1) + ill1_val[0] = ((0x04 + itercount * 8) % 0x100); + if (lane0_active == 1) + ill12_val[0] = + ((0x04 + itercount * 8) >= + 0x100) ? 0x10 : 0x00; + if (lane1_active == 1) + ill1_val[1] = ((0x04 + itercount * 8) % 0x100); + if (lane1_active == 1) + ill12_val[1] = + ((0x04 + itercount * 8) >= + 0x100) ? 0x10 : 0x00; + if (lane2_active == 1) + ill1_val[2] = ((0x04 + itercount * 8) % 0x100); + if (lane2_active == 1) + ill12_val[2] = + ((0x04 + itercount * 8) >= + 0x100) ? 0x10 : 0x00; + if (lane3_active == 1) + ill1_val[3] = ((0x04 + itercount * 8) % 0x100); + if (lane3_active == 1) + ill12_val[3] = + ((0x04 + itercount * 8) >= + 0x100) ? 0x10 : 0x00; + + if (lane0_active == 1) + Xil_Out32(0xFD401924, ill1_val[0]); + if (lane0_active == 1) + psu_mask_write(0xFD401990, 0x000000F0U, + ill12_val[0]); + if (lane1_active == 1) + Xil_Out32(0xFD405924, ill1_val[1]); + if (lane1_active == 1) + psu_mask_write(0xFD405990, 0x000000F0U, + ill12_val[1]); + if (lane2_active == 1) + Xil_Out32(0xFD409924, ill1_val[2]); + if (lane2_active == 1) + psu_mask_write(0xFD409990, 0x000000F0U, + ill12_val[2]); + if (lane3_active == 1) + Xil_Out32(0xFD40D924, ill1_val[3]); + if (lane3_active == 1) + psu_mask_write(0xFD40D990, 0x000000F0U, + ill12_val[3]); + } + if (gen2_calib == 1) { + if (lane0_active == 1) + ill1_val[0] = ((0x104 + itercount * 8) % 0x100); + if (lane0_active == 1) + ill12_val[0] = + ((0x104 + itercount * 8) >= + 0x200) ? 0x02 : 0x01; + if (lane1_active == 1) + ill1_val[1] = ((0x104 + itercount * 8) % 0x100); + if (lane1_active == 1) + ill12_val[1] = + ((0x104 + itercount * 8) >= + 0x200) ? 0x02 : 0x01; + if (lane2_active == 1) + ill1_val[2] = ((0x104 + itercount * 8) % 0x100); + if (lane2_active == 1) + ill12_val[2] = + ((0x104 + itercount * 8) >= + 0x200) ? 0x02 : 0x01; + if (lane3_active == 1) + ill1_val[3] = ((0x104 + itercount * 8) % 0x100); + if (lane3_active == 1) + ill12_val[3] = + ((0x104 + itercount * 8) >= + 0x200) ? 0x02 : 0x01; + + if (lane0_active == 1) + Xil_Out32(0xFD401928, ill1_val[0]); + if (lane0_active == 1) + psu_mask_write(0xFD401990, 0x0000000FU, + ill12_val[0]); + if (lane1_active == 1) + Xil_Out32(0xFD405928, ill1_val[1]); + if (lane1_active == 1) + psu_mask_write(0xFD405990, 0x0000000FU, + ill12_val[1]); + if (lane2_active == 1) + Xil_Out32(0xFD409928, ill1_val[2]); + if (lane2_active == 1) + psu_mask_write(0xFD409990, 0x0000000FU, + ill12_val[2]); + if (lane3_active == 1) + Xil_Out32(0xFD40D928, ill1_val[3]); + if (lane3_active == 1) + psu_mask_write(0xFD40D990, 0x0000000FU, + ill12_val[3]); + } + + if (lane0_active == 1) + psu_mask_write(0xFD401018, 0x00000030U, 0x00000010U); + if (lane1_active == 1) + psu_mask_write(0xFD405018, 0x00000030U, 0x00000010U); + if (lane2_active == 1) + psu_mask_write(0xFD409018, 0x00000030U, 0x00000010U); + if (lane3_active == 1) + psu_mask_write(0xFD40D018, 0x00000030U, 0x00000010U); + if (lane0_active == 1) + currbistresult[0] = 0; + if (lane1_active == 1) + currbistresult[1] = 0; + if (lane2_active == 1) + currbistresult[2] = 0; + if (lane3_active == 1) + currbistresult[3] = 0; + serdes_rst_seq(pllsel, lane3_protocol, lane3_rate, + lane2_protocol, lane2_rate, lane1_protocol, + lane1_rate, lane0_protocol, lane0_rate); + if (lane3_active == 1) + serdes_bist_run(3); + if (lane2_active == 1) + serdes_bist_run(2); + if (lane1_active == 1) + serdes_bist_run(1); + if (lane0_active == 1) + serdes_bist_run(0); + tempbistresult = 0; + if (lane3_active == 1) + tempbistresult = tempbistresult | serdes_bist_result(3); + tempbistresult = tempbistresult << 1; + if (lane2_active == 1) + tempbistresult = tempbistresult | serdes_bist_result(2); + tempbistresult = tempbistresult << 1; + if (lane1_active == 1) + tempbistresult = tempbistresult | serdes_bist_result(1); + tempbistresult = tempbistresult << 1; + if (lane0_active == 1) + tempbistresult = tempbistresult | serdes_bist_result(0); + Xil_Out32(0xFD410098, 0x0); + Xil_Out32(0xFD410098, 0x2); + + if (itercount < 32) { + iterresult[0] = + ((iterresult[0] << 1) | + ((tempbistresult & 0x1) == 0x1)); + iterresult[1] = + ((iterresult[1] << 1) | + ((tempbistresult & 0x2) == 0x2)); + iterresult[2] = + ((iterresult[2] << 1) | + ((tempbistresult & 0x4) == 0x4)); + iterresult[3] = + ((iterresult[3] << 1) | + ((tempbistresult & 0x8) == 0x8)); + } else { + iterresult[4] = + ((iterresult[4] << 1) | + ((tempbistresult & 0x1) == 0x1)); + iterresult[5] = + ((iterresult[5] << 1) | + ((tempbistresult & 0x2) == 0x2)); + iterresult[6] = + ((iterresult[6] << 1) | + ((tempbistresult & 0x4) == 0x4)); + iterresult[7] = + ((iterresult[7] << 1) | + ((tempbistresult & 0x8) == 0x8)); + } + currbistresult[0] = + currbistresult[0] | ((tempbistresult & 0x1) == 1); + currbistresult[1] = + currbistresult[1] | ((tempbistresult & 0x2) == 0x2); + currbistresult[2] = + currbistresult[2] | ((tempbistresult & 0x4) == 0x4); + currbistresult[3] = + currbistresult[3] | ((tempbistresult & 0x8) == 0x8); + + for (loop = 0; loop <= 3; loop++) { + if (currbistresult[loop] == 1 && + prevbistresult[loop] == 1) + bistpasscount[loop] = bistpasscount[loop] + 1; + if (bistpasscount[loop] < 4 && + currbistresult[loop] == 0 && itercount > 2) { + if (meancountalt_bistpasscount[loop] < + bistpasscount[loop]) { + meancountalt_bistpasscount[loop] = + bistpasscount[loop]; + meancountalt[loop] = + ((itercount - 1) - + ((bistpasscount[loop] + 1) / 2)); + } + bistpasscount[loop] = 0; + } + if (meancount[loop] == 0 && bistpasscount[loop] >= 4 && + (currbistresult[loop] == 0 || itercount == 63) && + prevbistresult[loop] == 1) + meancount[loop] = + itercount - 1 - + ((bistpasscount[loop] + 1) / 2); + prevbistresult[loop] = currbistresult[loop]; + } + } while (++itercount < 64); + + for (loop = 0; loop <= 3; loop++) { + if (lane0_active == 0 && loop == 0) + continue; + if (lane1_active == 0 && loop == 1) + continue; + if (lane2_active == 0 && loop == 2) + continue; + if (lane3_active == 0 && loop == 3) + continue; + + if (meancount[loop] == 0) + meancount[loop] = meancountalt[loop]; + + if (gen2_calib != 1) { + ill1_val[loop] = ((0x04 + meancount[loop] * 8) % 0x100); + ill12_val[loop] = + ((0x04 + meancount[loop] * 8) >= + 0x100) ? 0x10 : 0x00; + } + if (gen2_calib == 1) { + ill1_val[loop] = + ((0x104 + meancount[loop] * 8) % 0x100); + ill12_val[loop] = + ((0x104 + meancount[loop] * 8) >= + 0x200) ? 0x02 : 0x01; + } + } + if (gen2_calib != 1) { + if (lane0_active == 1) + Xil_Out32(0xFD401924, ill1_val[0]); + if (lane0_active == 1) + psu_mask_write(0xFD401990, 0x000000F0U, ill12_val[0]); + if (lane1_active == 1) + Xil_Out32(0xFD405924, ill1_val[1]); + if (lane1_active == 1) + psu_mask_write(0xFD405990, 0x000000F0U, ill12_val[1]); + if (lane2_active == 1) + Xil_Out32(0xFD409924, ill1_val[2]); + if (lane2_active == 1) + psu_mask_write(0xFD409990, 0x000000F0U, ill12_val[2]); + if (lane3_active == 1) + Xil_Out32(0xFD40D924, ill1_val[3]); + if (lane3_active == 1) + psu_mask_write(0xFD40D990, 0x000000F0U, ill12_val[3]); + } + if (gen2_calib == 1) { + if (lane0_active == 1) + Xil_Out32(0xFD401928, ill1_val[0]); + if (lane0_active == 1) + psu_mask_write(0xFD401990, 0x0000000FU, ill12_val[0]); + if (lane1_active == 1) + Xil_Out32(0xFD405928, ill1_val[1]); + if (lane1_active == 1) + psu_mask_write(0xFD405990, 0x0000000FU, ill12_val[1]); + if (lane2_active == 1) + Xil_Out32(0xFD409928, ill1_val[2]); + if (lane2_active == 1) + psu_mask_write(0xFD409990, 0x0000000FU, ill12_val[2]); + if (lane3_active == 1) + Xil_Out32(0xFD40D928, ill1_val[3]); + if (lane3_active == 1) + psu_mask_write(0xFD40D990, 0x0000000FU, ill12_val[3]); + } + + if (lane0_active == 1) + psu_mask_write(0xFD401018, 0x00000030U, 0x00000000U); + if (lane1_active == 1) + psu_mask_write(0xFD405018, 0x00000030U, 0x00000000U); + if (lane2_active == 1) + psu_mask_write(0xFD409018, 0x00000030U, 0x00000000U); + if (lane3_active == 1) + psu_mask_write(0xFD40D018, 0x00000030U, 0x00000000U); + + Xil_Out32(0xFD410098, 0); + if (lane0_active == 1) { + Xil_Out32(0xFD403004, 0); + Xil_Out32(0xFD403008, 0); + Xil_Out32(0xFD40300C, 0); + Xil_Out32(0xFD403010, 0); + Xil_Out32(0xFD403014, 0); + Xil_Out32(0xFD403018, 0); + Xil_Out32(0xFD40301C, 0); + Xil_Out32(0xFD403020, 0); + Xil_Out32(0xFD403024, 0); + Xil_Out32(0xFD403028, 0); + Xil_Out32(0xFD40302C, 0); + Xil_Out32(0xFD403030, 0); + Xil_Out32(0xFD403034, 0); + Xil_Out32(0xFD403038, 0); + Xil_Out32(0xFD40303C, 0); + Xil_Out32(0xFD403040, 0); + Xil_Out32(0xFD403044, 0); + Xil_Out32(0xFD403048, 0); + Xil_Out32(0xFD40304C, 0); + Xil_Out32(0xFD403050, 0); + Xil_Out32(0xFD403054, 0); + Xil_Out32(0xFD403058, 0); + Xil_Out32(0xFD403068, 1); + Xil_Out32(0xFD40306C, 0); + Xil_Out32(0xFD4010AC, 0); + psu_mask_write(0xFD410044, 0x00000003U, 0x00000001U); + psu_mask_write(0xFD410040, 0x00000003U, 0x00000001U); + psu_mask_write(0xFD410038, 0x00000007U, 0x00000000U); + } + if (lane1_active == 1) { + Xil_Out32(0xFD407004, 0); + Xil_Out32(0xFD407008, 0); + Xil_Out32(0xFD40700C, 0); + Xil_Out32(0xFD407010, 0); + Xil_Out32(0xFD407014, 0); + Xil_Out32(0xFD407018, 0); + Xil_Out32(0xFD40701C, 0); + Xil_Out32(0xFD407020, 0); + Xil_Out32(0xFD407024, 0); + Xil_Out32(0xFD407028, 0); + Xil_Out32(0xFD40702C, 0); + Xil_Out32(0xFD407030, 0); + Xil_Out32(0xFD407034, 0); + Xil_Out32(0xFD407038, 0); + Xil_Out32(0xFD40703C, 0); + Xil_Out32(0xFD407040, 0); + Xil_Out32(0xFD407044, 0); + Xil_Out32(0xFD407048, 0); + Xil_Out32(0xFD40704C, 0); + Xil_Out32(0xFD407050, 0); + Xil_Out32(0xFD407054, 0); + Xil_Out32(0xFD407058, 0); + Xil_Out32(0xFD407068, 1); + Xil_Out32(0xFD40706C, 0); + Xil_Out32(0xFD4050AC, 0); + psu_mask_write(0xFD410044, 0x0000000CU, 0x00000004U); + psu_mask_write(0xFD410040, 0x0000000CU, 0x00000004U); + psu_mask_write(0xFD410038, 0x00000070U, 0x00000000U); + } + if (lane2_active == 1) { + Xil_Out32(0xFD40B004, 0); + Xil_Out32(0xFD40B008, 0); + Xil_Out32(0xFD40B00C, 0); + Xil_Out32(0xFD40B010, 0); + Xil_Out32(0xFD40B014, 0); + Xil_Out32(0xFD40B018, 0); + Xil_Out32(0xFD40B01C, 0); + Xil_Out32(0xFD40B020, 0); + Xil_Out32(0xFD40B024, 0); + Xil_Out32(0xFD40B028, 0); + Xil_Out32(0xFD40B02C, 0); + Xil_Out32(0xFD40B030, 0); + Xil_Out32(0xFD40B034, 0); + Xil_Out32(0xFD40B038, 0); + Xil_Out32(0xFD40B03C, 0); + Xil_Out32(0xFD40B040, 0); + Xil_Out32(0xFD40B044, 0); + Xil_Out32(0xFD40B048, 0); + Xil_Out32(0xFD40B04C, 0); + Xil_Out32(0xFD40B050, 0); + Xil_Out32(0xFD40B054, 0); + Xil_Out32(0xFD40B058, 0); + Xil_Out32(0xFD40B068, 1); + Xil_Out32(0xFD40B06C, 0); + Xil_Out32(0xFD4090AC, 0); + psu_mask_write(0xFD410044, 0x00000030U, 0x00000010U); + psu_mask_write(0xFD410040, 0x00000030U, 0x00000010U); + psu_mask_write(0xFD41003C, 0x00000007U, 0x00000000U); + } + if (lane3_active == 1) { + Xil_Out32(0xFD40F004, 0); + Xil_Out32(0xFD40F008, 0); + Xil_Out32(0xFD40F00C, 0); + Xil_Out32(0xFD40F010, 0); + Xil_Out32(0xFD40F014, 0); + Xil_Out32(0xFD40F018, 0); + Xil_Out32(0xFD40F01C, 0); + Xil_Out32(0xFD40F020, 0); + Xil_Out32(0xFD40F024, 0); + Xil_Out32(0xFD40F028, 0); + Xil_Out32(0xFD40F02C, 0); + Xil_Out32(0xFD40F030, 0); + Xil_Out32(0xFD40F034, 0); + Xil_Out32(0xFD40F038, 0); + Xil_Out32(0xFD40F03C, 0); + Xil_Out32(0xFD40F040, 0); + Xil_Out32(0xFD40F044, 0); + Xil_Out32(0xFD40F048, 0); + Xil_Out32(0xFD40F04C, 0); + Xil_Out32(0xFD40F050, 0); + Xil_Out32(0xFD40F054, 0); + Xil_Out32(0xFD40F058, 0); + Xil_Out32(0xFD40F068, 1); + Xil_Out32(0xFD40F06C, 0); + Xil_Out32(0xFD40D0AC, 0); + psu_mask_write(0xFD410044, 0x000000C0U, 0x00000040U); + psu_mask_write(0xFD410040, 0x000000C0U, 0x00000040U); + psu_mask_write(0xFD41003C, 0x00000070U, 0x00000000U); + } + return 1; +} + +static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate, + u32 lane2_protocol, u32 lane2_rate, + u32 lane1_protocol, u32 lane1_rate, + u32 lane0_protocol, u32 lane0_rate) +{ + unsigned int rdata = 0; + unsigned int sata_gen2 = 1; + unsigned int temp_ill12 = 0; + unsigned int temp_PLL_REF_SEL_OFFSET; + unsigned int temp_TM_IQ_ILL1; + unsigned int temp_TM_E_ILL1; + unsigned int temp_tx_dig_tm_61; + unsigned int temp_tm_dig_6; + unsigned int temp_pll_fbdiv_frac_3_msb_offset; + + if (lane0_protocol == 2 || lane0_protocol == 1) { + Xil_Out32(0xFD401910, 0xF3); + Xil_Out32(0xFD40193C, 0xF3); + Xil_Out32(0xFD401914, 0xF3); + Xil_Out32(0xFD401940, 0xF3); + } + if (lane1_protocol == 2 || lane1_protocol == 1) { + Xil_Out32(0xFD405910, 0xF3); + Xil_Out32(0xFD40593C, 0xF3); + Xil_Out32(0xFD405914, 0xF3); + Xil_Out32(0xFD405940, 0xF3); + } + if (lane2_protocol == 2 || lane2_protocol == 1) { + Xil_Out32(0xFD409910, 0xF3); + Xil_Out32(0xFD40993C, 0xF3); + Xil_Out32(0xFD409914, 0xF3); + Xil_Out32(0xFD409940, 0xF3); + } + if (lane3_protocol == 2 || lane3_protocol == 1) { + Xil_Out32(0xFD40D910, 0xF3); + Xil_Out32(0xFD40D93C, 0xF3); + Xil_Out32(0xFD40D914, 0xF3); + Xil_Out32(0xFD40D940, 0xF3); + } + + if (sata_gen2 == 1) { + if (lane0_protocol == 2) { + temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD402360); + Xil_Out32(0xFD402360, 0x0); + temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410000); + psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000DU); + temp_TM_IQ_ILL1 = Xil_In32(0xFD4018F8); + temp_TM_E_ILL1 = Xil_In32(0xFD401924); + Xil_Out32(0xFD4018F8, 0x78); + temp_tx_dig_tm_61 = Xil_In32(0xFD4000F4); + temp_tm_dig_6 = Xil_In32(0xFD40106C); + psu_mask_write(0xFD4000F4, 0x0000000BU, 0x00000000U); + psu_mask_write(0xFD40106C, 0x0000000FU, 0x00000000U); + temp_ill12 = Xil_In32(0xFD401990) & 0xF0; + + serdes_illcalib_pcie_gen1(0, 0, 0, 0, 0, 0, 0, 1, 0, 0); + + Xil_Out32(0xFD402360, temp_pll_fbdiv_frac_3_msb_offset); + Xil_Out32(0xFD410000, temp_PLL_REF_SEL_OFFSET); + Xil_Out32(0xFD4018F8, temp_TM_IQ_ILL1); + Xil_Out32(0xFD4000F4, temp_tx_dig_tm_61); + Xil_Out32(0xFD40106C, temp_tm_dig_6); + Xil_Out32(0xFD401928, Xil_In32(0xFD401924)); + temp_ill12 = + temp_ill12 | (Xil_In32(0xFD401990) >> 4 & 0xF); + Xil_Out32(0xFD401990, temp_ill12); + Xil_Out32(0xFD401924, temp_TM_E_ILL1); + } + if (lane1_protocol == 2) { + temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD406360); + Xil_Out32(0xFD406360, 0x0); + temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410004); + psu_mask_write(0xFD410004, 0x0000001FU, 0x0000000DU); + temp_TM_IQ_ILL1 = Xil_In32(0xFD4058F8); + temp_TM_E_ILL1 = Xil_In32(0xFD405924); + Xil_Out32(0xFD4058F8, 0x78); + temp_tx_dig_tm_61 = Xil_In32(0xFD4040F4); + temp_tm_dig_6 = Xil_In32(0xFD40506C); + psu_mask_write(0xFD4040F4, 0x0000000BU, 0x00000000U); + psu_mask_write(0xFD40506C, 0x0000000FU, 0x00000000U); + temp_ill12 = Xil_In32(0xFD405990) & 0xF0; + + serdes_illcalib_pcie_gen1(1, 0, 0, 0, 0, 1, 0, 0, 0, 0); + + Xil_Out32(0xFD406360, temp_pll_fbdiv_frac_3_msb_offset); + Xil_Out32(0xFD410004, temp_PLL_REF_SEL_OFFSET); + Xil_Out32(0xFD4058F8, temp_TM_IQ_ILL1); + Xil_Out32(0xFD4040F4, temp_tx_dig_tm_61); + Xil_Out32(0xFD40506C, temp_tm_dig_6); + Xil_Out32(0xFD405928, Xil_In32(0xFD405924)); + temp_ill12 = + temp_ill12 | (Xil_In32(0xFD405990) >> 4 & 0xF); + Xil_Out32(0xFD405990, temp_ill12); + Xil_Out32(0xFD405924, temp_TM_E_ILL1); + } + if (lane2_protocol == 2) { + temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40A360); + Xil_Out32(0xFD40A360, 0x0); + temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410008); + psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000DU); + temp_TM_IQ_ILL1 = Xil_In32(0xFD4098F8); + temp_TM_E_ILL1 = Xil_In32(0xFD409924); + Xil_Out32(0xFD4098F8, 0x78); + temp_tx_dig_tm_61 = Xil_In32(0xFD4080F4); + temp_tm_dig_6 = Xil_In32(0xFD40906C); + psu_mask_write(0xFD4080F4, 0x0000000BU, 0x00000000U); + psu_mask_write(0xFD40906C, 0x0000000FU, 0x00000000U); + temp_ill12 = Xil_In32(0xFD409990) & 0xF0; + + serdes_illcalib_pcie_gen1(2, 0, 0, 1, 0, 0, 0, 0, 0, 0); + + Xil_Out32(0xFD40A360, temp_pll_fbdiv_frac_3_msb_offset); + Xil_Out32(0xFD410008, temp_PLL_REF_SEL_OFFSET); + Xil_Out32(0xFD4098F8, temp_TM_IQ_ILL1); + Xil_Out32(0xFD4080F4, temp_tx_dig_tm_61); + Xil_Out32(0xFD40906C, temp_tm_dig_6); + Xil_Out32(0xFD409928, Xil_In32(0xFD409924)); + temp_ill12 = + temp_ill12 | (Xil_In32(0xFD409990) >> 4 & 0xF); + Xil_Out32(0xFD409990, temp_ill12); + Xil_Out32(0xFD409924, temp_TM_E_ILL1); + } + if (lane3_protocol == 2) { + temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40E360); + Xil_Out32(0xFD40E360, 0x0); + temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD41000C); + psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000DU); + temp_TM_IQ_ILL1 = Xil_In32(0xFD40D8F8); + temp_TM_E_ILL1 = Xil_In32(0xFD40D924); + Xil_Out32(0xFD40D8F8, 0x78); + temp_tx_dig_tm_61 = Xil_In32(0xFD40C0F4); + temp_tm_dig_6 = Xil_In32(0xFD40D06C); + psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x00000000U); + psu_mask_write(0xFD40D06C, 0x0000000FU, 0x00000000U); + temp_ill12 = Xil_In32(0xFD40D990) & 0xF0; + + serdes_illcalib_pcie_gen1(3, 1, 0, 0, 0, 0, 0, 0, 0, 0); + + Xil_Out32(0xFD40E360, temp_pll_fbdiv_frac_3_msb_offset); + Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET); + Xil_Out32(0xFD40D8F8, temp_TM_IQ_ILL1); + Xil_Out32(0xFD40C0F4, temp_tx_dig_tm_61); + Xil_Out32(0xFD40D06C, temp_tm_dig_6); + Xil_Out32(0xFD40D928, Xil_In32(0xFD40D924)); + temp_ill12 = + temp_ill12 | (Xil_In32(0xFD40D990) >> 4 & 0xF); + Xil_Out32(0xFD40D990, temp_ill12); + Xil_Out32(0xFD40D924, temp_TM_E_ILL1); + } + rdata = Xil_In32(0xFD410098); + rdata = (rdata & 0xDF); + Xil_Out32(0xFD410098, rdata); + } + + if (lane0_protocol == 2 && lane0_rate == 3) { + psu_mask_write(0xFD40198C, 0x000000F0U, 0x00000020U); + psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000094U); + } + if (lane1_protocol == 2 && lane1_rate == 3) { + psu_mask_write(0xFD40598C, 0x000000F0U, 0x00000020U); + psu_mask_write(0xFD40592C, 0x000000FFU, 0x00000094U); + } + if (lane2_protocol == 2 && lane2_rate == 3) { + psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U); + psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000094U); + } + if (lane3_protocol == 2 && lane3_rate == 3) { + psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U); + psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000094U); + } + + if (lane0_protocol == 1) { + if (lane0_rate == 0) { + serdes_illcalib_pcie_gen1(0, lane3_protocol, lane3_rate, + lane2_protocol, lane2_rate, + lane1_protocol, lane1_rate, + lane0_protocol, 0, 0); + } else { + serdes_illcalib_pcie_gen1(0, lane3_protocol, lane3_rate, + lane2_protocol, lane2_rate, + lane1_protocol, lane1_rate, + lane0_protocol, 0, 0); + serdes_illcalib_pcie_gen1(0, lane3_protocol, lane3_rate, + lane2_protocol, lane2_rate, + lane1_protocol, lane1_rate, + lane0_protocol, lane0_rate, + 1); + } + } + + if (lane0_protocol == 3) + Xil_Out32(0xFD401914, 0xF3); + if (lane0_protocol == 3) + Xil_Out32(0xFD401940, 0xF3); + if (lane0_protocol == 3) + Xil_Out32(0xFD401990, 0x20); + if (lane0_protocol == 3) + Xil_Out32(0xFD401924, 0x37); + + if (lane1_protocol == 3) + Xil_Out32(0xFD405914, 0xF3); + if (lane1_protocol == 3) + Xil_Out32(0xFD405940, 0xF3); + if (lane1_protocol == 3) + Xil_Out32(0xFD405990, 0x20); + if (lane1_protocol == 3) + Xil_Out32(0xFD405924, 0x37); + + if (lane2_protocol == 3) + Xil_Out32(0xFD409914, 0xF3); + if (lane2_protocol == 3) + Xil_Out32(0xFD409940, 0xF3); + if (lane2_protocol == 3) + Xil_Out32(0xFD409990, 0x20); + if (lane2_protocol == 3) + Xil_Out32(0xFD409924, 0x37); + + if (lane3_protocol == 3) + Xil_Out32(0xFD40D914, 0xF3); + if (lane3_protocol == 3) + Xil_Out32(0xFD40D940, 0xF3); + if (lane3_protocol == 3) + Xil_Out32(0xFD40D990, 0x20); + if (lane3_protocol == 3) + Xil_Out32(0xFD40D924, 0x37); + + return 1; +} + +static void dpll_prog(int div2, int ddr_pll_fbdiv, int d_lock_dly, + int d_lock_cnt, int d_lfhf, int d_cp, int d_res) +{ + unsigned int pll_ctrl_regval; + unsigned int pll_status_regval; + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00010000U); + pll_ctrl_regval = pll_ctrl_regval | (div2 << 16); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x00000030)); + pll_ctrl_regval = pll_ctrl_regval & (~0xFE000000U); + pll_ctrl_regval = pll_ctrl_regval | (d_lock_dly << 25); + Xil_Out32(((0xFD1A0000U) + 0x00000030), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x00000030)); + pll_ctrl_regval = pll_ctrl_regval & (~0x007FE000U); + pll_ctrl_regval = pll_ctrl_regval | (d_lock_cnt << 13); + Xil_Out32(((0xFD1A0000U) + 0x00000030), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x00000030)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00000C00U); + pll_ctrl_regval = pll_ctrl_regval | (d_lfhf << 10); + Xil_Out32(((0xFD1A0000U) + 0x00000030), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x00000030)); + pll_ctrl_regval = pll_ctrl_regval & (~0x000001E0U); + pll_ctrl_regval = pll_ctrl_regval | (d_cp << 5); + Xil_Out32(((0xFD1A0000U) + 0x00000030), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x00000030)); + pll_ctrl_regval = pll_ctrl_regval & (~0x0000000FU); + pll_ctrl_regval = pll_ctrl_regval | (d_res << 0); + Xil_Out32(((0xFD1A0000U) + 0x00000030), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00007F00U); + pll_ctrl_regval = pll_ctrl_regval | (ddr_pll_fbdiv << 8); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00000008U); + pll_ctrl_regval = pll_ctrl_regval | (1 << 3); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00000001U); + pll_ctrl_regval = pll_ctrl_regval | (1 << 0); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00000001U); + pll_ctrl_regval = pll_ctrl_regval | (0 << 0); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); + + pll_status_regval = 0x00000000; + while ((pll_status_regval & 0x00000002U) != 0x00000002U) + pll_status_regval = Xil_In32(((0xFD1A0000U) + 0x00000044)); + + pll_ctrl_regval = Xil_In32(((0xFD1A0000U) + 0x0000002C)); + pll_ctrl_regval = pll_ctrl_regval & (~0x00000008U); + pll_ctrl_regval = pll_ctrl_regval | (0 << 3); + Xil_Out32(((0xFD1A0000U) + 0x0000002C), pll_ctrl_regval); +} + +static int serdes_enb_coarse_saturation(void) +{ + Xil_Out32(0xFD402094, 0x00000010); + Xil_Out32(0xFD406094, 0x00000010); + Xil_Out32(0xFD40A094, 0x00000010); + Xil_Out32(0xFD40E094, 0x00000010); + return 1; +} + +static int serdes_fixcal_code(void) +{ + int maskstatus = 1; + unsigned int rdata = 0; + unsigned int match_pmos_code[23]; + unsigned int match_nmos_code[23]; + unsigned int match_ical_code[7]; + unsigned int match_rcal_code[7]; + unsigned int p_code = 0; + unsigned int n_code = 0; + unsigned int i_code = 0; + unsigned int r_code = 0; + unsigned int repeat_count = 0; + unsigned int L3_TM_CALIB_DIG20 = 0; + unsigned int L3_TM_CALIB_DIG19 = 0; + unsigned int L3_TM_CALIB_DIG18 = 0; + unsigned int L3_TM_CALIB_DIG16 = 0; + unsigned int L3_TM_CALIB_DIG15 = 0; + unsigned int L3_TM_CALIB_DIG14 = 0; + int i = 0; + int count = 0; + + rdata = Xil_In32(0xFD40289C); + rdata = rdata & ~0x03; + rdata = rdata | 0x1; + Xil_Out32(0xFD40289C, rdata); + + do { + if (count == 1100000) + break; + rdata = Xil_In32(0xFD402B1C); + count++; + } while ((rdata & 0x0000000E) != 0x0000000E); + + for (i = 0; i < 23; i++) { + match_pmos_code[i] = 0; + match_nmos_code[i] = 0; + } + for (i = 0; i < 7; i++) { + match_ical_code[i] = 0; + match_rcal_code[i] = 0; + } + + do { + Xil_Out32(0xFD410010, 0x00000000); + Xil_Out32(0xFD410014, 0x00000000); + + Xil_Out32(0xFD410010, 0x00000001); + Xil_Out32(0xFD410014, 0x00000000); + + maskstatus = mask_poll(0xFD40EF14, 0x2); + if (maskstatus == 0) { + xil_printf("#SERDES initialization timed out\n\r"); + return maskstatus; + } + + p_code = mask_read(0xFD40EF18, 0xFFFFFFFF); + n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF); + ; + i_code = mask_read(0xFD40EF24, 0xFFFFFFFF); + r_code = mask_read(0xFD40EF28, 0xFFFFFFFF); + ; + + if (p_code >= 0x26 && p_code <= 0x3C) + match_pmos_code[p_code - 0x26] += 1; + + if (n_code >= 0x26 && n_code <= 0x3C) + match_nmos_code[n_code - 0x26] += 1; + + if (i_code >= 0xC && i_code <= 0x12) + match_ical_code[i_code - 0xc] += 1; + + if (r_code >= 0x6 && r_code <= 0xC) + match_rcal_code[r_code - 0x6] += 1; + + } while (repeat_count++ < 10); + + for (i = 0; i < 23; i++) { + if (match_pmos_code[i] >= match_pmos_code[0]) { + match_pmos_code[0] = match_pmos_code[i]; + p_code = 0x26 + i; + } + if (match_nmos_code[i] >= match_nmos_code[0]) { + match_nmos_code[0] = match_nmos_code[i]; + n_code = 0x26 + i; + } + } + + for (i = 0; i < 7; i++) { + if (match_ical_code[i] >= match_ical_code[0]) { + match_ical_code[0] = match_ical_code[i]; + i_code = 0xC + i; + } + if (match_rcal_code[i] >= match_rcal_code[0]) { + match_rcal_code[0] = match_rcal_code[i]; + r_code = 0x6 + i; + } + } + + L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0); + L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7); + + L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18); + L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6) + | 0x20 | 0x4 | ((n_code >> 3) & 0x3); + + L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F); + L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10; + + L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8); + L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7); + + L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30); + L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7) + | 0x40 | 0x8 | ((i_code >> 1) & 0x7); + + L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F); + L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40; + + Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20); + Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19); + Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18); + Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16); + Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15); + Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14); + return maskstatus; +} + +static int init_serdes(void) +{ + int status = 1; + + status &= psu_resetin_init_data(); + + status &= serdes_fixcal_code(); + status &= serdes_enb_coarse_saturation(); + + status &= psu_serdes_init_data(); + status &= psu_resetout_init_data(); + + return status; +} + +static void init_peripheral(void) +{ + psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU); +} + +int psu_init(void) +{ + int status = 1; + + status &= psu_mio_init_data(); + status &= psu_peripherals_pre_init_data(); + status &= psu_pll_init_data(); + status &= psu_clock_init_data(); + status &= psu_ddr_init_data(); + status &= psu_ddr_phybringup_data(); + status &= psu_peripherals_init_data(); + status &= init_serdes(); + init_peripheral(); + + status &= psu_afi_config(); + psu_ddr_qos_init_data(); + + if (status == 0) + return 1; + return 0; +} From 1db1acbb848ef1b10eccedb52edd6c37078bbd38 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Tue, 28 Sep 2021 11:30:27 +0530 Subject: [PATCH 15/17] clk: versal: Enable only GATE type clocks Clocks should be enabled or disabled only if they are of GATE type clocks. If they are not of GATE type clocks, don't touch them. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1632808827-6109-1-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/clk/clk_versal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index 62523d290999..a9dd57b098fe 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -725,7 +725,10 @@ static int versal_clk_enable(struct clk *clk) clk_id = priv->clk[clk->id].clk_id; - return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, NULL); + if (versal_clock_gate(clk_id)) + return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, NULL); + + return 0; } static struct clk_ops versal_clk_ops = { From 8c287ed8c3a392d2fd717054511b53851bce02f0 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Tue, 28 Sep 2021 11:31:58 +0530 Subject: [PATCH 16/17] watchdog: versal: Add support for basic window watchdog Existing driver uses generic watchdog mode which generates a signal to PLM firmware, but the signal cannot be used to reset the system. Change driver to use window watchdog basic mode. This window watchdog mode generates a signal to PLM firmware which decides what action to take upon expiry of watchdog. Timeout value for xlnx_wwdt_start will come in milli seconds from wdt framework. Make changes to load count value accordingly. Add checks before loading the timer for min and max possible values. Fix authour email id of Ashok Reddy Soma to long email id. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1632808919-8600-2-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/watchdog/xilinx_wwdt.c | 98 +++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c index c8e6c60cdd22..d8b2ae72483b 100644 --- a/drivers/watchdog/xilinx_wwdt.c +++ b/drivers/watchdog/xilinx_wwdt.c @@ -3,7 +3,7 @@ * Xilinx window watchdog timer driver. * * Author(s): Michal Simek - * Ashok Reddy Soma + * Ashok Reddy Soma * * Copyright (c) 2020, Xilinx Inc. */ @@ -23,13 +23,22 @@ /* Generic Control/Status Register Masks */ #define XWT_WWCSR_GWEN_MASK BIT(0) /* Enable Bit */ -/* Register offsets for the Wdt device */ -#define XWT_WWREF_OFFSET 0x1000 /* Refresh Register */ -#define XWT_WWCSR_OFFSET 0x2000 /* Control/Status Register */ -#define XWT_WWOFF_OFFSET 0x2008 /* Offset Register */ -#define XWT_WWCMP0_OFFSET 0x2010 /* Compare Value Register0 */ -#define XWT_WWCMP1_OFFSET 0x2014 /* Compare Value Register1 */ -#define XWT_WWWRST_OFFSET 0x2FD0 /* Warm Reset Register */ +/* Register offsets for the WWDT device */ +#define XWT_WWDT_MWR_OFFSET 0x00 +#define XWT_WWDT_ESR_OFFSET 0x04 +#define XWT_WWDT_FCR_OFFSET 0x08 +#define XWT_WWDT_FWR_OFFSET 0x0c +#define XWT_WWDT_SWR_OFFSET 0x10 +#define XWT_WWDT_CNT_MIN 1 +#define XWT_WWDT_CNT_MAX 0xffffffff + +/* Master Write Control Register Masks */ +#define XWT_WWDT_MWR_MASK BIT(0) + +/* Enable and Status Register Masks */ +#define XWT_WWDT_ESR_WINT_MASK BIT(16) +#define XWT_WWDT_ESR_WSW_MASK BIT(8) +#define XWT_WWDT_ESR_WEN_MASK BIT(0) struct xlnx_wwdt_priv { bool enable_once; @@ -43,16 +52,23 @@ struct xlnx_wwdt_plat { static int xlnx_wwdt_reset(struct udevice *dev) { + u32 esr; struct xlnx_wwdt_priv *wdt = dev_get_priv(dev); - regmap_write(wdt->regs, XWT_WWREF_OFFSET, XWT_WWREF_GWRR_MASK); + regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK); + regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr); + esr |= XWT_WWDT_ESR_WINT_MASK; + esr &= ~XWT_WWDT_ESR_WSW_MASK; + regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr); + regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr); + esr |= XWT_WWDT_ESR_WSW_MASK; + regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr); return 0; } static int xlnx_wwdt_stop(struct udevice *dev) { - u32 csr; struct xlnx_wwdt_priv *wdt = dev_get_priv(dev); if (wdt->enable_once) { @@ -60,10 +76,9 @@ static int xlnx_wwdt_stop(struct udevice *dev) return -EBUSY; } - /* Disable the generic watchdog timer */ - regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr); - csr &= ~(XWT_WWCSR_GWEN_MASK); - regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr); + /* Disable the window watchdog timer */ + regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK); + regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, ~(u32)XWT_WWDT_ESR_WEN_MASK); clk_disable(&wdt->clk); @@ -72,11 +87,11 @@ static int xlnx_wwdt_stop(struct udevice *dev) return 0; } -static int xlnx_wwdt_start(struct udevice *dev, u64 timeout, ulong flags) +static int xlnx_wwdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { int ret; - u32 csr; - u64 count; + u32 esr; + u64 count, timeout; unsigned long clock_f; struct xlnx_wwdt_priv *wdt = dev_get_priv(dev); @@ -88,36 +103,43 @@ static int xlnx_wwdt_start(struct udevice *dev, u64 timeout, ulong flags) dev_dbg(dev, "%s: CLK %ld\n", __func__, clock_f); + /* Convert timeout from msec to sec */ + timeout = timeout_ms / 1000; + /* Calculate timeout count */ count = timeout * clock_f; + /* Count should be at least 1 */ + if (count < XWT_WWDT_CNT_MIN) { + debug("%s: watchdog won't fire with 0 ticks\n", __func__); + count = XWT_WWDT_CNT_MIN; + } + + /* Limit the count to maximum possible value */ + if (count > XWT_WWDT_CNT_MAX) { + debug("%s: maximum watchdog timeout exceeded\n", __func__); + count = XWT_WWDT_CNT_MAX; + } + ret = clk_enable(&wdt->clk); if (ret) { dev_err(dev, "failed to enable clock\n"); return ret; } - /* - * Timeout count is half as there are two windows - * first window overflow is ignored (interrupt), - * reset is only generated at second window overflow - */ - count = count >> 1; - - /* Disable the generic watchdog timer */ - regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr); - csr &= ~(XWT_WWCSR_GWEN_MASK); - regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr); - - /* Set compare and offset registers for generic watchdog timeout */ - regmap_write(wdt->regs, XWT_WWCMP0_OFFSET, (u32)count); - regmap_write(wdt->regs, XWT_WWCMP1_OFFSET, 0); - regmap_write(wdt->regs, XWT_WWOFF_OFFSET, (u32)count); - - /* Enable the generic watchdog timer */ - regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr); - csr |= (XWT_WWCSR_GWEN_MASK); - regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr); + /* Disable the window watchdog timer */ + regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK); + regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, ~(u32)XWT_WWDT_ESR_WEN_MASK); + + /* Set first window and second window registers with timeout */ + regmap_write(wdt->regs, XWT_WWDT_FWR_OFFSET, 0); /* No pre-timeout */ + regmap_write(wdt->regs, XWT_WWDT_SWR_OFFSET, (u32)count); + regmap_write(wdt->regs, XWT_WWDT_FCR_OFFSET, 0); + + /* Enable the window watchdog timer */ + regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr); + esr |= XWT_WWDT_ESR_WEN_MASK; + regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr); return 0; } From dced079c53b283e15f04282f405de410a9be584d Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Tue, 28 Sep 2021 11:31:59 +0530 Subject: [PATCH 17/17] watchdog: versal: Add support for expire now Wdt expire command makes the wdt to count least possible ticks(1) and expires immediately. Add expire_now option to the xlnx_wwdt_ops and implement it by calling xlnx_wwdt_start() with minimum possible count(1). Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1632808919-8600-3-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/watchdog/xilinx_wwdt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c index d8b2ae72483b..d582e3cc8f41 100644 --- a/drivers/watchdog/xilinx_wwdt.c +++ b/drivers/watchdog/xilinx_wwdt.c @@ -144,6 +144,11 @@ static int xlnx_wwdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) return 0; } +static int xlnx_wwdt_expire_now(struct udevice *dev, ulong flags) +{ + return xlnx_wwdt_start(dev, XWT_WWDT_CNT_MIN, flags); +} + static int xlnx_wwdt_probe(struct udevice *dev) { int ret; @@ -182,6 +187,7 @@ static const struct wdt_ops xlnx_wwdt_ops = { .start = xlnx_wwdt_start, .reset = xlnx_wwdt_reset, .stop = xlnx_wwdt_stop, + .expire_now = xlnx_wwdt_expire_now, }; static const struct udevice_id xlnx_wwdt_ids[] = {