Merge tag 'xilinx-for-v2022.07-rc1' of https://source.denx.de/u-boot/custodians/u...
authorTom Rini <trini@konsulko.com>
Wed, 16 Mar 2022 16:52:02 +0000 (12:52 -0400)
committerTom Rini <trini@konsulko.com>
Wed, 16 Mar 2022 16:52:02 +0000 (12:52 -0400)
Xilinx changes for v2022.07-rc1

microblaze:
- Add support for reserved memory

xilinx:
- Update FRU code with MAC reading

zynqmp:
- Remove double AMS setting
- DT updates (mostly for SOMs)
- Add support for zcu106 rev 1.0

zynq:
- Update nand binding

nand:
- Aligned zynq_nand to upstream DT binding

net:
- Add support for ethernet-phy-id

mmc:
- Workaround CD in zynq_sdhci driver also for ZynqMP
- Add support for dynamic/run-time SD config for SOMs

gpio:
- Add driver for slg7xl45106

firmware:
- Add support for dynamic SD config

power-domain:
- Update zynqmp driver with the latest firmware

video:
- Add skeleton driver for DP and DPDMA

i2c:
- Fix i2c to work with QEMU

pinctrl:
- Add driver for zynqmp pinctrl driver

47 files changed:
MAINTAINERS
arch/arm/dts/Makefile
arch/arm/dts/bitmain-antminer-s9.dts
arch/arm/dts/zynq-7000.dtsi
arch/arm/dts/zynq-zc770-xm011.dts
arch/arm/dts/zynqmp-clk-ccf.dtsi
arch/arm/dts/zynqmp-p-a2197-00-revA.dts
arch/arm/dts/zynqmp-sck-kv-g-revA.dts
arch/arm/dts/zynqmp-sck-kv-g-revB.dts
arch/arm/dts/zynqmp-sm-k26-revA.dts
arch/arm/dts/zynqmp-zcu106-rev1.0.dts [new file with mode: 0644]
arch/microblaze/include/asm/system.h
board/xilinx/common/board.c
board/xilinx/common/fru.h
board/xilinx/common/fru_ops.c
board/xilinx/microblaze-generic/microblaze-generic.c
board/xilinx/zynqmp/zynqmp-zcu106-rev1.0/psu_init_gpl.c [new file with mode: 0644]
board/xilinx/zynqmp/zynqmp.c
configs/xilinx_zynqmp_virt_defconfig
drivers/core/ofnode.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/xilinx_dpdma.c [new file with mode: 0644]
drivers/firmware/firmware-zynqmp.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio_slg7xl45106.c [new file with mode: 0644]
drivers/i2c/i2c-cdns.c
drivers/mmc/zynq_sdhci.c
drivers/mtd/nand/raw/zynq_nand.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/ethernet_id.c [new file with mode: 0644]
drivers/net/phy/phy.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/pinctrl-zynqmp.c [new file with mode: 0644]
drivers/power/domain/zynqmp-power-domain.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/zynqmp_dpsub.c [new file with mode: 0644]
include/dm/ofnode.h
include/dm/pinctrl.h
include/linux/math64.h
include/phy.h
include/zynqmp_firmware.h
test/cmd/pinmux.c

index f25ca7c..126bb43 100644 (file)
@@ -617,8 +617,10 @@ F: drivers/i2c/muxes/pca954x.c
 F:     drivers/i2c/zynq_i2c.c
 F:     drivers/mmc/zynq_sdhci.c
 F:     drivers/mtd/nand/raw/zynq_nand.c
+F:     drivers/net/phy/ethernet_id.c
 F:     drivers/net/phy/xilinx_phy.c
 F:     drivers/net/zynq_gem.c
+F:     drivers/pinctrl/pinctrl-zynqmp.c
 F:     drivers/serial/serial_zynq.c
 F:     drivers/spi/zynq_qspi.c
 F:     drivers/spi/zynq_spi.c
@@ -636,6 +638,7 @@ F:  arch/arm/mach-zynqmp/
 F:     drivers/clk/clk_zynqmp.c
 F:     driver/firmware/firmware-zynqmp.c
 F:     drivers/fpga/zynqpl.c
+F:     drivers/gpio/gpio_slg7xl45106.c
 F:     drivers/gpio/zynq_gpio.c
 F:     drivers/gpio/zynqmp_gpio_modepin.c
 F:     drivers/i2c/i2c-cdns.c
@@ -655,7 +658,6 @@ F:  drivers/soc/soc_xilinx_zynqmp.c
 F:     drivers/spi/zynq_qspi.c
 F:     drivers/spi/zynq_spi.c
 F:     drivers/timer/cadence-ttc.c
-F:     drivers/usb/host/ehci-zynq.c
 F:     drivers/video/seps525.c
 F:     drivers/watchdog/cdns_wdt.c
 F:     include/zynqmppl.h
index 56ed7b6..770a519 100644 (file)
@@ -349,6 +349,7 @@ dtb-$(CONFIG_ARCH_ZYNQMP) += \
        zynqmp-zcu104-revA.dtb                  \
        zynqmp-zcu104-revC.dtb                  \
        zynqmp-zcu106-revA.dtb                  \
+       zynqmp-zcu106-rev1.0.dtb                \
        zynqmp-zcu111-revA.dtb                  \
        zynqmp-zcu1275-revA.dtb                 \
        zynqmp-zcu1275-revB.dtb                 \
index 0694350..408862b 100644 (file)
@@ -50,7 +50,7 @@
        ps-clk-frequency = <33333333>;
 };
 
-&nand0 {
+&nfc0 {
        status = "okay";
 };
 
index 4dda753..9495911 100644 (file)
                        #size-cells = <0>;
                };
 
-               smcc: memory-controller@e000e000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       status = "disabled";
-                       clock-names = "memclk", "apb_pclk";
-                       clocks = <&clkc 11>, <&clkc 44>;
-                       compatible = "arm,pl353-smc-r2p1", "arm,primecell";
-                       interrupt-parent = <&intc>;
-                       interrupts = <0 18 4>;
-                       ranges ;
-                       reg = <0xe000e000 0x1000>;
-                       nand0: flash@e1000000 {
-                               status = "disabled";
-                               compatible = "arm,pl353-nand-r2p1";
-                               reg = <0xe1000000 0x1000000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                       };
-                       nor0: flash@e2000000 {
-                               status = "disabled";
-                               compatible = "cfi-flash";
-                               reg = <0xe2000000 0x2000000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                       };
-               };
-
                gem0: ethernet@e000b000 {
                        compatible = "cdns,zynq-gem", "cdns,gem";
                        reg = <0xe000b000 0x1000>;
                        #size-cells = <0>;
                };
 
+               smcc: memory-controller@e000e000 {
+                       compatible = "arm,pl353-smc-r2p1", "arm,primecell";
+                       reg = <0xe000e000 0x0001000>;
+                       status = "disabled";
+                       clock-names = "memclk", "apb_pclk";
+                       clocks = <&clkc 11>, <&clkc 44>;
+                       ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
+                                 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
+                                 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+                       interrupt-parent = <&intc>;
+                       interrupts = <0 18 4>;
+
+                       nfc0: nand-controller@0,0 {
+                               compatible = "arm,pl353-nand-r2p1";
+                               reg = <0 0 0x1000000>;
+                               status = "disabled";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                       };
+                       nor0: flash@1,0 {
+                               status = "disabled";
+                               compatible = "cfi-flash";
+                               reg = <1 0 0x2000000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                       };
+               };
+
                sdhci0: mmc@e0100000 {
                        compatible = "arasan,sdhci-8.9a";
                        status = "disabled";
index b6e3e25..0ef2ae1 100644 (file)
@@ -47,7 +47,7 @@
        };
 };
 
-&nand0 {
+&nfc0 {
        status = "okay";
 };
 
index 664e658..7b09d75 100644 (file)
 
 &sdhci0 {
        clocks = <&zynqmp_clk SDIO0_REF>, <&zynqmp_clk LPD_LSBUS>;
+       assigned-clocks = <&zynqmp_clk SDIO0_REF>;
 };
 
 &sdhci1 {
        clocks = <&zynqmp_clk SDIO1_REF>, <&zynqmp_clk LPD_LSBUS>;
+       assigned-clocks = <&zynqmp_clk SDIO1_REF>;
 };
 
 &spi0 {
 
 &usb0 {
        clocks = <&zynqmp_clk USB0_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
+       assigned-clocks = <&zynqmp_clk USB0_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
 };
 
 &usb1 {
        clocks = <&zynqmp_clk USB1_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
+       assigned-clocks = <&zynqmp_clk USB1_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
 };
 
 &watchdog0 {
 
 &zynqmp_dpdma {
        clocks = <&zynqmp_clk DPDMA_REF>;
+       assigned-clocks = <&zynqmp_clk DPDMA_REF>; /* apll */
 };
 
 &zynqmp_dpsub {
        clocks = <&zynqmp_clk TOPSW_LSBUS>,
                 <&zynqmp_clk DP_AUDIO_REF>,
                 <&zynqmp_clk DP_VIDEO_REF>;
+       assigned-clocks = <&zynqmp_clk DP_STC_REF>,
+                         <&zynqmp_clk DP_AUDIO_REF>,
+                         <&zynqmp_clk DP_VIDEO_REF>;  /* rpll, rpll, vpll */
 };
index 5d21795..b3fe42f 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <6>;
-                       si570_hsdp: clock-generator@5d { /* u5 */
+                       si570_hsdp: clock-generator@60 { /* u5 */
                                #clock-cells = <0>;
                                compatible = "silabs,si570";
-                               reg = <0x5d>;   /* 570JAC000900DG */
+                               reg = <0x60>;   /* 570JAC000900DG */
                                temperature-stability = <50>;
                                factory-fout = <156250000>;
                                clock-frequency = <156250000>;
                        /* u36 0xd8 or 0xde - pcie clk buf - 9ZML1241EKILF PCIe GEN 4 CLOCK BUFFER FIXME - no driver */
                        /* u37 0xd0 DNP - pcie clocking 1 - 9FGV1006BQ505LTGI - PCIe GEN 4 CLOCK GENERATOR FIXME - no linux driver */
                        /* u38 0xca - pcie clocking 2 - 9ZML1241EKILF PCIe GEN 4 CLOCK BUFFER FIXME - no driver */
-                       clock_8t49n287: clock-generator@d8 { /* u39 8T49N240 - pcie clocking 3 */
+                       clock_8t49n287: clock-generator@60 { /* u39 8T49N240 - pcie clocking 3 */
                                #clock-cells = <1>; /* author David Cater <david.cater@idt.com>*/
                                compatible = "idt,8t49n240", "idt,8t49n241"; /* FIXME no driver for 240 */
-                               reg = <0xd8>;
+                               reg = <0x60>;
                                /* Documentation/devicetree/bindings/clock/idt,idt8t49n24x.txt */
                                /* FIXME there input via J241 Samtec CLK1 and CLK0 from U38 - selection PIN */
 
index 22602d8..85994be 100644 (file)
        status = "disabled";
        phy-names = "dp-phy0", "dp-phy1";
        phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
+       assigned-clock-rates = <27000000>, <25000000>, <300000000>;
 };
 
 &zynqmp_dpdma {
        status = "okay";
+       assigned-clock-rates = <600000000>;
 };
 
 &usb0 {
        phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
        usbhub: usb5744 { /* u43 */
                compatible = "microchip,usb5744";
-               reset-gpios = <&gpio 44 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio 44 GPIO_ACTIVE_LOW>;
        };
 };
 
        no-1-8-v;
        disable-wp;
        xlnx,mio-bank = <1>;
+       assigned-clock-rates = <187498123>;
+       bus-width = <8>;
 };
 
 &gem3 { /* required by spec */
        mdio: mdio {
                #address-cells = <1>;
                #size-cells = <0>;
-               reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
-               reset-delay-us = <2>;
 
                phy0: ethernet-phy@1 {
                        #phy-cells = <1>;
                        reg = <1>;
+                       compatible = "ethernet-phy-id2000.a231";
                        ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
                        ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
                        ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
                        ti,dp83867-rxctrl-strap-quirk;
+                       reset-assert-us = <100>;
+                       reset-deassert-us = <280>;
+                       reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
                };
        };
 };
index df054e1..b81c2e6 100644 (file)
                label = "ina260-u14";
                reg = <0x40>;
        };
-       usbhub: usb5744@2d { /* u43 */
-               compatible = "microchip,usb5744";
-               reg = <0x2d>;
-               reset-gpios = <&gpio 44 GPIO_ACTIVE_HIGH>;
-       };
+       /* u43 - 0x2d - USB hub */
        /* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
 };
 
 };
 
 &zynqmp_dpsub {
-       status = "disabled";
+       status = "okay";
        phy-names = "dp-phy0", "dp-phy1";
        phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
+       assigned-clock-rates = <27000000>, <25000000>, <300000000>;
 };
 
 &zynqmp_dpdma {
        status = "okay";
+       assigned-clock-rates = <600000000>;
 };
 
 &usb0 {
        pinctrl-0 = <&pinctrl_usb0_default>;
        phy-names = "usb3-phy";
        phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
+       assigned-clock-rates = <250000000>, <20000000>;
+
+       usb5744: usb-hub { /* u43 */
+               status = "okay";
+               compatible = "microchip,usb5744";
+               i2c-bus = <&i2c1>;
+               reset-gpios = <&gpio 44 GPIO_ACTIVE_LOW>;
+       };
 };
 
 &dwc3_0 {
        clk-phase-sd-hs = <126>, <60>;
        clk-phase-uhs-sdr25 = <120>, <60>;
        clk-phase-uhs-ddr50 = <126>, <48>;
+       assigned-clock-rates = <187498123>;
+       bus-width = <8>;
 };
 
 &gem3 { /* required by spec */
        mdio: mdio {
                #address-cells = <1>;
                #size-cells = <0>;
-               reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
-               reset-delay-us = <2>;
 
                phy0: ethernet-phy@1 {
                        #phy-cells = <1>;
                        reg = <1>;
+                       compatible = "ethernet-phy-id2000.a231";
                        ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
                        ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
                        ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
                        ti,dp83867-rxctrl-strap-quirk;
+                       reset-assert-us = <100>;
+                       reset-deassert-us = <280>;
+                       reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
                };
        };
 };
index 5f55df2..14ab316 100644 (file)
@@ -14,6 +14,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 / {
        model = "ZynqMP SM-K26 Rev1/B/A";
        status = "okay";
 };
 
+&pinctrl0 {
+       status = "okay";
+       pinctrl_sdhci0_default: sdhci0-default {
+               conf {
+                       groups = "sdio0_0_grp";
+                       slew-rate = <SLEW_RATE_SLOW>;
+                       power-source = <IO_STANDARD_LVCMOS18>;
+                       bias-disable;
+               };
+
+               mux {
+                       groups = "sdio0_0_grp";
+                       function = "sdio0";
+               };
+       };
+};
+
 &qspi { /* MIO 0-5 - U143 */
        status = "okay";
        flash@0 { /* MT25QU512A */
 
 &sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A */
        status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sdhci0_default>;
        non-removable;
        disable-wp;
        bus-width = <8>;
        xlnx,mio-bank = <0>;
+       assigned-clock-rates = <187498123>;
 };
 
 &spi1 { /* MIO6, 9-11 */
 &ams_pl {
        status = "okay";
 };
+
+&zynqmp_dpsub {
+       status = "okay";
+};
diff --git a/arch/arm/dts/zynqmp-zcu106-rev1.0.dts b/arch/arm/dts/zynqmp-zcu106-rev1.0.dts
new file mode 100644 (file)
index 0000000..f43c477
--- /dev/null
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Xilinx ZynqMP ZCU106 Rev1.0
+ *
+ * (C) Copyright 2016 - 2022, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include "zynqmp-zcu106-revA.dts"
+
+/ {
+       model = "ZynqMP ZCU106 Rev1.0";
+       compatible = "xlnx,zynqmp-zcu106-rev1.0", "xlnx,zynqmp-zcu106-revA",
+                    "xlnx,zynqmp-zcu106", "xlnx,zynqmp";
+};
index 3107748..050a8b4 100644 (file)
@@ -23,6 +23,8 @@
 #endif
 #include <asm/ptrace.h>
 
+#define MMU_SECTION_SIZE       (1 * 1024 * 1024)
+
 #define prepare_to_switch()    do { } while (0)
 
 /*
index 0068cb8..0769189 100644 (file)
@@ -171,6 +171,7 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
 {
        int i, ret, eeprom_size;
        u8 *fru_content;
+       u8 id = 0;
 
        /* FIXME this is shortcut - if eeprom type is wrong it will fail */
        eeprom_size = i2c_eeprom_size(dev);
@@ -218,6 +219,14 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
                sizeof(desc->revision));
        strncpy(desc->serial, (char *)fru_data.brd.serial_number,
                sizeof(desc->serial));
+
+       while (id < EEPROM_HDR_NO_OF_MAC_ADDR) {
+               if (is_valid_ethaddr((const u8 *)fru_data.mac.macid[id]))
+                       memcpy(&desc->mac_addr[id],
+                              (char *)fru_data.mac.macid[id], ETH_ALEN);
+               id++;
+       }
+
        desc->header = EEPROM_HEADER_MAGIC;
 
 end:
@@ -416,7 +425,7 @@ int board_late_init_xilinx(void)
 
                        for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
                                if (!desc->mac_addr[i])
-                                       continue;
+                                       break;
 
                                if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
                                        ret |= eth_env_set_enetaddr_by_index("eth",
index e728470..59f6b72 100644 (file)
@@ -6,6 +6,7 @@
 
 #ifndef __FRU_H
 #define __FRU_H
+#include <net.h>
 
 struct fru_common_hdr {
        u8 version;
@@ -19,6 +20,7 @@ struct fru_common_hdr {
 };
 
 #define FRU_BOARD_MAX_LEN      32
+#define FRU_MAX_NO_OF_MAC_ADDR 4
 
 struct __packed fru_board_info_header {
        u8 ver;
@@ -56,9 +58,24 @@ struct fru_board_data {
        u8 uuid[FRU_BOARD_MAX_LEN];
 };
 
+struct fru_multirec_hdr {
+       u8 rec_type;
+       u8 type;
+       u8 len;
+       u8 csum;
+       u8 hdr_csum;
+};
+
+struct fru_multirec_mac {
+       u8 xlnx_iana_id[3];
+       u8 ver;
+       u8 macid[FRU_MAX_NO_OF_MAC_ADDR][ETH_ALEN];
+};
+
 struct fru_table {
        struct fru_common_hdr hdr;
        struct fru_board_data brd;
+       struct fru_multirec_mac mac;
        bool captured;
 };
 
@@ -69,6 +86,10 @@ struct fru_table {
 #define FRU_LANG_CODE_ENGLISH          0
 #define FRU_LANG_CODE_ENGLISH_1                25
 #define FRU_TYPELEN_EOF                        0xC1
+#define FRU_MULTIREC_TYPE_OEM          0xD2
+#define FRU_MULTIREC_MAC_OFFSET                4
+#define FRU_LAST_REC                   BIT(7)
+#define FRU_DUT_MACID                  0x31
 
 /* This should be minimum of fields */
 #define FRU_BOARD_AREA_TOTAL_FIELDS    5
index 6ed63bb..49846ae 100644 (file)
@@ -9,6 +9,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <malloc.h>
+#include <net.h>
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
 
@@ -39,12 +40,20 @@ static int fru_check_language(u8 code)
 u8 fru_checksum(u8 *addr, u8 len)
 {
        u8 checksum = 0;
+       u8 cnt = len;
 
        while (len--) {
+               if (*addr == 0)
+                       cnt--;
+
                checksum += *addr;
                addr++;
        }
 
+       /* If all data bytes are 0's return error */
+       if (!cnt)
+               return EINVAL;
+
        return checksum;
 }
 
@@ -210,10 +219,43 @@ static int fru_parse_board(unsigned long addr)
        return 0;
 }
 
+static int fru_parse_multirec(unsigned long addr)
+{
+       struct fru_multirec_hdr mrc;
+       u8 checksum = 0;
+       u8 hdr_len = sizeof(struct fru_multirec_hdr);
+       int mac_len = 0;
+
+       debug("%s: multirec addr %lx\n", __func__, addr);
+
+       do {
+               memcpy(&mrc.rec_type, (void *)addr, hdr_len);
+
+               checksum = fru_checksum((u8 *)addr, hdr_len);
+               if (checksum) {
+                       debug("%s header CRC error\n", __func__);
+                       return -EINVAL;
+               }
+
+               if (mrc.rec_type == FRU_MULTIREC_TYPE_OEM) {
+                       struct fru_multirec_mac *mac = (void *)addr + hdr_len;
+
+                       if (mac->ver == FRU_DUT_MACID) {
+                               mac_len = mrc.len - FRU_MULTIREC_MAC_OFFSET;
+                               memcpy(&fru_data.mac.macid, mac->macid, mac_len);
+                       }
+               }
+               addr += mrc.len + hdr_len;
+       } while (!(mrc.type & FRU_LAST_REC));
+
+       return 0;
+}
+
 int fru_capture(unsigned long addr)
 {
        struct fru_common_hdr *hdr;
        u8 checksum = 0;
+       unsigned long multirec_addr = addr;
 
        checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr));
        if (checksum) {
@@ -222,7 +264,7 @@ int fru_capture(unsigned long addr)
        }
 
        hdr = (struct fru_common_hdr *)addr;
-
+       memset((void *)&fru_data, 0, sizeof(fru_data));
        memcpy((void *)&fru_data, (void *)hdr,
               sizeof(struct fru_common_hdr));
 
@@ -235,6 +277,11 @@ int fru_capture(unsigned long addr)
 
        env_set_hex("fru_addr", addr);
 
+       if (hdr->off_multirec) {
+               multirec_addr += fru_cal_area_len(hdr->off_multirec);
+               fru_parse_multirec(multirec_addr);
+       }
+
        return 0;
 }
 
index a427ac9..f58ecd1 100644 (file)
@@ -14,6 +14,8 @@
 #include <config.h>
 #include <env.h>
 #include <init.h>
+#include <image.h>
+#include <lmb.h>
 #include <log.h>
 #include <asm/global_data.h>
 #include <dm/lists.h>
@@ -36,6 +38,25 @@ int dram_init(void)
        return 0;
 };
 
+ulong board_get_usable_ram_top(ulong total_size)
+{
+       phys_size_t size;
+       phys_addr_t reg;
+       struct lmb lmb;
+
+       /* found enough not-reserved memory to relocated U-Boot */
+       lmb_init(&lmb);
+       lmb_add(&lmb, gd->ram_base, gd->ram_size);
+       boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
+       size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
+       reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
+
+       if (!reg)
+               reg = gd->ram_top - size;
+
+       return reg + size;
+}
+
 int board_late_init(void)
 {
        ulong max_size;
diff --git a/board/xilinx/zynqmp/zynqmp-zcu106-rev1.0/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu106-rev1.0/psu_init_gpl.c
new file mode 100644 (file)
index 0000000..2ac4e03
--- /dev/null
@@ -0,0 +1,842 @@
+// 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 unsigned long psu_pll_init_data(void)
+{
+       psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4E2C62U);
+       psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00014600U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+       mask_poll(0xFF5E0040, 0x00000002U);
+       psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000200U);
+       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(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(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+       psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014000U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000002U);
+       psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000200U);
+       psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C82U);
+       psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00015900U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+       mask_poll(0xFD1A0044, 0x00000004U);
+       psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+       psu_mask_write(0xFD1A0040, 0x8000FFFFU, 0x80008E69U);
+
+       return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+       psu_mask_write(0xFF5E005C, 0x063F3F07U, 0x06010C00U);
+       psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+       psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+       psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010500U);
+       psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010502U);
+       psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+       psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0078, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0088, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+       psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+       psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000602U);
+       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, 0x01010A02U);
+       psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010F00U);
+       psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010A02U);
+       psu_mask_write(0xFF5E00CC, 0x013F3F07U, 0x01010A02U);
+       psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011D02U);
+       psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+       psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
+       psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0070, 0x013F3F07U, 0x01010203U);
+       psu_mask_write(0xFD1A0074, 0x013F3F07U, 0x01013C00U);
+       psu_mask_write(0xFD1A007C, 0x013F3F07U, 0x01011303U);
+       psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+       psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+       psu_mask_write(0xFD1A0084, 0x07003F07U, 0x07000100U);
+       psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+       psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000302U);
+       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, 0x81040010U);
+       psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+       psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
+       psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+       psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+       psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408410U);
+       psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+       psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+       psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+       psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x008180BBU);
+       psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+       psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+       psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+       psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0040051FU);
+       psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020106U);
+       psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00020000U);
+       psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002305U);
+       psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x07300301U);
+       psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00200200U);
+       psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U);
+       psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x08190000U);
+       psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+       psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+       psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x11102412U);
+       psu_mask_write(0xFD070104, 0x001F1F7FU, 0x0004041AU);
+       psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0708060EU);
+       psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x0050400CU);
+       psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08030409U);
+       psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+       psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+       psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+       psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040D07U);
+       psu_mask_write(0xFD070124, 0x40070F3FU, 0x0002030BU);
+       psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x1207010EU);
+       psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+       psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x81000040U);
+       psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x020196DCU);
+       psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B820BU);
+       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, 0x00000000U);
+       psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000909U);
+       psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U);
+       psu_mask_write(0XFD070200, 0x0000001FU, 0x0000001FU);
+       psu_mask_write(0XFD070204, 0x001F1F1FU, 0x001F0909U);
+       psu_mask_write(0XFD070208, 0x0F0F0F0FU, 0x01010100U);
+       psu_mask_write(0XFD07020C, 0x0F0F0F0FU, 0x01010101U);
+       psu_mask_write(0XFD070210, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0XFD070214, 0x0F0F0F0FU, 0x070F0707U);
+       psu_mask_write(0XFD070218, 0x8F0F0F0FU, 0x07070707U);
+       psu_mask_write(0XFD07021C, 0x00000F0FU, 0x00000F0FU);
+       psu_mask_write(0XFD070220, 0x00001F1FU, 0x00001F01U);
+       psu_mask_write(0XFD070224, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0XFD070228, 0x0F0F0F0FU, 0x07070707U);
+       psu_mask_write(0XFD07022C, 0x0000000FU, 0x00000007U);
+       psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000600U);
+       psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+       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, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+       psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F10010U);
+       psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+       psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+       psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x42C21590U);
+       psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xD05112C0U);
+       psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
+       psu_mask_write(0XFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E5U);
+       psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040CU);
+       psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x07240F08U);
+       psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200008U);
+       psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0300U);
+       psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x83000800U);
+       psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01762B07U);
+       psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00330F08U);
+       psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000E0FU);
+       psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+       psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+       psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000300U);
+       psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000630U);
+       psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000301U);
+       psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000020U);
+       psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000200U);
+       psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x000006C0U);
+       psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000819U);
+       psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+       psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+       psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+       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, 0x12341000U);
+       psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+       psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+       psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+       psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+       psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0CEU);
+       psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF9032019U);
+       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, 0x008AAA58U);
+       psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000079DDU);
+       psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+       psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+       psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x00087BDBU);
+       psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09095555U);
+       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, 0x0E00B03CU);
+       psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09095555U);
+       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, 0x0E00B004U);
+       psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09095555U);
+       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, 0x0E00B004U);
+       psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0XFD080B08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0XFD080C08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0XFD080D08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+       psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+       psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+       psu_mask_write(0XFD080E08, 0xFFFFFFFFU, 0x00000000U);
+       psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+       psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B03CU);
+       psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09095555U);
+       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, 0x0C00B000U);
+       psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09095555U);
+       psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+       psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+       psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+       psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70800000U);
+       psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+       psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+       psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
+       psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+       psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
+       psu_mask_write(0xFD0817C4, 0xFFFFFFFFU, 0x01100000U);
+       psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+       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, 0x00000002U);
+       psu_mask_write(0xFF180020, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180024, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180028, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180030, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180038, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180040, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180044, 0x000000FEU, 0x00000040U);
+       psu_mask_write(0xFF180048, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF18004C, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180050, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180054, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180060, 0x000000FEU, 0x00000020U);
+       psu_mask_write(0xFF180064, 0x000000FEU, 0x00000020U);
+       psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000018U);
+       psu_mask_write(0xFF180070, 0x000000FEU, 0x00000018U);
+       psu_mask_write(0xFF180074, 0x000000FEU, 0x00000018U);
+       psu_mask_write(0xFF180078, 0x000000FEU, 0x00000018U);
+       psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF180080, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180084, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180088, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF18008C, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180090, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180094, 0x000000FEU, 0x00000008U);
+       psu_mask_write(0xFF180098, 0x000000FEU, 0x00000000U);
+       psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+       psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+       psu_mask_write(0xFF180100, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180104, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180108, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180110, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180114, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180118, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180120, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
+       psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+       psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x52240000U);
+       psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B03000U);
+       psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
+       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_init_data(void)
+{
+       psu_mask_write(0xFF5E0238, 0x00100000U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF180390, 0x00000004U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000000U);
+       psu_mask_write(0xFD1A0100, 0x0001807EU, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+       psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF180320, 0x33800000U, 0x02800000U);
+       psu_mask_write(0xFF18031C, 0x7F800000U, 0x63800000U);
+       psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000100U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
+       psu_mask_write(0xFF5E0238, 0x00000006U, 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, 0x05F5E100U);
+       psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+       psu_mask_write(0xFD410000, 0x0000001FU, 0x00000009U);
+       psu_mask_write(0xFD410004, 0x0000001FU, 0x00000009U);
+       psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+       psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000FU);
+       psu_mask_write(0xFD402860, 0x00000088U, 0x00000008U);
+       psu_mask_write(0xFD402864, 0x00000088U, 0x00000008U);
+       psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40286C, 0x00000082U, 0x00000002U);
+       psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+       psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+       psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD40E368, 0x000000FFU, 0x000000E0U);
+       psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD402368, 0x000000FFU, 0x00000058U);
+       psu_mask_write(0xFD40236C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD406368, 0x000000FFU, 0x00000058U);
+       psu_mask_write(0xFD40636C, 0x00000007U, 0x00000003U);
+       psu_mask_write(0xFD402370, 0x000000FFU, 0x0000007CU);
+       psu_mask_write(0xFD402374, 0x000000FFU, 0x00000033U);
+       psu_mask_write(0xFD402378, 0x000000FFU, 0x00000002U);
+       psu_mask_write(0xFD40237C, 0x00000033U, 0x00000030U);
+       psu_mask_write(0xFD406370, 0x000000FFU, 0x0000007CU);
+       psu_mask_write(0xFD406374, 0x000000FFU, 0x00000033U);
+       psu_mask_write(0xFD406378, 0x000000FFU, 0x00000002U);
+       psu_mask_write(0xFD40637C, 0x00000033U, 0x00000030U);
+       psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+       psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+       psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+       psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+       psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000C9U);
+       psu_mask_write(0xFD40E374, 0x000000FFU, 0x000000D2U);
+       psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40E37C, 0x000000B3U, 0x000000B0U);
+       psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD40E360, 0x00000040U, 0x00000040U);
+       psu_mask_write(0xFD40D06C, 0x0000000FU, 0x0000000FU);
+       psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x0000000BU);
+       psu_mask_write(0xFD40CB00, 0x000000F0U, 0x000000F0U);
+       psu_mask_write(0xFD4090CC, 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, 0x0000001AU);
+       psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+       psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+       psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+       psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+       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, 0x0000007DU);
+       psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000001U);
+       psu_mask_write(0xFD40D924, 0x000000FFU, 0x0000009CU);
+       psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000039U);
+       psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+       psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000007DU);
+       psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000064U);
+       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, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD405978, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD409978, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD40D978, 0x00000080U, 0x00000080U);
+       psu_mask_write(0xFD410010, 0x00000077U, 0x00000044U);
+       psu_mask_write(0xFD410014, 0x00000077U, 0x00000023U);
+       psu_mask_write(0xFD400CB4, 0x00000037U, 0x00000037U);
+       psu_mask_write(0xFD404CB4, 0x00000037U, 0x00000037U);
+       psu_mask_write(0xFD4001D8, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD4041D8, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40C1D8, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFD40DC14, 0x000000FFU, 0x000000E6U);
+       psu_mask_write(0xFD40DC40, 0x0000001FU, 0x0000000CU);
+       psu_mask_write(0xFD40D94C, 0x00000020U, 0x00000020U);
+       psu_mask_write(0xFD40D950, 0x00000007U, 0x00000006U);
+       psu_mask_write(0xFD404CC0, 0x0000001FU, 0x00000000U);
+       psu_mask_write(0xFD400CC0, 0x0000001FU, 0x00000000U);
+       psu_mask_write(0xFD404048, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD400048, 0x000000FFU, 0x00000000U);
+       psu_mask_write(0xFD40C048, 0x000000FFU, 0x00000001U);
+
+       return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+       psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+       psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+       psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+       psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+       psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000003U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFD1A0100, 0x00010000U, 0x00000000U);
+       psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000000U);
+       psu_mask_write(0xFD4A0238, 0x0000000FU, 0x00000000U);
+       psu_mask_write(0xFE20C200, 0x00003FFFU, 0x00002457U);
+       psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+       psu_mask_write(0xFE20C11C, 0x00000400U, 0x00000400U);
+       psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+       mask_poll(0xFD4063E4, 0x00000010U);
+       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, 0x00000540U, 0x00000540U);
+       psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000008U);
+       psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+       psu_mask_write(0xFD4A0238, 0x0000000FU, 0x0000000AU);
+       psu_mask_write(0xFD4A0200, 0x00000002U, 0x00000002U);
+       psu_mask_write(0xFD1A0100, 0x00010000U, 0x00010000U);
+
+       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_locked &= (Xil_In32(0xFD080BE0) & 0x10000) >> 16;
+               pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000) >> 16;
+               pll_retry--;
+       }
+       Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+       Xil_Out32(0xFD080004U, 0x00040063U);
+
+       while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+               ;
+       prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+       while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+               ;
+
+       Xil_Out32(0xFD0701B0U, 0x00000001U);
+       Xil_Out32(0xFD070320U, 0x00000001U);
+       while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+               ;
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+       Xil_Out32(0xFD080004, 0x0004FE01);
+       regval = Xil_In32(0xFD080030);
+       while (regval != 0x80000FFF)
+               regval = Xil_In32(0xFD080030);
+
+       Xil_Out32(0xFD080200U, 0x100091C7U);
+       Xil_Out32(0xFD080018U, 0x00F01EF2U);
+       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);
+
+       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);
+       Xil_Out32(0xFD080018U, 0x00F12302U);
+
+       Xil_Out32(0xFD080004, 0x0000C001);
+       regval = Xil_In32(0xFD080030);
+       while ((regval & 0x80000C01) != 0x80000C01)
+               regval = Xil_In32(0xFD080030);
+
+       Xil_Out32(0xFD070180U, 0x01000040U);
+       Xil_Out32(0xFD070060U, 0x00000000U);
+       prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+       return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+       int maskstatus = 1;
+       unsigned int tmp_0_1, tmp_0_2, tmp_0_3, tmp_0_2_mod;
+
+       Xil_Out32(0xFD40EC4C, 0x00000020);
+
+       Xil_Out32(0xFD410010, 0x00000001);
+
+       maskstatus = mask_poll(0xFD40EF14, 0x2);
+
+       if (maskstatus == 0) {
+               xil_printf("SERDES initialization timed out\n\r");
+               return maskstatus;
+       }
+
+       tmp_0_1 = mask_read(0xFD400B0C, 0x3F);
+
+       tmp_0_2 = tmp_0_1 & (0x7);
+       tmp_0_3 = tmp_0_1 & (0x38);
+
+       Xil_Out32(0xFD410010, 0x00000000);
+       Xil_Out32(0xFD410014, 0x00000000);
+
+       tmp_0_2_mod = (tmp_0_2 << 1) | (0x1);
+       tmp_0_2_mod = (tmp_0_2_mod << 4);
+
+       tmp_0_3 = tmp_0_3 >> 3;
+       Xil_Out32(0xFD40EC4C, tmp_0_3);
+
+       Xil_Out32(0xFD40EC48, tmp_0_2_mod);
+       return maskstatus;
+}
+
+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 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)
+{
+       unsigned int regvalue;
+       unsigned int tmp_regval;
+
+       Xil_Out32(((0xFF5E0000U) + 0x00000230U), 0x00000000);
+       Xil_Out32(((0xFF5E0000U) + 0x00000234U), 0x00000000);
+       Xil_Out32(((0xFF5E0000U) + 0x00000238U), 0x00000000);
+
+       regvalue = Xil_In32(((0xFF5E0000U) + 0x0000023CU));
+       regvalue &= 0x7;
+       Xil_Out32(((0xFF5E0000U) + 0x0000023CU), regvalue);
+
+       Xil_Out32(((0xFD1A0000U) + 0x00000100U), 0x00000000);
+
+       tmp_regval = Xil_In32(0xFD690040);
+       tmp_regval &= ~0x00000001;
+       Xil_Out32(0xFD690040, tmp_regval);
+
+       tmp_regval = Xil_In32(0xFD690030);
+       tmp_regval &= ~0x00000001;
+       Xil_Out32(0xFD690030, tmp_regval);
+}
+
+int psu_init(void)
+{
+       int status = 1;
+
+       status &= psu_mio_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();
+
+       if (status == 0)
+               return 1;
+       return 0;
+}
index 70b3c81..bc20909 100644 (file)
@@ -399,9 +399,6 @@ static void print_secure_boot(void)
               status & ZYNQMP_CSU_STATUS_ENCRYPTED ? "" : "not ");
 }
 
-#define PS_SYSMON_ANALOG_BUS_VAL       0x3210
-#define PS_SYSMON_ANALOG_BUS_REG       0xFFA50914
-
 int board_init(void)
 {
 #if defined(CONFIG_ZYNQMP_FIRMWARE)
@@ -429,9 +426,6 @@ int board_init(void)
 
        printf("EL Level:\tEL%d\n", current_el());
 
-       /* Bug in ROM sets wrong value in this register */
-       writel(PS_SYSMON_ANALOG_BUS_VAL, PS_SYSMON_ANALOG_BUS_REG);
-
 #if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
        zynqmppl.name = zynqmp_get_silicon_idcode_name();
        printf("Chip ID:\t%s\n", zynqmppl.name);
index f12bad7..2777332 100644 (file)
@@ -84,7 +84,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-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-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
index 709bea2..8042847 100644 (file)
@@ -898,6 +898,42 @@ int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
        return -ENOENT;
 }
 
+int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
+{
+       const char *list, *end;
+       int len;
+
+       list = ofnode_get_property(node, "compatible", &len);
+
+       if (!list)
+               return -ENOENT;
+
+       end = list + len;
+       while (list < end) {
+               len = strlen(list);
+
+               if (len >= strlen("ethernet-phy-idVVVV,DDDD")) {
+                       char *s = strstr(list, "ethernet-phy-id");
+
+                       /*
+                        * check if the string is something like
+                        * ethernet-phy-idVVVV,DDDD
+                        */
+                       if (s && s[19] == '.') {
+                               s += strlen("ethernet-phy-id");
+                               *vendor = simple_strtol(s, NULL, 16);
+                               s += 5;
+                               *device = simple_strtol(s, NULL, 16);
+
+                               return 0;
+                       }
+               }
+               list += (len + 1);
+       }
+
+       return -ENOENT;
+}
+
 int ofnode_read_addr_cells(ofnode node)
 {
        if (ofnode_is_np(node)) {
index 9cacea8..0af5460 100644 (file)
@@ -68,6 +68,13 @@ config APBH_DMA
        help
          Enable APBH DMA driver.
 
+config XILINX_DPDMA
+       bool "Enable ZynqMP Display Port DMA driver"
+       depends on DMA && ZYNQMP_POWER_DOMAIN
+       help
+         Enable support for Xilinx ZynqMP Display DMA driver. Currently
+         this file is used as placeholder for driver. The main reason is
+         to record compatible string and calling power domain driver.
 
 if APBH_DMA
 config APBH_DMA_BURST
index afab324..a75572f 100644 (file)
@@ -13,5 +13,6 @@ obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
 obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
+obj-$(CONFIG_XILINX_DPDMA) += xilinx_dpdma.o
 
 obj-y += ti/
diff --git a/drivers/dma/xilinx_dpdma.c b/drivers/dma/xilinx_dpdma.c
new file mode 100644 (file)
index 0000000..d4ee21d
--- /dev/null
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Xilinx Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <dma.h>
+#include <dma-uclass.h>
+#include <errno.h>
+#include <dm/device_compat.h>
+
+/**
+ * struct zynqmp_dpdma_priv - Private structure
+ * @dev: Device uclass for video_ops
+ */
+struct zynqmp_dpdma_priv {
+       struct udevice *dev;
+};
+
+static int zynqmp_dpdma_probe(struct udevice *dev)
+{
+       /* Only placeholder for power domain driver */
+       return 0;
+}
+
+static const struct dma_ops zynqmp_dpdma_ops = {
+};
+
+static const struct udevice_id zynqmp_dpdma_ids[] = {
+       { .compatible = "xlnx,zynqmp-dpdma" },
+       { }
+};
+
+U_BOOT_DRIVER(zynqmp_dpdma) = {
+       .name = "zynqmp_dpdma",
+       .id = UCLASS_DMA,
+       .of_match = zynqmp_dpdma_ids,
+       .ops = &zynqmp_dpdma_ops,
+       .probe = zynqmp_dpdma_probe,
+       .priv_auto = sizeof(struct zynqmp_dpdma_priv),
+};
index 8d8492d..8916c55 100644 (file)
@@ -140,6 +140,57 @@ unsigned int zynqmp_firmware_version(void)
        return pm_api_version;
 };
 
+int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
+{
+       int ret;
+
+       ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_SD_CONFIG,
+                               config, value, NULL);
+       if (ret)
+               printf("%s: node %d: set_sd_config %d failed\n",
+                      __func__, node, config);
+
+       return ret;
+}
+
+int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
+{
+       int ret;
+       u32 *bit_mask;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       /* Input arguments validation */
+       if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
+               return -EINVAL;
+
+       /* Check feature check API version */
+       ret = xilinx_pm_request(PM_FEATURE_CHECK, PM_FEATURE_CHECK, 0, 0, 0,
+                               ret_payload);
+       if (ret)
+               return ret;
+
+       /* Check if feature check version 2 is supported or not */
+       if ((ret_payload[1] & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
+               /*
+                * Call feature check for IOCTL/QUERY API to get IOCTL ID or
+                * QUERY ID feature status.
+                */
+
+               ret = xilinx_pm_request(PM_FEATURE_CHECK, api_id, 0, 0, 0,
+                                       ret_payload);
+               if (ret)
+                       return ret;
+
+               bit_mask = &ret_payload[2];
+               if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0)
+                       return -EOPNOTSUPP;
+       } else {
+               return -ENODATA;
+       }
+
+       return 0;
+}
+
 /**
  * Send a configuration object to the PMU firmware.
  *
index 12972cd..c3f1109 100644 (file)
@@ -558,4 +558,12 @@ config SL28CPLD_GPIO
        help
          Support GPIO access on Kontron sl28cpld board management controllers.
 
+config SLG7XL45106_I2C_GPO
+       bool "slg7xl45106 i2c gpo expander"
+       depends on DM_GPIO
+       help
+          Support for slg7xl45106 i2c gpo expander. It is an i2c based
+          8-bit gpo expander, all gpo lines are controlled by writing
+          value into data register.
+
 endif
index 44f0153..b39dde1 100644 (file)
@@ -73,3 +73,4 @@ obj-$(CONFIG_NOMADIK_GPIO)    += nmk_gpio.o
 obj-$(CONFIG_MAX7320_GPIO)     += max7320_gpio.o
 obj-$(CONFIG_SL28CPLD_GPIO)    += sl28cpld-gpio.o
 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN)      += zynqmp_gpio_modepin.o
+obj-$(CONFIG_SLG7XL45106_I2C_GPO)      += gpio_slg7xl45106.o
diff --git a/drivers/gpio/gpio_slg7xl45106.c b/drivers/gpio/gpio_slg7xl45106.c
new file mode 100644 (file)
index 0000000..2cbf748
--- /dev/null
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * slg7xl45106_i2c_gpo driver
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm/arch/hardware.h>
+
+#define SLG7XL45106_REG                0xdb
+
+static int slg7xl45106_i2c_gpo_direction_input(struct udevice *dev,
+                                              unsigned int offset)
+{
+       return 0;
+}
+
+static int slg7xl45106_i2c_gpo_xlate(struct udevice *dev,
+                                    struct gpio_desc *desc,
+                                    struct ofnode_phandle_args *args)
+{
+       desc->offset = (unsigned int)args->args[0];
+
+       return 0;
+}
+
+static int slg7xl45106_i2c_gpo_set_value(struct udevice *dev,
+                                        unsigned int offset, int value)
+{
+       int ret;
+       u8 val;
+
+       ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
+       if (ret)
+               return ret;
+
+       if (value)
+               val |= BIT(offset);
+       else
+               val &= ~BIT(offset);
+
+       return dm_i2c_write(dev, SLG7XL45106_REG, &val, 1);
+}
+
+static int slg7xl45106_i2c_gpo_direction_output(struct udevice *dev,
+                                               unsigned int offset, int value)
+{
+       return slg7xl45106_i2c_gpo_set_value(dev, offset, value);
+}
+
+static int slg7xl45106_i2c_gpo_get_value(struct udevice *dev,
+                                        unsigned int offset)
+{
+       int ret;
+       u8 val;
+
+       ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
+       if (ret)
+               return ret;
+
+       return !!(val & BIT(offset));
+}
+
+static int slg7xl45106_i2c_gpo_get_function(struct udevice *dev,
+                                           unsigned int offset)
+{
+       return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops slg7xl45106_i2c_gpo_ops = {
+       .direction_input = slg7xl45106_i2c_gpo_direction_input,
+       .direction_output = slg7xl45106_i2c_gpo_direction_output,
+       .get_value = slg7xl45106_i2c_gpo_get_value,
+       .set_value = slg7xl45106_i2c_gpo_set_value,
+       .get_function = slg7xl45106_i2c_gpo_get_function,
+       .xlate = slg7xl45106_i2c_gpo_xlate,
+};
+
+static int slg7xl45106_i2c_gpo_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+       const void *label_ptr;
+
+       label_ptr = dev_read_prop(dev, "label", NULL);
+       if (label_ptr) {
+               uc_priv->bank_name = strdup(label_ptr);
+               if (!uc_priv->bank_name)
+                       return -ENOMEM;
+       } else {
+               uc_priv->bank_name = dev->name;
+       }
+
+       uc_priv->gpio_count = 8;
+
+       return 0;
+}
+
+static const struct udevice_id slg7xl45106_i2c_gpo_ids[] = {
+       { .compatible = "dlg,slg7xl45106",},
+       { }
+};
+
+U_BOOT_DRIVER(slg7xl45106_i2c_gpo) = {
+       .name = "slg7xl45106_i2c_gpo",
+       .id = UCLASS_GPIO,
+       .ops = &slg7xl45106_i2c_gpo_ops,
+       .of_match = slg7xl45106_i2c_gpo_ids,
+       .probe = slg7xl45106_i2c_gpo_probe,
+};
index a650dd6..0da9f6f 100644 (file)
@@ -251,24 +251,32 @@ static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
        u8 *cur_data = data;
        struct cdns_i2c_regs *regs = i2c_bus->regs;
        u32 ret;
+       bool start = 1;
 
        /* Set the controller in Master transmit mode and clear FIFO */
        setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO);
        clrbits_le32(&regs->control, CDNS_I2C_CONTROL_RW);
 
-       /* Check message size against FIFO depth, and set hold bus bit
-        * if it is greater than FIFO depth
+       /*
+        * For sequential data load hold the bus.
         */
-       if (len > CDNS_I2C_FIFO_DEPTH)
+       if (len > 1)
                setbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
 
        /* Clear the interrupts in status register */
        writel(CDNS_I2C_INTERRUPTS_MASK, &regs->interrupt_status);
 
-       writel(addr, &regs->address);
+       /* In case of Probe (i.e no data), start the transfer */
+       if (!len)
+               writel(addr, &regs->address);
 
        while (len-- && !is_arbitration_lost(regs)) {
                writel(*(cur_data++), &regs->data);
+               /* Trigger write only after loading data */
+               if (start) {
+                       writel(addr, &regs->address);
+                       start = 0;
+               }
                if (len && readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
                        ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
                                            CDNS_I2C_INTERRUPT_ARBLOST);
@@ -375,7 +383,6 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
                                curr_recv_count = recv_count;
                        }
                } else if (recv_count && !hold_quirk && !curr_recv_count) {
-                       writel(addr, &regs->address);
                        if (recv_count > CDNS_I2C_TRANSFER_SIZE) {
                                writel(CDNS_I2C_TRANSFER_SIZE,
                                       &regs->transfer_size);
@@ -384,6 +391,7 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
                                writel(recv_count, &regs->transfer_size);
                                curr_recv_count = recv_count;
                        }
+                       writel(addr, &regs->address);
                }
        }
 
index 5cea4c6..d96f5d5 100644 (file)
 #include <linux/delay.h>
 #include "mmc_private.h"
 #include <log.h>
+#include <reset.h>
 #include <dm/device_compat.h>
 #include <linux/err.h>
 #include <linux/libfdt.h>
+#include <asm/types.h>
+#include <linux/math64.h>
 #include <asm/cache.h>
 #include <malloc.h>
 #include <sdhci.h>
@@ -61,6 +64,7 @@ struct arasan_sdhci_priv {
        u8 deviceid;
        u8 bank;
        u8 no_1p8;
+       struct reset_ctl_bulk resets;
 };
 
 /* For Versal platforms zynqmp_mmio_write() won't be available */
@@ -243,7 +247,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
        char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
        u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 
-       debug("%s\n", __func__);
+       dev_dbg(mmc->dev, "%s\n", __func__);
 
        host = priv->host;
 
@@ -703,6 +707,87 @@ static const struct sdhci_ops arasan_ops = {
 };
 #endif
 
+#if defined(CONFIG_ARCH_ZYNQMP)
+static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
+                                          struct udevice *dev)
+{
+       int ret;
+       u32 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
+       struct clk clk;
+       unsigned long clock, mhz;
+
+       ret = xilinx_pm_request(PM_REQUEST_NODE, node_id, ZYNQMP_PM_CAPABILITY_ACCESS,
+                               ZYNQMP_PM_MAX_QOS, ZYNQMP_PM_REQUEST_ACK_NO, NULL);
+       if (ret) {
+               dev_err(dev, "Request node failed for %d\n", node_id);
+               return ret;
+       }
+
+       ret = reset_get_bulk(dev, &priv->resets);
+       if (ret == -ENOTSUPP || ret == -ENOENT) {
+               dev_err(dev, "Reset not found\n");
+               return 0;
+       } else if (ret) {
+               dev_err(dev, "Reset failed\n");
+               return ret;
+       }
+
+       ret = reset_assert_bulk(&priv->resets);
+       if (ret) {
+               dev_err(dev, "Reset assert failed\n");
+               return ret;
+       }
+
+       ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_FIXED, 0);
+       if (ret) {
+               dev_err(dev, "SD_CONFIG_FIXED failed\n");
+               return ret;
+       }
+
+       ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_EMMC_SEL,
+                                     dev_read_bool(dev, "non-removable"));
+       if (ret) {
+               dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
+               return ret;
+       }
+
+       ret = clk_get_by_index(dev, 0, &clk);
+       if (ret < 0) {
+               dev_err(dev, "failed to get clock\n");
+               return ret;
+       }
+
+       clock = clk_get_rate(&clk);
+       if (IS_ERR_VALUE(clock)) {
+               dev_err(dev, "failed to get rate\n");
+               return clock;
+       }
+
+       mhz = DIV64_U64_ROUND_UP(clock, 1000000);
+
+       ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz);
+       if (ret) {
+               dev_err(dev, "SD_CONFIG_BASECLK failed\n");
+               return ret;
+       }
+
+       ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_8BIT,
+                                     (dev_read_u32_default(dev, "bus-width", 1) == 8));
+       if (ret) {
+               dev_err(dev, "SD_CONFIG_8BIT failed\n");
+               return ret;
+       }
+
+       ret = reset_deassert_bulk(&priv->resets);
+       if (ret) {
+               dev_err(dev, "Reset release failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
        struct arasan_sdhci_plat *plat = dev_get_plat(dev);
@@ -715,6 +800,18 @@ static int arasan_sdhci_probe(struct udevice *dev)
 
        host = priv->host;
 
+#if defined(CONFIG_ARCH_ZYNQMP)
+       if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+               ret = zynqmp_pm_is_function_supported(PM_IOCTL,
+                                                     IOCTL_SET_SD_CONFIG);
+               if (!ret) {
+                       ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
+                       if (ret)
+                               return ret;
+               }
+       }
+#endif
+
        ret = clk_get_by_index(dev, 0, &clk);
        if (ret < 0) {
                dev_err(dev, "failed to get clock\n");
@@ -727,7 +824,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
                return clock;
        }
 
-       debug("%s: CLK %ld\n", __func__, clock);
+       dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
 
        ret = clk_enable(&clk);
        if (ret) {
@@ -769,12 +866,13 @@ static int arasan_sdhci_probe(struct udevice *dev)
         * causing sd card timeout error. Workaround this by adding a wait for
         * 1000msec till the card detect state gets stable.
         */
-       if (IS_ENABLED(CONFIG_ARCH_VERSAL)) {
-               u32 timeout = 1000;
+       if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
+               u32 timeout = 1000000;
 
                while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
-                        SDHCI_CARD_STATE_STABLE) == 0) && timeout--) {
-                       mdelay(1);
+                        SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
+                       udelay(1);
+                       timeout--;
                }
                if (!timeout) {
                        dev_err(dev, "Sdhci card detect state not stable\n");
index d792528..10e9cd1 100644 (file)
@@ -1086,10 +1086,13 @@ static int zynq_nand_probe(struct udevice *dev)
        int is_16bit_bw;
 
        smc->reg = (struct zynq_nand_smc_regs *)dev_read_addr(dev);
-       of_nand = dev_read_subnode(dev, "flash@e1000000");
+       of_nand = dev_read_subnode(dev, "nand-controller@0,0");
        if (!ofnode_valid(of_nand)) {
-               printf("Failed to find nand node in dt\n");
-               return -ENODEV;
+               of_nand = dev_read_subnode(dev, "flash@e1000000");
+               if (!ofnode_valid(of_nand)) {
+                       printf("Failed to find nand node in dt\n");
+                       return -ENODEV;
+               }
        }
 
        if (!ofnode_is_available(of_nand)) {
index 4f8d33c..74339a2 100644 (file)
@@ -307,6 +307,14 @@ config PHY_XILINX_GMII2RGMII
          as bridge between MAC connected over GMII and external phy that
          is connected over RGMII interface.
 
+config PHY_ETHERNET_ID
+       bool "Read ethernet PHY id"
+       depends on DM_GPIO
+       default y if ZYNQ_GEM
+       help
+         Enable this config to read ethernet phy id from the phy node of DT
+         and create a phy device using id.
+
 config PHY_FIXED
        bool "Fixed-Link PHY"
        depends on DM_ETH
index 77f7f60..b28440b 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o
 obj-$(CONFIG_PHY_TI_DP83869) += dp83869.o
 obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
 obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+obj-$(CONFIG_PHY_ETHERNET_ID) += ethernet_id.o
 obj-$(CONFIG_PHY_VITESSE) += vitesse.o
 obj-$(CONFIG_PHY_MSCC) += mscc.o
 obj-$(CONFIG_PHY_FIXED) += fixed.o
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
new file mode 100644 (file)
index 0000000..5617ac3
--- /dev/null
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx ethernet phy reset driver
+ *
+ * Copyright (C) 2022 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <dm/device_compat.h>
+#include <phy.h>
+#include <linux/delay.h>
+#include <asm/gpio.h>
+
+struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
+                                     phy_interface_t interface)
+{
+       struct phy_device *phydev;
+       struct ofnode_phandle_args phandle_args;
+       struct gpio_desc gpio;
+       ofnode node;
+       u32 id, assert, deassert;
+       u16 vendor, device;
+       int ret;
+
+       if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+                                      &phandle_args))
+               return NULL;
+
+       if (!ofnode_valid(phandle_args.node))
+               return NULL;
+
+       node = phandle_args.node;
+
+       ret = ofnode_read_eth_phy_id(node, &vendor, &device);
+       if (ret) {
+               dev_err(dev, "Failed to read eth PHY id, err: %d\n", ret);
+               return NULL;
+       }
+
+       ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
+                                        GPIOD_ACTIVE_LOW);
+       if (!ret) {
+               assert = ofnode_read_u32_default(node, "reset-assert-us", 0);
+               deassert = ofnode_read_u32_default(node,
+                                                  "reset-deassert-us", 0);
+               ret = dm_gpio_set_value(&gpio, 1);
+               if (ret) {
+                       dev_err(dev, "Failed assert gpio, err: %d\n", ret);
+                       return NULL;
+               }
+
+               udelay(assert);
+
+               ret = dm_gpio_set_value(&gpio, 0);
+               if (ret) {
+                       dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
+                       return NULL;
+               }
+
+               udelay(deassert);
+       }
+
+       id =  vendor << 16 | device;
+       phydev = phy_device_create(bus, 0, id, false, interface);
+       if (phydev)
+               phydev->node = node;
+
+       return phydev;
+}
index c9fc208..fffa10f 100644 (file)
@@ -659,9 +659,9 @@ static struct phy_driver *get_phy_driver(struct phy_device *phydev,
        return generic_for_interface(interface);
 }
 
-static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
-                                           u32 phy_id, bool is_c45,
-                                           phy_interface_t interface)
+struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
+                                    u32 phy_id, bool is_c45,
+                                    phy_interface_t interface)
 {
        struct phy_device *dev;
 
@@ -1047,6 +1047,11 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
                phydev = phy_device_create(bus, 0, PHY_NCSI_ID, false, interface);
 #endif
 
+#ifdef CONFIG_PHY_ETHERNET_ID
+       if (!phydev)
+               phydev = phy_connect_phy_id(bus, dev, interface);
+#endif
+
 #ifdef CONFIG_PHY_XILINX_GMII2RGMII
        if (!phydev)
                phydev = phy_connect_gmii2rgmii(bus, dev, interface);
index 0394624..d7477d7 100644 (file)
@@ -318,6 +318,16 @@ config PINCTRL_K210
          Support pin multiplexing on the K210. The "FPIOA" can remap any
          supported function to any multifunctional IO pin. It can also perform
          basic GPIO functions, such as reading the current value of a pin.
+
+config PINCTRL_ZYNQMP
+       bool "Xilinx ZynqMP pin control driver"
+       depends on DM && PINCTRL_GENERIC && ARCH_ZYNQMP
+       default y
+       help
+         Support pin multiplexing control on Xilinx ZynqMP. The driver uses
+         Generic Pinctrl framework and is compatible with the Linux driver,
+         i.e. it uses the same device tree configuration.
+
 endif
 
 source "drivers/pinctrl/broadcom/Kconfig"
index fd736a7..ddddd13 100644 (file)
@@ -30,3 +30,4 @@ obj-$(CONFIG_PINCTRL_STI)     += pinctrl-sti.o
 obj-$(CONFIG_PINCTRL_STM32)    += pinctrl_stm32.o
 obj-$(CONFIG_$(SPL_)PINCTRL_STMFX)     += pinctrl-stmfx.o
 obj-y                          += broadcom/
+obj-$(CONFIG_PINCTRL_ZYNQMP)   += pinctrl-zynqmp.o
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
new file mode 100644 (file)
index 0000000..7c5a02d
--- /dev/null
@@ -0,0 +1,644 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx pinctrl driver for ZynqMP
+ *
+ * Author(s):   Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
+ *              Michal Simek <michal.simek@xilinx.com>
+ *
+ * Copyright (C) 2021 Xilinx, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <zynqmp_firmware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/pinctrl.h>
+#include <linux/compat.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+
+#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN       12
+#define PINCTRL_GET_PIN_GROUPS_RESP_LEN                12
+#define NUM_GROUPS_PER_RESP                    6
+#define NA_GROUP                               -1
+#define RESERVED_GROUP                         -2
+#define MAX_GROUP_PIN                          50
+#define MAX_PIN_GROUPS                         50
+#define MAX_GROUP_NAME_LEN                     32
+#define MAX_FUNC_NAME_LEN                      16
+
+#define DRIVE_STRENGTH_2MA     2
+#define DRIVE_STRENGTH_4MA     4
+#define DRIVE_STRENGTH_8MA     8
+#define DRIVE_STRENGTH_12MA    12
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+struct zynqmp_pinctrl_priv {
+       u32 npins;
+       u32 nfuncs;
+       u32 ngroups;
+       struct zynqmp_pmux_function *funcs;
+       struct zynqmp_pctrl_group *groups;
+};
+
+/**
+ * struct zynqmp_pinctrl_config - pinconfig parameters
+ * @slew:              Slew rate slow or fast
+ * @bias:              Bias enabled or disabled
+ * @pull_ctrl:         Pull control pull up or pull down
+ * @input_type:                CMOS or Schmitt
+ * @drive_strength:    Drive strength 2mA/4mA/8mA/12mA
+ * @volt_sts:          Voltage status 1.8V or 3.3V
+ * @tri_state:         Tristate enabled or disabled
+ *
+ * This structure holds information about pin control config
+ * option that can be set for each pin.
+ */
+struct zynqmp_pinctrl_config {
+       u32 slew;
+       u32 bias;
+       u32 pull_ctrl;
+       u32 input_type;
+       u32 drive_strength;
+       u32 volt_sts;
+       u32 tri_state;
+};
+
+/**
+ * enum zynqmp_pin_config_param - possible pin configuration parameters
+ * @PIN_CONFIG_IOSTANDARD:     if the pin can select an IO standard,
+ *                             the argument to this parameter (on a
+ *                             custom format) tells the driver which
+ *                             alternative IO standard to use
+ * @PIN_CONFIG_SCHMITTCMOS:    this parameter (on a custom format) allows
+ *                             to select schmitt or cmos input for MIO pins
+ */
+enum zynqmp_pin_config_param {
+       PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1,
+       PIN_CONFIG_SCHMITTCMOS,
+};
+
+/**
+ * struct zynqmp_pmux_function - a pinmux function
+ * @name:      Name of the pinmux function
+ * @groups:    List of pingroups for this function
+ * @ngroups:   Number of entries in @groups
+ *
+ * This structure holds information about pin control function
+ * and function group names supporting that function.
+ */
+struct zynqmp_pmux_function {
+       char name[MAX_FUNC_NAME_LEN];
+       const char * const *groups;
+       unsigned int ngroups;
+};
+
+/**
+ * struct zynqmp_pctrl_group - Pin control group info
+ * @name:      Group name
+ * @pins:      Group pin numbers
+ * @npins:     Number of pins in group
+ */
+struct zynqmp_pctrl_group {
+       const char *name;
+       unsigned int pins[MAX_GROUP_PIN];
+       unsigned int npins;
+};
+
+static char pin_name[PINNAME_SIZE];
+
+/**
+ * zynqmp_pm_query_data() - Get query data from firmware
+ * @qid:       Value of enum pm_query_id
+ * @arg1:      Argument 1
+ * @arg2:      Argument 2
+ * @out:       Returned output value
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_query_data(enum pm_query_id qid, u32 arg1, u32 arg2, u32 *out)
+{
+       int ret;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       ret = xilinx_pm_request(PM_QUERY_DATA, qid, arg1, arg2, 0, ret_payload);
+       if (ret)
+               return ret;
+
+       *out = ret_payload[1];
+
+       return ret;
+}
+
+static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, u32 *value)
+{
+       int ret;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       /* Get config for the pin */
+       ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 0, 0, ret_payload);
+       if (ret) {
+               printf("%s failed\n", __func__);
+               return ret;
+       }
+
+       *value = ret_payload[1];
+
+       return ret;
+}
+
+static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, u32 value)
+{
+       int ret;
+
+       /* Request the pin first */
+       ret = xilinx_pm_request(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
+       if (ret) {
+               printf("%s: pin request failed\n", __func__);
+               return ret;
+       }
+
+       /* Set config for the pin */
+       ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, pin, param, value, 0, NULL);
+       if (ret) {
+               printf("%s failed\n", __func__);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups)
+{
+       int ret;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+                               fid, index, 0, ret_payload);
+       if (ret) {
+               printf("%s failed\n", __func__);
+               return ret;
+       }
+
+       memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN);
+
+       return ret;
+}
+
+static int zynqmp_pinctrl_prepare_func_groups(u32 fid,
+                                             struct zynqmp_pmux_function *func,
+                                             struct zynqmp_pctrl_group *groups)
+{
+       const char **fgroups;
+       char name[MAX_GROUP_NAME_LEN];
+       u16 resp[NUM_GROUPS_PER_RESP] = {0};
+       int ret, index, i;
+
+       fgroups = kcalloc(func->ngroups, sizeof(*fgroups), GFP_KERNEL);
+       if (!fgroups)
+               return -ENOMEM;
+
+       for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) {
+               ret = zynqmp_pinctrl_get_function_groups(fid, index, resp);
+               if (ret)
+                       return ret;
+
+               for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+                       if (resp[i] == (u16)NA_GROUP)
+                               goto done;
+                       if (resp[i] == (u16)RESERVED_GROUP)
+                               continue;
+
+                       snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
+                                func->name, index + i);
+                       fgroups[index + i] = strdup(name);
+
+                       snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
+                                func->name, index + i);
+                       groups[resp[i]].name = strdup(name);
+               }
+       }
+done:
+       func->groups = fgroups;
+
+       return ret;
+}
+
+static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups)
+{
+       int ret;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_PIN_GROUPS,
+                               pin, index, 0, ret_payload);
+       if (ret) {
+               printf("%s failed to get pin groups\n", __func__);
+               return ret;
+       }
+
+       memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN);
+
+       return ret;
+}
+
+static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group,
+                                        unsigned int pin)
+{
+       group->pins[group->npins++] = pin;
+}
+
+static int zynqmp_pinctrl_create_pin_groups(struct zynqmp_pctrl_group *groups,
+                                           unsigned int pin)
+{
+       u16 resp[NUM_GROUPS_PER_RESP] = {0};
+       int ret, i, index = 0;
+
+       do {
+               ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp);
+               if (ret)
+                       return ret;
+
+               for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+                       if (resp[i] == (u16)NA_GROUP)
+                               goto done;
+                       if (resp[i] == (u16)RESERVED_GROUP)
+                               continue;
+                       zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin);
+               }
+               index += NUM_GROUPS_PER_RESP;
+       } while (index <= MAX_PIN_GROUPS);
+
+done:
+       return ret;
+}
+
+static int zynqmp_pinctrl_probe(struct udevice *dev)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+       int ret, i;
+       u32 pin;
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+
+       /* Get number of pins first */
+       ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_PINS, 0, 0, &priv->npins);
+       if (ret) {
+               printf("%s failed to get no of pins\n", __func__);
+               return ret;
+       }
+
+       /* Get number of functions available */
+       ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_FUNCTIONS, 0, 0, &priv->nfuncs);
+       if (ret) {
+               printf("%s failed to get no of functions\n", __func__);
+               return ret;
+       }
+
+       /* Allocating structures for functions and its groups */
+       priv->funcs = kzalloc(sizeof(*priv->funcs) * priv->nfuncs, GFP_KERNEL);
+       if (!priv->funcs)
+               return -ENOMEM;
+
+       for (i = 0; i < priv->nfuncs; i++) {
+               /* Get function name for the function and fill */
+               xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_NAME,
+                                 i, 0, 0, ret_payload);
+
+               memcpy((void *)priv->funcs[i].name, ret_payload, MAX_FUNC_NAME_LEN);
+
+               /* And fill number of groups available for certain function */
+               xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+                                 i, 0, 0, ret_payload);
+
+               priv->funcs[i].ngroups = ret_payload[1];
+               priv->ngroups += priv->funcs[i].ngroups;
+       }
+
+       /* Prepare all groups */
+       priv->groups = kzalloc(sizeof(*priv->groups) * priv->ngroups,
+                              GFP_KERNEL);
+       if (!priv->groups)
+               return -ENOMEM;
+
+       for (i = 0; i < priv->nfuncs; i++) {
+               ret = zynqmp_pinctrl_prepare_func_groups(i, &priv->funcs[i],
+                                                        priv->groups);
+               if (ret) {
+                       printf("Failed to prepare_func_groups\n");
+                       return ret;
+               }
+       }
+
+       for (pin = 0; pin < priv->npins; pin++) {
+               ret = zynqmp_pinctrl_create_pin_groups(priv->groups, pin);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int zynqmp_pinctrl_get_functions_count(struct udevice *dev)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->nfuncs;
+}
+
+static const char *zynqmp_pinctrl_get_function_name(struct udevice *dev,
+                                                   unsigned int selector)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->funcs[selector].name;
+}
+
+static int zynqmp_pinmux_set(struct udevice *dev, unsigned int selector,
+                            unsigned int func_selector)
+{
+       int ret;
+
+       /* Request the pin first */
+       ret = xilinx_pm_request(PM_PINCTRL_REQUEST, selector, 0, 0, 0, NULL);
+       if (ret) {
+               printf("%s: pin request failed\n", __func__);
+               return ret;
+       }
+
+       /* Set the pin function */
+       ret = xilinx_pm_request(PM_PINCTRL_SET_FUNCTION, selector, func_selector,
+                               0, 0, NULL);
+       if (ret) {
+               printf("%s: Failed to set pinmux function\n", __func__);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int zynqmp_pinmux_group_set(struct udevice *dev, unsigned int selector,
+                                  unsigned int func_selector)
+{
+       int i;
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct zynqmp_pctrl_group *pgrp = &priv->groups[selector];
+
+       for (i = 0; i < pgrp->npins; i++)
+               zynqmp_pinmux_set(dev, pgrp->pins[i], func_selector);
+
+       return 0;
+}
+
+static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
+                             unsigned int param, unsigned int arg)
+{
+       int ret = 0;
+       unsigned int value;
+
+       switch (param) {
+       case PIN_CONFIG_SLEW_RATE:
+               param = PM_PINCTRL_CONFIG_SLEW_RATE;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               param = PM_PINCTRL_CONFIG_PULL_CTRL;
+               arg = PM_PINCTRL_BIAS_PULL_UP;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               param = PM_PINCTRL_CONFIG_PULL_CTRL;
+               arg = PM_PINCTRL_BIAS_PULL_DOWN;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_BIAS_DISABLE:
+               param = PM_PINCTRL_CONFIG_BIAS_STATUS;
+               arg = PM_PINCTRL_BIAS_DISABLE;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_SCHMITTCMOS:
+               param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+               param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+               break;
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               switch (arg) {
+               case DRIVE_STRENGTH_2MA:
+                       value = PM_PINCTRL_DRIVE_STRENGTH_2MA;
+                       break;
+               case DRIVE_STRENGTH_4MA:
+                       value = PM_PINCTRL_DRIVE_STRENGTH_4MA;
+                       break;
+               case DRIVE_STRENGTH_8MA:
+                       value = PM_PINCTRL_DRIVE_STRENGTH_8MA;
+                       break;
+               case DRIVE_STRENGTH_12MA:
+                       value = PM_PINCTRL_DRIVE_STRENGTH_12MA;
+                       break;
+               default:
+                       /* Invalid drive strength */
+                       dev_warn(dev, "Invalid drive strength for pin %d\n", pin);
+                       return -EINVAL;
+               }
+
+               param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH;
+               ret = zynqmp_pm_pinctrl_set_config(pin, param, value);
+               break;
+       case PIN_CONFIG_IOSTANDARD:
+               param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
+               ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
+               if (arg != value)
+                       dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
+                                pin);
+               break;
+       case PIN_CONFIG_POWER_SOURCE:
+               param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
+               ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
+               if (arg != value)
+                       dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
+                                pin);
+               break;
+       case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+       case PIN_CONFIG_LOW_POWER_MODE:
+               /*
+                * This cases are mentioned in dts but configurable
+                * registers are unknown. So falling through to ignore
+                * boot time warnings as of now.
+                */
+               ret = 0;
+               break;
+       default:
+               dev_warn(dev, "unsupported configuration parameter '%u'\n",
+                        param);
+               ret = -ENOTSUPP;
+               break;
+       }
+
+       return ret;
+}
+
+static int zynqmp_pinconf_group_set(struct udevice *dev,
+                                   unsigned int group_selector,
+                                   unsigned int param, unsigned int arg)
+{
+       int i;
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct zynqmp_pctrl_group *pgrp = &priv->groups[group_selector];
+
+       for (i = 0; i < pgrp->npins; i++)
+               zynqmp_pinconf_set(dev, pgrp->pins[i], param, arg);
+
+       return 0;
+}
+
+static int zynqmp_pinctrl_get_pins_count(struct udevice *dev)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->npins;
+}
+
+static const char *zynqmp_pinctrl_get_pin_name(struct udevice *dev,
+                                              unsigned int selector)
+{
+       snprintf(pin_name, PINNAME_SIZE, "MIO%d", selector);
+
+       return pin_name;
+}
+
+static int zynqmp_pinctrl_get_pin_muxing(struct udevice *dev,
+                                        unsigned int selector,
+                                        char *buf,
+                                        int size)
+{
+       struct zynqmp_pinctrl_config pinmux;
+
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SLEW_RATE,
+                                    &pinmux.slew);
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_BIAS_STATUS,
+                                    &pinmux.bias);
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_PULL_CTRL,
+                                    &pinmux.pull_ctrl);
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+                                    &pinmux.input_type);
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
+                                    &pinmux.drive_strength);
+       zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
+                                    &pinmux.volt_sts);
+
+       switch (pinmux.drive_strength) {
+       case PM_PINCTRL_DRIVE_STRENGTH_2MA:
+               pinmux.drive_strength = DRIVE_STRENGTH_2MA;
+               break;
+       case PM_PINCTRL_DRIVE_STRENGTH_4MA:
+               pinmux.drive_strength = DRIVE_STRENGTH_4MA;
+               break;
+       case PM_PINCTRL_DRIVE_STRENGTH_8MA:
+               pinmux.drive_strength = DRIVE_STRENGTH_8MA;
+               break;
+       case PM_PINCTRL_DRIVE_STRENGTH_12MA:
+               pinmux.drive_strength = DRIVE_STRENGTH_12MA;
+               break;
+       default:
+               /* Invalid drive strength */
+               dev_warn(dev, "Invalid drive strength\n");
+               return -EINVAL;
+       }
+
+       snprintf(buf, size, "slew:%s\tbias:%s\tpull:%s\tinput:%s\tdrive:%dmA\tvolt:%s",
+                pinmux.slew ? "slow" : "fast",
+                pinmux.bias ? "enabled" : "disabled",
+                pinmux.pull_ctrl ? "up" : "down",
+                pinmux.input_type ? "schmitt" : "cmos",
+                pinmux.drive_strength,
+                pinmux.volt_sts ? "1.8" : "3.3");
+
+       return 0;
+}
+
+static int zynqmp_pinctrl_get_groups_count(struct udevice *dev)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->ngroups;
+}
+
+static const char *zynqmp_pinctrl_get_group_name(struct udevice *dev,
+                                                unsigned int selector)
+{
+       struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+       return priv->groups[selector].name;
+}
+
+static const struct pinconf_param zynqmp_conf_params[] = {
+       { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
+       { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+       { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
+       { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+       { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+       { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+       { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+       { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
+       { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+       { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+       { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
+       { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
+       { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+       { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+       { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
+       { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+       { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+       { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
+       { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
+       { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
+       { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
+       { "output-high", PIN_CONFIG_OUTPUT, 1, },
+       { "output-low", PIN_CONFIG_OUTPUT, 0, },
+       { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
+       { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
+       { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
+       { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
+       /* zynqmp specific */
+       {"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18},
+       {"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, PM_PINCTRL_INPUT_TYPE_SCHMITT},
+};
+
+static struct pinctrl_ops zynqmp_pinctrl_ops = {
+       .get_pins_count = zynqmp_pinctrl_get_pins_count,
+       .get_pin_name = zynqmp_pinctrl_get_pin_name,
+       .get_pin_muxing = zynqmp_pinctrl_get_pin_muxing,
+       .set_state = pinctrl_generic_set_state,
+       .get_groups_count = zynqmp_pinctrl_get_groups_count,
+       .get_group_name = zynqmp_pinctrl_get_group_name,
+       .get_functions_count = zynqmp_pinctrl_get_functions_count,
+       .get_function_name = zynqmp_pinctrl_get_function_name,
+       .pinmux_group_set = zynqmp_pinmux_group_set,
+       .pinmux_set = zynqmp_pinmux_set,
+       .pinconf_params = zynqmp_conf_params,
+       .pinconf_group_set = zynqmp_pinconf_group_set,
+       .pinconf_set = zynqmp_pinconf_set,
+       .pinconf_num_params = ARRAY_SIZE(zynqmp_conf_params),
+};
+
+static const struct udevice_id zynqmp_pinctrl_ids[] = {
+       { .compatible = "xlnx,zynqmp-pinctrl" },
+       { }
+};
+
+U_BOOT_DRIVER(pinctrl_zynqmp) = {
+       .name = "zynqmp-pinctrl",
+       .id = UCLASS_PINCTRL,
+       .of_match = zynqmp_pinctrl_ids,
+       .priv_auto = sizeof(struct zynqmp_pinctrl_priv),
+       .ops = &zynqmp_pinctrl_ops,
+       .probe = zynqmp_pinctrl_probe,
+};
index 5383d09..6943658 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <log.h>
 #include <malloc.h>
 #include <misc.h>
 
 #include <zynqmp_firmware.h>
 
-#define NODE_ID_LOCATION       5
-
-static unsigned int xpm_configobject[] = {
-       /* HEADER */
-       2,      /* Number of remaining words in the header */
-       1,      /* Number of sections included in config object */
-       PM_CONFIG_OBJECT_TYPE_OVERLAY,  /* Type of Config object as overlay */
-       /* SLAVE SECTION */
-
-       PM_CONFIG_SLAVE_SECTION_ID,     /* Section ID */
-       1,                              /* Number of slaves */
-
-       0, /* Node ID which will be changed below */
-       PM_SLAVE_FLAG_IS_SHAREABLE,
-       PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK |
-       PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK |
-       PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK, /* IPI Mask */
-};
-
 static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
                                  const u32 qos, const enum zynqmp_pm_request_ack ack)
 {
@@ -41,12 +23,9 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
 
 static int zynqmp_power_domain_request(struct power_domain *power_domain)
 {
-       /* Record power domain id */
-       xpm_configobject[NODE_ID_LOCATION] = power_domain->id;
-
-       zynqmp_pmufw_load_config_object(xpm_configobject, sizeof(xpm_configobject));
+       dev_dbg(power_domain->dev, "Request for id: %ld\n", power_domain->id);
 
-       return 0;
+       return zynqmp_pmufw_node(power_domain->id);
 }
 
 static int zynqmp_power_domain_free(struct power_domain *power_domain)
@@ -57,6 +36,8 @@ static int zynqmp_power_domain_free(struct power_domain *power_domain)
 
 static int zynqmp_power_domain_on(struct power_domain *power_domain)
 {
+       dev_dbg(power_domain->dev, "Domain ON for id: %ld\n", power_domain->id);
+
        return zynqmp_pm_request_node(power_domain->id,
                                      ZYNQMP_PM_CAPABILITY_ACCESS,
                                      ZYNQMP_PM_MAX_QOS,
index ff8e11f..646fec7 100644 (file)
@@ -680,6 +680,14 @@ config VIDEO_SEPS525
          Enable support for the Syncoam PM-OLED display driver (RGB 160x128).
          Currently driver is supporting only SPI interface.
 
+config VIDEO_ZYNQMP_DPSUB
+       bool "Enable video support for ZynqMP Display Port"
+       depends on DM_VIDEO && ZYNQMP_POWER_DOMAIN
+       help
+         Enable support for Xilinx ZynqMP Display Port. Currently this file
+         is used as placeholder for driver. The main reason is to record
+         compatible string and calling power domain driver.
+
 source "drivers/video/nexell/Kconfig"
 
 config VIDEO
index 4038395..2530791 100644 (file)
@@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_VIDEO_VESA) += vesa.o
 obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
+obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp_dpsub.o
 
 obj-y += bridge/
 obj-y += sunxi/
diff --git a/drivers/video/zynqmp_dpsub.c b/drivers/video/zynqmp_dpsub.c
new file mode 100644 (file)
index 0000000..4ead663
--- /dev/null
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Xilinx Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <video.h>
+#include <dm/device_compat.h>
+
+#define WIDTH  640
+#define HEIGHT 480
+
+/**
+ * struct zynqmp_dpsub_priv - Private structure
+ * @dev: Device uclass for video_ops
+ */
+struct zynqmp_dpsub_priv {
+       struct udevice *dev;
+};
+
+static int zynqmp_dpsub_probe(struct udevice *dev)
+{
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct zynqmp_dpsub_priv *priv = dev_get_priv(dev);
+
+       uc_priv->bpix = VIDEO_BPP16;
+       uc_priv->xsize = WIDTH;
+       uc_priv->ysize = HEIGHT;
+       uc_priv->rot = 0;
+
+       priv->dev = dev;
+
+       /* Only placeholder for power domain driver */
+       return 0;
+}
+
+static int zynqmp_dpsub_bind(struct udevice *dev)
+{
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+       plat->size = WIDTH * HEIGHT * 16;
+
+       return 0;
+}
+
+static const struct video_ops zynqmp_dpsub_ops = {
+};
+
+static const struct udevice_id zynqmp_dpsub_ids[] = {
+       { .compatible = "xlnx,zynqmp-dpsub-1.7" },
+       { }
+};
+
+U_BOOT_DRIVER(zynqmp_dpsub_video) = {
+       .name = "zynqmp_dpsub_video",
+       .id = UCLASS_VIDEO,
+       .of_match = zynqmp_dpsub_ids,
+       .ops = &zynqmp_dpsub_ops,
+       .plat_auto = sizeof(struct video_uc_plat),
+       .bind = zynqmp_dpsub_bind,
+       .probe = zynqmp_dpsub_probe,
+       .priv_auto = sizeof(struct zynqmp_dpsub_priv),
+};
index 0cb324c..744dffe 100644 (file)
@@ -895,6 +895,19 @@ int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device);
 
 /**
+ * ofnode_read_eth_phy_id() - look up eth phy vendor and device id
+ *
+ * Look at the compatible property of a device node that represents a eth phy
+ * device and extract phy vendor id and device id from it.
+ *
+ * @param node         node to examine
+ * @param vendor       vendor id of the eth phy device
+ * @param device       device id of the eth phy device
+ * @return 0 if ok, negative on error
+ */
+int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device);
+
+/**
  * ofnode_read_addr_cells() - Get the number of address cells for a node
  *
  * This walks back up the tree to find the closest #address-cells property
index 8b869c4..a09b242 100644 (file)
@@ -7,7 +7,7 @@
 #define __PINCTRL_H
 
 #define PINNAME_SIZE   10
-#define PINMUX_SIZE    40
+#define PINMUX_SIZE    80
 
 /**
  * struct pinconf_param - pin config parameters
@@ -453,30 +453,30 @@ struct pinctrl_ops {
  *     presented using the packed format.
  */
 enum pin_config_param {
-       PIN_CONFIG_BIAS_BUS_HOLD,
-       PIN_CONFIG_BIAS_DISABLE,
-       PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
-       PIN_CONFIG_BIAS_PULL_DOWN,
-       PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
-       PIN_CONFIG_BIAS_PULL_UP,
-       PIN_CONFIG_DRIVE_OPEN_DRAIN,
-       PIN_CONFIG_DRIVE_OPEN_SOURCE,
-       PIN_CONFIG_DRIVE_PUSH_PULL,
-       PIN_CONFIG_DRIVE_STRENGTH,
-       PIN_CONFIG_DRIVE_STRENGTH_UA,
-       PIN_CONFIG_INPUT_DEBOUNCE,
-       PIN_CONFIG_INPUT_ENABLE,
-       PIN_CONFIG_INPUT_SCHMITT,
-       PIN_CONFIG_INPUT_SCHMITT_ENABLE,
-       PIN_CONFIG_LOW_POWER_MODE,
-       PIN_CONFIG_OUTPUT_ENABLE,
-       PIN_CONFIG_OUTPUT,
-       PIN_CONFIG_POWER_SOURCE,
-       PIN_CONFIG_SLEEP_HARDWARE_STATE,
-       PIN_CONFIG_SLEW_RATE,
-       PIN_CONFIG_SKEW_DELAY,
-       PIN_CONFIG_END = 0x7F,
-       PIN_CONFIG_MAX = 0xFF,
+       PIN_CONFIG_BIAS_BUS_HOLD = 0,
+       PIN_CONFIG_BIAS_DISABLE = 1,
+       PIN_CONFIG_BIAS_HIGH_IMPEDANCE = 2,
+       PIN_CONFIG_BIAS_PULL_DOWN = 3,
+       PIN_CONFIG_BIAS_PULL_PIN_DEFAULT = 4,
+       PIN_CONFIG_BIAS_PULL_UP = 5,
+       PIN_CONFIG_DRIVE_OPEN_DRAIN = 6,
+       PIN_CONFIG_DRIVE_OPEN_SOURCE = 7,
+       PIN_CONFIG_DRIVE_PUSH_PULL = 8,
+       PIN_CONFIG_DRIVE_STRENGTH = 9,
+       PIN_CONFIG_DRIVE_STRENGTH_UA = 10,
+       PIN_CONFIG_INPUT_DEBOUNCE = 11,
+       PIN_CONFIG_INPUT_ENABLE = 12,
+       PIN_CONFIG_INPUT_SCHMITT = 13,
+       PIN_CONFIG_INPUT_SCHMITT_ENABLE = 14,
+       PIN_CONFIG_LOW_POWER_MODE = 15,
+       PIN_CONFIG_OUTPUT_ENABLE = 16,
+       PIN_CONFIG_OUTPUT = 17,
+       PIN_CONFIG_POWER_SOURCE = 18,
+       PIN_CONFIG_SLEEP_HARDWARE_STATE = 19,
+       PIN_CONFIG_SLEW_RATE = 20,
+       PIN_CONFIG_SKEW_DELAY = 21,
+       PIN_CONFIG_END = 127,   /* 0x7F */
+       PIN_CONFIG_MAX = 255, /* 0xFF */
 };
 
 #if CONFIG_IS_ENABLED(PINCTRL_GENERIC)
index 08584c8..eaa9fd5 100644 (file)
@@ -48,6 +48,9 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
        return dividend / divisor;
 }
 
+#define DIV64_U64_ROUND_UP(ll, d)      \
+       ({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
+
 /**
  * div64_s64 - signed 64bit divide with 64bit divisor
  */
index c66fd43..9ea4bd4 100644 (file)
@@ -454,6 +454,32 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev);
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
                                struct udevice *dev,
                                phy_interface_t interface);
+/**
+ * phy_device_create() - Create a PHY device
+ *
+ * @bus:               MII/MDIO bus that hosts the PHY
+ * @addr:              PHY address on MDIO bus
+ * @phy_id:            where to store the ID retrieved
+ * @is_c45:            Device Identifiers if is_c45
+ * @interface:         interface between the MAC and PHY
+ * @return: pointer to phy_device if a PHY is found, or NULL otherwise
+ */
+struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
+                                    u32 phy_id, bool is_c45,
+                                    phy_interface_t interface);
+
+/**
+ * phy_connect_phy_id() - Connect to phy device by reading PHY id
+ *                       from phy node.
+ *
+ * @bus:               MII/MDIO bus that hosts the PHY
+ * @dev:               Ethernet device to associate to the PHY
+ * @interface:         Interface between the MAC and PHY
+ * @return:            pointer to phy_device if a PHY is found,
+ *                     or NULL otherwise
+ */
+struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
+                                     phy_interface_t interface);
 
 static inline ofnode phy_get_ofnode(struct phy_device *phydev)
 {
index 50bf4ef..f577008 100644 (file)
@@ -177,6 +177,49 @@ enum pm_query_id {
        PM_QID_CLOCK_GET_MAX_DIVISOR = 13,
 };
 
+enum pm_pinctrl_config_param {
+       PM_PINCTRL_CONFIG_SLEW_RATE = 0,
+       PM_PINCTRL_CONFIG_BIAS_STATUS = 1,
+       PM_PINCTRL_CONFIG_PULL_CTRL = 2,
+       PM_PINCTRL_CONFIG_SCHMITT_CMOS = 3,
+       PM_PINCTRL_CONFIG_DRIVE_STRENGTH = 4,
+       PM_PINCTRL_CONFIG_VOLTAGE_STATUS = 5,
+       PM_PINCTRL_CONFIG_TRI_STATE = 6,
+       PM_PINCTRL_CONFIG_MAX = 7,
+};
+
+enum pm_pinctrl_slew_rate {
+       PM_PINCTRL_SLEW_RATE_FAST = 0,
+       PM_PINCTRL_SLEW_RATE_SLOW = 1,
+};
+
+enum pm_pinctrl_bias_status {
+       PM_PINCTRL_BIAS_DISABLE = 0,
+       PM_PINCTRL_BIAS_ENABLE = 1,
+};
+
+enum pm_pinctrl_pull_ctrl {
+       PM_PINCTRL_BIAS_PULL_DOWN = 0,
+       PM_PINCTRL_BIAS_PULL_UP = 1,
+};
+
+enum pm_pinctrl_schmitt_cmos {
+       PM_PINCTRL_INPUT_TYPE_CMOS = 0,
+       PM_PINCTRL_INPUT_TYPE_SCHMITT = 1,
+};
+
+enum pm_pinctrl_drive_strength {
+       PM_PINCTRL_DRIVE_STRENGTH_2MA = 0,
+       PM_PINCTRL_DRIVE_STRENGTH_4MA = 1,
+       PM_PINCTRL_DRIVE_STRENGTH_8MA = 2,
+       PM_PINCTRL_DRIVE_STRENGTH_12MA = 3,
+};
+
+enum pm_pinctrl_tri_state {
+       PM_PINCTRL_TRI_STATE_DISABLE = 0,
+       PM_PINCTRL_TRI_STATE_ENABLE = 1,
+};
+
 enum zynqmp_pm_reset_action {
        PM_RESET_ACTION_RELEASE = 0,
        PM_RESET_ACTION_ASSERT = 1,
@@ -340,6 +383,29 @@ enum pm_ioctl_id {
        IOCTL_GET_LAST_RESET_REASON = 23,
        /* AIE ISR Clear */
        IOCTL_AIE_ISR_CLEAR = 24,
+       /* Register SGI to ATF */
+       IOCTL_REGISTER_SGI = 25,
+       /* Runtime feature configuration */
+       IOCTL_SET_FEATURE_CONFIG = 26,
+       IOCTL_GET_FEATURE_CONFIG = 27,
+       /* IOCTL for Secure Read/Write Interface */
+       IOCTL_READ_REG = 28,
+       IOCTL_MASK_WRITE_REG = 29,
+       /* Dynamic SD/GEM/USB configuration */
+       IOCTL_SET_SD_CONFIG = 30,
+       IOCTL_SET_GEM_CONFIG = 31,
+       IOCTL_SET_USB_CONFIG = 32,
+       /* AIE/AIEML Operations */
+       IOCTL_AIE_OPS = 33,
+       /* IOCTL to get default/current QoS */
+       IOCTL_GET_QOS = 34,
+};
+
+enum pm_sd_config_type {
+       SD_CONFIG_EMMC_SEL = 1, /* To set SD_EMMC_SEL in CTRL_REG_SD */
+       SD_CONFIG_BASECLK = 2,  /* To set SD_BASECLK in SD_CONFIG_REG1 */
+       SD_CONFIG_8BIT = 3,     /* To set SD_8BIT in SD_CONFIG_REG2 */
+       SD_CONFIG_FIXED = 4,    /* To set fixed config registers */
 };
 
 #define PM_SIP_SVC     0xc2000000
@@ -372,6 +438,8 @@ int zynqmp_pmufw_config_close(void);
 void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
 int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
                      u32 arg3, u32 *ret_payload);
+int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
+int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id);
 
 /* Type of Config Object */
 #define PM_CONFIG_OBJECT_TYPE_BASE     0x1U
@@ -403,5 +471,9 @@ enum zynqmp_pm_request_ack {
 #define ZYNQMP_PM_CAPABILITY_UNUSABLE  0x8U
 
 #define ZYNQMP_PM_MAX_QOS              100U
+/* Firmware feature check version mask */
+#define FIRMWARE_VERSION_MASK          GENMASK(15, 0)
+/* PM API versions */
+#define PM_API_VERSION_2               2
 
 #endif /* _ZYNQMP_FIRMWARE_H_ */
index 8ae807b..ba338b8 100644 (file)
@@ -16,18 +16,18 @@ static int dm_test_cmd_pinmux_status_pinname(struct unit_test_state *uts)
        /* Test that 'pinmux status <pinname>' displays the selected pin. */
        console_record_reset();
        run_command("pinmux status a5", 0);
-       ut_assert_nextline("a5        : gpio input .                            ");
+       ut_assert_nextlinen("a5        : gpio input .");
        ut_assert_console_end();
 
        console_record_reset();
        run_command("pinmux status P7", 0);
-       ut_assert_nextline("P7        : GPIO2 bias-pull-down input-enable.      ");
+       ut_assert_nextlinen("P7        : GPIO2 bias-pull-down input-enable.");
        ut_assert_console_end();
 
        console_record_reset();
        run_command("pinmux status P9", 0);
-       ut_assert_nextline("single-pinctrl pinctrl-single-no-width: missing register width");
-       ut_assert_nextline("P9 not found");
+       ut_assert_nextlinen("single-pinctrl pinctrl-single-no-width: missing register width");
+       ut_assert_nextlinen("P9 not found");
        ut_assert_console_end();
 
        return 0;