public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200
@ 2023-08-30 14:03 Steffen Dirkwinkel
  2023-08-30 14:03 ` [PATCH 1/5] drivers: rtc: add rv3032 driver Steffen Dirkwinkel
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot
  Cc: Steffen Dirkwinkel, Alexandre Belloni, Chris Packham, Jagan Teki,
	Jonas Karlman, Kunihiko Hayashi, Marek Vasut, Michal Simek,
	Sergei Antonov, Simon Glass, Venkatesh Yadav Abbarapu

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>


This adds support for the Beckhoff CX8200 series of industrial embedded PCs.
There is some information about the device and features here:
https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/

We also add the rtc rv3032 driver from linux, as it is required for
mac address loading, fix usb without reset gpios on zynqmp and move the
fdt loadaddr to be compatible with less memory.


Steffen Dirkwinkel (5):
  drivers: rtc: add rv3032 driver
  drivers/usb/dwc3: zynqmp: only free reset gpio if we have one
  xilinx: zynqmp: move fdt_addr so we can use devices with less memory
  xilinx: zynqmp: add Beckhoff CX8200
  xilinx: zynqmp: beckhoff cx8200: setup inner cache broadcasting

 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
 .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
 .../zynqmp/zynqmp-beckhoff-cx8200/regs.init   |    1 +
 configs/xilinx_zynqmp_virt_defconfig          |    2 +-
 drivers/rtc/Kconfig                           |   10 +
 drivers/rtc/Makefile                          |    1 +
 drivers/rtc/rv3032.c                          |  334 +++
 drivers/usb/dwc3/dwc3-generic.c               |    4 +-
 include/configs/xilinx_zynqmp.h               |    2 +-
 10 files changed, 2559 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
 create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
 create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init
 create mode 100644 drivers/rtc/rv3032.c

-- 
2.42.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/5] drivers: rtc: add rv3032 driver
  2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
@ 2023-08-30 14:03 ` Steffen Dirkwinkel
  2023-08-30 19:43   ` Alexandre Belloni
  2023-08-30 14:03 ` [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one Steffen Dirkwinkel
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot
  Cc: Steffen Dirkwinkel, Alexandre Belloni, Chris Packham,
	Sergei Antonov, Simon Glass

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

Based on linux driver, with these differences:
- no support for trickle charger
- no support for hwmon
- no support for battery backed memory
- dm_i2c instead of regmap
- different tm_year and tm_mon

read/write access the user eeprom. The read and write functions access
the user eeprom so it can be used for nvmem-cells. (like in
arch/sandbox/dts/test.dts). This is currently different from linux as
you'd get nvram using nvmem-cells. I'm hoping to switch the order there
too (there are currently no users) or to make a more specific binding.
Currently this would also just work as is if used for mac addresses, as
u-boot will put these into fdt before booting linux and linux will then
prefer the u-boot provided mac.

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

---

 drivers/rtc/Kconfig  |  10 ++
 drivers/rtc/Makefile |   1 +
 drivers/rtc/rv3032.c | 334 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 345 insertions(+)
 create mode 100644 drivers/rtc/rv3032.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 23173139e0..a41ec9b6cc 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -172,6 +172,16 @@ config RTC_RV3029
 	  This driver supports reading and writing the RTC/calendar and the
 	  battery-baced SRAM section.
 
+config RTC_RV3032
+	bool "Enable RV3032 driver"
+	depends on DM_RTC
+	help
+	  The MicroCrystal RV3032 is a I2C Real Time Clock (RTC) with a 16-byte
+	  battery-backed SRAM and a 32-byte user eeprom.
+
+	  This driver supports reading and writing the RTC/calendar and the
+	  user eeprom.
+
 config RTC_RV8803
 	bool "Enable RV8803 driver"
 	depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 308fab8da9..9c2d8c7aa9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_PL031) += pl031.o
 obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
 obj-$(CONFIG_RTC_RV3028) += rv3028.o
 obj-$(CONFIG_RTC_RV3029) += rv3029.o
+obj-$(CONFIG_RTC_RV3032) += rv3032.o
 obj-$(CONFIG_RTC_RV8803) += rv8803.o
 obj-$(CONFIG_RTC_RX8025) += rx8025.o
 obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
diff --git a/drivers/rtc/rv3032.c b/drivers/rtc/rv3032.c
new file mode 100644
index 0000000000..8d5d860c0a
--- /dev/null
+++ b/drivers/rtc/rv3032.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RTC driver for the Micro Crystal RV3032
+ *
+ * based on linux driver from
+ * Copyright (C) 2020 Micro Crystal SA
+ *
+ * Alexandre Belloni <alexandre.belloni@bootlin.com>
+ *
+ */
+
+#include <dm.h>
+#include <i2c.h>
+#include <linux/delay.h>
+#include <regmap.h>
+#include <rtc.h>
+#include <time.h>
+
+#define RV3032_SEC			0x01
+#define RV3032_MIN			0x02
+#define RV3032_HOUR			0x03
+#define RV3032_WDAY			0x04
+#define RV3032_DAY			0x05
+#define RV3032_MONTH			0x06
+#define RV3032_YEAR			0x07
+#define RV3032_ALARM_MIN		0x08
+#define RV3032_ALARM_HOUR		0x09
+#define RV3032_ALARM_DAY		0x0A
+#define RV3032_STATUS			0x0D
+#define RV3032_TLSB			0x0E
+#define RV3032_TMSB			0x0F
+#define RV3032_CTRL1			0x10
+#define RV3032_CTRL2			0x11
+#define RV3032_CTRL3			0x12
+#define RV3032_TS_CTRL			0x13
+#define RV3032_CLK_IRQ			0x14
+#define RV3032_EEPROM_ADDR		0x3D
+#define RV3032_EEPROM_DATA		0x3E
+#define RV3032_EEPROM_CMD		0x3F
+#define RV3032_RAM1			0x40
+#define RV3032_PMU			0xC0
+#define RV3032_OFFSET			0xC1
+#define RV3032_CLKOUT1			0xC2
+#define RV3032_CLKOUT2			0xC3
+#define RV3032_TREF0			0xC4
+#define RV3032_TREF1			0xC5
+
+#define RV3032_STATUS_VLF		BIT(0)
+#define RV3032_STATUS_PORF		BIT(1)
+#define RV3032_STATUS_EVF		BIT(2)
+#define RV3032_STATUS_AF		BIT(3)
+#define RV3032_STATUS_TF		BIT(4)
+#define RV3032_STATUS_UF		BIT(5)
+#define RV3032_STATUS_TLF		BIT(6)
+#define RV3032_STATUS_THF		BIT(7)
+
+#define RV3032_TLSB_CLKF		BIT(1)
+#define RV3032_TLSB_EEBUSY		BIT(2)
+#define RV3032_TLSB_TEMP		GENMASK(7, 4)
+
+#define RV3032_CLKOUT2_HFD_MSK		GENMASK(4, 0)
+#define RV3032_CLKOUT2_FD_MSK		GENMASK(6, 5)
+#define RV3032_CLKOUT2_OS		BIT(7)
+
+#define RV3032_CTRL1_EERD		BIT(3)
+#define RV3032_CTRL1_WADA		BIT(5)
+
+#define RV3032_CTRL2_STOP		BIT(0)
+#define RV3032_CTRL2_EIE		BIT(2)
+#define RV3032_CTRL2_AIE		BIT(3)
+#define RV3032_CTRL2_TIE		BIT(4)
+#define RV3032_CTRL2_UIE		BIT(5)
+#define RV3032_CTRL2_CLKIE		BIT(6)
+#define RV3032_CTRL2_TSE		BIT(7)
+
+#define RV3032_PMU_TCM			GENMASK(1, 0)
+#define RV3032_PMU_TCR			GENMASK(3, 2)
+#define RV3032_PMU_BSM			GENMASK(5, 4)
+#define RV3032_PMU_NCLKE		BIT(6)
+
+#define RV3032_PMU_BSM_DSM		1
+#define RV3032_PMU_BSM_LSM		2
+
+#define RV3032_OFFSET_MSK		GENMASK(5, 0)
+
+#define RV3032_EVT_CTRL_TSR		BIT(2)
+
+#define RV3032_EEPROM_CMD_UPDATE	0x11
+#define RV3032_EEPROM_CMD_WRITE		0x21
+#define RV3032_EEPROM_CMD_READ		0x22
+
+#define RV3032_EEPROM_USER		0xCB
+
+#define RV3032_EEBUSY_POLL		10000
+#define RV3032_EEBUSY_TIMEOUT		100000
+
+#define OFFSET_STEP_PPT			238419
+
+static int rv3032_update_bits(struct udevice *dev, u8 reg, u8 mask, u8 set)
+{
+	u8 buf;
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	if ((buf & mask) == (set && mask))
+		return 0;
+
+	buf = (buf & ~mask) | (set & mask);
+	ret = dm_i2c_read(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rv3032_exit_eerd(struct udevice *dev, u32 eerd)
+{
+	if (eerd)
+		return 0;
+
+	return rv3032_update_bits(dev, RV3032_CTRL1, RV3032_CTRL1_EERD, 0);
+}
+
+static int rv3032_eeprom_busywait(struct udevice *dev)
+{
+	int ret;
+	u8 status;
+	unsigned long start = get_timer(0);
+
+	for (;;) {
+		ret = dm_i2c_read(dev, RV3032_TLSB, &status, 1);
+		if (ret < 0)
+			break;
+		if (!(status & RV3032_TLSB_EEBUSY))
+			break;
+		if (get_timer(start) > RV3032_EEBUSY_TIMEOUT)
+			return -ETIMEDOUT;
+		udelay(RV3032_EEBUSY_POLL);
+	}
+
+	return ret;
+}
+
+static int rv3032_enter_eerd(struct udevice *dev, u32 *eerd)
+{
+	u8 ctrl1;
+	int ret;
+
+	ret = dm_i2c_read(dev, RV3032_CTRL1, &ctrl1, sizeof(ctrl1));
+	if (ret)
+		return ret;
+
+	*eerd = ctrl1 & RV3032_CTRL1_EERD;
+	if (*eerd)
+		return 0;
+
+	ret = rv3032_update_bits(dev, RV3032_CTRL1,
+				 RV3032_CTRL1_EERD, RV3032_CTRL1_EERD);
+	if (ret)
+		return ret;
+
+	ret = rv3032_eeprom_busywait(dev);
+	if (ret) {
+		rv3032_exit_eerd(dev, *eerd);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rv3032_get_time(struct udevice *dev, struct rtc_time *tm)
+{
+	u8 date[7];
+	int ret;
+	u8 status;
+
+	ret = dm_i2c_read(dev, RV3032_STATUS, &status, 1);
+	if (ret < 0)
+		return ret;
+
+	if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
+		return -EINVAL;
+
+	ret = dm_i2c_read(dev, RV3032_SEC, date, sizeof(date));
+	if (ret)
+		return ret;
+
+	tm->tm_sec  = bcd2bin(date[0] & 0x7f);
+	tm->tm_min  = bcd2bin(date[1] & 0x7f);
+	tm->tm_hour = bcd2bin(date[2] & 0x3f);
+	tm->tm_wday = date[3] & 0x7;
+	tm->tm_mday = bcd2bin(date[4] & 0x3f);
+	tm->tm_mon  = bcd2bin(date[5] & 0x1f);
+	tm->tm_year = bcd2bin(date[6]) + 2000;
+
+	return 0;
+}
+
+static int rv3032_set_time(struct udevice *dev, const struct rtc_time *tm)
+{
+	u8 date[7];
+	int ret;
+
+	date[0] = bin2bcd(tm->tm_sec);
+	date[1] = bin2bcd(tm->tm_min);
+	date[2] = bin2bcd(tm->tm_hour);
+	date[3] = tm->tm_wday;
+	date[4] = bin2bcd(tm->tm_mday);
+	date[5] = bin2bcd(tm->tm_mon);
+	date[6] = bin2bcd(tm->tm_year - 2000);
+
+	ret = dm_i2c_write(dev, RV3032_SEC, date,
+			   sizeof(date));
+	if (ret)
+		return ret;
+
+	ret = rv3032_update_bits(dev, RV3032_STATUS,
+				 RV3032_STATUS_PORF | RV3032_STATUS_VLF, 0);
+
+	return ret;
+}
+
+static int rv3032_eeprom_write(struct udevice *dev, unsigned int reg,
+			       const u8 *buf, unsigned int len)
+{
+	u32 eerd;
+	int i, ret;
+	u8 cmd;
+
+	ret = rv3032_enter_eerd(dev, &eerd);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		cmd	= RV3032_EEPROM_USER + reg + i;
+		ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
+				   &cmd, 1);
+		if (ret)
+			goto exit_eerd;
+
+		ret = dm_i2c_write(dev, RV3032_EEPROM_DATA, &buf[i], 1);
+		if (ret)
+			goto exit_eerd;
+
+		cmd = RV3032_EEPROM_CMD_WRITE;
+		ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
+				   &cmd, 1);
+		if (ret)
+			goto exit_eerd;
+
+		udelay(RV3032_EEBUSY_POLL);
+
+		ret = rv3032_eeprom_busywait(dev);
+		if (ret)
+			goto exit_eerd;
+	}
+
+exit_eerd:
+	rv3032_exit_eerd(dev, eerd);
+
+	return ret;
+}
+
+static int rv3032_eeprom_read(struct udevice *dev, unsigned int reg,
+			      u8 *buf, unsigned int len)
+{
+	u32 eerd;
+	int i, ret;
+	u8 cmd, data;
+
+	ret = rv3032_enter_eerd(dev, &eerd);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		cmd = RV3032_EEPROM_USER + reg + i;
+		ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
+				   &cmd, 1);
+		if (ret)
+			goto exit_eerd;
+
+		cmd = RV3032_EEPROM_CMD_READ;
+		ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
+				   &cmd, 1);
+		if (ret)
+			goto exit_eerd;
+
+		ret = rv3032_eeprom_busywait(dev);
+		if (ret)
+			goto exit_eerd;
+
+		ret = dm_i2c_read(dev, RV3032_EEPROM_DATA, &data, sizeof(data));
+		if (ret)
+			goto exit_eerd;
+		buf[i] = data;
+	}
+
+exit_eerd:
+	rv3032_exit_eerd(dev, eerd);
+
+	return ret;
+}
+
+static int rv3032_probe(struct udevice *dev)
+{
+	i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
+			DM_I2C_CHIP_WR_ADDRESS);
+
+	return 0;
+}
+
+static const struct rtc_ops rv3032_rtc_ops = {
+	.get = rv3032_get_time,
+	.set = rv3032_set_time,
+	.read = rv3032_eeprom_read,
+	.write = rv3032_eeprom_write,
+};
+
+static const struct udevice_id rv3032_rtc_ids[] = {
+	{ .compatible = "microcrystal,rv3032", },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_rv3032) = {
+	.name	= "rtc-rv3028",
+	.id	= UCLASS_RTC,
+	.probe	= rv3032_probe,
+	.of_match = rv3032_rtc_ids,
+	.ops	= &rv3032_rtc_ops,
+};
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one
  2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
  2023-08-30 14:03 ` [PATCH 1/5] drivers: rtc: add rv3032 driver Steffen Dirkwinkel
@ 2023-08-30 14:03 ` Steffen Dirkwinkel
  2023-09-01  7:18   ` Michal Simek
  2023-08-30 14:03 ` [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory Steffen Dirkwinkel
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot
  Cc: Steffen Dirkwinkel, Jagan Teki, Jonas Karlman, Kunihiko Hayashi,
	Marek Vasut, Venkatesh Yadav Abbarapu

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

This gpio is optional so undonditionally freeing it will crash.

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
---

 drivers/usb/dwc3/dwc3-generic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 7f0af05855..dcc342ed04 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -149,7 +149,9 @@ static int dwc3_generic_remove(struct udevice *dev,
 	    priv->ulpi_reset) {
 		struct gpio_desc *ulpi_reset = priv->ulpi_reset;
 
-		dm_gpio_free(ulpi_reset->dev, ulpi_reset);
+		if (priv->ulpi_reset) {
+			dm_gpio_free(ulpi_reset->dev, ulpi_reset);
+		}
 	}
 
 	dwc3_remove(dwc3);
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory
  2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
  2023-08-30 14:03 ` [PATCH 1/5] drivers: rtc: add rv3032 driver Steffen Dirkwinkel
  2023-08-30 14:03 ` [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one Steffen Dirkwinkel
@ 2023-08-30 14:03 ` Steffen Dirkwinkel
  2023-09-01  7:23   ` Michal Simek
  2023-08-30 14:03 ` [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200 Steffen Dirkwinkel
  2023-08-30 14:03 ` [PATCH 5/5] xilinx: zynqmp: beckhoff cx8200: setup inner cache broadcasting Steffen Dirkwinkel
  4 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot; +Cc: Steffen Dirkwinkel, Michal Simek

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

With the current config we'd put the fdt outside of memory.

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
---

 include/configs/xilinx_zynqmp.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 74264b7bee..334fe95d66 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -50,7 +50,7 @@
 #endif
 
 #define ENV_MEM_LAYOUT_SETTINGS \
-	"fdt_addr_r=0x40000000\0" \
+	"fdt_addr_r=0x28000000\0" \
 	"fdt_size_r=0x400000\0" \
 	"pxefile_addr_r=0x10000000\0" \
 	"kernel_addr_r=0x18000000\0" \
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
                   ` (2 preceding siblings ...)
  2023-08-30 14:03 ` [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory Steffen Dirkwinkel
@ 2023-08-30 14:03 ` Steffen Dirkwinkel
  2023-09-01  7:36   ` Michal Simek
  2023-08-30 14:03 ` [PATCH 5/5] xilinx: zynqmp: beckhoff cx8200: setup inner cache broadcasting Steffen Dirkwinkel
  4 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot; +Cc: Steffen Dirkwinkel, Michal Simek

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

This adds support for the Beckhoff CX8200 series of industrial embedded PCs.
There is some information about the device and features here:
https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/

Currently supported/tested:
- Boot from microSD
- Ethernet
- USB
- rtc / rtc eeprom
- tpm access
- uart

Open points:
- adding the psgtr usb phy doesn't work in linux (failed to get pll
  lock)
- fpga loading currently only as u-boot script or pre launch cmd (type
  may be stored in eeprom of rtc so this could be made generic)

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
---

 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
 .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
 configs/xilinx_zynqmp_virt_defconfig          |    2 +-
 4 files changed, 2209 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
 create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 85fd5b1157..c5b5615362 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -393,6 +393,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
 dtb-$(CONFIG_ARCH_ZYNQMP) += \
 	avnet-ultra96-rev1.dtb			\
 	zynqmp-a2197-revA.dtb			\
+	zynqmp-beckhoff-cx8200.dtb		\
 	zynqmp-dlc21-revA.dtb			\
 	zynqmp-e-a2197-00-revA.dtb		\
 	zynqmp-g-a2197-00-revA.dtb		\
diff --git a/arch/arm/dts/zynqmp-beckhoff-cx8200.dts b/arch/arm/dts/zynqmp-beckhoff-cx8200.dts
new file mode 100644
index 0000000000..9ed54b29b9
--- /dev/null
+++ b/arch/arm/dts/zynqmp-beckhoff-cx8200.dts
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Beckhoff CX8200
+ *
+ * (C) Copyright 2023, Beckhoff Automation GmbH & Co. KG
+ *
+ * Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Beckhoff CX8200";
+	compatible = "beckhoff,cx8200-rev1", "beckhoff,cx8200",
+		     "xlnx,zynqmp";
+
+	aliases {
+		ethernet0 = &gem2;
+		rtc0 = &rv3032;
+		serial0 = &uart1;
+		usb0 = &usb1;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	cpus {
+		/delete-node/ cpu@2 ;
+		/delete-node/ cpu@3 ;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x3ff00000>;
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupt-parent = <&gic>;
+		interrupts = <0 143 4>,
+			     <0 144 4>,
+			     <0 145 4>,
+			     <0 146 4>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>;
+	};
+
+	usb1_clk: usb1_clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+};
+
+&fpd_dma_chan1 {
+	status = "okay";
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+};
+
+&gem2 {
+	status = "okay";
+	nvmem-cells = <&gem2_mac_address>;
+	nvmem-cell-names = "mac-address";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+	phy0: ethernet-phy@0 { /* Broadcom B50212E */
+		reg = <0>;
+	};
+};
+
+&gpio {
+	status = "okay";
+
+	/* USB_EN */
+	enable-hog {
+		gpio-hog;
+		gpios = <47 0>;
+		output-high;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <200000>;
+	scl-gpios = <&gpio 32 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio 33 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+
+	rv3032: rtc@51 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "microcrystal,rv3032";
+		reg = <0x51>;
+		interrupt-parent = <&gpio>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		gem2_mac_address: mac-address@0 {
+			reg = <0x0 6>;
+		};
+	};
+};
+
+&pinctrl0 {
+	status = "okay";
+
+	pinctrl_usb1_default: usb1-default {
+		mux {
+			groups = "usb1_0_grp";
+			function = "usb1";
+		};
+
+		conf {
+			groups = "usb1_0_grp";
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO64", "MIO65", "MIO67";
+			bias-high-impedance;
+			drive-strength = <12>;
+			slew-rate = <SLEW_RATE_FAST>;
+		};
+
+		conf-tx {
+			pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
+			       "MIO72", "MIO73", "MIO74", "MIO75";
+			bias-disable;
+			drive-strength = <4>;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_8_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_8_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS33>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_32_grp", "gpio0_33_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_32_grp", "gpio0_33_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS33>;
+		};
+	};
+};
+
+&sdhci0 {
+	clock-frequency = <200000000>;
+	status = "okay";
+	disable-wp;
+	no-1-8-v;
+	xlnx,mio-bank = <0x0>;
+};
+
+&spi0 {
+	status = "okay";
+	label = "TPM";
+	num-cs = <1>;
+	tpm@0 {
+		compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+		reg = <0>;
+		spi-max-frequency = <18500000>;
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb1_default>;
+};
+
+&dwc3_1 {
+	status = "okay";
+	dr_mode = "host";
+	maximum-speed = "super-speed";
+};
+
+&watchdog0 {
+	status = "okay";
+};
+
+&xilinx_ams {
+	status = "okay";
+};
+
+&ams_ps {
+	status = "okay";
+};
+
+&ams_pl {
+	status = "okay";
+};
\ No newline at end of file
diff --git a/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
new file mode 100644
index 0000000000..7437d46c59
--- /dev/null
+++ b/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
@@ -0,0 +1,1960 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+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 unsigned long psu_pll_init_data(void)
+{
+	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00014800U);
+	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, 0x00000200U);
+	psu_mask_write(0xFF5E0038, 0x8000FFFFU, 0x00000000U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+	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, 0x00015000U);
+	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, 0x00013F00U);
+	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, 0x00000200U);
+	psu_mask_write(0xFD1A0040, 0x8000FFFFU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+	psu_mask_write(0xFF5E0058, 0x063F3F07U, 0x06010C00U);
+	psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+	psu_mask_write(0xFF5E0064, 0x023F3F07U, 0x02010600U);
+	psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+	psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010500U);
+	psu_mask_write(0xFF5E006C, 0x013F3F07U, 0x01020302U);
+	psu_mask_write(0xFF18030C, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFF5E0078, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E007C, 0x013F3F07U, 0x01020302U);
+	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, 0x01010802U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011E02U);
+	psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000104U);
+	psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+	psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000500U);
+	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000202U);
+	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, 0x00000102U);
+	psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x0028B0AAU);
+	psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00404310U);
+	psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+	psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+	psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x00208030U);
+	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, 0x0002020AU);
+	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00360000U);
+	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00001205U);
+	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x00240052U);
+	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, 0x100B080CU);
+	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00030411U);
+	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0607150FU);
+	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00A05000U);
+	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08040306U);
+	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x01020404U);
+	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000201U);
+	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x03030303U);
+	psu_mask_write(0xFD070124, 0x40070F3FU, 0x0004040DU);
+	psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x440C011CU);
+	psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x810B0008U);
+	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x00E32DCDU);
+	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B820AU);
+	psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U);
+	psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+	psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+	psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+	psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+	psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000004U);
+	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000908U);
+	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, 0x0F060606U);
+	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, 0x00F03D28U);
+	psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+	psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x21610AD0U);
+	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0x682B0960U);
+	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x05102000U);
+	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A040A1U);
+	psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E5U);
+	psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0000040DU);
+	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x06180C08U);
+	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x2816070BU);
+	psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0064U);
+	psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x82000501U);
+	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x00602B08U);
+	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00221008U);
+	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000C0EU);
+	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, 0x00000024U);
+	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000052U);
+	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, 0x12340400U);
+	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, 0x00894C58U);
+	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, 0x05102000U);
+	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, 0x05102000U);
+	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, 0x25102000U);
+	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, 0x25102000U);
+	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, 0x25102000U);
+	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, 0x00000002U);
+	psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180008, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+	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, 0x00000008U);
+	psu_mask_write(0xFF180038, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180040, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180044, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180048, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF18004C, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180050, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180054, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180058, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180060, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180064, 0x000000FEU, 0x00000008U);
+	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, 0x00000040U);
+	psu_mask_write(0xFF180084, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180088, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF18008C, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180090, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180094, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180098, 0x000000FEU, 0x00000080U);
+	psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000080U);
+	psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000080U);
+	psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000080U);
+	psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000080U);
+	psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180100, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180104, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180108, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180110, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180114, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180118, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180120, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180124, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180128, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180130, 0x000000FEU, 0x000000A0U);
+	psu_mask_write(0xFF180134, 0x000000FEU, 0x000000A0U);
+	psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x03000000U);
+	psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0xFC000020U);
+	psu_mask_write(0xFF18020C, 0x00003FFFU, 0x0000000BU);
+	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);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00000046U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000004U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180390, 0x00000004U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000800U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000020U, 0x00000000U);
+	psu_mask_write(0xFF180310, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180320, 0x00003384U, 0x00000284U);
+	psu_mask_write(0xFF18031C, 0x00007FFEU, 0x00006450U);
+	psu_mask_write(0xFF180358, 0x00080000U, 0x00080000U);
+	psu_mask_write(0xFF180324, 0x000003C0U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000004U, 0x00000000U);
+	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, 0x01FCA054U);
+	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	mask_delay(1);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+	mask_delay(5);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+	psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000FU);
+	psu_mask_write(0xFD41000C, 0x0000001FU, 0x00000008U);
+	psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40286C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40E094, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40A368, 0x000000FFU, 0x000000E0U);
+	psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40E368, 0x000000FFU, 0x00000038U);
+	psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000C9U);
+	psu_mask_write(0xFD40A374, 0x000000FFU, 0x000000D2U);
+	psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD40A37C, 0x000000B3U, 0x000000B0U);
+	psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000F4U);
+	psu_mask_write(0xFD40E374, 0x000000FFU, 0x00000031U);
+	psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000002U);
+	psu_mask_write(0xFD40E37C, 0x00000033U, 0x00000030U);
+	psu_mask_write(0xFD40A360, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40906C, 0x0000000FU, 0x0000000FU);
+	psu_mask_write(0xFD4080F4, 0x0000000BU, 0x0000000BU);
+	psu_mask_write(0xFD40D06C, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD40C0F4, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD40D0CC, 0x00000020U, 0x00000020U);
+	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(0xFD401994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD409990, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD409924, 0x000000FFU, 0x0000009CU);
+	psu_mask_write(0xFD409928, 0x000000FFU, 0x00000039U);
+	psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U);
+	psu_mask_write(0xFD409900, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000064U);
+	psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40D89C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40D8F8, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000010U);
+	psu_mask_write(0xFD40D924, 0x000000FFU, 0x000000FEU);
+	psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD40D980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40D940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D944, 0x00000001U, 0x00000001U);
+	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(3, 0, 2, 3, 0, 0, 0, 0);
+	psu_mask_write(0xFD410014, 0x00000077U, 0x00000032U);
+	psu_mask_write(0xFD4081D8, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409C14, 0x000000FFU, 0x000000E6U);
+	psu_mask_write(0xFD409C40, 0x0000001FU, 0x0000000CU);
+	psu_mask_write(0xFD40994C, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD409950, 0x00000007U, 0x00000006U);
+	psu_mask_write(0xFD408048, 0x000000FFU, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000800U, 0x00000000U);
+	psu_mask_write(0xFF9E0080, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF9E007C, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000280U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000004U, 0x00000000U);
+	psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFE30C200, 0x00023FFFU, 0x00022457U);
+	psu_mask_write(0xFE30C630, 0x003FFF00U, 0x00000000U);
+	psu_mask_write(0xFE30C12C, 0x00004000U, 0x00004000U);
+	psu_mask_write(0xFE30C11C, 0x00000600U, 0x00000600U);
+	psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+	mask_poll(0xFD40A3E4, 0x00000010U);
+	mask_poll(0xFD40E3E4, 0x00000010U);
+	psu_mask_write(0xFD0C00AC, 0xFFFFFFFFU, 0x28184018U);
+	psu_mask_write(0xFD0C00B0, 0xFFFFFFFFU, 0x0E081406U);
+	psu_mask_write(0xFD0C00B4, 0xFFFFFFFFU, 0x064A0813U);
+	psu_mask_write(0xFD0C00B8, 0xFFFFFFFFU, 0x3FFC96A4U);
+
+	return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000A80U, 0x00000A80U);
+	psu_mask_write(0xFF5E0230, 0x00000004U, 0x00000004U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+
+	return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+	psu_mask_write(0xFD615000, 0x00000300U, 0x00000100U);
+	psu_mask_write(0xFD360000, 0x00000003U, 0x00000001U);
+	psu_mask_write(0xFD360014, 0x00000003U, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+	unsigned int regval = 0;
+	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(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;
+
+	Xil_Out32(0xFD080200U, 0x800091C7U);
+	int cur_R006_tREFPRD;
+
+	cur_R006_tREFPRD = (Xil_In32(0xFD080018U) & 0x0003FFFFU) >> 0x00000000U;
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000003U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000003U);
+
+	Xil_Out32(0xFD080004, 0x00060001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80004001) != 0x80004001)
+		regval = Xil_In32(0xFD080030);
+
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000000U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000000U);
+
+	Xil_Out32(0xFD080200U, 0x800091C7U);
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	Xil_Out32(0xFD080004, 0x0000C001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80000C01) != 0x80000C01)
+		regval = Xil_In32(0xFD080030);
+
+	Xil_Out32(0xFD070180U, 0x010B0008U);
+	Xil_Out32(0xFD070060U, 0x00000000U);
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+	return 1;
+}
+
+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;
+
+	rdata = Xil_In32(0xFD40289C);
+	rdata = rdata & ~0x03;
+	rdata = rdata | 0x1;
+	Xil_Out32(0xFD40289C, rdata);
+	int count = 0;
+	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;
+}
diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig
index acab38fefe..347a822eaf 100644
--- a/configs/xilinx_zynqmp_virt_defconfig
+++ b/configs/xilinx_zynqmp_virt_defconfig
@@ -104,7 +104,7 @@ CONFIG_CMD_UBI=y
 CONFIG_PARTITION_TYPE_GUID=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_BOARD=y
-CONFIG_OF_LIST="avnet-ultra96-rev1 zynqmp-a2197-revA zynqmp-e-a2197-00-revA zynqmp-g-a2197-00-revA zynqmp-m-a2197-01-revA zynqmp-m-a2197-02-revA zynqmp-m-a2197-03-revA zynqmp-p-a2197-00-revA zynqmp-zc1232-revA zynqmp-zc1254-revA zynqmp-zc1751-xm015-dc1 zynqmp-zc1751-xm016-dc2 zynqmp-zc1751-xm017-dc3 zynqmp-zc1751-xm018-dc4 zynqmp-zc1751-xm019-dc5 zynqmp-zcu100-revC zynqmp-zcu102-rev1.1 zynqmp-zcu102-rev1.0 zynqmp-zcu102-revA zynqmp-zcu102-revB zynqmp-zcu104-revA zynqmp-zcu104-revC zynqmp-zcu106-revA zynqmp-zcu106-rev1.0 zynqmp-zcu111-revA zynqmp-zcu1275-revA zynqmp-zcu1275-revB zynqmp-zcu1285-revA zynqmp-zcu208-revA zynqmp-zcu216-revA zynqmp-topic-miamimp-xilinx-xdp-v1r1 zynqmp-sm-k26-revA zynqmp-smk-k26-revA zynqmp-dlc21-revA"
+CONFIG_OF_LIST="avnet-ultra96-rev1 zynqmp-a2197-revA zynqmp-beckhoff-cx8200 zynqmp-e-a2197-00-revA zynqmp-g-a2197-00-revA zynqmp-m-a2197-01-revA zynqmp-m-a2197-02-revA zynqmp-m-a2197-03-revA zynqmp-p-a2197-00-revA zynqmp-zc1232-revA zynqmp-zc1254-revA zynqmp-zc1751-xm015-dc1 zynqmp-zc1751-xm016-dc2 zynqmp-zc1751-xm017-dc3 zynqmp-zc1751-xm018-dc4 zynqmp-zc1751-xm019-dc5 zynqmp-zcu100-revC zynqmp-zcu102-rev1.1 zynqmp-zcu102-rev1.0 zynqmp-zcu102-revA zynqmp-zcu102-revB zynqmp-zcu104-revA zynqmp-zcu104-revC zynqmp-zcu106-revA zynqmp-zcu106-rev1.0 zynqmp-zcu111-revA zynqmp-zcu1275-revA zynqmp-zcu1275-revB zynqmp-zcu1285-revA zynqmp-zcu208-revA zynqmp-zcu216-revA zynqmp-topic-miamimp-xilinx-xdp-v1r1 zynqmp-sm-k26-revA zynqmp-smk-k26-revA zynqmp-dlc21-revA"
 CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent interrupts iommus power-domains"
 CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_FAT=y
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/5] xilinx: zynqmp: beckhoff cx8200: setup inner cache broadcasting
  2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
                   ` (3 preceding siblings ...)
  2023-08-30 14:03 ` [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200 Steffen Dirkwinkel
@ 2023-08-30 14:03 ` Steffen Dirkwinkel
  4 siblings, 0 replies; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 14:03 UTC (permalink / raw)
  To: u-boot; +Cc: Steffen Dirkwinkel, Michal Simek

From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

We need it for coherent access between pl and ps.

From xilinx documentation:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842098/Zynq+UltraScale+MPSoC+Cache+Coherency

Inner Cache Broadcasting

Linux sets up the MMU for cacheable memory to be inner shareable as that supports SMP operation.
As modifying the MMU tables from kernel or userspace is not a straightforwards task, the inner
cache broadcasting feature can be used to allow inner cacheble transactions be broadcasted.
Outside the APU, in the outer domain, the CCI handles coherency across the system.
The brdc_inner bit of the lpd_apu register within the LPD_SLCR module must be written while
the APU is in reset.

The requirement to alter the register while the APU is in reset can be accomplished using the
register initialization feature in the boot image.
.set. 0xFF41A040 = 0x3;

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>

---

 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init

diff --git a/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init b/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init
new file mode 100644
index 0000000000..e7038dd80a
--- /dev/null
+++ b/board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/regs.init
@@ -0,0 +1 @@
+0xFF41A040 0x3
\ No newline at end of file
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/5] drivers: rtc: add rv3032 driver
  2023-08-30 14:03 ` [PATCH 1/5] drivers: rtc: add rv3032 driver Steffen Dirkwinkel
@ 2023-08-30 19:43   ` Alexandre Belloni
  2023-08-30 19:52     ` Steffen Dirkwinkel
  0 siblings, 1 reply; 15+ messages in thread
From: Alexandre Belloni @ 2023-08-30 19:43 UTC (permalink / raw)
  To: Steffen Dirkwinkel
  Cc: u-boot, Steffen Dirkwinkel, Chris Packham, Sergei Antonov,
	Simon Glass

Hello,

On 30/08/2023 16:03:30+0200, Steffen Dirkwinkel wrote:
> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> 
> Based on linux driver, with these differences:
> - no support for trickle charger
> - no support for hwmon
> - no support for battery backed memory
> - dm_i2c instead of regmap
> - different tm_year and tm_mon
> 
> read/write access the user eeprom. The read and write functions access
> the user eeprom so it can be used for nvmem-cells. (like in
> arch/sandbox/dts/test.dts). This is currently different from linux as
> you'd get nvram using nvmem-cells. I'm hoping to switch the order there

I'm not sure I get this as both nvram and eeprom are exposed through
nvmem. The solution is not to reorder but instead to fix the nvmem core
so you can expose both using nvmem-cells as there are users that access
the nvram to handle A/B updates (bootcount, rescue mode,...)

> too (there are currently no users) or to make a more specific binding.
> Currently this would also just work as is if used for mac addresses, as
> u-boot will put these into fdt before booting linux and linux will then
> prefer the u-boot provided mac.
> 
> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> 
> ---
> 
>  drivers/rtc/Kconfig  |  10 ++
>  drivers/rtc/Makefile |   1 +
>  drivers/rtc/rv3032.c | 334 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 345 insertions(+)
>  create mode 100644 drivers/rtc/rv3032.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 23173139e0..a41ec9b6cc 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -172,6 +172,16 @@ config RTC_RV3029
>  	  This driver supports reading and writing the RTC/calendar and the
>  	  battery-baced SRAM section.
>  
> +config RTC_RV3032
> +	bool "Enable RV3032 driver"
> +	depends on DM_RTC
> +	help
> +	  The MicroCrystal RV3032 is a I2C Real Time Clock (RTC) with a 16-byte
> +	  battery-backed SRAM and a 32-byte user eeprom.
> +
> +	  This driver supports reading and writing the RTC/calendar and the
> +	  user eeprom.
> +
>  config RTC_RV8803
>  	bool "Enable RV8803 driver"
>  	depends on DM_RTC
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 308fab8da9..9c2d8c7aa9 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_PL031) += pl031.o
>  obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
>  obj-$(CONFIG_RTC_RV3028) += rv3028.o
>  obj-$(CONFIG_RTC_RV3029) += rv3029.o
> +obj-$(CONFIG_RTC_RV3032) += rv3032.o
>  obj-$(CONFIG_RTC_RV8803) += rv8803.o
>  obj-$(CONFIG_RTC_RX8025) += rx8025.o
>  obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
> diff --git a/drivers/rtc/rv3032.c b/drivers/rtc/rv3032.c
> new file mode 100644
> index 0000000000..8d5d860c0a
> --- /dev/null
> +++ b/drivers/rtc/rv3032.c
> @@ -0,0 +1,334 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * RTC driver for the Micro Crystal RV3032
> + *
> + * based on linux driver from
> + * Copyright (C) 2020 Micro Crystal SA
> + *
> + * Alexandre Belloni <alexandre.belloni@bootlin.com>
> + *
> + */
> +
> +#include <dm.h>
> +#include <i2c.h>
> +#include <linux/delay.h>
> +#include <regmap.h>
> +#include <rtc.h>
> +#include <time.h>
> +
> +#define RV3032_SEC			0x01
> +#define RV3032_MIN			0x02
> +#define RV3032_HOUR			0x03
> +#define RV3032_WDAY			0x04
> +#define RV3032_DAY			0x05
> +#define RV3032_MONTH			0x06
> +#define RV3032_YEAR			0x07
> +#define RV3032_ALARM_MIN		0x08
> +#define RV3032_ALARM_HOUR		0x09
> +#define RV3032_ALARM_DAY		0x0A
> +#define RV3032_STATUS			0x0D
> +#define RV3032_TLSB			0x0E
> +#define RV3032_TMSB			0x0F
> +#define RV3032_CTRL1			0x10
> +#define RV3032_CTRL2			0x11
> +#define RV3032_CTRL3			0x12
> +#define RV3032_TS_CTRL			0x13
> +#define RV3032_CLK_IRQ			0x14
> +#define RV3032_EEPROM_ADDR		0x3D
> +#define RV3032_EEPROM_DATA		0x3E
> +#define RV3032_EEPROM_CMD		0x3F
> +#define RV3032_RAM1			0x40
> +#define RV3032_PMU			0xC0
> +#define RV3032_OFFSET			0xC1
> +#define RV3032_CLKOUT1			0xC2
> +#define RV3032_CLKOUT2			0xC3
> +#define RV3032_TREF0			0xC4
> +#define RV3032_TREF1			0xC5
> +
> +#define RV3032_STATUS_VLF		BIT(0)
> +#define RV3032_STATUS_PORF		BIT(1)
> +#define RV3032_STATUS_EVF		BIT(2)
> +#define RV3032_STATUS_AF		BIT(3)
> +#define RV3032_STATUS_TF		BIT(4)
> +#define RV3032_STATUS_UF		BIT(5)
> +#define RV3032_STATUS_TLF		BIT(6)
> +#define RV3032_STATUS_THF		BIT(7)
> +
> +#define RV3032_TLSB_CLKF		BIT(1)
> +#define RV3032_TLSB_EEBUSY		BIT(2)
> +#define RV3032_TLSB_TEMP		GENMASK(7, 4)
> +
> +#define RV3032_CLKOUT2_HFD_MSK		GENMASK(4, 0)
> +#define RV3032_CLKOUT2_FD_MSK		GENMASK(6, 5)
> +#define RV3032_CLKOUT2_OS		BIT(7)
> +
> +#define RV3032_CTRL1_EERD		BIT(3)
> +#define RV3032_CTRL1_WADA		BIT(5)
> +
> +#define RV3032_CTRL2_STOP		BIT(0)
> +#define RV3032_CTRL2_EIE		BIT(2)
> +#define RV3032_CTRL2_AIE		BIT(3)
> +#define RV3032_CTRL2_TIE		BIT(4)
> +#define RV3032_CTRL2_UIE		BIT(5)
> +#define RV3032_CTRL2_CLKIE		BIT(6)
> +#define RV3032_CTRL2_TSE		BIT(7)
> +
> +#define RV3032_PMU_TCM			GENMASK(1, 0)
> +#define RV3032_PMU_TCR			GENMASK(3, 2)
> +#define RV3032_PMU_BSM			GENMASK(5, 4)
> +#define RV3032_PMU_NCLKE		BIT(6)
> +
> +#define RV3032_PMU_BSM_DSM		1
> +#define RV3032_PMU_BSM_LSM		2
> +
> +#define RV3032_OFFSET_MSK		GENMASK(5, 0)
> +
> +#define RV3032_EVT_CTRL_TSR		BIT(2)
> +
> +#define RV3032_EEPROM_CMD_UPDATE	0x11
> +#define RV3032_EEPROM_CMD_WRITE		0x21
> +#define RV3032_EEPROM_CMD_READ		0x22
> +
> +#define RV3032_EEPROM_USER		0xCB
> +
> +#define RV3032_EEBUSY_POLL		10000
> +#define RV3032_EEBUSY_TIMEOUT		100000
> +
> +#define OFFSET_STEP_PPT			238419
> +
> +static int rv3032_update_bits(struct udevice *dev, u8 reg, u8 mask, u8 set)
> +{
> +	u8 buf;
> +	int ret;
> +
> +	ret = dm_i2c_read(dev, reg, &buf, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	if ((buf & mask) == (set && mask))
> +		return 0;
> +
> +	buf = (buf & ~mask) | (set & mask);
> +	ret = dm_i2c_read(dev, reg, &buf, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int rv3032_exit_eerd(struct udevice *dev, u32 eerd)
> +{
> +	if (eerd)
> +		return 0;
> +
> +	return rv3032_update_bits(dev, RV3032_CTRL1, RV3032_CTRL1_EERD, 0);
> +}
> +
> +static int rv3032_eeprom_busywait(struct udevice *dev)
> +{
> +	int ret;
> +	u8 status;
> +	unsigned long start = get_timer(0);
> +
> +	for (;;) {
> +		ret = dm_i2c_read(dev, RV3032_TLSB, &status, 1);
> +		if (ret < 0)
> +			break;
> +		if (!(status & RV3032_TLSB_EEBUSY))
> +			break;
> +		if (get_timer(start) > RV3032_EEBUSY_TIMEOUT)
> +			return -ETIMEDOUT;
> +		udelay(RV3032_EEBUSY_POLL);
> +	}
> +
> +	return ret;
> +}
> +
> +static int rv3032_enter_eerd(struct udevice *dev, u32 *eerd)
> +{
> +	u8 ctrl1;
> +	int ret;
> +
> +	ret = dm_i2c_read(dev, RV3032_CTRL1, &ctrl1, sizeof(ctrl1));
> +	if (ret)
> +		return ret;
> +
> +	*eerd = ctrl1 & RV3032_CTRL1_EERD;
> +	if (*eerd)
> +		return 0;
> +
> +	ret = rv3032_update_bits(dev, RV3032_CTRL1,
> +				 RV3032_CTRL1_EERD, RV3032_CTRL1_EERD);
> +	if (ret)
> +		return ret;
> +
> +	ret = rv3032_eeprom_busywait(dev);
> +	if (ret) {
> +		rv3032_exit_eerd(dev, *eerd);
> +
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rv3032_get_time(struct udevice *dev, struct rtc_time *tm)
> +{
> +	u8 date[7];
> +	int ret;
> +	u8 status;
> +
> +	ret = dm_i2c_read(dev, RV3032_STATUS, &status, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
> +		return -EINVAL;
> +
> +	ret = dm_i2c_read(dev, RV3032_SEC, date, sizeof(date));
> +	if (ret)
> +		return ret;
> +
> +	tm->tm_sec  = bcd2bin(date[0] & 0x7f);
> +	tm->tm_min  = bcd2bin(date[1] & 0x7f);
> +	tm->tm_hour = bcd2bin(date[2] & 0x3f);
> +	tm->tm_wday = date[3] & 0x7;
> +	tm->tm_mday = bcd2bin(date[4] & 0x3f);
> +	tm->tm_mon  = bcd2bin(date[5] & 0x1f);
> +	tm->tm_year = bcd2bin(date[6]) + 2000;
> +
> +	return 0;
> +}
> +
> +static int rv3032_set_time(struct udevice *dev, const struct rtc_time *tm)
> +{
> +	u8 date[7];
> +	int ret;
> +
> +	date[0] = bin2bcd(tm->tm_sec);
> +	date[1] = bin2bcd(tm->tm_min);
> +	date[2] = bin2bcd(tm->tm_hour);
> +	date[3] = tm->tm_wday;
> +	date[4] = bin2bcd(tm->tm_mday);
> +	date[5] = bin2bcd(tm->tm_mon);
> +	date[6] = bin2bcd(tm->tm_year - 2000);
> +
> +	ret = dm_i2c_write(dev, RV3032_SEC, date,
> +			   sizeof(date));
> +	if (ret)
> +		return ret;
> +
> +	ret = rv3032_update_bits(dev, RV3032_STATUS,
> +				 RV3032_STATUS_PORF | RV3032_STATUS_VLF, 0);
> +
> +	return ret;
> +}
> +
> +static int rv3032_eeprom_write(struct udevice *dev, unsigned int reg,
> +			       const u8 *buf, unsigned int len)
> +{
> +	u32 eerd;
> +	int i, ret;
> +	u8 cmd;
> +
> +	ret = rv3032_enter_eerd(dev, &eerd);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < len; i++) {
> +		cmd	= RV3032_EEPROM_USER + reg + i;
> +		ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
> +				   &cmd, 1);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		ret = dm_i2c_write(dev, RV3032_EEPROM_DATA, &buf[i], 1);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		cmd = RV3032_EEPROM_CMD_WRITE;
> +		ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
> +				   &cmd, 1);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		udelay(RV3032_EEBUSY_POLL);
> +
> +		ret = rv3032_eeprom_busywait(dev);
> +		if (ret)
> +			goto exit_eerd;
> +	}
> +
> +exit_eerd:
> +	rv3032_exit_eerd(dev, eerd);
> +
> +	return ret;
> +}
> +
> +static int rv3032_eeprom_read(struct udevice *dev, unsigned int reg,
> +			      u8 *buf, unsigned int len)
> +{
> +	u32 eerd;
> +	int i, ret;
> +	u8 cmd, data;
> +
> +	ret = rv3032_enter_eerd(dev, &eerd);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < len; i++) {
> +		cmd = RV3032_EEPROM_USER + reg + i;
> +		ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
> +				   &cmd, 1);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		cmd = RV3032_EEPROM_CMD_READ;
> +		ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
> +				   &cmd, 1);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		ret = rv3032_eeprom_busywait(dev);
> +		if (ret)
> +			goto exit_eerd;
> +
> +		ret = dm_i2c_read(dev, RV3032_EEPROM_DATA, &data, sizeof(data));
> +		if (ret)
> +			goto exit_eerd;
> +		buf[i] = data;
> +	}
> +
> +exit_eerd:
> +	rv3032_exit_eerd(dev, eerd);
> +
> +	return ret;
> +}
> +
> +static int rv3032_probe(struct udevice *dev)
> +{
> +	i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
> +			DM_I2C_CHIP_WR_ADDRESS);
> +
> +	return 0;
> +}
> +
> +static const struct rtc_ops rv3032_rtc_ops = {
> +	.get = rv3032_get_time,
> +	.set = rv3032_set_time,
> +	.read = rv3032_eeprom_read,
> +	.write = rv3032_eeprom_write,
> +};
> +
> +static const struct udevice_id rv3032_rtc_ids[] = {
> +	{ .compatible = "microcrystal,rv3032", },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(rtc_rv3032) = {
> +	.name	= "rtc-rv3028",
> +	.id	= UCLASS_RTC,
> +	.probe	= rv3032_probe,
> +	.of_match = rv3032_rtc_ids,
> +	.ops	= &rv3032_rtc_ops,
> +};
> -- 
> 2.42.0
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/5] drivers: rtc: add rv3032 driver
  2023-08-30 19:43   ` Alexandre Belloni
@ 2023-08-30 19:52     ` Steffen Dirkwinkel
  0 siblings, 0 replies; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-08-30 19:52 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Steffen Dirkwinkel, u-boot@lists.denx.de, Chris Packham,
	Sergei Antonov, Simon Glass

Hi,

> On 30. Aug 2023, at 21:43, Alexandre Belloni <alexandre.belloni@bootlin.com> wrote:
>
> Hello,
>
> On 30/08/2023 16:03:30+0200, Steffen Dirkwinkel wrote:
>> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>
>> Based on linux driver, with these differences:
>> - no support for trickle charger
>> - no support for hwmon
>> - no support for battery backed memory
>> - dm_i2c instead of regmap
>> - different tm_year and tm_mon
>>
>> read/write access the user eeprom. The read and write functions access
>> the user eeprom so it can be used for nvmem-cells. (like in
>> arch/sandbox/dts/test.dts). This is currently different from linux as
>> you'd get nvram using nvmem-cells. I'm hoping to switch the order there
>
> I'm not sure I get this as both nvram and eeprom are exposed through
> nvmem. The solution is not to reorder but instead to fix the nvmem core
> so you can expose both using nvmem-cells as there are users that access
> the nvram to handle A/B updates (bootcount, rescue mode,...)

How does one set the nvmem location to be in eeprom on the linux driver?
Maybe I just don’t understand the binding correctly?

Currently I have this:
rv3032: rtc@51 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "microcrystal,rv3032”;
reg = <0x51>;
interrupt-parent = <&gpio>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
gem2_mac_address: mac-address@0 {
reg = <0x0 6>;
};
};

On Linux that would read from battery backed ram.
Is there some way to specify it is in eeprom?

>
>> too (there are currently no users) or to make a more specific binding.
>> Currently this would also just work as is if used for mac addresses, as
>> u-boot will put these into fdt before booting linux and linux will then
>> prefer the u-boot provided mac.
>>
>> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>
>> ---
>>
>> drivers/rtc/Kconfig  |  10 ++
>> drivers/rtc/Makefile |   1 +
>> drivers/rtc/rv3032.c | 334 +++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 345 insertions(+)
>> create mode 100644 drivers/rtc/rv3032.c
>>
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index 23173139e0..a41ec9b6cc 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -172,6 +172,16 @@ config RTC_RV3029
>>   This driver supports reading and writing the RTC/calendar and the
>>   battery-baced SRAM section.
>>
>> +config RTC_RV3032
>> + bool "Enable RV3032 driver"
>> + depends on DM_RTC
>> + help
>> +   The MicroCrystal RV3032 is a I2C Real Time Clock (RTC) with a 16-byte
>> +   battery-backed SRAM and a 32-byte user eeprom.
>> +
>> +   This driver supports reading and writing the RTC/calendar and the
>> +   user eeprom.
>> +
>> config RTC_RV8803
>> bool "Enable RV8803 driver"
>> depends on DM_RTC
>> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
>> index 308fab8da9..9c2d8c7aa9 100644
>> --- a/drivers/rtc/Makefile
>> +++ b/drivers/rtc/Makefile
>> @@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_PL031) += pl031.o
>> obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
>> obj-$(CONFIG_RTC_RV3028) += rv3028.o
>> obj-$(CONFIG_RTC_RV3029) += rv3029.o
>> +obj-$(CONFIG_RTC_RV3032) += rv3032.o
>> obj-$(CONFIG_RTC_RV8803) += rv8803.o
>> obj-$(CONFIG_RTC_RX8025) += rx8025.o
>> obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
>> diff --git a/drivers/rtc/rv3032.c b/drivers/rtc/rv3032.c
>> new file mode 100644
>> index 0000000000..8d5d860c0a
>> --- /dev/null
>> +++ b/drivers/rtc/rv3032.c
>> @@ -0,0 +1,334 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * RTC driver for the Micro Crystal RV3032
>> + *
>> + * based on linux driver from
>> + * Copyright (C) 2020 Micro Crystal SA
>> + *
>> + * Alexandre Belloni <alexandre.belloni@bootlin.com>
>> + *
>> + */
>> +
>> +#include <dm.h>
>> +#include <i2c.h>
>> +#include <linux/delay.h>
>> +#include <regmap.h>
>> +#include <rtc.h>
>> +#include <time.h>
>> +
>> +#define RV3032_SEC 0x01
>> +#define RV3032_MIN 0x02
>> +#define RV3032_HOUR 0x03
>> +#define RV3032_WDAY 0x04
>> +#define RV3032_DAY 0x05
>> +#define RV3032_MONTH 0x06
>> +#define RV3032_YEAR 0x07
>> +#define RV3032_ALARM_MIN 0x08
>> +#define RV3032_ALARM_HOUR 0x09
>> +#define RV3032_ALARM_DAY 0x0A
>> +#define RV3032_STATUS 0x0D
>> +#define RV3032_TLSB 0x0E
>> +#define RV3032_TMSB 0x0F
>> +#define RV3032_CTRL1 0x10
>> +#define RV3032_CTRL2 0x11
>> +#define RV3032_CTRL3 0x12
>> +#define RV3032_TS_CTRL 0x13
>> +#define RV3032_CLK_IRQ 0x14
>> +#define RV3032_EEPROM_ADDR 0x3D
>> +#define RV3032_EEPROM_DATA 0x3E
>> +#define RV3032_EEPROM_CMD 0x3F
>> +#define RV3032_RAM1 0x40
>> +#define RV3032_PMU 0xC0
>> +#define RV3032_OFFSET 0xC1
>> +#define RV3032_CLKOUT1 0xC2
>> +#define RV3032_CLKOUT2 0xC3
>> +#define RV3032_TREF0 0xC4
>> +#define RV3032_TREF1 0xC5
>> +
>> +#define RV3032_STATUS_VLF BIT(0)
>> +#define RV3032_STATUS_PORF BIT(1)
>> +#define RV3032_STATUS_EVF BIT(2)
>> +#define RV3032_STATUS_AF BIT(3)
>> +#define RV3032_STATUS_TF BIT(4)
>> +#define RV3032_STATUS_UF BIT(5)
>> +#define RV3032_STATUS_TLF BIT(6)
>> +#define RV3032_STATUS_THF BIT(7)
>> +
>> +#define RV3032_TLSB_CLKF BIT(1)
>> +#define RV3032_TLSB_EEBUSY BIT(2)
>> +#define RV3032_TLSB_TEMP GENMASK(7, 4)
>> +
>> +#define RV3032_CLKOUT2_HFD_MSK GENMASK(4, 0)
>> +#define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5)
>> +#define RV3032_CLKOUT2_OS BIT(7)
>> +
>> +#define RV3032_CTRL1_EERD BIT(3)
>> +#define RV3032_CTRL1_WADA BIT(5)
>> +
>> +#define RV3032_CTRL2_STOP BIT(0)
>> +#define RV3032_CTRL2_EIE BIT(2)
>> +#define RV3032_CTRL2_AIE BIT(3)
>> +#define RV3032_CTRL2_TIE BIT(4)
>> +#define RV3032_CTRL2_UIE BIT(5)
>> +#define RV3032_CTRL2_CLKIE BIT(6)
>> +#define RV3032_CTRL2_TSE BIT(7)
>> +
>> +#define RV3032_PMU_TCM GENMASK(1, 0)
>> +#define RV3032_PMU_TCR GENMASK(3, 2)
>> +#define RV3032_PMU_BSM GENMASK(5, 4)
>> +#define RV3032_PMU_NCLKE BIT(6)
>> +
>> +#define RV3032_PMU_BSM_DSM 1
>> +#define RV3032_PMU_BSM_LSM 2
>> +
>> +#define RV3032_OFFSET_MSK GENMASK(5, 0)
>> +
>> +#define RV3032_EVT_CTRL_TSR BIT(2)
>> +
>> +#define RV3032_EEPROM_CMD_UPDATE 0x11
>> +#define RV3032_EEPROM_CMD_WRITE 0x21
>> +#define RV3032_EEPROM_CMD_READ 0x22
>> +
>> +#define RV3032_EEPROM_USER 0xCB
>> +
>> +#define RV3032_EEBUSY_POLL 10000
>> +#define RV3032_EEBUSY_TIMEOUT 100000
>> +
>> +#define OFFSET_STEP_PPT 238419
>> +
>> +static int rv3032_update_bits(struct udevice *dev, u8 reg, u8 mask, u8 set)
>> +{
>> + u8 buf;
>> + int ret;
>> +
>> + ret = dm_i2c_read(dev, reg, &buf, 1);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if ((buf & mask) == (set && mask))
>> + return 0;
>> +
>> + buf = (buf & ~mask) | (set & mask);
>> + ret = dm_i2c_read(dev, reg, &buf, 1);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> +static int rv3032_exit_eerd(struct udevice *dev, u32 eerd)
>> +{
>> + if (eerd)
>> + return 0;
>> +
>> + return rv3032_update_bits(dev, RV3032_CTRL1, RV3032_CTRL1_EERD, 0);
>> +}
>> +
>> +static int rv3032_eeprom_busywait(struct udevice *dev)
>> +{
>> + int ret;
>> + u8 status;
>> + unsigned long start = get_timer(0);
>> +
>> + for (;;) {
>> + ret = dm_i2c_read(dev, RV3032_TLSB, &status, 1);
>> + if (ret < 0)
>> + break;
>> + if (!(status & RV3032_TLSB_EEBUSY))
>> + break;
>> + if (get_timer(start) > RV3032_EEBUSY_TIMEOUT)
>> + return -ETIMEDOUT;
>> + udelay(RV3032_EEBUSY_POLL);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int rv3032_enter_eerd(struct udevice *dev, u32 *eerd)
>> +{
>> + u8 ctrl1;
>> + int ret;
>> +
>> + ret = dm_i2c_read(dev, RV3032_CTRL1, &ctrl1, sizeof(ctrl1));
>> + if (ret)
>> + return ret;
>> +
>> + *eerd = ctrl1 & RV3032_CTRL1_EERD;
>> + if (*eerd)
>> + return 0;
>> +
>> + ret = rv3032_update_bits(dev, RV3032_CTRL1,
>> +  RV3032_CTRL1_EERD, RV3032_CTRL1_EERD);
>> + if (ret)
>> + return ret;
>> +
>> + ret = rv3032_eeprom_busywait(dev);
>> + if (ret) {
>> + rv3032_exit_eerd(dev, *eerd);
>> +
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int rv3032_get_time(struct udevice *dev, struct rtc_time *tm)
>> +{
>> + u8 date[7];
>> + int ret;
>> + u8 status;
>> +
>> + ret = dm_i2c_read(dev, RV3032_STATUS, &status, 1);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
>> + return -EINVAL;
>> +
>> + ret = dm_i2c_read(dev, RV3032_SEC, date, sizeof(date));
>> + if (ret)
>> + return ret;
>> +
>> + tm->tm_sec  = bcd2bin(date[0] & 0x7f);
>> + tm->tm_min  = bcd2bin(date[1] & 0x7f);
>> + tm->tm_hour = bcd2bin(date[2] & 0x3f);
>> + tm->tm_wday = date[3] & 0x7;
>> + tm->tm_mday = bcd2bin(date[4] & 0x3f);
>> + tm->tm_mon  = bcd2bin(date[5] & 0x1f);
>> + tm->tm_year = bcd2bin(date[6]) + 2000;
>> +
>> + return 0;
>> +}
>> +
>> +static int rv3032_set_time(struct udevice *dev, const struct rtc_time *tm)
>> +{
>> + u8 date[7];
>> + int ret;
>> +
>> + date[0] = bin2bcd(tm->tm_sec);
>> + date[1] = bin2bcd(tm->tm_min);
>> + date[2] = bin2bcd(tm->tm_hour);
>> + date[3] = tm->tm_wday;
>> + date[4] = bin2bcd(tm->tm_mday);
>> + date[5] = bin2bcd(tm->tm_mon);
>> + date[6] = bin2bcd(tm->tm_year - 2000);
>> +
>> + ret = dm_i2c_write(dev, RV3032_SEC, date,
>> +    sizeof(date));
>> + if (ret)
>> + return ret;
>> +
>> + ret = rv3032_update_bits(dev, RV3032_STATUS,
>> +  RV3032_STATUS_PORF | RV3032_STATUS_VLF, 0);
>> +
>> + return ret;
>> +}
>> +
>> +static int rv3032_eeprom_write(struct udevice *dev, unsigned int reg,
>> +        const u8 *buf, unsigned int len)
>> +{
>> + u32 eerd;
>> + int i, ret;
>> + u8 cmd;
>> +
>> + ret = rv3032_enter_eerd(dev, &eerd);
>> + if (ret)
>> + return ret;
>> +
>> + for (i = 0; i < len; i++) {
>> + cmd = RV3032_EEPROM_USER + reg + i;
>> + ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
>> +    &cmd, 1);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + ret = dm_i2c_write(dev, RV3032_EEPROM_DATA, &buf[i], 1);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + cmd = RV3032_EEPROM_CMD_WRITE;
>> + ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
>> +    &cmd, 1);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + udelay(RV3032_EEBUSY_POLL);
>> +
>> + ret = rv3032_eeprom_busywait(dev);
>> + if (ret)
>> + goto exit_eerd;
>> + }
>> +
>> +exit_eerd:
>> + rv3032_exit_eerd(dev, eerd);
>> +
>> + return ret;
>> +}
>> +
>> +static int rv3032_eeprom_read(struct udevice *dev, unsigned int reg,
>> +       u8 *buf, unsigned int len)
>> +{
>> + u32 eerd;
>> + int i, ret;
>> + u8 cmd, data;
>> +
>> + ret = rv3032_enter_eerd(dev, &eerd);
>> + if (ret)
>> + return ret;
>> +
>> + for (i = 0; i < len; i++) {
>> + cmd = RV3032_EEPROM_USER + reg + i;
>> + ret = dm_i2c_write(dev, RV3032_EEPROM_ADDR,
>> +    &cmd, 1);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + cmd = RV3032_EEPROM_CMD_READ;
>> + ret = dm_i2c_write(dev, RV3032_EEPROM_CMD,
>> +    &cmd, 1);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + ret = rv3032_eeprom_busywait(dev);
>> + if (ret)
>> + goto exit_eerd;
>> +
>> + ret = dm_i2c_read(dev, RV3032_EEPROM_DATA, &data, sizeof(data));
>> + if (ret)
>> + goto exit_eerd;
>> + buf[i] = data;
>> + }
>> +
>> +exit_eerd:
>> + rv3032_exit_eerd(dev, eerd);
>> +
>> + return ret;
>> +}
>> +
>> +static int rv3032_probe(struct udevice *dev)
>> +{
>> + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
>> + DM_I2C_CHIP_WR_ADDRESS);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct rtc_ops rv3032_rtc_ops = {
>> + .get = rv3032_get_time,
>> + .set = rv3032_set_time,
>> + .read = rv3032_eeprom_read,
>> + .write = rv3032_eeprom_write,
>> +};
>> +
>> +static const struct udevice_id rv3032_rtc_ids[] = {
>> + { .compatible = "microcrystal,rv3032", },
>> + { }
>> +};
>> +
>> +U_BOOT_DRIVER(rtc_rv3032) = {
>> + .name = "rtc-rv3028",
>> + .id = UCLASS_RTC,
>> + .probe = rv3032_probe,
>> + .of_match = rv3032_rtc_ids,
>> + .ops = &rv3032_rtc_ops,
>> +};
>> --
>> 2.42.0
>>
>
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com


This email contains confidential information. If you have received it in error, you must not read, use, copy or pass on this e-mail or its attachments. If you have received the e-mail in error, please inform me immediately by reply e-mail and then delete this e-mail from your system. Thank you

Diese E-Mail enthält vertrauliche Informationen. Sollten Sie sie irrtümlich erhalten haben, dürfen Sie diese E-Mail oder ihre Anhänge nicht lesen, verwenden, kopieren oder weitergeben. Sollten Sie die Mail versehentlich erhalten haben, teilen Sie mir dies bitte umgehend per Antwort-E-Mail mit und löschen Sie diese E-Mail dann aus Ihrem System. Vielen Dank

Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff
Registered office: Verl, Germany | Register court: Guetersloh HRA 7075



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one
  2023-08-30 14:03 ` [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one Steffen Dirkwinkel
@ 2023-09-01  7:18   ` Michal Simek
  0 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2023-09-01  7:18 UTC (permalink / raw)
  To: Steffen Dirkwinkel
  Cc: u-boot, Steffen Dirkwinkel, Jagan Teki, Jonas Karlman,
	Kunihiko Hayashi, Marek Vasut, Venkatesh Yadav Abbarapu

st 30. 8. 2023 v 20:16 odesílatel Steffen Dirkwinkel <lists@steffen.cc> napsal:
>
> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>
> This gpio is optional so undonditionally freeing it will crash.
>
> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> ---
>
>  drivers/usb/dwc3/dwc3-generic.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
> index 7f0af05855..dcc342ed04 100644
> --- a/drivers/usb/dwc3/dwc3-generic.c
> +++ b/drivers/usb/dwc3/dwc3-generic.c
> @@ -149,7 +149,9 @@ static int dwc3_generic_remove(struct udevice *dev,
>             priv->ulpi_reset) {
>                 struct gpio_desc *ulpi_reset = priv->ulpi_reset;
>
> -               dm_gpio_free(ulpi_reset->dev, ulpi_reset);
> +               if (priv->ulpi_reset) {
> +                       dm_gpio_free(ulpi_reset->dev, ulpi_reset);
> +               }
>         }
>
>         dwc3_remove(dwc3);
> --
> 2.42.0
>

Already fixed by:
https://lore.kernel.org/all/20230809033350.5718-1-venkatesh.abbarapu@amd.com/

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory
  2023-08-30 14:03 ` [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory Steffen Dirkwinkel
@ 2023-09-01  7:23   ` Michal Simek
  0 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2023-09-01  7:23 UTC (permalink / raw)
  To: Steffen Dirkwinkel, u-boot; +Cc: Steffen Dirkwinkel



On 8/30/23 16:03, Steffen Dirkwinkel wrote:
> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> 
> With the current config we'd put the fdt outside of memory.
> 
> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> ---
> 
>   include/configs/xilinx_zynqmp.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
> index 74264b7bee..334fe95d66 100644
> --- a/include/configs/xilinx_zynqmp.h
> +++ b/include/configs/xilinx_zynqmp.h
> @@ -50,7 +50,7 @@
>   #endif
>   
>   #define ENV_MEM_LAYOUT_SETTINGS \
> -	"fdt_addr_r=0x40000000\0" \
> +	"fdt_addr_r=0x28000000\0" \
>   	"fdt_size_r=0x400000\0" \
>   	"pxefile_addr_r=0x10000000\0" \
>   	"kernel_addr_r=0x18000000\0" \

This is not the right way to go.

I have started to move these variables setting to DT.
You can take a look at
https://github.com/devicetree-org/dt-schema/commit/3815da51a138619f443abcf2f821ca0a6fd57949

And fdt_addr_r is the same case. It should be moved to DT and remove it from here.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-08-30 14:03 ` [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200 Steffen Dirkwinkel
@ 2023-09-01  7:36   ` Michal Simek
  2023-09-01  9:00     ` Steffen Dirkwinkel
  0 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2023-09-01  7:36 UTC (permalink / raw)
  To: Steffen Dirkwinkel, u-boot; +Cc: Steffen Dirkwinkel



On 8/30/23 16:03, Steffen Dirkwinkel wrote:
> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> 
> This adds support for the Beckhoff CX8200 series of industrial embedded PCs.
> There is some information about the device and features here:
> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/
> 
> Currently supported/tested:
> - Boot from microSD
> - Ethernet
> - USB
> - rtc / rtc eeprom
> - tpm access
> - uart
> 
> Open points:
> - adding the psgtr usb phy doesn't work in linux (failed to get pll
>    lock)
> - fpga loading currently only as u-boot script or pre launch cmd (type
>    may be stored in eeprom of rtc so this could be made generic)
> 
> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
> ---
> 
>   arch/arm/dts/Makefile                         |    1 +
>   arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
>   .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
>   configs/xilinx_zynqmp_virt_defconfig          |    2 +-
>   4 files changed, 2209 insertions(+), 1 deletion(-)
>   create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
>   create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c

First of all xilinx folder is not the right location because Xilinx/AMD is not 
manufacturer of this board.

Second I am normally pushing back on adding these custom boards because it just 
increase time for maintaining.
Your last commit was in 2019 but at least you have some commits that I can trust 
that you would maintain your board for some time.

My biggest question is in what category is your board unique that it should be 
added it to the tree?

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-09-01  7:36   ` Michal Simek
@ 2023-09-01  9:00     ` Steffen Dirkwinkel
  2023-09-01 11:16       ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-09-01  9:00 UTC (permalink / raw)
  To: Michal Simek, u-boot; +Cc: Steffen Dirkwinkel



Am 01.09.23 um 09:36 schrieb Michal Simek:
> 
> 
> On 8/30/23 16:03, Steffen Dirkwinkel wrote:
>> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>
>> This adds support for the Beckhoff CX8200 series of industrial 
>> embedded PCs.
>> There is some information about the device and features here:
>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/
>>
>> Currently supported/tested:
>> - Boot from microSD
>> - Ethernet
>> - USB
>> - rtc / rtc eeprom
>> - tpm access
>> - uart
>>
>> Open points:
>> - adding the psgtr usb phy doesn't work in linux (failed to get pll
>>    lock)
>> - fpga loading currently only as u-boot script or pre launch cmd (type
>>    may be stored in eeprom of rtc so this could be made generic)
>>
>> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>> ---
>>
>>   arch/arm/dts/Makefile                         |    1 +
>>   arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
>>   .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
>>   configs/xilinx_zynqmp_virt_defconfig          |    2 +-
>>   4 files changed, 2209 insertions(+), 1 deletion(-)
>>   create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
>>   create mode 100644 
>> board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
> 
> First of all xilinx folder is not the right location because Xilinx/AMD 
> is not manufacturer of this board.

Yeah, sorry. I saw the avnet board and copied that.

> 
> Second I am normally pushing back on adding these custom boards because 
> it just increase time for maintaining.
> Your last commit was in 2019 but at least you have some commits that I 
> can trust that you would maintain your board for some time.

Our last board [1] only had linux/u-boot support as an afterthought. 
Customers had to buy a special option to set the right boot fuses, so 
most devices don’t boot u-boot.
With this board and a second similar zynqmp board (CX9240 [2]) we’ll 
have u-boot as default (and probably only) bootloader, so we’ll be
more active. We can also set two of us as maintainers and it would be 
fine to drop the boards if nobody responds.
We generally support these industrial boards for long time frames and 
would like to stay close to mainline instead of maintaining forks.

The alternative would be to have a downstream u-boot repository on 
github or somewhere. We’ll still likely have something there for build 
scripts / firmware builds / integration, but don’t plan to really 
diverge from upstream u-boot.

The main advantage of being in upstream u-boot would be that we can 
trigger internal CI on upstream changes. We can still do that and apply 
patches, but even simple patches like adding files to a makefile may 
fail to apply and will need fixing.


> 
> My biggest question is in what category is your board unique that it 
> should be added it to the tree?

Currently the board isn’t really unique. I guess we’d be the only users 
of the rtc with eeprom and there might be something needed for loading 
the correct fpga file based on eeprom (this might be done in linux / 
userspace or even u-boot script though)

[1] 
https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9020-arm-cortex-a8/cx9020.html#tab_productdetails_1
[2] 
https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9240-arm-cortex-a53/cx9240.html

> 
> Thanks,
> Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-09-01  9:00     ` Steffen Dirkwinkel
@ 2023-09-01 11:16       ` Michal Simek
  2023-09-01 15:03         ` Steffen Dirkwinkel
  0 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2023-09-01 11:16 UTC (permalink / raw)
  To: Steffen Dirkwinkel, u-boot; +Cc: Steffen Dirkwinkel



On 9/1/23 11:00, Steffen Dirkwinkel wrote:
> 
> 
> Am 01.09.23 um 09:36 schrieb Michal Simek:
>>
>>
>> On 8/30/23 16:03, Steffen Dirkwinkel wrote:
>>> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>>
>>> This adds support for the Beckhoff CX8200 series of industrial embedded PCs.
>>> There is some information about the device and features here:
>>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/
>>>
>>> Currently supported/tested:
>>> - Boot from microSD
>>> - Ethernet
>>> - USB
>>> - rtc / rtc eeprom
>>> - tpm access
>>> - uart
>>>
>>> Open points:
>>> - adding the psgtr usb phy doesn't work in linux (failed to get pll
>>>    lock)
>>> - fpga loading currently only as u-boot script or pre launch cmd (type
>>>    may be stored in eeprom of rtc so this could be made generic)
>>>
>>> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>> ---
>>>
>>>   arch/arm/dts/Makefile                         |    1 +
>>>   arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
>>>   .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
>>>   configs/xilinx_zynqmp_virt_defconfig          |    2 +-
>>>   4 files changed, 2209 insertions(+), 1 deletion(-)
>>>   create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
>>>   create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
>>
>> First of all xilinx folder is not the right location because Xilinx/AMD is not 
>> manufacturer of this board.
> 
> Yeah, sorry. I saw the avnet board and copied that.
> 
>>
>> Second I am normally pushing back on adding these custom boards because it 
>> just increase time for maintaining.
>> Your last commit was in 2019 but at least you have some commits that I can 
>> trust that you would maintain your board for some time.
> 
> Our last board [1] only had linux/u-boot support as an afterthought. Customers 
> had to buy a special option to set the right boot fuses, so most devices don’t 
> boot u-boot.
> With this board and a second similar zynqmp board (CX9240 [2]) we’ll have u-boot 
> as default (and probably only) bootloader, so we’ll be
> more active. We can also set two of us as maintainers and it would be fine to 
> drop the boards if nobody responds.
> We generally support these industrial boards for long time frames and would like 
> to stay close to mainline instead of maintaining forks.
> 
> The alternative would be to have a downstream u-boot repository on github or 
> somewhere. We’ll still likely have something there for build scripts / firmware 
> builds / integration, but don’t plan to really diverge from upstream u-boot.
> 
> The main advantage of being in upstream u-boot would be that we can trigger 
> internal CI on upstream changes. We can still do that and apply patches, but 
> even simple patches like adding files to a makefile may fail to apply and will 
> need fixing.
> 
> 
>>
>> My biggest question is in what category is your board unique that it should be 
>> added it to the tree?
> 
> Currently the board isn’t really unique. I guess we’d be the only users of the 
> rtc with eeprom and there might be something needed for loading the correct fpga 
> file based on eeprom (this might be done in linux / userspace or even u-boot 
> script though)
> 
> [1] 
> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9020-arm-cortex-a8/cx9020.html#tab_productdetails_1
> [2] 
> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9240-arm-cortex-a53/cx9240.html

Regarding board itself.
It is DTB - we use OF_SEPARATE/OF_BOARD it means building is easy. I expect you 
have pretty much something in PL that's why your DT is bigger if you don't use 
DT overlays but for fixed design there is actually no reason to use it.

psu_init_gpl. You are adding it to specific folder which match DEVICE_TREE 
variable when you use it. You can actually just copy it to board/xilinx/zynqmp/ 
folder and it will be pick up for your build.

xilinx_zynqmp_virt_defconfig - you likely don't want to use this in your product 
because there are things enabled which you don't use on your board. That's why 
you should tune it for your usage.

regs.init - that's for boot.bin generation with SPL - BOOT_INIT_FILE should be 
used and it can't be wired via generic defconfig anyway.

That pretty much leads to the state that make no sense for you to use 
xilinx_zynqmp_virt_defconfig.

I think we are still supporting defconfig fragments which is the way how to 
maintain your board to be close to mainline as possible.

And fdt_addr change. I think this is for me the most problematic part which 
should be solved. Pretty much all these variables should be moved out and that's 
what we started to work on. But it will take some time to get there.

Definitely there shouldn't be a problem to merge that rtc driver and I would 
prefer if you can stay with your board out of upstream and try to maintain it 
via your build scripts only. And let me know if we can improve/fix something to 
be able to do it in long term. But pretty much all things should be in place 
already to do it without pain. At least I would like you to try it and see if 
there is any major blocker which we can try to fix.

Thanks,
Michal


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-09-01 11:16       ` Michal Simek
@ 2023-09-01 15:03         ` Steffen Dirkwinkel
  2023-09-04 10:02           ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Steffen Dirkwinkel @ 2023-09-01 15:03 UTC (permalink / raw)
  To: Michal Simek, u-boot; +Cc: Steffen Dirkwinkel



Am 01.09.23 um 13:16 schrieb Michal Simek:
> 
> 
> On 9/1/23 11:00, Steffen Dirkwinkel wrote:
>>
>>
>> Am 01.09.23 um 09:36 schrieb Michal Simek:
>>>
>>>
>>> On 8/30/23 16:03, Steffen Dirkwinkel wrote:
>>>> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>>>
>>>> This adds support for the Beckhoff CX8200 series of industrial 
>>>> embedded PCs.
>>>> There is some information about the device and features here:
>>>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/
>>>>
>>>> Currently supported/tested:
>>>> - Boot from microSD
>>>> - Ethernet
>>>> - USB
>>>> - rtc / rtc eeprom
>>>> - tpm access
>>>> - uart
>>>>
>>>> Open points:
>>>> - adding the psgtr usb phy doesn't work in linux (failed to get pll
>>>>    lock)
>>>> - fpga loading currently only as u-boot script or pre launch cmd (type
>>>>    may be stored in eeprom of rtc so this could be made generic)
>>>>
>>>> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>>> ---
>>>>
>>>>   arch/arm/dts/Makefile                         |    1 +
>>>>   arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
>>>>   .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 
>>>> +++++++++++++++++
>>>>   configs/xilinx_zynqmp_virt_defconfig          |    2 +-
>>>>   4 files changed, 2209 insertions(+), 1 deletion(-)
>>>>   create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
>>>>   create mode 100644 
>>>> board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
>>>
>>> First of all xilinx folder is not the right location because 
>>> Xilinx/AMD is not manufacturer of this board.
>>
>> Yeah, sorry. I saw the avnet board and copied that.
>>
>>>
>>> Second I am normally pushing back on adding these custom boards 
>>> because it just increase time for maintaining.
>>> Your last commit was in 2019 but at least you have some commits that 
>>> I can trust that you would maintain your board for some time.
>>
>> Our last board [1] only had linux/u-boot support as an afterthought. 
>> Customers had to buy a special option to set the right boot fuses, so 
>> most devices don’t boot u-boot.
>> With this board and a second similar zynqmp board (CX9240 [2]) we’ll 
>> have u-boot as default (and probably only) bootloader, so we’ll be
>> more active. We can also set two of us as maintainers and it would be 
>> fine to drop the boards if nobody responds.
>> We generally support these industrial boards for long time frames and 
>> would like to stay close to mainline instead of maintaining forks.
>>
>> The alternative would be to have a downstream u-boot repository on 
>> github or somewhere. We’ll still likely have something there for build 
>> scripts / firmware builds / integration, but don’t plan to really 
>> diverge from upstream u-boot.
>>
>> The main advantage of being in upstream u-boot would be that we can 
>> trigger internal CI on upstream changes. We can still do that and 
>> apply patches, but even simple patches like adding files to a makefile 
>> may fail to apply and will need fixing.
>>
>>
>>>
>>> My biggest question is in what category is your board unique that it 
>>> should be added it to the tree?
>>
>> Currently the board isn’t really unique. I guess we’d be the only 
>> users of the rtc with eeprom and there might be something needed for 
>> loading the correct fpga file based on eeprom (this might be done in 
>> linux / userspace or even u-boot script though)
>>
>> [1] 
>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9020-arm-cortex-a8/cx9020.html#tab_productdetails_1
>> [2] 
>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9240-arm-cortex-a53/cx9240.html
> 
> Regarding board itself.
> It is DTB - we use OF_SEPARATE/OF_BOARD it means building is easy. I 
> expect you have pretty much something in PL that's why your DT is bigger 
> if you don't use DT overlays but for fixed design there is actually no 
> reason to use it.
> 
> psu_init_gpl. You are adding it to specific folder which match 
> DEVICE_TREE variable when you use it. You can actually just copy it to 
> board/xilinx/zynqmp/ folder and it will be pick up for your build.
> 
> xilinx_zynqmp_virt_defconfig - you likely don't want to use this in your 
> product because there are things enabled which you don't use on your 
> board. That's why you should tune it for your usage.
> 
> regs.init - that's for boot.bin generation with SPL - BOOT_INIT_FILE 
> should be used and it can't be wired via generic defconfig anyway.
> 
> That pretty much leads to the state that make no sense for you to use 
> xilinx_zynqmp_virt_defconfig.

There are things in the defconfig we don't need, but size hasn't really 
been an issue, since we boot from relatively large sdcards. We might 
still do separate config for all our boards though.

We currently build virt_defconfig and set BOOT_INIT_FILE, 
PMUFW_INIT_FILE and ZYNQMP_SPL_PM_CFG_OBJ_FILE. If we ship this firmware 
somewhere (similar to linux-firmware?) we could set fixed paths for that 
and make rebuilding u-boot simpler. I've found reproducing images for 
zynqmp devboards with and without using petalinux and the xilinx fsbl to 
be quite annoying on the first try and this could be simpler if one just 
wants to support generic arm64 distros.

> 
> I think we are still supporting defconfig fragments which is the way how 
> to maintain your board to be close to mainline as possible.
> 
> And fdt_addr change. I think this is for me the most problematic part 
> which should be solved. Pretty much all these variables should be moved 
> out and that's what we started to work on. But it will take some time to 
> get there.
> 

I agree, I can also work on that, but it will likely be in October since 
I'm on vacation for most of September. Maybe one of our other developers 
will work on it instead.

> Definitely there shouldn't be a problem to merge that rtc driver and I 
> would prefer if you can stay with your board out of upstream and try to 
> maintain it via your build scripts only. And let me know if we can 
> improve/fix something to be able to do it in long term. But pretty much 
> all things should be in place already to do it without pain. At least I 
> would like you to try it and see if there is any major blocker which we 
> can try to fix.

I don't really understand why the board shouldn't be upstream, once it 
is just a dts file + psu_init_gpl + regs. There really isn't much to 
maintain there that wouldn't also break out of tree.

We might be different from most other out of tree zynqmp users, since we 
usually also offer to sell hardware without our software and users would 
then either download an image from us or build their own u-boot + linux 
and only download the fpga bitstreams. I expect most people would look 
at upstream u-boot and linux before looking for our downstream repositories.

We can and will of course start with a downstream repository, I just 
don't understand why real (non-devboard) hardware should be out of tree.

Thanks,
Steffen


> 
> Thanks,
> Michal
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200
  2023-09-01 15:03         ` Steffen Dirkwinkel
@ 2023-09-04 10:02           ` Michal Simek
  0 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2023-09-04 10:02 UTC (permalink / raw)
  To: Steffen Dirkwinkel, Michal Simek, u-boot; +Cc: Steffen Dirkwinkel



On 9/1/23 17:03, Steffen Dirkwinkel wrote:
> 
> 
> Am 01.09.23 um 13:16 schrieb Michal Simek:
>>
>>
>> On 9/1/23 11:00, Steffen Dirkwinkel wrote:
>>>
>>>
>>> Am 01.09.23 um 09:36 schrieb Michal Simek:
>>>>
>>>>
>>>> On 8/30/23 16:03, Steffen Dirkwinkel wrote:
>>>>> From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>>>>
>>>>> This adds support for the Beckhoff CX8200 series of industrial embedded PCs.
>>>>> There is some information about the device and features here:
>>>>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx8200-arm-cortex-a53/
>>>>>
>>>>> Currently supported/tested:
>>>>> - Boot from microSD
>>>>> - Ethernet
>>>>> - USB
>>>>> - rtc / rtc eeprom
>>>>> - tpm access
>>>>> - uart
>>>>>
>>>>> Open points:
>>>>> - adding the psgtr usb phy doesn't work in linux (failed to get pll
>>>>>    lock)
>>>>> - fpga loading currently only as u-boot script or pre launch cmd (type
>>>>>    may be stored in eeprom of rtc so this could be made generic)
>>>>>
>>>>> Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
>>>>> ---
>>>>>
>>>>>   arch/arm/dts/Makefile                         |    1 +
>>>>>   arch/arm/dts/zynqmp-beckhoff-cx8200.dts       |  247 +++
>>>>>   .../zynqmp-beckhoff-cx8200/psu_init_gpl.c     | 1960 +++++++++++++++++
>>>>>   configs/xilinx_zynqmp_virt_defconfig          |    2 +-
>>>>>   4 files changed, 2209 insertions(+), 1 deletion(-)
>>>>>   create mode 100644 arch/arm/dts/zynqmp-beckhoff-cx8200.dts
>>>>>   create mode 100644 board/xilinx/zynqmp/zynqmp-beckhoff-cx8200/psu_init_gpl.c
>>>>
>>>> First of all xilinx folder is not the right location because Xilinx/AMD is 
>>>> not manufacturer of this board.
>>>
>>> Yeah, sorry. I saw the avnet board and copied that.
>>>
>>>>
>>>> Second I am normally pushing back on adding these custom boards because it 
>>>> just increase time for maintaining.
>>>> Your last commit was in 2019 but at least you have some commits that I can 
>>>> trust that you would maintain your board for some time.
>>>
>>> Our last board [1] only had linux/u-boot support as an afterthought. 
>>> Customers had to buy a special option to set the right boot fuses, so most 
>>> devices don’t boot u-boot.
>>> With this board and a second similar zynqmp board (CX9240 [2]) we’ll have 
>>> u-boot as default (and probably only) bootloader, so we’ll be
>>> more active. We can also set two of us as maintainers and it would be fine to 
>>> drop the boards if nobody responds.
>>> We generally support these industrial boards for long time frames and would 
>>> like to stay close to mainline instead of maintaining forks.
>>>
>>> The alternative would be to have a downstream u-boot repository on github or 
>>> somewhere. We’ll still likely have something there for build scripts / 
>>> firmware builds / integration, but don’t plan to really diverge from upstream 
>>> u-boot.
>>>
>>> The main advantage of being in upstream u-boot would be that we can trigger 
>>> internal CI on upstream changes. We can still do that and apply patches, but 
>>> even simple patches like adding files to a makefile may fail to apply and 
>>> will need fixing.
>>>
>>>
>>>>
>>>> My biggest question is in what category is your board unique that it should 
>>>> be added it to the tree?
>>>
>>> Currently the board isn’t really unique. I guess we’d be the only users of 
>>> the rtc with eeprom and there might be something needed for loading the 
>>> correct fpga file based on eeprom (this might be done in linux / userspace or 
>>> even u-boot script though)
>>>
>>> [1] 
>>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9020-arm-cortex-a8/cx9020.html#tab_productdetails_1
>>> [2] 
>>> https://www.beckhoff.com/en-en/products/ipc/embedded-pcs/cx9240-arm-cortex-a53/cx9240.html
>>
>> Regarding board itself.
>> It is DTB - we use OF_SEPARATE/OF_BOARD it means building is easy. I expect 
>> you have pretty much something in PL that's why your DT is bigger if you don't 
>> use DT overlays but for fixed design there is actually no reason to use it.
>>
>> psu_init_gpl. You are adding it to specific folder which match DEVICE_TREE 
>> variable when you use it. You can actually just copy it to 
>> board/xilinx/zynqmp/ folder and it will be pick up for your build.
>>
>> xilinx_zynqmp_virt_defconfig - you likely don't want to use this in your 
>> product because there are things enabled which you don't use on your board. 
>> That's why you should tune it for your usage.
>>
>> regs.init - that's for boot.bin generation with SPL - BOOT_INIT_FILE should be 
>> used and it can't be wired via generic defconfig anyway.
>>
>> That pretty much leads to the state that make no sense for you to use 
>> xilinx_zynqmp_virt_defconfig.
> 
> There are things in the defconfig we don't need, but size hasn't really been an 
> issue, since we boot from relatively large sdcards. We might still do separate 
> config for all our boards though.
> 
> We currently build virt_defconfig and set BOOT_INIT_FILE, PMUFW_INIT_FILE and 
> ZYNQMP_SPL_PM_CFG_OBJ_FILE. If we ship this firmware somewhere (similar to 
> linux-firmware?) we could set fixed paths for that and make rebuilding u-boot 
> simpler. I've found reproducing images for zynqmp devboards with and without 
> using petalinux and the xilinx fsbl to be quite annoying on the first try and 
> this could be simpler if one just wants to support generic arm64 distros.
> 
>>
>> I think we are still supporting defconfig fragments which is the way how to 
>> maintain your board to be close to mainline as possible.
>>
>> And fdt_addr change. I think this is for me the most problematic part which 
>> should be solved. Pretty much all these variables should be moved out and 
>> that's what we started to work on. But it will take some time to get there.
>>
> 
> I agree, I can also work on that, but it will likely be in October since I'm on 
> vacation for most of September. Maybe one of our other developers will work on 
> it instead.
> 
>> Definitely there shouldn't be a problem to merge that rtc driver and I would 
>> prefer if you can stay with your board out of upstream and try to maintain it 
>> via your build scripts only. And let me know if we can improve/fix something 
>> to be able to do it in long term. But pretty much all things should be in 
>> place already to do it without pain. At least I would like you to try it and 
>> see if there is any major blocker which we can try to fix.
> 
> I don't really understand why the board shouldn't be upstream, once it is just a 
> dts file + psu_init_gpl + regs. There really isn't much to maintain there that 
> wouldn't also break out of tree.
> 
> We might be different from most other out of tree zynqmp users, since we usually 
> also offer to sell hardware without our software and users would then either 
> download an image from us or build their own u-boot + linux and only download 
> the fpga bitstreams. I expect most people would look at upstream u-boot and 
> linux before looking for our downstream repositories.

Sounds good.

> 
> We can and will of course start with a downstream repository, I just don't 
> understand why real (non-devboard) hardware should be out of tree.

It can be I just want to make sure that you don't disappear after short time.
Topic's platforms are also the part of tree. It means let's figure it out that 
fdt part which you need to solve and we can merge your platform if you give me 
commitment that you will test and support it.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP/Versal ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal/Versal NET SoCs
TF-A maintainer - Xilinx ZynqMP/Versal/Versal NET SoCs

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-09-04 10:02 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-30 14:03 [PATCH 0/5] board: xilinx: zyqmp: add Beckhoff CX8200 Steffen Dirkwinkel
2023-08-30 14:03 ` [PATCH 1/5] drivers: rtc: add rv3032 driver Steffen Dirkwinkel
2023-08-30 19:43   ` Alexandre Belloni
2023-08-30 19:52     ` Steffen Dirkwinkel
2023-08-30 14:03 ` [PATCH 2/5] drivers/usb/dwc3: zynqmp: only free reset gpio if we have one Steffen Dirkwinkel
2023-09-01  7:18   ` Michal Simek
2023-08-30 14:03 ` [PATCH 3/5] xilinx: zynqmp: move fdt_addr so we can use devices with less memory Steffen Dirkwinkel
2023-09-01  7:23   ` Michal Simek
2023-08-30 14:03 ` [PATCH 4/5] xilinx: zynqmp: add Beckhoff CX8200 Steffen Dirkwinkel
2023-09-01  7:36   ` Michal Simek
2023-09-01  9:00     ` Steffen Dirkwinkel
2023-09-01 11:16       ` Michal Simek
2023-09-01 15:03         ` Steffen Dirkwinkel
2023-09-04 10:02           ` Michal Simek
2023-08-30 14:03 ` [PATCH 5/5] xilinx: zynqmp: beckhoff cx8200: setup inner cache broadcasting Steffen Dirkwinkel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox