summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/axi/axi-emul-uclass.c2
-rw-r--r--drivers/block/Kconfig7
-rw-r--r--drivers/clk/clk-mux.c2
-rw-r--r--drivers/clk/clk_zynqmp.c1
-rw-r--r--drivers/clk/sifive/Makefile4
-rw-r--r--drivers/clk/starfive/clk-jh7110-pll.c2
-rw-r--r--drivers/dfu/Kconfig1
-rw-r--r--drivers/dfu/dfu.c2
-rw-r--r--drivers/dfu/dfu_mtd.c34
-rw-r--r--drivers/fastboot/fb_common.c2
-rw-r--r--drivers/firmware/firmware-zynqmp.c48
-rw-r--r--drivers/firmware/ti_sci.c2
-rw-r--r--drivers/fwu-mdata/Kconfig15
-rw-r--r--drivers/fwu-mdata/Makefile1
-rw-r--r--drivers/fwu-mdata/fwu-mdata-uclass.c151
-rw-r--r--drivers/fwu-mdata/gpt_blk.c175
-rw-r--r--drivers/fwu-mdata/raw_mtd.c269
-rw-r--r--drivers/gpio/gpio-fxl6408.c2
-rw-r--r--drivers/gpio/gpio-rcar.c15
-rw-r--r--drivers/gpio/npcm_gpio.c6
-rw-r--r--drivers/i2c/Kconfig1
-rw-r--r--drivers/mmc/mmc.c2
-rw-r--r--drivers/mmc/zynq_sdhci.c10
-rw-r--r--drivers/mtd/nand/raw/Kconfig6
-rw-r--r--drivers/mtd/nand/raw/fsl_ifc_spl.c4
-rw-r--r--drivers/mtd/nvmxip/nvmxip.h32
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/altera_tse.c8
-rw-r--r--drivers/net/eth-phy-uclass.c10
-rw-r--r--drivers/net/ethoc.c8
-rw-r--r--drivers/net/fsl-mc/dpbp.c180
-rw-r--r--drivers/net/fsl-mc/dpio/dpio.c194
-rw-r--r--drivers/net/fsl-mc/dpmac.c274
-rw-r--r--drivers/net/fsl-mc/dpmng.c20
-rw-r--r--drivers/net/fsl-mc/dpni.c680
-rw-r--r--drivers/net/fsl-mc/dprc.c405
-rw-r--r--drivers/net/fsl-mc/dpsparser.c124
-rw-r--r--drivers/net/fsl-mc/fsl_dpmng_cmd.h17
-rw-r--r--drivers/net/fsl-mc/mc.c14
-rw-r--r--drivers/net/fsl-mc/mc_sys.c13
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c268
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.h64
-rw-r--r--drivers/net/pch_gbe.c5
-rw-r--r--drivers/net/pfe_eth/pfe_hw.c2
-rw-r--r--drivers/net/phy/ethernet_id.c17
-rw-r--r--drivers/net/phy/phy.c4
-rw-r--r--drivers/net/ravb.c22
-rw-r--r--drivers/net/sh_eth.c48
-rw-r--r--drivers/net/sni_ave.c6
-rw-r--r--drivers/net/sunxi_emac.c7
-rw-r--r--drivers/net/ti/davinci_emac.c4
-rw-r--r--drivers/nvme/Makefile2
-rw-r--r--drivers/pci/Kconfig13
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/pcie-xilinx-nwl.c352
-rw-r--r--drivers/phy/marvell/comphy_cp110.c2
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c21
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos.h2
-rw-r--r--drivers/pinctrl/meson/Kconfig4
-rw-r--r--drivers/pinctrl/meson/Makefile1
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-a1.c867
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c4
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c4
-rw-r--r--drivers/power/domain/Kconfig7
-rw-r--r--drivers/power/domain/Makefile1
-rw-r--r--drivers/power/domain/meson-secure-pwrc.c160
-rw-r--r--drivers/power/domain/zynqmp-power-domain.c11
-rw-r--r--drivers/power/pmic/stpmic1.c2
-rw-r--r--drivers/power/regulator/fan53555.c10
-rw-r--r--drivers/power/regulator/fixed.c16
-rw-r--r--drivers/power/regulator/gpio-regulator.c46
-rw-r--r--drivers/power/regulator/regulator-uclass.c6
-rw-r--r--drivers/power/regulator/regulator_common.c61
-rw-r--r--drivers/power/regulator/regulator_common.h27
-rw-r--r--drivers/serial/serial_stm32.c21
-rw-r--r--drivers/serial/serial_stm32.h1
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/omap3_spi.c20
-rw-r--r--drivers/spi/renesas_rpc_spi.c206
-rw-r--r--drivers/spi/spi-qup.c2
-rw-r--r--drivers/usb/Kconfig22
-rw-r--r--drivers/usb/eth/lan78xx.c6
-rw-r--r--drivers/usb/gadget/Kconfig88
-rw-r--r--drivers/usb/gadget/Makefile8
-rw-r--r--drivers/usb/host/Kconfig13
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/video-uclass.c10
-rw-r--r--drivers/video/video_bmp.c36
-rw-r--r--drivers/video/zynqmp/Kconfig8
-rw-r--r--drivers/video/zynqmp/Makefile5
-rw-r--r--drivers/video/zynqmp/zynqmp_dpsub.c2225
-rw-r--r--drivers/video/zynqmp/zynqmp_dpsub.h680
-rw-r--r--drivers/video/zynqmp_dpsub.c66
95 files changed, 6624 insertions, 1619 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 29be78a3f28..78dcf62f76a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
obj-$(CONFIG_$(SPL_)SYSINFO) += sysinfo/
obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
+obj-$(CONFIG_$(SPL_)NVME) += nvme/
obj-$(CONFIG_XEN) += xen/
obj-$(CONFIG_$(SPL_)FPGA) += fpga/
obj-y += bus/
diff --git a/drivers/axi/axi-emul-uclass.c b/drivers/axi/axi-emul-uclass.c
index 793336d8c47..e6f3ef07200 100644
--- a/drivers/axi/axi-emul-uclass.c
+++ b/drivers/axi/axi-emul-uclass.c
@@ -14,7 +14,7 @@
#include <asm/axi.h>
int axi_sandbox_get_emul(struct udevice *bus, ulong address,
- enum axi_size_t size, struct udevice **emulp)
+ const enum axi_size_t size, struct udevice **emulp)
{
struct udevice *dev;
u32 reg[2];
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 5a1aeb3d2b4..6baaa6f0711 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -107,6 +107,13 @@ config EFI_MEDIA
For sandbox there is a test driver.
+config SPL_BLK_FS
+ bool "Load images from filesystems on block devices"
+ depends on SPL_BLK
+ help
+ Use generic support to load images from fat/ext filesystems on
+ different types of block devices such as NVMe.
+
if EFI_MEDIA
config EFI_MEDIA_SANDBOX
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 184d426d0b3..017f25f7a5a 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -184,7 +184,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name,
if (!mux)
return ERR_PTR(-ENOMEM);
- /* U-boot specific assignments */
+ /* U-Boot specific assignments */
mux->parent_names = parent_names;
mux->num_parents = num_parents;
diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c
index 45c679a627b..be0ee50e0e4 100644
--- a/drivers/clk/clk_zynqmp.c
+++ b/drivers/clk/clk_zynqmp.c
@@ -691,6 +691,7 @@ static ulong zynqmp_clk_get_rate(struct clk *clk)
case topsw_lsbus:
case sata_ref ... gpu_pp1_ref:
two_divs = true;
+ fallthrough;
case cpu_r5:
case dbg_fpd:
case ams_ref:
diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
index 51348b1ddc0..84859d92aba 100644
--- a/drivers/clk/sifive/Makefile
+++ b/drivers/clk/sifive/Makefile
@@ -1,5 +1,3 @@
# SPDX-License-Identifier: GPL-2.0+
-obj-y += sifive-prci.o
-
-obj-$(CONFIG_CLK_SIFIVE_PRCI) += fu540-prci.o fu740-prci.o
+obj-$(CONFIG_CLK_SIFIVE_PRCI) += sifive-prci.o fu540-prci.o fu740-prci.o
diff --git a/drivers/clk/starfive/clk-jh7110-pll.c b/drivers/clk/starfive/clk-jh7110-pll.c
index 02e6d9000e2..7492b1f70dd 100644
--- a/drivers/clk/starfive/clk-jh7110-pll.c
+++ b/drivers/clk/starfive/clk-jh7110-pll.c
@@ -185,7 +185,7 @@ static void jh7110_pll_set_rate(struct clk_jh7110_pllx *pll,
PLLX_SET(pll->offset->dsmpd, pll->offset->dsmpd_mask, 1);
PLLX_SET(pll->offset->prediv, pll->offset->prediv_mask, rate->prediv);
PLLX_SET(pll->offset->fbdiv, pll->offset->fbdiv_mask, rate->fbdiv);
- PLLX_SET(pll->offset->postdiv1, pll->offset->postdiv1, 0);
+ PLLX_SET(pll->offset->postdiv1, pll->offset->postdiv1_mask, 0);
PLLX_SET(pll->offset->pd, pll->offset->pd_mask, PLL_PD_ON);
if (set) {
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 8d7f13dcb0b..c3a0b93b25e 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -41,7 +41,6 @@ config DFU_MMC
config DFU_MTD
bool "MTD back end for DFU"
depends on DM_MTD
- depends on CMD_MTDPARTS
help
This option enables using DFU to read and write to on any MTD device.
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 516dda61796..b2ee5f1ede6 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -135,6 +135,7 @@ int dfu_config_interfaces(char *env)
a = s;
do {
part = strsep(&a, ";");
+ part = skip_spaces(part);
ret = dfu_alt_add(dfu, i, d, part);
if (ret)
return ret;
@@ -629,6 +630,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr)
for (i = 0; i < dfu_alt_num; i++) {
s = strsep(&env, ";");
+ s = skip_spaces(s);
ret = dfu_alt_add(dfu, interface, devstr, s);
if (ret) {
/* We will free "dfu" in dfu_free_entities() */
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c
index c7075f12eca..75e2f6a4215 100644
--- a/drivers/dfu/dfu_mtd.c
+++ b/drivers/dfu/dfu_mtd.c
@@ -10,7 +10,6 @@
#include <common.h>
#include <dfu.h>
#include <mtd.h>
-#include <jffs2/load_kernel.h>
#include <linux/err.h>
#include <linux/ctype.h>
@@ -275,7 +274,7 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char **argv, int a
{
char *s;
struct mtd_info *mtd;
- int ret, part;
+ int part;
mtd = get_mtd_device_nm(devstr);
if (IS_ERR_OR_NULL(mtd))
@@ -299,10 +298,9 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char **argv, int a
if (*s)
return -EINVAL;
} else if ((!strcmp(argv[0], "part")) || (!strcmp(argv[0], "partubi"))) {
- char mtd_id[32];
- struct mtd_device *mtd_dev;
- u8 part_num;
- struct part_info *pi;
+ struct mtd_info *partition;
+ int partnum = 0;
+ bool part_found = false;
if (argc != 2)
return -EINVAL;
@@ -313,19 +311,25 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char **argv, int a
if (*s)
return -EINVAL;
- sprintf(mtd_id, "%s,%d", devstr, part - 1);
- printf("using id '%s'\n", mtd_id);
+ /* register partitions with MTDIDS/MTDPARTS or OF fallback */
+ mtd_probe_devices();
- mtdparts_init();
-
- ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num, &pi);
- if (ret != 0) {
- printf("Could not locate '%s'\n", mtd_id);
+ partnum = 0;
+ list_for_each_entry(partition, &mtd->partitions, node) {
+ partnum++;
+ if (partnum == part) {
+ part_found = true;
+ break;
+ }
+ }
+ if (!part_found) {
+ printf("No partition %d in %s\n", part, mtd->name);
return -1;
}
+ log_debug("partition %d:%s in %s\n", partnum, partition->name, mtd->name);
- dfu->data.mtd.start = pi->offset;
- dfu->data.mtd.size = pi->size;
+ dfu->data.mtd.start = partition->offset;
+ dfu->data.mtd.size = partition->size;
if (!strcmp(argv[0], "partubi"))
dfu->data.mtd.ubi = 1;
} else {
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index 621146bc6b0..4e9d9b719c6 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -135,7 +135,7 @@ void fastboot_boot(void)
s = env_get("fastboot_bootcmd");
if (s) {
run_command(s, CMD_FLAG_ENV);
- } else {
+ } else if (IS_ENABLED(CONFIG_CMD_BOOTM)) {
static char boot_addr_start[20];
static char *const bootm_args[] = {
"bootm", boot_addr_start, NULL
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index dc8e3ad2b9d..ab4c4f1a690 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -23,10 +23,10 @@
#define XST_PM_NO_ACCESS 2002L
#define XST_PM_ALREADY_CONFIGURED 2009L
-struct zynqmp_power {
+static struct zynqmp_power {
struct mbox_chan tx_chan;
struct mbox_chan rx_chan;
-} zynqmp_power = {};
+} zynqmp_power __section(".data");
#define NODE_ID_LOCATION 5
@@ -63,29 +63,32 @@ static unsigned int xpm_configobject_close[] = {
int zynqmp_pmufw_config_close(void)
{
- zynqmp_pmufw_load_config_object(xpm_configobject_close,
- sizeof(xpm_configobject_close));
- return 0;
+ return zynqmp_pmufw_load_config_object(xpm_configobject_close,
+ sizeof(xpm_configobject_close));
}
int zynqmp_pmufw_node(u32 id)
{
- static bool skip_config;
- int ret;
+ static bool check = true;
+ static bool permission = true;
+
+ if (check) {
+ check = false;
+
+ if (zynqmp_pmufw_node(NODE_OCM_BANK_0) == -EACCES) {
+ printf("PMUFW: No permission to change config object\n");
+ permission = false;
+ }
+ }
- if (skip_config)
+ if (!permission)
return 0;
/* Record power domain id */
xpm_configobject[NODE_ID_LOCATION] = id;
- ret = zynqmp_pmufw_load_config_object(xpm_configobject,
- sizeof(xpm_configobject));
-
- if (ret == XST_PM_NO_ACCESS && id == NODE_OCM_BANK_0)
- skip_config = true;
-
- return 0;
+ return zynqmp_pmufw_load_config_object(xpm_configobject,
+ sizeof(xpm_configobject));
}
static int do_pm_probe(void)
@@ -235,8 +238,7 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
*
* @cfg_obj: Pointer to the configuration object
* @size: Size of @cfg_obj in bytes
- * Return: 0 on success otherwise negative errno. If the config object
- * is not loadable returns positive errno XST_PM_NO_ACCESS(2002)
+ * Return: 0 on success otherwise negative errno.
*/
int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
{
@@ -251,10 +253,6 @@ int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
err = xilinx_pm_request(PM_SET_CONFIGURATION, (u32)(u64)cfg_obj, 0, 0,
0, ret_payload);
if (err == XST_PM_NO_ACCESS) {
- if (((u32 *)cfg_obj)[NODE_ID_LOCATION] == NODE_OCM_BANK_0) {
- printf("PMUFW: No permission to change config object\n");
- return err;
- }
return -EACCES;
}
@@ -298,9 +296,6 @@ static int zynqmp_power_probe(struct udevice *dev)
ret >> ZYNQMP_PM_VERSION_MAJOR_SHIFT,
ret & ZYNQMP_PM_VERSION_MINOR_MASK);
- if (IS_ENABLED(CONFIG_ARCH_ZYNQMP))
- zynqmp_pmufw_node(NODE_OCM_BANK_0);
-
return 0;
};
@@ -320,7 +315,8 @@ U_BOOT_DRIVER(zynqmp_power) = {
int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
u32 arg3, u32 *ret_payload)
{
- debug("%s at EL%d, API ID: 0x%0x\n", __func__, current_el(), api_id);
+ debug("%s at EL%d, API ID: 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x\n",
+ __func__, current_el(), api_id, arg0, arg1, arg2, arg3);
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
#if defined(CONFIG_ZYNQMP_IPI)
@@ -398,7 +394,7 @@ static int zynqmp_firmware_bind(struct udevice *dev)
}
}
- return dm_scan_fdt_dev(dev);
+ return 0;
}
U_BOOT_DRIVER(zynqmp_firmware) = {
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index bd7379ae555..72f572d8248 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -265,7 +265,7 @@ static int ti_sci_do_xfer(struct ti_sci_info *info,
if (xfer->rx_len) {
ret = ti_sci_get_response(info, xfer, &info->chan_rx);
if (!ti_sci_is_response_ack(xfer->tx_message.buf)) {
- dev_err(info->dev, "Message not acknowledged");
+ dev_err(info->dev, "Message not acknowledged\n");
ret = -ENODEV;
}
}
diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
index 36c4479a59e..42736a5e43b 100644
--- a/drivers/fwu-mdata/Kconfig
+++ b/drivers/fwu-mdata/Kconfig
@@ -6,6 +6,11 @@ config FWU_MDATA
FWU Metadata partitions reside on the same storage device
which contains the other FWU updatable firmware images.
+choice
+ prompt "Storage Layout Scheme"
+ depends on FWU_MDATA
+ default FWU_MDATA_GPT_BLK
+
config FWU_MDATA_GPT_BLK
bool "FWU Metadata access for GPT partitioned Block devices"
select PARTITION_TYPE_GUID
@@ -14,3 +19,13 @@ config FWU_MDATA_GPT_BLK
help
Enable support for accessing FWU Metadata on GPT partitioned
block devices.
+
+config FWU_MDATA_MTD
+ bool "Raw MTD devices"
+ depends on MTD
+ help
+ Enable support for accessing FWU Metadata on non-partitioned
+ (or non-GPT partitioned, e.g. partition nodes in devicetree)
+ MTD devices.
+
+endchoice
diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
index 3fee64c10c9..06c49747ba8 100644
--- a/drivers/fwu-mdata/Makefile
+++ b/drivers/fwu-mdata/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_FWU_MDATA) += fwu-mdata-uclass.o
obj-$(CONFIG_FWU_MDATA_GPT_BLK) += gpt_blk.o
+obj-$(CONFIG_FWU_MDATA_MTD) += raw_mtd.o
diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c
index b477e9603fb..0a8edaaa418 100644
--- a/drivers/fwu-mdata/fwu-mdata-uclass.c
+++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
@@ -14,170 +14,39 @@
#include <linux/errno.h>
#include <linux/types.h>
-#include <u-boot/crc.h>
/**
- * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers
- * @dev: FWU metadata device
- * @mdata_parts: array for storing the metadata partition numbers
- *
- * Get the partition numbers on the storage device on which the
- * FWU metadata is stored. Two partition numbers will be returned.
- *
- * Return: 0 if OK, -ve on error
- *
- */
-int fwu_get_mdata_part_num(struct udevice *dev, uint *mdata_parts)
-{
- const struct fwu_mdata_ops *ops = device_get_ops(dev);
-
- if (!ops->get_mdata_part_num) {
- log_debug("get_mdata_part_num() method not defined\n");
- return -ENOSYS;
- }
-
- return ops->get_mdata_part_num(dev, mdata_parts);
-}
-
-/**
- * fwu_read_mdata_partition() - Read the FWU metadata from a partition
- * @dev: FWU metadata device
- * @mdata: Copy of the FWU metadata
- * @part_num: Partition number from which FWU metadata is to be read
- *
- * Read the FWU metadata from the specified partition number
- *
- * Return: 0 if OK, -ve on error
- *
- */
-int fwu_read_mdata_partition(struct udevice *dev, struct fwu_mdata *mdata,
- uint part_num)
-{
- const struct fwu_mdata_ops *ops = device_get_ops(dev);
-
- if (!ops->read_mdata_partition) {
- log_debug("read_mdata_partition() method not defined\n");
- return -ENOSYS;
- }
-
- return ops->read_mdata_partition(dev, mdata, part_num);
-}
-
-/**
- * fwu_write_mdata_partition() - Write the FWU metadata to a partition
- * @dev: FWU metadata device
- * @mdata: Copy of the FWU metadata
- * @part_num: Partition number to which FWU metadata is to be written
- *
- * Write the FWU metadata to the specified partition number
- *
- * Return: 0 if OK, -ve on error
- *
- */
-int fwu_write_mdata_partition(struct udevice *dev, struct fwu_mdata *mdata,
- uint part_num)
-{
- const struct fwu_mdata_ops *ops = device_get_ops(dev);
-
- if (!ops->write_mdata_partition) {
- log_debug("write_mdata_partition() method not defined\n");
- return -ENOSYS;
- }
-
- return ops->write_mdata_partition(dev, mdata, part_num);
-}
-
-/**
- * fwu_mdata_check() - Check if the FWU metadata is valid
- * @dev: FWU metadata device
- *
- * Validate both copies of the FWU metadata. If one of the copies
- * has gone bad, restore it from the other copy.
- *
- * Return: 0 if OK, -ve on error
- *
- */
-int fwu_mdata_check(struct udevice *dev)
-{
- const struct fwu_mdata_ops *ops = device_get_ops(dev);
-
- if (!ops->check_mdata) {
- log_debug("check_mdata() method not defined\n");
- return -ENOSYS;
- }
-
- return ops->check_mdata(dev);
-}
-
-/**
- * fwu_get_mdata() - Get a FWU metadata copy
- * @dev: FWU metadata device
- * @mdata: Copy of the FWU metadata
- *
- * Get a valid copy of the FWU metadata.
- *
- * Note: This function is to be called first when modifying any fields
- * in the metadata. The sequence of calls to modify any field in the
- * metadata would be 1) fwu_get_mdata 2) Modify metadata, followed by
- * 3) fwu_update_mdata
+ * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata()
*
* Return: 0 if OK, -ve on error
- *
*/
-int fwu_get_mdata(struct udevice *dev, struct fwu_mdata *mdata)
+int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
{
const struct fwu_mdata_ops *ops = device_get_ops(dev);
- if (!ops->get_mdata) {
- log_debug("get_mdata() method not defined\n");
+ if (!ops->read_mdata) {
+ log_debug("read_mdata() method not defined\n");
return -ENOSYS;
}
- return ops->get_mdata(dev, mdata);
+ return ops->read_mdata(dev, mdata, primary);
}
/**
- * fwu_update_mdata() - Update the FWU metadata
- * @dev: FWU metadata device
- * @mdata: Copy of the FWU metadata
- *
- * Update the FWU metadata structure by writing to the
- * FWU metadata partitions.
- *
- * Note: This function is not to be called directly to update the
- * metadata fields. The sequence of function calls should be
- * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata()
- *
- * The sequence of updating the partitions should be, update the
- * primary metadata partition (first partition encountered), followed
- * by updating the secondary partition. With this update sequence, in
- * the rare scenario that the two metadata partitions are valid but do
- * not match, maybe due to power outage at the time of updating the
- * metadata copies, the secondary partition can be updated from the
- * primary.
+ * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata()
*
* Return: 0 if OK, -ve on error
- *
*/
-int fwu_update_mdata(struct udevice *dev, struct fwu_mdata *mdata)
+int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
{
- void *buf;
const struct fwu_mdata_ops *ops = device_get_ops(dev);
- if (!ops->update_mdata) {
- log_debug("get_mdata() method not defined\n");
+ if (!ops->write_mdata) {
+ log_debug("write_mdata() method not defined\n");
return -ENOSYS;
}
- /*
- * Calculate the crc32 for the updated FWU metadata
- * and put the updated value in the FWU metadata crc32
- * field
- */
- buf = &mdata->version;
- mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
-
- return ops->update_mdata(dev, mdata);
+ return ops->write_mdata(dev, mdata, primary);
}
UCLASS_DRIVER(fwu_mdata) = {
diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c
index d35ce49c5c1..c7284916c4e 100644
--- a/drivers/fwu-mdata/gpt_blk.c
+++ b/drivers/fwu-mdata/gpt_blk.c
@@ -24,38 +24,40 @@ enum {
MDATA_WRITE,
};
-static int gpt_get_mdata_partitions(struct blk_desc *desc,
- uint mdata_parts[2])
+static uint g_mdata_part[2]; /* = {0, 0} to check against uninit parts */
+
+static int gpt_get_mdata_partitions(struct blk_desc *desc)
{
- int i, ret;
+ int i;
u32 nparts;
efi_guid_t part_type_guid;
struct disk_partition info;
const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID;
+ /* if primary and secondary partitions already found */
+ if (g_mdata_part[0] && g_mdata_part[1])
+ return 0;
+
nparts = 0;
- for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
+ for (i = 1; i < MAX_SEARCH_PARTITIONS && nparts < 2; i++) {
if (part_get_info(desc, i, &info))
continue;
uuid_str_to_bin(info.type_guid, part_type_guid.b,
UUID_STR_FORMAT_GUID);
- if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) {
- if (nparts < 2)
- mdata_parts[nparts] = i;
- ++nparts;
- }
+ if (!guidcmp(&fwu_mdata_guid, &part_type_guid))
+ g_mdata_part[nparts++] = i;
}
if (nparts != 2) {
log_debug("Expect two copies of the FWU metadata instead of %d\n",
nparts);
- ret = -EINVAL;
- } else {
- ret = 0;
+ g_mdata_part[0] = 0;
+ g_mdata_part[1] = 0;
+ return -EINVAL;
}
- return ret;
+ return 0;
}
static int gpt_get_mdata_disk_part(struct blk_desc *desc,
@@ -123,112 +125,6 @@ static int gpt_read_write_mdata(struct blk_desc *desc,
return 0;
}
-static int fwu_gpt_update_mdata(struct udevice *dev, struct fwu_mdata *mdata)
-{
- int ret;
- struct blk_desc *desc;
- uint mdata_parts[2];
- struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
-
- desc = dev_get_uclass_plat(priv->blk_dev);
-
- ret = gpt_get_mdata_partitions(desc, mdata_parts);
- if (ret < 0) {
- log_debug("Error getting the FWU metadata partitions\n");
- return -ENOENT;
- }
-
- /* First write the primary partition */
- ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, mdata_parts[0]);
- if (ret < 0) {
- log_debug("Updating primary FWU metadata partition failed\n");
- return ret;
- }
-
- /* And now the replica */
- ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, mdata_parts[1]);
- if (ret < 0) {
- log_debug("Updating secondary FWU metadata partition failed\n");
- return ret;
- }
-
- return 0;
-}
-
-static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata *mdata)
-{
- int ret;
- uint mdata_parts[2];
-
- ret = gpt_get_mdata_partitions(desc, mdata_parts);
-
- if (ret < 0) {
- log_debug("Error getting the FWU metadata partitions\n");
- return -ENOENT;
- }
-
- ret = gpt_read_write_mdata(desc, mdata, MDATA_READ, mdata_parts[0]);
- if (ret < 0) {
- log_debug("Failed to read the FWU metadata from the device\n");
- return -EIO;
- }
-
- ret = fwu_verify_mdata(mdata, 1);
- if (!ret)
- return 0;
-
- /*
- * Verification of the primary FWU metadata copy failed.
- * Try to read the replica.
- */
- memset(mdata, '\0', sizeof(struct fwu_mdata));
- ret = gpt_read_write_mdata(desc, mdata, MDATA_READ, mdata_parts[1]);
- if (ret < 0) {
- log_debug("Failed to read the FWU metadata from the device\n");
- return -EIO;
- }
-
- ret = fwu_verify_mdata(mdata, 0);
- if (!ret)
- return 0;
-
- /* Both the FWU metadata copies are corrupted. */
- return -EIO;
-}
-
-static int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata *mdata)
-{
- struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
-
- return gpt_get_mdata(dev_get_uclass_plat(priv->blk_dev), mdata);
-}
-
-static int fwu_gpt_get_mdata_partitions(struct udevice *dev, uint *mdata_parts)
-{
- struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
-
- return gpt_get_mdata_partitions(dev_get_uclass_plat(priv->blk_dev),
- mdata_parts);
-}
-
-static int fwu_gpt_read_mdata_partition(struct udevice *dev,
- struct fwu_mdata *mdata, uint part_num)
-{
- struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
-
- return gpt_read_write_mdata(dev_get_uclass_plat(priv->blk_dev),
- mdata, MDATA_READ, part_num);
-}
-
-static int fwu_gpt_write_mdata_partition(struct udevice *dev,
- struct fwu_mdata *mdata, uint part_num)
-{
- struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
-
- return gpt_read_write_mdata(dev_get_uclass_plat(priv->blk_dev),
- mdata, MDATA_WRITE, part_num);
-}
-
static int fwu_get_mdata_device(struct udevice *dev, struct udevice **mdata_dev)
{
u32 phandle;
@@ -267,12 +163,43 @@ static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
return 0;
}
+static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata,
+ bool primary)
+{
+ struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+ struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev);
+ int ret;
+
+ ret = gpt_get_mdata_partitions(desc);
+ if (ret < 0) {
+ log_debug("Error getting the FWU metadata partitions\n");
+ return -ENOENT;
+ }
+
+ return gpt_read_write_mdata(desc, mdata, MDATA_READ,
+ primary ? g_mdata_part[0] : g_mdata_part[1]);
+}
+
+static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata,
+ bool primary)
+{
+ struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+ struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev);
+ int ret;
+
+ ret = gpt_get_mdata_partitions(desc);
+ if (ret < 0) {
+ log_debug("Error getting the FWU metadata partitions\n");
+ return -ENOENT;
+ }
+
+ return gpt_read_write_mdata(desc, mdata, MDATA_WRITE,
+ primary ? g_mdata_part[0] : g_mdata_part[1]);
+}
+
static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
- .get_mdata = fwu_gpt_get_mdata,
- .update_mdata = fwu_gpt_update_mdata,
- .get_mdata_part_num = fwu_gpt_get_mdata_partitions,
- .read_mdata_partition = fwu_gpt_read_mdata_partition,
- .write_mdata_partition = fwu_gpt_write_mdata_partition,
+ .read_mdata = fwu_gpt_read_mdata,
+ .write_mdata = fwu_gpt_write_mdata,
};
static const struct udevice_id fwu_mdata_ids[] = {
diff --git a/drivers/fwu-mdata/raw_mtd.c b/drivers/fwu-mdata/raw_mtd.c
new file mode 100644
index 00000000000..17e45179738
--- /dev/null
+++ b/drivers/fwu-mdata/raw_mtd.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#define LOG_CATEGORY UCLASS_FWU_MDATA
+
+#include <fwu.h>
+#include <fwu_mdata.h>
+#include <memalign.h>
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/* Internal helper structure to move data around */
+struct fwu_mdata_mtd_priv {
+ struct mtd_info *mtd;
+ char pri_label[50];
+ char sec_label[50];
+ u32 pri_offset;
+ u32 sec_offset;
+};
+
+enum fwu_mtd_op {
+ FWU_MTD_READ,
+ FWU_MTD_WRITE,
+};
+
+extern struct fwu_mtd_image_info fwu_mtd_images[];
+
+static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
+{
+ return !do_div(size, mtd->erasesize);
+}
+
+static int mtd_io_data(struct mtd_info *mtd, u32 offs, u32 size, void *data,
+ enum fwu_mtd_op op)
+{
+ struct mtd_oob_ops io_op = {};
+ u64 lock_len;
+ size_t len;
+ void *buf;
+ int ret;
+
+ if (!mtd_is_aligned_with_block_size(mtd, offs)) {
+ log_err("Offset unaligned with a block (0x%x)\n", mtd->erasesize);
+ return -EINVAL;
+ }
+
+ /* This will expand erase size to align with the block size */
+ lock_len = round_up(size, mtd->erasesize);
+
+ ret = mtd_unlock(mtd, offs, lock_len);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
+
+ if (op == FWU_MTD_WRITE) {
+ struct erase_info erase_op = {};
+
+ erase_op.mtd = mtd;
+ erase_op.addr = offs;
+ erase_op.len = lock_len;
+ erase_op.scrub = 0;
+
+ ret = mtd_erase(mtd, &erase_op);
+ if (ret)
+ goto lock;
+ }
+
+ /* Also, expand the write size to align with the write size */
+ len = round_up(size, mtd->writesize);
+
+ buf = memalign(ARCH_DMA_MINALIGN, len);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto lock;
+ }
+ memset(buf, 0xff, len);
+
+ io_op.mode = MTD_OPS_AUTO_OOB;
+ io_op.len = len;
+ io_op.datbuf = buf;
+
+ if (op == FWU_MTD_WRITE) {
+ memcpy(buf, data, size);
+ ret = mtd_write_oob(mtd, offs, &io_op);
+ } else {
+ ret = mtd_read_oob(mtd, offs, &io_op);
+ if (!ret)
+ memcpy(data, buf, size);
+ }
+ free(buf);
+
+lock:
+ mtd_lock(mtd, offs, lock_len);
+
+ return ret;
+}
+
+static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
+{
+ struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
+ struct mtd_info *mtd = mtd_priv->mtd;
+ u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset;
+
+ return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_READ);
+}
+
+static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
+{
+ struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
+ struct mtd_info *mtd = mtd_priv->mtd;
+ u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset;
+
+ return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_WRITE);
+}
+
+static int flash_partition_offset(struct udevice *dev, const char *part_name, fdt_addr_t *offset)
+{
+ ofnode node, parts_node;
+ fdt_addr_t size = 0;
+
+ parts_node = ofnode_by_compatible(dev_ofnode(dev), "fixed-partitions");
+ node = ofnode_by_prop_value(parts_node, "label", part_name, strlen(part_name) + 1);
+ if (!ofnode_valid(node)) {
+ log_err("Warning: Failed to find partition by label <%s>\n", part_name);
+ return -ENOENT;
+ }
+
+ *offset = ofnode_get_addr_size_index_notrans(node, 0, &size);
+
+ return (int)size;
+}
+
+static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
+{
+ struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
+ const fdt32_t *phandle_p = NULL;
+ struct udevice *mtd_dev;
+ struct mtd_info *mtd;
+ const char *label;
+ fdt_addr_t offset;
+ int ret, size;
+ u32 phandle;
+ ofnode bank;
+ int off_img;
+
+ /* Find the FWU mdata storage device */
+ phandle_p = ofnode_get_property(dev_ofnode(dev),
+ "fwu-mdata-store", &size);
+ if (!phandle_p) {
+ log_err("FWU meta data store not defined in device-tree\n");
+ return -ENOENT;
+ }
+
+ phandle = fdt32_to_cpu(*phandle_p);
+
+ ret = device_get_global_by_ofnode(ofnode_get_by_phandle(phandle),
+ &mtd_dev);
+ if (ret) {
+ log_err("FWU: failed to get mtd device\n");
+ return ret;
+ }
+
+ mtd_probe_devices();
+
+ mtd_for_each_device(mtd) {
+ if (mtd->dev == mtd_dev) {
+ mtd_priv->mtd = mtd;
+ log_debug("Found the FWU mdata mtd device %s\n", mtd->name);
+ break;
+ }
+ }
+ if (!mtd_priv->mtd) {
+ log_err("Failed to find mtd device by fwu-mdata-store\n");
+ return -ENODEV;
+ }
+
+ /* Get the offset of primary and secondary mdata */
+ ret = ofnode_read_string_index(dev_ofnode(dev), "mdata-parts", 0, &label);
+ if (ret)
+ return ret;
+ strncpy(mtd_priv->pri_label, label, 50);
+
+ ret = flash_partition_offset(mtd_dev, mtd_priv->pri_label, &offset);
+ if (ret <= 0)
+ return ret;
+ mtd_priv->pri_offset = offset;
+
+ ret = ofnode_read_string_index(dev_ofnode(dev), "mdata-parts", 1, &label);
+ if (ret)
+ return ret;
+ strncpy(mtd_priv->sec_label, label, 50);
+
+ ret = flash_partition_offset(mtd_dev, mtd_priv->sec_label, &offset);
+ if (ret <= 0)
+ return ret;
+ mtd_priv->sec_offset = offset;
+
+ off_img = 0;
+
+ ofnode_for_each_subnode(bank, dev_ofnode(dev)) {
+ int bank_num, bank_offset, bank_size;
+ const char *bank_name;
+ ofnode image;
+
+ ofnode_read_u32(bank, "id", &bank_num);
+ bank_name = ofnode_read_string(bank, "label");
+ bank_size = flash_partition_offset(mtd_dev, bank_name, &offset);
+ if (bank_size <= 0)
+ return bank_size;
+ bank_offset = offset;
+ log_debug("Bank%d: %s [0x%x - 0x%x]\n",
+ bank_num, bank_name, bank_offset, bank_offset + bank_size);
+
+ ofnode_for_each_subnode(image, bank) {
+ int image_num, image_offset, image_size;
+ const char *uuid;
+
+ if (off_img == CONFIG_FWU_NUM_BANKS *
+ CONFIG_FWU_NUM_IMAGES_PER_BANK) {
+ log_err("DT provides more images than configured!\n");
+ break;
+ }
+
+ uuid = ofnode_read_string(image, "uuid");
+ ofnode_read_u32(image, "id", &image_num);
+ ofnode_read_u32(image, "offset", &image_offset);
+ ofnode_read_u32(image, "size", &image_size);
+
+ fwu_mtd_images[off_img].start = bank_offset + image_offset;
+ fwu_mtd_images[off_img].size = image_size;
+ fwu_mtd_images[off_img].bank_num = bank_num;
+ fwu_mtd_images[off_img].image_num = image_num;
+ strcpy(fwu_mtd_images[off_img].uuidbuf, uuid);
+ log_debug("\tImage%d: %s @0x%x\n\n",
+ image_num, uuid, bank_offset + image_offset);
+ off_img++;
+ }
+ }
+
+ return 0;
+}
+
+static int fwu_mdata_mtd_probe(struct udevice *dev)
+{
+ /* Ensure the metadata can be read. */
+ return fwu_get_mdata(NULL);
+}
+
+static struct fwu_mdata_ops fwu_mtd_ops = {
+ .read_mdata = fwu_mtd_read_mdata,
+ .write_mdata = fwu_mtd_write_mdata,
+};
+
+static const struct udevice_id fwu_mdata_ids[] = {
+ { .compatible = "u-boot,fwu-mdata-mtd" },
+ { }
+};
+
+U_BOOT_DRIVER(fwu_mdata_mtd) = {
+ .name = "fwu-mdata-mtd",
+ .id = UCLASS_FWU_MDATA,
+ .of_match = fwu_mdata_ids,
+ .ops = &fwu_mtd_ops,
+ .probe = fwu_mdata_mtd_probe,
+ .of_to_plat = fwu_mdata_mtd_of_to_plat,
+ .priv_auto = sizeof(struct fwu_mdata_mtd_priv),
+};
diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c
index 902da050fbf..ca7aa14eeb2 100644
--- a/drivers/gpio/gpio-fxl6408.c
+++ b/drivers/gpio/gpio-fxl6408.c
@@ -27,7 +27,7 @@
* https://patchwork.kernel.org/patch/9148419/
* - the Toradex version by Max Krummenacher <max.krummenacher@toradex.com>:
* http://git.toradex.com/cgit/linux-toradex.git/tree/drivers/gpio/gpio-fxl6408.c?h=toradex_5.4-2.3.x-imx
- * - the U-boot PCA953x driver by Peng Fan <van.freenix@gmail.com>:
+ * - the U-Boot PCA953x driver by Peng Fan <van.freenix@gmail.com>:
* drivers/gpio/pca953x_gpio.c
*
* TODO:
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 9ffb4a56258..d6cfbd231a8 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -130,20 +130,9 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int rcar_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- return pinctrl_gpio_request(dev, offset, label);
-}
-
-static int rcar_gpio_free(struct udevice *dev, unsigned offset)
-{
- return pinctrl_gpio_free(dev, offset);
-}
-
static const struct dm_gpio_ops rcar_gpio_ops = {
- .request = rcar_gpio_request,
- .rfree = rcar_gpio_free,
+ .request = pinctrl_gpio_request,
+ .rfree = pinctrl_gpio_free,
.direction_input = rcar_gpio_direction_input,
.direction_output = rcar_gpio_direction_output,
.get_value = rcar_gpio_get_value,
diff --git a/drivers/gpio/npcm_gpio.c b/drivers/gpio/npcm_gpio.c
index 8afd57fa8e5..98e5dc79c1c 100644
--- a/drivers/gpio/npcm_gpio.c
+++ b/drivers/gpio/npcm_gpio.c
@@ -37,14 +37,14 @@ static int npcm_gpio_direction_output(struct udevice *dev, unsigned int offset,
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
- clrbits_le32(priv->base + GPIO_IEM, BIT(offset));
- writel(BIT(offset), priv->base + GPIO_OES);
-
if (value)
setbits_le32(priv->base + GPIO_DOUT, BIT(offset));
else
clrbits_le32(priv->base + GPIO_DOUT, BIT(offset));
+ clrbits_le32(priv->base + GPIO_IEM, BIT(offset));
+ writel(BIT(offset), priv->base + GPIO_OES);
+
return 0;
}
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 05b14d2451c..5e81698143a 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -744,7 +744,6 @@ config SYS_I2C_SPEED
config SYS_I2C_BUS_MAX
int "Max I2C busses"
depends on ARCH_OMAP2PLUS || ARCH_SOCFPGA
- default 2 if TI816X
default 3 if OMAP34XX || AM33XX || AM43XX
default 4 if ARCH_SOCFPGA || OMAP44XX
default 5 if OMAP54XX
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1af6af82e6b..72c1076c56d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2262,7 +2262,7 @@ static int mmc_startup_v4(struct mmc *mmc)
return 0;
if (!mmc->ext_csd)
- memset(ext_csd_bkup, 0, sizeof(ext_csd_bkup));
+ memset(ext_csd_bkup, 0, MMC_MAX_BLOCK_LEN);
err = mmc_send_ext_csd(mmc, ext_csd);
if (err)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index e44868aaec5..e779251ce34 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -873,7 +873,7 @@ static int arasan_sdhci_set_tapdelay(struct sdhci_host *host)
if (ret)
return ret;
} else if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
- device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) {
+ device_is_compatible(dev, "xlnx,versal-net-emmc")) {
if (mmc->clock >= MIN_PHY_CLK_HZ)
if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN)
iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL;
@@ -948,7 +948,7 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev)
}
if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
- device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) {
+ device_is_compatible(dev, "xlnx,versal-net-emmc")) {
for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i];
clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i];
@@ -1102,7 +1102,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
}
}
#endif
- if (device_is_compatible(dev, "xlnx,versal-net-5.1-emmc"))
+ if (device_is_compatible(dev, "xlnx,versal-net-emmc"))
priv->internal_phy_reg = true;
ret = clk_get_by_index(dev, 0, &clk);
@@ -1136,7 +1136,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->quirks |= SDHCI_QUIRK_NO_1_8_V;
if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) &&
- device_is_compatible(dev, "xlnx,versal-net-5.1-emmc"))
+ device_is_compatible(dev, "xlnx,versal-net-emmc"))
host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400;
plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
@@ -1219,7 +1219,7 @@ static int arasan_sdhci_bind(struct udevice *dev)
static const struct udevice_id arasan_sdhci_ids[] = {
{ .compatible = "arasan,sdhci-8.9a" },
- { .compatible = "xlnx,versal-net-5.1-emmc" },
+ { .compatible = "xlnx,versal-net-emmc" },
{ }
};
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index d115fcf841f..d624589a892 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -553,7 +553,7 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS
bool "Enable use of 1st stage bootloader timing for NAND"
depends on NAND_ZYNQ
help
- This flag prevent U-boot reconfigure NAND flash controller and reuse
+ This flag prevent U-Boot reconfigure NAND flash controller and reuse
the NAND timing from 1st stage bootloader.
config NAND_OCTEONTX
@@ -732,10 +732,10 @@ config SYS_NAND_BAD_BLOCK_POS
default 5 if HAS_NAND_SMALL_BADBLOCK_POS
config SYS_NAND_U_BOOT_LOCATIONS
- bool "Define U-boot binaries locations in NAND"
+ bool "Define U-Boot binaries locations in NAND"
help
Enable CONFIG_SYS_NAND_U_BOOT_OFFS though Kconfig.
- This option should not be enabled when compiling U-boot for boards
+ This option should not be enabled when compiling U-Boot for boards
defining CONFIG_SYS_NAND_U_BOOT_OFFS in their include/configs/<board>.h
file.
diff --git a/drivers/mtd/nand/raw/fsl_ifc_spl.c b/drivers/mtd/nand/raw/fsl_ifc_spl.c
index 60a865b5667..c67065eaf8c 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_spl.c
@@ -275,8 +275,8 @@ void nand_boot(void)
#ifdef CONFIG_CHAIN_OF_TRUST
/*
- * U-Boot header is appended at end of U-boot image, so
- * calculate U-boot header address using U-boot header size.
+ * U-Boot header is appended at end of U-Boot image, so
+ * calculate U-Boot header address using U-Boot header size.
*/
#define FSL_U_BOOT_HDR_ADDR \
((CFG_SYS_NAND_U_BOOT_START + \
diff --git a/drivers/mtd/nvmxip/nvmxip.h b/drivers/mtd/nvmxip/nvmxip.h
deleted file mode 100644
index f4ef37725d2..00000000000
--- a/drivers/mtd/nvmxip/nvmxip.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
- *
- * Authors:
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
- */
-
-#ifndef __DRIVER_NVMXIP_H__
-#define __DRIVER_NVMXIP_H__
-
-#include <blk.h>
-
-#define NVMXIP_BLKDRV_NAME "nvmxip-blk"
-#define NVMXIP_BLKDEV_NAME_SZ 20
-
-/**
- * struct nvmxip_plat - the NVMXIP driver plat
- *
- * @phys_base: NVM XIP device base address
- * @lba_shift: block size shift count
- * @lba: number of blocks
- *
- * The NVMXIP information read from the DT.
- */
-struct nvmxip_plat {
- phys_addr_t phys_base;
- u32 lba_shift;
- lbaint_t lba;
-};
-
-#endif /* __DRIVER_NVMXIP_H__ */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 39eee98ca79..d662dd34989 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -696,6 +696,7 @@ config SUN8I_EMAC
config SH_ETHER
bool "Renesas SH Ethernet MAC"
select PHYLIB
+ select PHY_ETHERNET_ID
help
This driver supports the Ethernet for Renesas SH and ARM SoCs.
@@ -765,6 +766,7 @@ config RENESAS_RAVB
bool "Renesas Ethernet AVB MAC"
depends on RCAR_64
select PHYLIB
+ select PHY_ETHERNET_ID
help
This driver implements support for the Ethernet AVB block in
Renesas M3 and H3 SoCs.
diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
index 912d28fca2e..e2340936fa6 100644
--- a/drivers/net/altera_tse.c
+++ b/drivers/net/altera_tse.c
@@ -430,17 +430,11 @@ static int tse_mdio_init(const char *name, struct altera_tse_priv *priv)
static int tse_phy_init(struct altera_tse_priv *priv, void *dev)
{
struct phy_device *phydev;
- unsigned int mask = 0xffffffff;
- if (priv->phyaddr)
- mask = 1 << priv->phyaddr;
-
- phydev = phy_find_by_mask(priv->bus, mask);
+ phydev = phy_connect(priv->bus, -1, dev, priv->interface);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, priv->interface);
-
phydev->supported &= PHY_GBIT_FEATURES;
phydev->advertising = phydev->supported;
diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c
index 27b77444a0c..9d1e8d38ffa 100644
--- a/drivers/net/eth-phy-uclass.c
+++ b/drivers/net/eth-phy-uclass.c
@@ -144,10 +144,18 @@ static int eth_phy_of_to_plat(struct udevice *dev)
uc_priv->reset_assert_delay = dev_read_u32_default(dev, "reset-assert-us", 0);
uc_priv->reset_deassert_delay = dev_read_u32_default(dev, "reset-deassert-us", 0);
+ /* These are used by some DTs, try these as a fallback. */
+ if (!uc_priv->reset_assert_delay && !uc_priv->reset_deassert_delay) {
+ uc_priv->reset_assert_delay =
+ dev_read_u32_default(dev, "reset-delay-us", 0);
+ uc_priv->reset_deassert_delay =
+ dev_read_u32_default(dev, "reset-post-delay-us", 0);
+ }
+
return 0;
}
-void eth_phy_reset(struct udevice *dev, int value)
+static void eth_phy_reset(struct udevice *dev, int value)
{
struct eth_phy_device_priv *uc_priv = dev_get_uclass_priv(dev);
u32 delay;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 29067e9e949..13fad8119bb 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -608,18 +608,16 @@ static int ethoc_mdio_init(const char *name, struct ethoc *priv)
static int ethoc_phy_init(struct ethoc *priv, void *dev)
{
struct phy_device *phydev;
- int mask = 0xffffffff;
+ int mask = -1;
#ifdef CONFIG_PHY_ADDR
- mask = 1 << CONFIG_PHY_ADDR;
+ mask = CONFIG_PHY_ADDR;
#endif
- phydev = phy_find_by_mask(priv->bus, mask);
+ phydev = phy_connect(priv->bus, mask, dev, PHY_INTERFACE_MODE_MII);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, PHY_INTERFACE_MODE_MII);
-
phydev->supported &= PHY_BASIC_FEATURES;
phydev->advertising = phydev->supported;
diff --git a/drivers/net/fsl-mc/dpbp.c b/drivers/net/fsl-mc/dpbp.c
index c609efb9abc..5e17ccf73d3 100644
--- a/drivers/net/fsl-mc/dpbp.c
+++ b/drivers/net/fsl-mc/dpbp.c
@@ -3,25 +3,40 @@
* Freescale Layerscape MC I/O wrapper
*
* Copyright 2013-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017-2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpbp.h>
-int dpbp_open(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- int dpbp_id,
- uint16_t *token)
+/**
+ * dpbp_open() - Open a control session for the specified object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpbp_id: DPBP unique ID
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpbp_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpbp_id, u16 *token)
{
+ struct dpbp_cmd_open *cmd_params;
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
- cmd_flags,
- 0);
- DPBP_CMD_OPEN(cmd, dpbp_id);
+ cmd_flags, 0);
+ cmd_params = (struct dpbp_cmd_open *)cmd.params;
+ cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -29,14 +44,23 @@ int dpbp_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return err;
}
-int dpbp_close(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpbp_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPBP object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -48,11 +72,26 @@ int dpbp_close(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpbp_create(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- const struct dpbp_cfg *cfg,
- uint32_t *obj_id)
+/**
+ * dpbp_create() - Create the DPBP object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg: Configuration structure
+ * @obj_id: Returned object id; use in subsequent API calls
+ *
+ * Create the DPBP object, allocate required resources and
+ * perform required initialization.
+ *
+ * This function accepts an authentication token of a parent
+ * container that this object should be assigned to and returns
+ * an object id. This object_id will be used in all subsequent calls to
+ * this specific object.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ const struct dpbp_cfg *cfg, u32 *obj_id)
{
struct mc_command cmd = { 0 };
int err;
@@ -61,8 +100,7 @@ int dpbp_create(struct fsl_mc_io *mc_io,
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE,
- cmd_flags,
- dprc_token);
+ cmd_flags, dprc_token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -70,33 +108,46 @@ int dpbp_create(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- MC_CMD_READ_OBJ_ID(cmd, *obj_id);
+ *obj_id = mc_cmd_read_object_id(&cmd);
return 0;
}
-int dpbp_destroy(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- uint32_t obj_id)
+/**
+ * dpbp_destroy() - Destroy the DPBP object and release all its resources.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @obj_id: ID of DPBP object
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpbp_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ u32 obj_id)
{
+ struct dpbp_cmd_destroy *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY,
- cmd_flags,
- dprc_token);
+ cmd_flags, dprc_token);
- /* set object id to destroy */
- CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id);
+ cmd_params = (struct dpbp_cmd_destroy *)cmd.params;
+ cmd_params->object_id = cpu_to_le32(obj_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpbp_enable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpbp_enable() - Enable the DPBP.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPBP object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -108,48 +159,66 @@ int dpbp_enable(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpbp_disable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpbp_disable() - Disable the DPBP.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPBP object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
- cmd_flags,
- token);
+ cmd_flags, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpbp_reset(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpbp_reset() - Reset the DPBP, returns the object to initial state.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPBP object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
- cmd_flags,
- token);
+ cmd_flags, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpbp_get_attributes(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpbp_get_attributes - Retrieve DPBP attributes.
+ *
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPBP object
+ * @attr: Returned object's attributes
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
struct dpbp_attr *attr)
{
+ struct dpbp_rsp_get_attributes *rsp_params;
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
- cmd_flags,
- token);
+ cmd_flags, token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -157,15 +226,24 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPBP_RSP_GET_ATTRIBUTES(cmd, attr);
+ rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
+ attr->bpid = le16_to_cpu(rsp_params->bpid);
+ attr->id = le32_to_cpu(rsp_params->id);
return 0;
}
-int dpbp_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dpbp_get_api_version - Get Data Path Buffer Pool API version
+ * @mc_io: Pointer to Mc portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of Buffer Pool API
+ * @minor_ver: Minor version of Buffer Pool API
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpbp_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
diff --git a/drivers/net/fsl-mc/dpio/dpio.c b/drivers/net/fsl-mc/dpio/dpio.c
index 8884455963d..d17210bf451 100644
--- a/drivers/net/fsl-mc/dpio/dpio.c
+++ b/drivers/net/fsl-mc/dpio/dpio.c
@@ -1,18 +1,34 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017, 2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpio.h>
-int dpio_open(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint32_t dpio_id,
- uint16_t *token)
+/**
+ * dpio_open() - Open a control session for the specified object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpio_id: DPIO unique ID
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpio_create() function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and any MC portals
+ * assigned to the parent container; this token must be used in
+ * all subsequent commands for this specific object.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpio_id,
+ u16 *token)
{
+ struct dpio_cmd_open *cmd_params;
struct mc_command cmd = { 0 };
int err;
@@ -20,7 +36,8 @@ int dpio_open(struct fsl_mc_io *mc_io,
cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
cmd_flags,
0);
- DPIO_CMD_OPEN(cmd, dpio_id);
+ cmd_params = (struct dpio_cmd_open *)cmd.params;
+ cmd_params->dpio_id = cpu_to_le32(dpio_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -28,14 +45,20 @@ int dpio_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return 0;
}
-int dpio_close(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpio_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -48,12 +71,32 @@ int dpio_close(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpio_create(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- const struct dpio_cfg *cfg,
- uint32_t *obj_id)
+/**
+ * dpio_create() - Create the DPIO object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg: Configuration structure
+ * @obj_id: Returned object id
+ *
+ * Create the DPIO object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ *
+ * The function accepts an authentication token of a parent
+ * container that this object should be assigned to. The token
+ * can be '0' so the object will be assigned to the default container.
+ * The newly created object can be opened with the returned
+ * object id and using the container's associated tokens and MC portals.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ const struct dpio_cfg *cfg, u32 *obj_id)
{
+ struct dpio_cmd_create *cmd_params;
struct mc_command cmd = { 0 };
int err;
@@ -61,7 +104,11 @@ int dpio_create(struct fsl_mc_io *mc_io,
cmd.header = mc_encode_cmd_header(DPIO_CMDID_CREATE,
cmd_flags,
dprc_token);
- DPIO_CMD_CREATE(cmd, cfg);
+ cmd_params = (struct dpio_cmd_create *)cmd.params;
+ cmd_params->num_priorities = cfg->num_priorities;
+ dpio_set_field(cmd_params->channel_mode,
+ CHANNEL_MODE,
+ cfg->channel_mode);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -69,33 +116,54 @@ int dpio_create(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- MC_CMD_READ_OBJ_ID(cmd, *obj_id);
+ *obj_id = mc_cmd_read_object_id(&cmd);
return 0;
}
-int dpio_destroy(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- uint32_t obj_id)
+/**
+ * dpio_destroy() - Destroy the DPIO object and release all its resources.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @object_id: The object id; it must be a valid id within the container that
+ * created this object;
+ *
+ * The function accepts the authentication token of the parent container that
+ * created the object (not the one that currently owns the object). The object
+ * is searched within parent using the provided 'object_id'.
+ * All tokens to the object must be closed before calling destroy.
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ u32 object_id)
{
+ struct dpio_cmd_destroy *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_DESTROY,
- cmd_flags,
- dprc_token);
+ cmd_flags,
+ dprc_token);
/* set object id to destroy */
- CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id);
+ cmd_params = (struct dpio_cmd_destroy *)cmd.params;
+ cmd_params->dpio_id = cpu_to_le32(object_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpio_enable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpio_enable() - Enable the DPIO, allow I/O portal operations.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -108,9 +176,15 @@ int dpio_enable(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpio_disable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpio_disable() - Disable the DPIO, stop any I/O portal operation.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -123,26 +197,19 @@ int dpio_disable(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpio_reset(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
- cmd_flags,
- token);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpio_get_attributes(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpio_get_attributes() - Retrieve DPIO attributes
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ * @attr: Returned object's attributes
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
struct dpio_attr *attr)
{
+ struct dpio_rsp_get_attr *rsp_params;
struct mc_command cmd = { 0 };
int err;
@@ -157,29 +224,42 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPIO_RSP_GET_ATTR(cmd, attr);
+ rsp_params = (struct dpio_rsp_get_attr *)cmd.params;
+ attr->id = le32_to_cpu(rsp_params->id);
+ attr->qbman_portal_id = le16_to_cpu(rsp_params->qbman_portal_id);
+ attr->num_priorities = rsp_params->num_priorities;
+ attr->qbman_portal_ce_offset = le64_to_cpu(rsp_params->qbman_portal_ce_offset);
+ attr->qbman_portal_ci_offset = le64_to_cpu(rsp_params->qbman_portal_ci_offset);
+ attr->qbman_version = le32_to_cpu(rsp_params->qbman_version);
+ attr->clk = le32_to_cpu(rsp_params->clk);
+ attr->channel_mode = dpio_get_field(rsp_params->channel_mode, ATTR_CHANNEL_MODE);
return 0;
}
-int dpio_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dpio_get_api_version() - Get Data Path I/O API version
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of data path i/o API
+ * @minor_ver: Minor version of data path i/o API
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
- /* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION,
- cmd_flags, 0);
+ cmd_flags,
+ 0);
- /* send command to mc */
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
- /* retrieve response parameters */
mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
return 0;
diff --git a/drivers/net/fsl-mc/dpmac.c b/drivers/net/fsl-mc/dpmac.c
index 43a2ff43f88..5d4f6c67fd0 100644
--- a/drivers/net/fsl-mc/dpmac.c
+++ b/drivers/net/fsl-mc/dpmac.c
@@ -11,19 +11,33 @@
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpmac.h>
-int dpmac_open(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- int dpmac_id,
- uint16_t *token)
+/**
+ * dpmac_open() - Open a control session for the specified object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpmac_id: DPMAC unique ID
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpmac_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpmac_id, u16 *token)
{
+ struct dpmac_cmd_open *cmd_params;
struct mc_command cmd = { 0 };
int err;
/* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
- cmd_flags,
- 0);
- DPMAC_CMD_OPEN(cmd, dpmac_id);
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN, cmd_flags, 0);
+ cmd_params = (struct dpmac_cmd_open *)cmd.params;
+ cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -31,39 +45,63 @@ int dpmac_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return err;
}
-int dpmac_close(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpmac_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
/* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
- token);
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpmac_create(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- const struct dpmac_cfg *cfg,
- uint32_t *obj_id)
+/**
+ * dpmac_create() - Create the DPMAC object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg: Configuration structure
+ * @obj_id: Returned object id
+ *
+ * Create the DPMAC object, allocate required resources and
+ * perform required initialization.
+ *
+ * The function accepts an authentication token of a parent
+ * container that this object should be assigned to. The token
+ * can be '0' so the object will be assigned to the default container.
+ * The newly created object can be opened with the returned
+ * object id and using the container's associated tokens and MC portals.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ const struct dpmac_cfg *cfg, u32 *obj_id)
{
+ struct dpmac_cmd_create *cmd_params;
struct mc_command cmd = { 0 };
int err;
/* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
- cmd_flags,
- dprc_token);
- DPMAC_CMD_CREATE(cmd, cfg);
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE, cmd_flags, dprc_token);
+ cmd_params = (struct dpmac_cmd_create *)cmd.params;
+ cmd_params->mac_id = cpu_to_le32(cfg->mac_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -71,142 +109,87 @@ int dpmac_create(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- MC_CMD_READ_OBJ_ID(cmd, *obj_id);
+ *obj_id = mc_cmd_read_object_id(&cmd);
return 0;
}
-int dpmac_destroy(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- uint32_t obj_id)
+/**
+ * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @object_id: The object id; it must be a valid id within the container that
+ * created this object;
+ *
+ * The function accepts the authentication token of the parent container that
+ * created the object (not the one that currently owns the object). The object
+ * is searched within parent using the provided 'object_id'.
+ * All tokens to the object must be closed before calling destroy.
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpmac_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ u32 object_id)
{
+ struct dpmac_cmd_destroy *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
cmd_flags,
dprc_token);
-
- /* set object id to destroy */
- CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpmac_get_attributes(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dpmac_attr *attr)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
- cmd_flags,
- token);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPMAC_RSP_GET_ATTRIBUTES(cmd, attr);
-
- return 0;
-}
-
-int dpmac_mdio_read(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dpmac_mdio_cfg *cfg)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ,
- cmd_flags,
- token);
- DPMAC_CMD_MDIO_READ(cmd, cfg);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPMAC_RSP_MDIO_READ(cmd, cfg->data);
-
- return 0;
-}
-
-int dpmac_mdio_write(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dpmac_mdio_cfg *cfg)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE,
- cmd_flags,
- token);
- DPMAC_CMD_MDIO_WRITE(cmd, cfg);
+ cmd_params = (struct dpmac_cmd_destroy *)cmd.params;
+ cmd_params->dpmac_id = cpu_to_le32(object_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dpmac_link_cfg *cfg)
-{
- struct mc_command cmd = { 0 };
- int err = 0;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
- cmd_flags,
- token);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- DPMAC_RSP_GET_LINK_CFG(cmd, cfg);
-
- return 0;
-}
-
-int dpmac_set_link_state(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpmac_set_link_state() - Set the Ethernet link status
+ * @mc_io: Pointer to opaque I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @link_state: Link state configuration
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_set_link_state(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
struct dpmac_link_state *link_state)
{
+ struct dpmac_cmd_set_link_state *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
- cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
- cmd_flags,
- token);
- DPMAC_CMD_SET_LINK_STATE(cmd, link_state);
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE, cmd_flags, token);
+ cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params;
+ cmd_params->options = cpu_to_le64(link_state->options);
+ cmd_params->rate = cpu_to_le32(link_state->rate);
+ cmd_params->up = dpmac_get_field(link_state->up, STATE);
+ dpmac_set_field(cmd_params->up, STATE_VALID, link_state->state_valid);
+ cmd_params->supported = cpu_to_le64(link_state->supported);
+ cmd_params->advertising = cpu_to_le64(link_state->advertising);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpmac_get_counter(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- enum dpmac_counter type,
- uint64_t *counter)
+/**
+ * dpmac_get_counter() - Read a specific DPMAC counter
+ * @mc_io: Pointer to opaque I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @type: The requested counter
+ * @counter: Returned counter value
+ *
+ * Return: The requested counter; '0' otherwise.
+ */
+int dpmac_get_counter(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ enum dpmac_counter type, uint64_t *counter)
{
+ struct dpmac_cmd_get_counter *dpmac_cmd;
+ struct dpmac_rsp_get_counter *dpmac_rsp;
struct mc_command cmd = { 0 };
int err = 0;
@@ -214,36 +197,43 @@ int dpmac_get_counter(struct fsl_mc_io *mc_io,
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
cmd_flags,
token);
- DPMAC_CMD_GET_COUNTER(cmd, type);
+ dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
+ dpmac_cmd->type = type;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
- DPMAC_RSP_GET_COUNTER(cmd, *counter);
+ dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
+ *counter = le64_to_cpu(dpmac_rsp->counter);
return 0;
}
-int dpmac_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dpmac_get_api_version() - Get Data Path MAC version
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of data path mac API
+ * @minor_ver: Minor version of data path mac API
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
- /* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
- cmd_flags, 0);
+ cmd_flags,
+ 0);
- /* send command to mc */
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
- /* retrieve response parameters */
mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
return 0;
diff --git a/drivers/net/fsl-mc/dpmng.c b/drivers/net/fsl-mc/dpmng.c
index 8314243f356..147ca6da9e1 100644
--- a/drivers/net/fsl-mc/dpmng.c
+++ b/drivers/net/fsl-mc/dpmng.c
@@ -1,15 +1,24 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ * Copyright 2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpmng.h>
#include "fsl_dpmng_cmd.h"
-int mc_get_version(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- struct mc_version *mc_ver_info)
+/**
+ * mc_get_version() - Retrieves the Management Complex firmware
+ * version information
+ * @mc_io: Pointer to opaque I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @mc_ver_info: Returned version information structure
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int mc_get_version(struct fsl_mc_io *mc_io, uint32_t cmd_flags, struct mc_version *mc_ver_info)
{
+ struct dpmng_rsp_get_version *rsp_params;
struct mc_command cmd = { 0 };
int err;
@@ -24,7 +33,10 @@ int mc_get_version(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPMNG_RSP_GET_VERSION(cmd, mc_ver_info);
+ rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
+ mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
+ mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
+ mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
return 0;
}
diff --git a/drivers/net/fsl-mc/dpni.c b/drivers/net/fsl-mc/dpni.c
index 5290be20c85..5b815a45a99 100644
--- a/drivers/net/fsl-mc/dpni.c
+++ b/drivers/net/fsl-mc/dpni.c
@@ -1,46 +1,43 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017, 2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpni.h>
-int dpni_prepare_cfg(const struct dpni_cfg *cfg,
- uint8_t *cfg_buf)
-{
- uint64_t *params = (uint64_t *)cfg_buf;
-
- DPNI_PREP_CFG(params, cfg);
-
- return 0;
-}
-
-int dpni_extract_cfg(struct dpni_cfg *cfg,
- const uint8_t *cfg_buf)
-{
- uint64_t *params = (uint64_t *)cfg_buf;
-
- DPNI_EXT_CFG(params, cfg);
-
- return 0;
-}
-
-int dpni_open(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- int dpni_id,
- uint16_t *token)
+/**
+ * dpni_open() - Open a control session for the specified object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpni_id: DPNI unique ID
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpni_create() function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpni_id, u16 *token)
{
+ struct dpni_cmd_open *cmd_params;
struct mc_command cmd = { 0 };
+
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
cmd_flags,
0);
- DPNI_CMD_OPEN(cmd, dpni_id);
+ cmd_params = (struct dpni_cmd_open *)cmd.params;
+ cmd_params->dpni_id = cpu_to_le32(dpni_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -48,14 +45,23 @@ int dpni_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return 0;
}
-int dpni_close(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpni_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -68,12 +74,32 @@ int dpni_close(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpni_create(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- const struct dpni_cfg *cfg,
- uint32_t *obj_id)
+/**
+ * dpni_create() - Create the DPNI object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg: Configuration structure
+ * @obj_id: Returned object id
+ *
+ * Create the DPNI object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ *
+ * The function accepts an authentication token of a parent
+ * container that this object should be assigned to. The token
+ * can be '0' so the object will be assigned to the default container.
+ * The newly created object can be opened with the returned
+ * object id and using the container's associated tokens and MC portals.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ const struct dpni_cfg *cfg, u32 *obj_id)
{
+ struct dpni_cmd_create *cmd_params;
struct mc_command cmd = { 0 };
int err;
@@ -81,7 +107,19 @@ int dpni_create(struct fsl_mc_io *mc_io,
cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE,
cmd_flags,
dprc_token);
- DPNI_CMD_CREATE(cmd, cfg);
+ cmd_params = (struct dpni_cmd_create *)cmd.params;
+ cmd_params->options = cpu_to_le32(cfg->options);
+ cmd_params->num_queues = cfg->num_queues;
+ cmd_params->num_tcs = cfg->num_tcs;
+ cmd_params->mac_filter_entries = cfg->mac_filter_entries;
+ cmd_params->num_rx_tcs = cfg->num_rx_tcs;
+ cmd_params->vlan_filter_entries = cfg->vlan_filter_entries;
+ cmd_params->qos_entries = cfg->qos_entries;
+ cmd_params->fs_entries = cpu_to_le16(cfg->fs_entries);
+ cmd_params->num_cgs = cfg->num_cgs;
+ cmd_params->num_opr = cfg->num_opr;
+ cmd_params->dist_key_size = cfg->dist_key_size;
+ cmd_params->num_channels = cfg->num_channels;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -89,50 +127,94 @@ int dpni_create(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- MC_CMD_READ_OBJ_ID(cmd, *obj_id);
+ *obj_id = mc_cmd_read_object_id(&cmd);
return 0;
}
-int dpni_destroy(struct fsl_mc_io *mc_io,
- uint16_t dprc_token,
- uint32_t cmd_flags,
- uint32_t obj_id)
+/**
+ * dpni_destroy() - Destroy the DPNI object and release all its resources.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @dprc_token: Parent container token; '0' for default container
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @object_id: The object id; it must be a valid id within the container that
+ * created this object;
+ *
+ * The function accepts the authentication token of the parent container that
+ * created the object (not the one that currently owns the object). The object
+ * is searched within parent using the provided 'object_id'.
+ * All tokens to the object must be closed before calling destroy.
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpni_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags,
+ u32 object_id)
{
+ struct dpni_cmd_destroy *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY,
cmd_flags,
dprc_token);
-
/* set object id to destroy */
- CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id);
+ cmd_params = (struct dpni_cmd_destroy *)cmd.params;
+ cmd_params->dpni_id = cpu_to_le32(object_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_set_pools(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpni_set_pools() - Set buffer pools configuration
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @cfg: Buffer pools configuration
+ *
+ * mandatory for DPNI operation
+ * warning:Allowed only when DPNI is disabled
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_set_pools(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
const struct dpni_pools_cfg *cfg)
{
struct mc_command cmd = { 0 };
+ struct dpni_cmd_set_pools *cmd_params;
+ int i;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
cmd_flags,
token);
- DPNI_CMD_SET_POOLS(cmd, cfg);
+ cmd_params = (struct dpni_cmd_set_pools *)cmd.params;
+ cmd_params->num_dpbp = cfg->num_dpbp;
+ cmd_params->pool_options = cfg->pool_options;
+ for (i = 0; i < DPNI_MAX_DPBP; i++) {
+ cmd_params->pool[i].dpbp_id =
+ cpu_to_le16(cfg->pools[i].dpbp_id);
+ cmd_params->pool[i].priority_mask =
+ cfg->pools[i].priority_mask;
+ cmd_params->buffer_size[i] =
+ cpu_to_le16(cfg->pools[i].buffer_size);
+ cmd_params->backup_pool_mask |=
+ DPNI_BACKUP_POOL(cfg->pools[i].backup_pool, i);
+ }
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_enable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpni_enable() - Enable the DPNI, allow sending and receiving frames.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -145,9 +227,15 @@ int dpni_enable(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpni_disable(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpni_disable() - Disable the DPNI, stop sending and receiving frames.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -160,9 +248,15 @@ int dpni_disable(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpni_reset(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dpni_reset() - Reset the DPNI, returns the object to initial state.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -175,76 +269,121 @@ int dpni_reset(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_attributes(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpni_get_attributes() - Retrieve DPNI attributes.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @attr: Object's attributes
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
struct dpni_attr *attr)
{
struct mc_command cmd = { 0 };
+ struct dpni_rsp_get_attr *rsp_params;
+
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
cmd_flags,
token);
+
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_ATTR(cmd, attr);
+ rsp_params = (struct dpni_rsp_get_attr *)cmd.params;
+ attr->options = le32_to_cpu(rsp_params->options);
+ attr->num_queues = rsp_params->num_queues;
+ attr->num_rx_tcs = rsp_params->num_rx_tcs;
+ attr->num_tx_tcs = rsp_params->num_tx_tcs;
+ attr->mac_filter_entries = rsp_params->mac_filter_entries;
+ attr->vlan_filter_entries = rsp_params->vlan_filter_entries;
+ attr->num_channels = rsp_params->num_channels;
+ attr->qos_entries = rsp_params->qos_entries;
+ attr->fs_entries = le16_to_cpu(rsp_params->fs_entries);
+ attr->num_opr = le16_to_cpu(rsp_params->num_opr);
+ attr->qos_key_size = rsp_params->qos_key_size;
+ attr->fs_key_size = rsp_params->fs_key_size;
+ attr->wriop_version = le16_to_cpu(rsp_params->wriop_version);
+ attr->num_cgs = rsp_params->num_cgs;
return 0;
}
-int dpni_set_errors_behavior(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dpni_error_cfg *cfg)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR,
- cmd_flags,
- token);
- DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpni_set_buffer_layout(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- const struct dpni_buffer_layout *layout,
- enum dpni_queue_type type)
+/**
+ * dpni_set_buffer_layout() - Set buffer layout configuration.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue this configuration applies to
+ * @layout: Buffer layout configuration
+ *
+ * Return: '0' on Success; Error code otherwise.
+ *
+ * @warning Allowed only when DPNI is disabled
+ */
+int dpni_set_buffer_layout(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ enum dpni_queue_type qtype,
+ const struct dpni_buffer_layout *layout)
{
+ struct dpni_cmd_set_buffer_layout *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_BUFFER_LAYOUT,
cmd_flags,
token);
- DPNI_CMD_SET_BUFFER_LAYOUT(cmd, layout, type);
+ cmd_params = (struct dpni_cmd_set_buffer_layout *)cmd.params;
+ cmd_params->qtype = qtype;
+ cmd_params->options = cpu_to_le16((u16)layout->options);
+ dpni_set_field(cmd_params->flags, PASS_TS, layout->pass_timestamp);
+ dpni_set_field(cmd_params->flags, PASS_PR, layout->pass_parser_result);
+ dpni_set_field(cmd_params->flags, PASS_FS, layout->pass_frame_status);
+ dpni_set_field(cmd_params->flags, PASS_SWO, layout->pass_sw_opaque);
+ cmd_params->private_data_size = cpu_to_le16(layout->private_data_size);
+ cmd_params->data_align = cpu_to_le16(layout->data_align);
+ cmd_params->head_room = cpu_to_le16(layout->data_head_room);
+ cmd_params->tail_room = cpu_to_le16(layout->data_tail_room);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_qdid(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- uint16_t *qdid)
+/**
+ * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used
+ * for enqueue operations
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue to receive QDID for
+ * @qdid: Returned virtual QDID value that should be used as an argument
+ * in all enqueue operations
+ *
+ * Return: '0' on Success; Error code otherwise.
+ *
+ * If dpni object is created using multiple Tc channels this function will return
+ * qdid value for the first channel
+ */
+int dpni_get_qdid(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ enum dpni_queue_type qtype, u16 *qdid)
{
struct mc_command cmd = { 0 };
+ struct dpni_cmd_get_qdid *cmd_params;
+ struct dpni_rsp_get_qdid *rsp_params;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
cmd_flags,
token);
+ cmd_params = (struct dpni_cmd_get_qdid *)cmd.params;
+ cmd_params->qtype = qtype;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -252,17 +391,26 @@ int dpni_get_qdid(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_QDID(cmd, *qdid);
+ rsp_params = (struct dpni_rsp_get_qdid *)cmd.params;
+ *qdid = le16_to_cpu(rsp_params->qdid);
return 0;
}
-int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- uint16_t *data_offset)
+/**
+ * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer)
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @data_offset: Tx data offset (from start of buffer)
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ u16 *data_offset)
{
struct mc_command cmd = { 0 };
+ struct dpni_rsp_get_tx_data_offset *rsp_params;
int err;
/* prepare command */
@@ -276,34 +424,54 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset);
+ rsp_params = (struct dpni_rsp_get_tx_data_offset *)cmd.params;
+ *data_offset = le16_to_cpu(rsp_params->data_offset);
return 0;
}
-int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpni_set_link_cfg() - set the link configuration.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @cfg: Link configuration
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_set_link_cfg(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
const struct dpni_link_cfg *cfg)
{
struct mc_command cmd = { 0 };
+ struct dpni_cmd_set_link_cfg *cmd_params;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
cmd_flags,
token);
- DPNI_CMD_SET_LINK_CFG(cmd, cfg);
+ cmd_params = (struct dpni_cmd_set_link_cfg *)cmd.params;
+ cmd_params->rate = cpu_to_le32(cfg->rate);
+ cmd_params->options = cpu_to_le64(cfg->options);
+ cmd_params->advertising = cpu_to_le64(cfg->advertising);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_link_state(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dpni_get_link_state() - Return the link state (either up or down)
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @state: Returned link state;
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_link_state(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
struct dpni_link_state *state)
{
struct mc_command cmd = { 0 };
+ struct dpni_rsp_get_link_state *rsp_params;
int err;
/* prepare command */
@@ -317,211 +485,279 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_LINK_STATE(cmd, state);
-
- return 0;
-}
-
-
-int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- const uint8_t mac_addr[6])
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
- cmd_flags,
- token);
- DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- uint8_t mac_addr[6])
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
- cmd_flags,
- token);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr);
+ rsp_params = (struct dpni_rsp_get_link_state *)cmd.params;
+ state->up = dpni_get_field(rsp_params->flags, LINK_STATE);
+ state->state_valid = dpni_get_field(rsp_params->flags, STATE_VALID);
+ state->rate = le32_to_cpu(rsp_params->rate);
+ state->options = le64_to_cpu(rsp_params->options);
+ state->supported = le64_to_cpu(rsp_params->supported);
+ state->advertising = le64_to_cpu(rsp_params->advertising);
return 0;
}
-int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- const uint8_t mac_addr[6])
+/**
+ * dpni_add_mac_addr() - Add MAC address filter
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @mac_addr: MAC address to add
+ * @flags :0 - tc_id and flow_id will be ignored.
+ * Pkt with this mac_id will be passed to the next
+ * classification stages
+ * DPNI_MAC_SET_QUEUE_ACTION
+ * Pkt with this mac will be forward directly to
+ * queue defined by the tc_id and flow_id
+ * @tc_id : Traffic class selection (0-7)
+ * @flow_id : Selects the specific queue out of the set allocated for the
+ * same as tc_id. Value must be in range 0 to NUM_QUEUES - 1
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_add_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ const u8 mac_addr[6], u8 flags,
+ u8 tc_id, u8 flow_id)
{
+ struct dpni_cmd_add_mac_addr *cmd_params;
struct mc_command cmd = { 0 };
+ int i;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
cmd_flags,
token);
- DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr);
+ cmd_params = (struct dpni_cmd_add_mac_addr *)cmd.params;
+ cmd_params->flags = flags;
+ cmd_params->tc_id = tc_id;
+ cmd_params->fq_id = flow_id;
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- const uint8_t mac_addr[6])
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
- cmd_flags,
- token);
- DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr);
+ for (i = 0; i < 6; i++)
+ cmd_params->mac_addr[i] = mac_addr[5 - i];
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dpni_get_api_version() - Get Data Path Network Interface API version
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of data path network interface API
+ * @minor_ver: Minor version of data path network interface API
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
- /* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_API_VERSION,
- cmd_flags, 0);
+ cmd_flags,
+ 0);
- /* send command to mc */
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
- /* retrieve response parameters */
mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
return 0;
}
-int dpni_set_queue(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- enum dpni_queue_type type,
- uint8_t tc,
- uint8_t index,
- const struct dpni_queue *queue)
+/**
+ * dpni_set_queue() - Set queue parameters
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue - all queue types are supported, although
+ * the command is ignored for Tx
+ * @tc: Traffic class, in range 0 to NUM_TCS - 1
+ * @index: Selects the specific queue out of the set allocated for the
+ * same TC. Value must be in range 0 to NUM_QUEUES - 1
+ * @options: A combination of DPNI_QUEUE_OPT_ values that control what
+ * configuration options are set on the queue
+ * @queue: Queue structure
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_set_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ enum dpni_queue_type qtype, u16 param, u8 index,
+ u8 options, const struct dpni_queue *queue)
{
struct mc_command cmd = { 0 };
+ struct dpni_cmd_set_queue *cmd_params;
+
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QUEUE,
cmd_flags,
token);
- DPNI_CMD_SET_QUEUE(cmd, type, tc, index, queue);
+ cmd_params = (struct dpni_cmd_set_queue *)cmd.params;
+ cmd_params->qtype = qtype;
+ cmd_params->tc = (u8)(param & 0xff);
+ cmd_params->channel_id = (u8)((param >> 8) & 0xff);
+ cmd_params->index = index;
+ cmd_params->options = options;
+ cmd_params->dest_id = cpu_to_le32(queue->destination.id);
+ cmd_params->dest_prio = queue->destination.priority;
+ dpni_set_field(cmd_params->flags, DEST_TYPE, queue->destination.type);
+ dpni_set_field(cmd_params->flags, STASH_CTRL, queue->flc.stash_control);
+ dpni_set_field(cmd_params->flags, HOLD_ACTIVE,
+ queue->destination.hold_active);
+ cmd_params->flc = cpu_to_le64(queue->flc.value);
+ cmd_params->user_context = cpu_to_le64(queue->user_context);
+ cmd_params->cgid = queue->cgid;
- /* send command to mc*/
+ /* send command to mc */
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_queue(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- enum dpni_queue_type type,
- uint8_t tc,
- uint8_t index,
- struct dpni_queue *queue)
+/**
+ * dpni_get_queue() - Get queue parameters
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @qtype: Type of queue - all queue types are supported
+ * @param: Traffic class and channel ID.
+ * MSB - channel id; used only for DPNI_QUEUE_TX and
+ * DPNI_QUEUE_TX_CONFIRM, ignored for the rest
+ * LSB - traffic class
+ * Use macro DPNI_BUILD_PARAM() to build correct value.
+ * If dpni uses a single channel (uses only channel zero)
+ * the parameter can receive traffic class directly.
+ * @index: Selects the specific queue out of the set allocated for the
+ * same TC. Value must be in range 0 to NUM_QUEUES - 1
+ * @queue: Queue configuration structure
+ * @qid: Queue identification
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ enum dpni_queue_type qtype, u16 param, u8 index,
+ struct dpni_queue *queue, struct dpni_queue_id *qid)
{
struct mc_command cmd = { 0 };
+ struct dpni_cmd_get_queue *cmd_params;
+ struct dpni_rsp_get_queue *rsp_params;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QUEUE,
cmd_flags,
token);
- DPNI_CMD_GET_QUEUE(cmd, type, tc, index);
+ cmd_params = (struct dpni_cmd_get_queue *)cmd.params;
+ cmd_params->qtype = qtype;
+ cmd_params->tc = (u8)(param & 0xff);
+ cmd_params->index = index;
+ cmd_params->channel_id = (u8)((param >> 8) & 0xff);
- /* send command to mc*/
+ /* send command to mc */
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_QUEUE(cmd, queue);
+ rsp_params = (struct dpni_rsp_get_queue *)cmd.params;
+ queue->destination.id = le32_to_cpu(rsp_params->dest_id);
+ queue->destination.priority = rsp_params->dest_prio;
+ queue->destination.type = dpni_get_field(rsp_params->flags, DEST_TYPE);
+ queue->flc.stash_control = dpni_get_field(rsp_params->flags, STASH_CTRL);
+ queue->destination.hold_active = dpni_get_field(rsp_params->flags, HOLD_ACTIVE);
+ queue->flc.value = le64_to_cpu(rsp_params->flc);
+ queue->user_context = le64_to_cpu(rsp_params->user_context);
+ qid->fqid = le32_to_cpu(rsp_params->fqid);
+ qid->qdbin = le16_to_cpu(rsp_params->qdbin);
+ if (dpni_get_field(rsp_params->flags, CGID_VALID))
+ queue->cgid = rsp_params->cgid;
+ else
+ queue->cgid = -1;
+
return 0;
}
-int dpni_set_tx_confirmation_mode(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- enum dpni_confirmation_mode mode)
+/**
+ * dpni_set_tx_confirmation_mode() - Tx confirmation mode
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @ceetm_ch_idx: ceetm channel index
+ * @mode: Tx confirmation mode
+ *
+ * This function is useful only when 'DPNI_OPT_TX_CONF_DISABLED' is not
+ * selected at DPNI creation.
+ * Calling this function with 'mode' set to DPNI_CONF_DISABLE disables all
+ * transmit confirmation (including the private confirmation queues), regardless
+ * of previous settings; Note that in this case, Tx error frames are still
+ * enqueued to the general transmit errors queue.
+ * Calling this function with 'mode' set to DPNI_CONF_SINGLE switches all
+ * Tx confirmations to a shared Tx conf queue. 'index' field in dpni_get_queue
+ * command will be ignored.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_confirmation_mode(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ u8 ceetm_ch_idx, enum dpni_confirmation_mode mode)
{
struct dpni_tx_confirmation_mode *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONFIRMATION_MODE,
- cmd_flags,
- token);
-
+ cmd_flags, token);
cmd_params = (struct dpni_tx_confirmation_mode *)cmd.params;
+ cmd_params->ceetm_ch_idx = ceetm_ch_idx;
cmd_params->confirmation_mode = mode;
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpni_get_statistics(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- uint8_t page,
- struct dpni_statistics *stat)
+/**
+ * dpni_get_statistics() - Get DPNI statistics
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPNI object
+ * @page: Selects the statistics page to retrieve, see
+ * DPNI_GET_STATISTICS output. Pages are numbered 0 to 6.
+ * @param: Custom parameter for some pages used to select
+ * a certain statistic source, for example the TC.
+ * - page_0: not used
+ * - page_1: not used
+ * - page_2: not used
+ * - page_3: high_byte - channel_id, low_byte - traffic class
+ * - page_4: high_byte - queue_index have meaning only if dpni is
+ * created using option DPNI_OPT_CUSTOM_CG, low_byte - traffic class
+ * - page_5: not used
+ * - page_6: not used
+ * @stat: Structure containing the statistics
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpni_get_statistics(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ u8 page, u16 param, union dpni_statistics *stat)
{
+ struct dpni_cmd_get_statistics *cmd_params;
+ struct dpni_rsp_get_statistics *rsp_params;
struct mc_command cmd = { 0 };
- int err;
+ int i, err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_STATISTICS,
- cmd_flags, token);
- DPNI_CMD_GET_STATISTICS(cmd, page);
+ cmd_flags,
+ token);
+ cmd_params = (struct dpni_cmd_get_statistics *)cmd.params;
+ cmd_params->page_number = page;
+ cmd_params->param = param;
- /* send command to mc*/
+ /* send command to mc */
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
- DPNI_RSP_GET_STATISTICS(cmd, stat);
+ rsp_params = (struct dpni_rsp_get_statistics *)cmd.params;
+ for (i = 0; i < DPNI_STATISTICS_CNT; i++)
+ stat->raw.counter[i] = le64_to_cpu(rsp_params->counter[i]);
return 0;
}
-
-int dpni_reset_statistics(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET_STATISTICS,
- cmd_flags, token);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
diff --git a/drivers/net/fsl-mc/dprc.c b/drivers/net/fsl-mc/dprc.c
index e0a2865ab8f..d1a74ab47a9 100644
--- a/drivers/net/fsl-mc/dprc.c
+++ b/drivers/net/fsl-mc/dprc.c
@@ -3,16 +3,22 @@
* Freescale Layerscape MC I/O wrapper
*
* Copyright 2013-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017, 2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dprc.h>
-int dprc_get_container_id(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- int *container_id)
+/**
+ * dprc_get_container_id - Get container ID associated with a given portal.
+ * @mc_io: Pointer to Mc portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @container_id: Requested container id
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_get_container_id(struct fsl_mc_io *mc_io, u32 cmd_flags, int *container_id)
{
struct mc_command cmd = { 0 };
int err;
@@ -28,23 +34,33 @@ int dprc_get_container_id(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id);
+ *container_id = (int)mc_cmd_read_object_id(&cmd);
return 0;
}
-int dprc_open(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- int container_id,
- uint16_t *token)
+/**
+ * dprc_open() - Open DPRC object for use
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @container_id: Container ID to open
+ * @token: Returned token of DPRC object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ *
+ * @warning Required before any operation on the object.
+ */
+int dprc_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int container_id, u16 *token)
{
+ struct dprc_cmd_open *cmd_params;
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
0);
- DPRC_CMD_OPEN(cmd, container_id);
+ cmd_params = (struct dprc_cmd_open *)cmd.params;
+ cmd_params->container_id = cpu_to_le32(container_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -52,14 +68,23 @@ int dprc_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return 0;
}
-int dprc_close(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token)
+/**
+ * dprc_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -71,22 +96,35 @@ int dprc_close(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dprc_create_container(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dprc_cfg *cfg,
- int *child_container_id,
- uint64_t *child_portal_paddr)
+/**
+ * dprc_create_container() - Create child container
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @cfg: Child container configuration
+ * @child_container_id: Returned child container ID
+ * @child_portal_offset:Returned child portal offset from MC portal base
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_create_container(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ struct dprc_cfg *cfg, int *child_container_id,
+ uint64_t *child_portal_offset)
{
+ struct dprc_cmd_create_container *cmd_params;
+ struct dprc_rsp_create_container *rsp_params;
struct mc_command cmd = { 0 };
- int err;
+ int err, i;
/* prepare command */
- DPRC_CMD_CREATE_CONTAINER(cmd, cfg);
-
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT,
- cmd_flags,
- token);
+ cmd_flags, token);
+ cmd_params = (struct dprc_cmd_create_container *)cmd.params;
+ cmd_params->options = cpu_to_le32(cfg->options);
+ cmd_params->icid = cpu_to_le32(cfg->icid);
+ cmd_params->portal_id = cpu_to_le32(cfg->portal_id);
+ for (i = 0; i < 16; i++)
+ cmd_params->label[i] = cfg->label[i];
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -94,253 +132,156 @@ int dprc_create_container(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPRC_RSP_CREATE_CONTAINER(cmd, *child_container_id,
- *child_portal_paddr);
+ rsp_params = (struct dprc_rsp_create_container *)cmd.params;
+ *child_container_id = le32_to_cpu(rsp_params->child_container_id);
+ *child_portal_offset = le64_to_cpu(rsp_params->child_portal_addr);
return 0;
}
-int dprc_destroy_container(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dprc_destroy_container() - Destroy child container.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @child_container_id: ID of the container to destroy
+ *
+ * This function terminates the child container, so following this call the
+ * child container ID becomes invalid.
+ *
+ * Notes:
+ * - All resources and objects of the destroyed container are returned to the
+ * parent container or destroyed if were created be the destroyed container.
+ * - This function destroy all the child containers of the specified
+ * container prior to destroying the container itself.
+ *
+ * warning: Only the parent container is allowed to destroy a child policy
+ * Container 0 can't be destroyed
+ *
+ * Return: '0' on Success; Error code otherwise.
+ *
+ */
+int dprc_destroy_container(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
int child_container_id)
{
+ struct dprc_cmd_destroy_container *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT,
- cmd_flags,
- token);
- DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id);
+ cmd_flags, token);
+ cmd_params = (struct dprc_cmd_destroy_container *)cmd.params;
+ cmd_params->child_container_id = cpu_to_le32(child_container_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dprc_reset_container(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- int child_container_id)
-{
- struct mc_command cmd = { 0 };
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
- cmd_flags,
- token);
- DPRC_CMD_RESET_CONTAINER(cmd, child_container_id);
-
- /* send command to mc*/
- return mc_send_command(mc_io, &cmd);
-}
-
-int dprc_get_attributes(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- struct dprc_attributes *attr)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
- cmd_flags,
- token);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_ATTRIBUTES(cmd, attr);
-
- return 0;
-}
-
-int dprc_get_obj_count(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- int *obj_count)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
- cmd_flags,
- token);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count);
-
- return 0;
-}
-
-int dprc_get_obj(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- int obj_index,
- struct dprc_obj_desc *obj_desc)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
- cmd_flags,
- token);
- DPRC_CMD_GET_OBJ(cmd, obj_index);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_OBJ(cmd, obj_desc);
-
- return 0;
-}
-
-int dprc_get_res_count(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- char *type,
- int *res_count)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- *res_count = 0;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
- cmd_flags,
- token);
- DPRC_CMD_GET_RES_COUNT(cmd, type);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_RES_COUNT(cmd, *res_count);
-
- return 0;
-}
-
-int dprc_get_res_ids(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- char *type,
- struct dprc_res_ids_range_desc *range_desc)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
- cmd_flags,
- token);
- DPRC_CMD_GET_RES_IDS(cmd, range_desc, type);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_RES_IDS(cmd, range_desc);
-
- return 0;
-}
-
-int dprc_get_obj_region(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
- char *obj_type,
- int obj_id,
- uint8_t region_index,
- struct dprc_region_desc *region_desc)
-{
- struct mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
- cmd_flags,
- token);
- DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- DPRC_RSP_GET_OBJ_REGION(cmd, region_desc);
-
- return 0;
-}
-
-int dprc_connect(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dprc_connect() - Connect two endpoints to create a network link between them
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @endpoint1: Endpoint 1 configuration parameters
+ * @endpoint2: Endpoint 2 configuration parameters
+ * @cfg: Connection configuration. The connection configuration
+ * is ignored for connections made to DPMAC objects, where
+ * rate is retrieved from the MAC configuration.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_connect(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
const struct dprc_endpoint *endpoint1,
const struct dprc_endpoint *endpoint2,
const struct dprc_connection_cfg *cfg)
{
+ struct dprc_cmd_connect *cmd_params;
struct mc_command cmd = { 0 };
+ int i;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
cmd_flags,
token);
- DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg);
+ cmd_params = (struct dprc_cmd_connect *)cmd.params;
+ cmd_params->ep1_id = cpu_to_le32(endpoint1->id);
+ cmd_params->ep1_interface_id = cpu_to_le16(endpoint1->if_id);
+ cmd_params->ep2_id = cpu_to_le32(endpoint2->id);
+ cmd_params->ep2_interface_id = cpu_to_le16(endpoint2->if_id);
+ cmd_params->max_rate = cpu_to_le32(cfg->max_rate);
+ cmd_params->committed_rate = cpu_to_le32(cfg->committed_rate);
+ for (i = 0; i < 16; i++) {
+ cmd_params->ep1_type[i] = endpoint1->type[i];
+ cmd_params->ep2_type[i] = endpoint2->type[i];
+ }
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dprc_disconnect(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dprc_disconnect() - Disconnect one endpoint to remove its network connection
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @endpoint: Endpoint configuration parameters
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_disconnect(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
const struct dprc_endpoint *endpoint)
{
+ struct dprc_cmd_disconnect *cmd_params;
struct mc_command cmd = { 0 };
+ int i;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
cmd_flags,
token);
- DPRC_CMD_DISCONNECT(cmd, endpoint);
+ cmd_params = (struct dprc_cmd_disconnect *)cmd.params;
+ cmd_params->id = cpu_to_le32(endpoint->id);
+ cmd_params->interface_id = cpu_to_le32(endpoint->if_id);
+ for (i = 0; i < 16; i++)
+ cmd_params->type[i] = endpoint->type[i];
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dprc_get_connection(struct fsl_mc_io *mc_io,
- uint32_t cmd_flags,
- uint16_t token,
+/**
+ * dprc_get_connection() - Get connected endpoint and link status if connection
+ * exists.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPRC object
+ * @endpoint1: Endpoint 1 configuration parameters
+ * @endpoint2: Returned endpoint 2 configuration parameters
+ * @state: Returned link state:
+ * 1 - link is up;
+ * 0 - link is down;
+ * -1 - no connection (endpoint2 information is irrelevant)
+ *
+ * Return: '0' on Success; -ENAVAIL if connection does not exist.
+ */
+int dprc_get_connection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
const struct dprc_endpoint *endpoint1,
- struct dprc_endpoint *endpoint2,
- int *state)
+ struct dprc_endpoint *endpoint2, int *state)
{
+ struct dprc_cmd_get_connection *cmd_params;
+ struct dprc_rsp_get_connection *rsp_params;
struct mc_command cmd = { 0 };
- int err;
+ int err, i;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
cmd_flags,
token);
- DPRC_CMD_GET_CONNECTION(cmd, endpoint1);
+ cmd_params = (struct dprc_cmd_get_connection *)cmd.params;
+ cmd_params->ep1_id = cpu_to_le32(endpoint1->id);
+ cmd_params->ep1_interface_id = cpu_to_le16(endpoint1->if_id);
+ for (i = 0; i < 16; i++)
+ cmd_params->ep1_type[i] = endpoint1->type[i];
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -348,15 +289,27 @@ int dprc_get_connection(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state);
+ rsp_params = (struct dprc_rsp_get_connection *)cmd.params;
+ endpoint2->id = le32_to_cpu(rsp_params->ep2_id);
+ endpoint2->if_id = le16_to_cpu(rsp_params->ep2_interface_id);
+ *state = le32_to_cpu(rsp_params->state);
+ for (i = 0; i < 16; i++)
+ endpoint2->type[i] = rsp_params->ep2_type[i];
return 0;
}
-int dprc_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dprc_get_api_version - Get Data Path Resource Container API version
+ * @mc_io: Pointer to Mc portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of Data Path Resource Container API
+ * @minor_ver: Minor version of Data Path Resource Container API
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dprc_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
diff --git a/drivers/net/fsl-mc/dpsparser.c b/drivers/net/fsl-mc/dpsparser.c
index cfd1ba66a05..09dfb8f1fc0 100644
--- a/drivers/net/fsl-mc/dpsparser.c
+++ b/drivers/net/fsl-mc/dpsparser.c
@@ -2,15 +2,29 @@
/*
* Data Path Soft Parser
*
- * Copyright 2018 NXP
+ * Copyright 2018, 2023 NXP
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpsparser.h>
-int dpsparser_open(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *token)
+/**
+ * dpsparser_open() - Open a control session for the specified object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpsparser_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpsparser_open(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 *token)
{
struct mc_command cmd = { 0 };
int err;
@@ -26,14 +40,23 @@ int dpsparser_open(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+ *token = mc_cmd_hdr_read_token(&cmd);
return err;
}
-int dpsparser_close(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 token)
+/**
+ * dpsparser_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPSPARSER object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpsparser_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
{
struct mc_command cmd = { 0 };
@@ -45,9 +68,27 @@ int dpsparser_close(struct fsl_mc_io *mc_io,
return mc_send_command(mc_io, &cmd);
}
-int dpsparser_create(struct fsl_mc_io *mc_io,
- u16 token,
- u32 cmd_flags,
+/**
+ * dpsparser_create() - Create the DPSPARSER object.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Returned token; use in subsequent API calls
+ *
+ * Create the DPSPARSER object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent calls to
+ * this specific object. For objects that are created using the
+ * DPL file, call dpsparser_open function to get an authentication
+ * token first.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpsparser_create(struct fsl_mc_io *mc_io, u16 token, u32 cmd_flags,
u32 *obj_id)
{
struct mc_command cmd = { 0 };
@@ -64,36 +105,51 @@ int dpsparser_create(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters */
- MC_CMD_READ_OBJ_ID(cmd, *obj_id);
+ *obj_id = mc_cmd_read_object_id(&cmd);
return 0;
}
-int dpsparser_destroy(struct fsl_mc_io *mc_io,
- u16 token,
- u32 cmd_flags,
+/**
+ * dpsparser_destroy() - Destroy the DPSPARSER object and release all its resources.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPSPARSER object
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpsparser_destroy(struct fsl_mc_io *mc_io, u16 token, u32 cmd_flags,
u32 obj_id)
{
+ struct dpsparser_cmd_destroy *cmd_params;
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPSPARSER_CMDID_DESTROY,
cmd_flags,
token);
-
- /* set object id to destroy */
- CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id);
+ cmd_params = (struct dpsparser_cmd_destroy *)cmd.params;
+ cmd_params->dpsparser_id = cpu_to_le32(obj_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
-int dpsparser_apply_spb(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 token,
- u64 blob_addr,
- u16 *error)
+/**
+ * dpsparser_apply_spb() - Applies the Soft Parser Blob loaded at specified address.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPSPARSER object
+ * @blob_addr: Blob loading address
+ * @error: Error reported by MC related to SP Blob parsing and apply
+ *
+ * Return: '0' on Success; error code otherwise.
+ */
+int dpsparser_apply_spb(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+ u64 blob_addr, u16 *error)
{
+ struct dpsparser_rsp_blob_report_error *rsp_params;
+ struct dpsparser_cmd_blob_set_address *cmd_params;
struct mc_command cmd = { 0 };
int err;
@@ -101,7 +157,8 @@ int dpsparser_apply_spb(struct fsl_mc_io *mc_io,
cmd.header = mc_encode_cmd_header(DPSPARSER_CMDID_APPLY_SPB,
cmd_flags,
token);
- DPSPARSER_CMD_BLOB_SET_ADDR(cmd, blob_addr);
+ cmd_params = (struct dpsparser_cmd_blob_set_address *)cmd.params;
+ cmd_params->blob_addr = cpu_to_le64(blob_addr);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -109,15 +166,24 @@ int dpsparser_apply_spb(struct fsl_mc_io *mc_io,
return err;
/* retrieve response parameters: MC error code */
- DPSPARSER_CMD_BLOB_REPORT_ERROR(cmd, *error);
+ rsp_params = (struct dpsparser_rsp_blob_report_error *)cmd.params;
+ *error = le16_to_cpu(rsp_params->error);
return 0;
}
-int dpsparser_get_api_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- u16 *major_ver,
- u16 *minor_ver)
+/**
+ * dpsparser_get_api_version - Retrieve DPSPARSER Major and Minor version info.
+ *
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: DPSPARSER major version
+ * @minor_ver: DPSPARSER minor version
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpsparser_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
+ u16 *major_ver, u16 *minor_ver)
{
struct mc_command cmd = { 0 };
int err;
diff --git a/drivers/net/fsl-mc/fsl_dpmng_cmd.h b/drivers/net/fsl-mc/fsl_dpmng_cmd.h
index e18c88da097..e6efceab7ac 100644
--- a/drivers/net/fsl-mc/fsl_dpmng_cmd.h
+++ b/drivers/net/fsl-mc/fsl_dpmng_cmd.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright 2013-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017, 2023 NXP
*/
#ifndef __FSL_DPMNG_CMD_H
#define __FSL_DPMNG_CMD_H
@@ -8,12 +8,13 @@
/* Command IDs */
#define DPMNG_CMDID_GET_VERSION 0x8311
-/* cmd, param, offset, width, type, arg_name */
-#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \
-do { \
- MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mc_ver_info->revision); \
- MC_RSP_OP(cmd, 0, 32, 32, uint32_t, mc_ver_info->major); \
- MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \
-} while (0)
+#pragma pack(push, 1)
+struct dpmng_rsp_get_version {
+ __le32 revision;
+ __le32 version_major;
+ __le32 version_minor;
+};
+
+#pragma pack(pop)
#endif /* __FSL_DPMNG_CMD_H */
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 78a40f285aa..984616fb65c 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -1353,10 +1353,9 @@ err:
static int dpni_init(void)
{
- int err;
- uint8_t cfg_buf[256] = {0};
- struct dpni_cfg dpni_cfg;
+ struct dpni_cfg dpni_cfg = {0};
uint16_t major_ver, minor_ver;
+ int err;
dflt_dpni = calloc(sizeof(struct fsl_dpni_obj), 1);
if (!dflt_dpni) {
@@ -1365,14 +1364,6 @@ static int dpni_init(void)
goto err_calloc;
}
- memset(&dpni_cfg, 0, sizeof(dpni_cfg));
- err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]);
- if (err < 0) {
- err = -ENODEV;
- printf("dpni_prepare_cfg() failed: %d\n", err);
- goto err_prepare_cfg;
- }
-
err = dpni_create(dflt_mc_io,
dflt_dprc_handle,
MC_CMD_NO_FLAGS,
@@ -1429,7 +1420,6 @@ err_get_version:
MC_CMD_NO_FLAGS,
dflt_dpni->dpni_id);
err_create:
-err_prepare_cfg:
free(dflt_dpni);
err_calloc:
return err;
diff --git a/drivers/net/fsl-mc/mc_sys.c b/drivers/net/fsl-mc/mc_sys.c
index b5ae2ea3eb5..4d32516b005 100644
--- a/drivers/net/fsl-mc/mc_sys.c
+++ b/drivers/net/fsl-mc/mc_sys.c
@@ -13,8 +13,13 @@
#include <asm/io.h>
#include <linux/delay.h>
-#define MC_CMD_HDR_READ_CMDID(_hdr) \
- ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S))
+static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
+{
+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
+ u16 cmd_id = le16_to_cpu(hdr->cmd_id);
+
+ return cmd_id;
+}
/**
* mc_send_command - Send MC command and wait for response
@@ -52,8 +57,8 @@ int mc_send_command(struct fsl_mc_io *mc_io,
if (status != MC_CMD_STATUS_OK) {
printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
mc_io->mmio_regs,
- (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
- (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
+ (unsigned int)mc_cmd_hdr_read_token(cmd),
+ (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
(unsigned int)status);
return -EIO;
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index 2cb6e9b7d70..87fbada06ba 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -38,146 +38,90 @@ static void init_phy(struct udevice *dev)
}
#endif
-#ifdef DEBUG
-
-#define DPNI_STATS_PER_PAGE 6
-
-static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
- {
- "DPNI_CNT_ING_ALL_FRAMES",
- "DPNI_CNT_ING_ALL_BYTES",
- "DPNI_CNT_ING_MCAST_FRAMES",
- "DPNI_CNT_ING_MCAST_BYTES",
- "DPNI_CNT_ING_BCAST_FRAMES",
- "DPNI_CNT_ING_BCAST_BYTES",
- }, {
- "DPNI_CNT_EGR_ALL_FRAMES",
- "DPNI_CNT_EGR_ALL_BYTES",
- "DPNI_CNT_EGR_MCAST_FRAMES",
- "DPNI_CNT_EGR_MCAST_BYTES",
- "DPNI_CNT_EGR_BCAST_FRAMES",
- "DPNI_CNT_EGR_BCAST_BYTES",
- }, {
- "DPNI_CNT_ING_FILTERED_FRAMES",
- "DPNI_CNT_ING_DISCARDED_FRAMES",
- "DPNI_CNT_ING_NOBUFFER_DISCARDS",
- "DPNI_CNT_EGR_DISCARDED_FRAMES",
- "DPNI_CNT_EGR_CNF_FRAMES",
- ""
- },
-};
-
-static void print_dpni_stats(const char *strings[],
- struct dpni_statistics dpni_stats)
+static void ldpaa_eth_collect_dpni_stats(struct udevice *dev, u64 *data)
{
- uint64_t *stat;
- int i;
+ union dpni_statistics dpni_stats;
+ int dpni_stats_page_size[DPNI_STATISTICS_CNT] = {
+ sizeof(dpni_stats.page_0),
+ sizeof(dpni_stats.page_1),
+ sizeof(dpni_stats.page_2),
+ sizeof(dpni_stats.page_3),
+ sizeof(dpni_stats.page_4),
+ sizeof(dpni_stats.page_5),
+ sizeof(dpni_stats.page_6),
+ };
+ int j, k, num_cnt, err, i = 0;
- stat = (uint64_t *)&dpni_stats;
- for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
- if (strcmp(strings[i], "\0") == 0)
- break;
- printf("%s= %llu\n", strings[i], *stat);
- stat++;
+ for (j = 0; j <= 6; j++) {
+ /* We're not interested in pages 4 & 5 for now */
+ if (j == 4 || j == 5)
+ continue;
+ err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
+ dflt_dpni->dpni_handle,
+ j, 0, &dpni_stats);
+ if (err) {
+ memset(&dpni_stats, 0, sizeof(dpni_stats));
+ printf("dpni_get_stats(%d) failed\n", j);
+ }
+
+ num_cnt = dpni_stats_page_size[j] / sizeof(u64);
+ for (k = 0; k < num_cnt; k++)
+ *(data + i++) = dpni_stats.raw.counter[k];
}
}
-static void ldpaa_eth_get_dpni_counter(void)
+static void ldpaa_eth_add_dpni_stats(struct udevice *dev, u64 *data)
{
- int err = 0;
- unsigned int page = 0;
- struct dpni_statistics dpni_stats;
+ struct ldpaa_eth_priv *priv = dev_get_priv(dev);
+ int i;
- printf("DPNI counters ..\n");
- for (page = 0; page < 3; page++) {
- err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
- dflt_dpni->dpni_handle, page,
- &dpni_stats);
- if (err < 0) {
- printf("dpni_get_statistics: failed:");
- printf("%d for page[%d]\n", err, page);
- return;
- }
- print_dpni_stats(dpni_statistics[page], dpni_stats);
- }
+ for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
+ priv->dpni_stats[i] += data[i];
}
-static void ldpaa_eth_get_dpmac_counter(struct udevice *dev)
+static void ldpaa_eth_collect_dpmac_stats(struct udevice *dev, u64 *data)
{
struct ldpaa_eth_priv *priv = dev_get_priv(dev);
- int err = 0;
+ int err, i;
u64 value;
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_ING_BYTE,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
- return;
- }
- printf("\nDPMAC counters ..\n");
- printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
+ for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
+ err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
+ priv->dpmac_handle, i,
+ &value);
+ if (err)
+ printf("dpmac_get_counter(%d) failed\n", i);
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_ING_FRAME_DISCARD,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
- return;
+ *(data + i) = value;
}
- printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
+}
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_ING_ALIGN_ERR,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
- return;
- }
- printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
+static void ldpaa_eth_add_dpmac_stats(struct udevice *dev, u64 *data)
+{
+ struct ldpaa_eth_priv *priv = dev_get_priv(dev);
+ int i;
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_ING_BYTE,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
- return;
- }
- printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
+ for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
+ priv->dpmac_stats[i] += data[i];
+}
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_ING_ERR_FRAME,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
- return;
- }
- printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
+#ifdef DEBUG
+static void ldpaa_eth_dump_dpni_stats(struct udevice *dev, u64 *data)
+{
+ int i;
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_EGR_BYTE ,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
- return;
- }
- printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
+ printf("DPNI counters:\n");
+ for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
+ printf(" %s: %llu\n", ldpaa_eth_dpni_stat_strings[i], data[i]);
+}
- err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
- priv->dpmac_handle,
- DPMAC_CNT_EGR_ERR_FRAME ,
- &value);
- if (err < 0) {
- printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
- return;
- }
- printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
+static void ldpaa_eth_dump_dpmac_stats(struct udevice *dev, u64 *data)
+{
+ int i;
+
+ printf("DPMAC counters:\n");
+ for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
+ printf(" %s: %llu\n", ldpaa_eth_dpmac_stat_strings[i], data[i]);
}
#endif
@@ -434,7 +378,8 @@ static int ldpaa_eth_open(struct udevice *dev)
struct dpni_link_state link_state;
#endif
int err = 0;
- struct dpni_queue d_queue;
+ struct dpni_queue d_queue_cfg = { 0 };
+ struct dpni_queue_id d_queue;
if (eth_is_active(dev))
return 0;
@@ -478,7 +423,7 @@ static int ldpaa_eth_open(struct udevice *dev)
goto err_dpni_bind;
err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
- dflt_dpni->dpni_handle, plat->enetaddr);
+ dflt_dpni->dpni_handle, plat->enetaddr, 0, 0, 0);
if (err) {
printf("dpni_add_mac_addr() failed\n");
return err;
@@ -517,7 +462,7 @@ static int ldpaa_eth_open(struct udevice *dev)
memset(&d_queue, 0, sizeof(struct dpni_queue));
err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
- 0, 0, &d_queue);
+ 0, 0, &d_queue_cfg, &d_queue);
if (err) {
printf("dpni_get_queue failed\n");
goto err_get_queue;
@@ -526,7 +471,7 @@ static int ldpaa_eth_open(struct udevice *dev)
priv->rx_dflt_fqid = d_queue.fqid;
err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
- &priv->tx_qdid);
+ DPNI_QUEUE_TX, &priv->tx_qdid);
if (err) {
printf("dpni_get_qdid() failed\n");
goto err_qdid;
@@ -556,14 +501,30 @@ static void ldpaa_eth_stop(struct udevice *dev)
struct ldpaa_eth_priv *priv = dev_get_priv(dev);
struct phy_device *phydev = NULL;
int err = 0;
+ u64 *data;
if (!eth_is_active(dev))
return;
+ data = kzalloc(sizeof(u64) * LDPAA_ETH_DPNI_NUM_STATS, GFP_KERNEL);
+ if (data) {
+ ldpaa_eth_collect_dpni_stats(dev, data);
+ ldpaa_eth_add_dpni_stats(dev, data);
#ifdef DEBUG
- ldpaa_eth_get_dpni_counter();
- ldpaa_eth_get_dpmac_counter(dev);
+ ldpaa_eth_dump_dpni_stats(dev, data);
#endif
+ }
+ kfree(data);
+
+ data = kzalloc(sizeof(u64) * LDPAA_ETH_DPMAC_NUM_STATS, GFP_KERNEL);
+ if (data) {
+ ldpaa_eth_collect_dpmac_stats(dev, data);
+ ldpaa_eth_add_dpmac_stats(dev, data);
+#ifdef DEBUG
+ ldpaa_eth_dump_dpmac_stats(dev, data);
+#endif
+ }
+ kfree(data);
err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dprc_handle, &dpmac_endpoint);
@@ -885,7 +846,7 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
/* ...rx, ... */
err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle,
- &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
+ DPNI_QUEUE_RX, &dflt_dpni->buf_layout);
if (err) {
printf("dpni_set_buffer_layout() failed");
goto err_buf_layout;
@@ -897,7 +858,7 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle,
- &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
+ DPNI_QUEUE_TX, &dflt_dpni->buf_layout);
if (err) {
printf("dpni_set_buffer_layout() failed");
goto err_buf_layout;
@@ -907,8 +868,7 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle,
- &dflt_dpni->buf_layout,
- DPNI_QUEUE_TX_CONFIRM);
+ DPNI_QUEUE_TX_CONFIRM, &dflt_dpni->buf_layout);
if (err) {
printf("dpni_set_buffer_layout() failed");
goto err_buf_layout;
@@ -963,7 +923,7 @@ static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle,
- DPNI_QUEUE_TX, 0, 0, &tx_queue);
+ DPNI_QUEUE_TX, 0, 0, 0, &tx_queue);
if (err) {
printf("dpni_set_queue() failed\n");
@@ -972,7 +932,7 @@ static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
dflt_dpni->dpni_handle,
- DPNI_CONF_DISABLE);
+ 0, DPNI_CONF_DISABLE);
if (err) {
printf("dpni_set_tx_confirmation_mode() failed\n");
return err;
@@ -1038,11 +998,47 @@ static int ldpaa_eth_of_to_plat(struct udevice *dev)
return 0;
}
+static int ldpaa_eth_get_sset_count(struct udevice *dev)
+{
+ return LDPAA_ETH_DPNI_NUM_STATS + LDPAA_ETH_DPMAC_NUM_STATS;
+}
+
+static void ldpaa_eth_get_strings(struct udevice *dev, u8 *data)
+{
+ u8 *p = data;
+ int i;
+
+ for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++) {
+ strlcpy(p, ldpaa_eth_dpni_stat_strings[i], ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+
+ for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
+ strlcpy(p, ldpaa_eth_dpmac_stat_strings[i], ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+}
+
+static void ldpaa_eth_get_stats(struct udevice *dev, u64 *data)
+{
+ struct ldpaa_eth_priv *priv = dev_get_priv(dev);
+ int i, j = 0;
+
+ for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
+ *(data + j++) = priv->dpni_stats[i];
+
+ for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
+ *(data + j++) = priv->dpmac_stats[i];
+}
+
static const struct eth_ops ldpaa_eth_ops = {
- .start = ldpaa_eth_open,
- .send = ldpaa_eth_tx,
- .recv = ldpaa_eth_pull_dequeue_rx,
- .stop = ldpaa_eth_stop,
+ .start = ldpaa_eth_open,
+ .send = ldpaa_eth_tx,
+ .recv = ldpaa_eth_pull_dequeue_rx,
+ .stop = ldpaa_eth_stop,
+ .get_sset_count = ldpaa_eth_get_sset_count,
+ .get_strings = ldpaa_eth_get_strings,
+ .get_stats = ldpaa_eth_get_stats,
};
static const struct udevice_id ldpaa_eth_of_ids[] = {
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h
index 16d0106233e..af082e34cae 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.h
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.h
@@ -115,6 +115,66 @@ struct ldpaa_fas {
LDPAA_ETH_FAS_MNLE | \
LDPAA_ETH_FAS_TIDE)
+static const char ldpaa_eth_dpni_stat_strings[][ETH_GSTRING_LEN] = {
+ "[dpni ] rx frames",
+ "[dpni ] rx bytes",
+ "[dpni ] rx mcast frames",
+ "[dpni ] rx mcast bytes",
+ "[dpni ] rx bcast frames",
+ "[dpni ] rx bcast bytes",
+ "[dpni ] tx frames",
+ "[dpni ] tx bytes",
+ "[dpni ] tx mcast frames",
+ "[dpni ] tx mcast bytes",
+ "[dpni ] tx bcast frames",
+ "[dpni ] tx bcast bytes",
+ "[dpni ] rx filtered frames",
+ "[dpni ] rx discarded frames",
+ "[dpni ] rx nobuffer discards",
+ "[dpni ] tx discarded frames",
+ "[dpni ] tx confirmed frames",
+ "[dpni ] tx dequeued bytes",
+ "[dpni ] tx dequeued frames",
+ "[dpni ] tx rejected bytes",
+ "[dpni ] tx rejected frames",
+ "[dpni ] tx pending frames",
+};
+
+#define LDPAA_ETH_DPNI_NUM_STATS ARRAY_SIZE(ldpaa_eth_dpni_stat_strings)
+
+static const char ldpaa_eth_dpmac_stat_strings[][ETH_GSTRING_LEN] = {
+ [DPMAC_CNT_ING_ALL_FRAME] = "[mac] rx all frames",
+ [DPMAC_CNT_ING_GOOD_FRAME] = "[mac] rx frames ok",
+ [DPMAC_CNT_ING_ERR_FRAME] = "[mac] rx frame errors",
+ [DPMAC_CNT_ING_FRAME_DISCARD] = "[mac] rx frame discards",
+ [DPMAC_CNT_ING_UCAST_FRAME] = "[mac] rx u-cast",
+ [DPMAC_CNT_ING_BCAST_FRAME] = "[mac] rx b-cast",
+ [DPMAC_CNT_ING_MCAST_FRAME] = "[mac] rx m-cast",
+ [DPMAC_CNT_ING_FRAME_64] = "[mac] rx 64 bytes",
+ [DPMAC_CNT_ING_FRAME_127] = "[mac] rx 65-127 bytes",
+ [DPMAC_CNT_ING_FRAME_255] = "[mac] rx 128-255 bytes",
+ [DPMAC_CNT_ING_FRAME_511] = "[mac] rx 256-511 bytes",
+ [DPMAC_CNT_ING_FRAME_1023] = "[mac] rx 512-1023 bytes",
+ [DPMAC_CNT_ING_FRAME_1518] = "[mac] rx 1024-1518 bytes",
+ [DPMAC_CNT_ING_FRAME_1519_MAX] = "[mac] rx 1519-max bytes",
+ [DPMAC_CNT_ING_FRAG] = "[mac] rx frags",
+ [DPMAC_CNT_ING_JABBER] = "[mac] rx jabber",
+ [DPMAC_CNT_ING_ALIGN_ERR] = "[mac] rx align errors",
+ [DPMAC_CNT_ING_OVERSIZED] = "[mac] rx oversized",
+ [DPMAC_CNT_ING_VALID_PAUSE_FRAME] = "[mac] rx pause",
+ [DPMAC_CNT_ING_BYTE] = "[mac] rx bytes",
+ [DPMAC_CNT_EGR_GOOD_FRAME] = "[mac] tx frames ok",
+ [DPMAC_CNT_EGR_UCAST_FRAME] = "[mac] tx u-cast",
+ [DPMAC_CNT_EGR_MCAST_FRAME] = "[mac] tx m-cast",
+ [DPMAC_CNT_EGR_BCAST_FRAME] = "[mac] tx b-cast",
+ [DPMAC_CNT_EGR_ERR_FRAME] = "[mac] tx frame errors",
+ [DPMAC_CNT_EGR_UNDERSIZED] = "[mac] tx undersized",
+ [DPMAC_CNT_EGR_VALID_PAUSE_FRAME] = "[mac] tx b-pause",
+ [DPMAC_CNT_EGR_BYTE] = "[mac] tx bytes",
+};
+
+#define LDPAA_ETH_DPMAC_NUM_STATS ARRAY_SIZE(ldpaa_eth_dpmac_stat_strings)
+
struct ldpaa_eth_priv {
struct phy_device *phy;
int phy_mode;
@@ -129,6 +189,10 @@ struct ldpaa_eth_priv {
uint16_t tx_flow_id;
enum ldpaa_eth_type type; /* 1G or 10G ethernet */
+
+ /* SW kept statistics */
+ u64 dpni_stats[LDPAA_ETH_DPNI_NUM_STATS];
+ u64 dpmac_stats[LDPAA_ETH_DPMAC_NUM_STATS];
};
struct dprc_endpoint dpmac_endpoint;
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index ad7b5b8e99b..ecf8c28fe41 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -414,16 +414,13 @@ static int pch_gbe_phy_init(struct udevice *dev)
struct pch_gbe_priv *priv = dev_get_priv(dev);
struct eth_pdata *plat = dev_get_plat(dev);
struct phy_device *phydev;
- int mask = 0xffffffff;
- phydev = phy_find_by_mask(priv->bus, mask);
+ phydev = phy_connect(priv->bus, -1, dev, plat->phy_interface);
if (!phydev) {
printf("pch_gbe: cannot find the phy\n");
return -1;
}
- phy_connect_dev(phydev, dev, plat->phy_interface);
-
phydev->supported &= PHY_GBIT_FEATURES;
phydev->advertising = phydev->supported;
diff --git a/drivers/net/pfe_eth/pfe_hw.c b/drivers/net/pfe_eth/pfe_hw.c
index 4db6f3158c3..9f2f92d116d 100644
--- a/drivers/net/pfe_eth/pfe_hw.c
+++ b/drivers/net/pfe_eth/pfe_hw.c
@@ -814,7 +814,7 @@ static inline void class_set_config(struct class_cfg *cfg)
writel(0x1, CLASS_AXI_CTRL);
/*Make Util AXI transactions non-bufferable */
- /*Util is disabled in U-boot, do it from here */
+ /*Util is disabled in U-Boot, do it from here */
writel(0x1, UTIL_AXI_CTRL);
}
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
index a715e83db98..877a51c3d00 100644
--- a/drivers/net/phy/ethernet_id.c
+++ b/drivers/net/phy/ethernet_id.c
@@ -7,6 +7,8 @@
#include <common.h>
#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
#include <phy.h>
#include <linux/delay.h>
#include <asm/gpio.h>
@@ -17,6 +19,8 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
struct phy_device *phydev;
struct ofnode_phandle_args phandle_args;
struct gpio_desc gpio;
+ const char *node_name;
+ struct udevice *pdev;
ofnode node;
u32 id, assert, deassert;
u16 vendor, device;
@@ -72,5 +76,18 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
if (phydev)
phydev->node = node;
+ if (IS_ENABLED(CONFIG_DM_ETH_PHY) && ofnode_valid(node)) {
+ node_name = ofnode_get_name(node);
+ ret = device_bind_driver_to_node(dev, "eth_phy_generic_drv",
+ node_name, node,
+ &pdev);
+ if (ret)
+ return NULL;
+
+ ret = device_probe(pdev);
+ if (ret)
+ return NULL;
+ }
+
return phydev;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 0eeb0cb3a85..ae21acb059b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -812,8 +812,8 @@ struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask)
return get_phy_device_by_mask(bus, phy_mask);
}
-void phy_connect_dev(struct phy_device *phydev, struct udevice *dev,
- phy_interface_t interface)
+static void phy_connect_dev(struct phy_device *phydev, struct udevice *dev,
+ phy_interface_t interface)
{
/* Soft Reset the PHY */
phy_reset(phydev);
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index c74c8a81f94..0bcd6cfd3f3 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -131,7 +131,6 @@ struct ravb_priv {
struct mii_dev *bus;
void __iomem *iobase;
struct clk_bulk clks;
- struct gpio_desc reset_gpio;
};
static inline void ravb_flush_dcache(u32 addr, u32 len)
@@ -312,13 +311,6 @@ static int ravb_phy_config(struct udevice *dev)
struct phy_device *phydev;
int reg;
- if (dm_gpio_is_valid(&eth->reset_gpio)) {
- dm_gpio_set_value(&eth->reset_gpio, 1);
- mdelay(20);
- dm_gpio_set_value(&eth->reset_gpio, 0);
- mdelay(1);
- }
-
phydev = phy_connect(eth->bus, -1, dev, pdata->phy_interface);
if (!phydev)
return -ENODEV;
@@ -503,7 +495,6 @@ static int ravb_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct ravb_priv *eth = dev_get_priv(dev);
- struct ofnode_phandle_args phandle_args;
struct mii_dev *mdiodev;
void __iomem *iobase;
int ret;
@@ -515,17 +506,6 @@ static int ravb_probe(struct udevice *dev)
if (ret < 0)
goto err_mdio_alloc;
- ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &phandle_args);
- if (!ret) {
- gpio_request_by_name_nodev(phandle_args.node, "reset-gpios", 0,
- &eth->reset_gpio, GPIOD_IS_OUT);
- }
-
- if (!dm_gpio_is_valid(&eth->reset_gpio)) {
- gpio_request_by_name(dev, "reset-gpios", 0, &eth->reset_gpio,
- GPIOD_IS_OUT);
- }
-
mdiodev = mdio_alloc();
if (!mdiodev) {
ret = -ENOMEM;
@@ -576,8 +556,6 @@ static int ravb_remove(struct udevice *dev)
free(eth->phydev);
mdio_unregister(eth->bus);
mdio_free(eth->bus);
- if (dm_gpio_is_valid(&eth->reset_gpio))
- dm_gpio_free(dev, &eth->reset_gpio);
unmap_physmem(eth->iobase, MAP_NOCACHE);
return 0;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 8f162ca58fb..7b1f59dc498 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -129,11 +129,11 @@ static int sh_eth_recv_start(struct sh_eth_dev *eth)
/* Check if the rx descriptor is ready */
invalidate_cache(port_info->rx_desc_cur, sizeof(struct rx_desc_s));
if (port_info->rx_desc_cur->rd0 & RD_RACT)
- return -EINVAL;
+ return -EAGAIN;
/* Check for errors */
if (port_info->rx_desc_cur->rd0 & RD_RFE)
- return -EINVAL;
+ return 0;
return port_info->rx_desc_cur->rd1 & 0xffff;
}
@@ -142,6 +142,8 @@ static void sh_eth_recv_finish(struct sh_eth_dev *eth)
{
struct sh_eth_info *port_info = &eth->port_info[eth->port];
+ invalidate_cache(ADDR_TO_P2(port_info->rx_desc_cur->rd2), MAX_BUF_SIZE);
+
/* Make current descriptor available again */
if (port_info->rx_desc_cur->rd0 & RD_RDLE)
port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
@@ -210,8 +212,6 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
goto err;
}
- flush_cache_wback(port_info->tx_desc_alloc, alloc_desc_size);
-
/* Make sure we use a P2 address (non-cacheable) */
port_info->tx_desc_base =
(struct tx_desc_s *)ADDR_TO_P2((uintptr_t)port_info->tx_desc_alloc);
@@ -229,6 +229,7 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
cur_tx_desc--;
cur_tx_desc->td0 |= TD_TDLE;
+ flush_cache_wback(port_info->tx_desc_alloc, alloc_desc_size);
/*
* Point the controller to the tx descriptor list. Must use physical
* addresses
@@ -264,8 +265,6 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
goto err;
}
- flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
-
/* Make sure we use a P2 address (non-cacheable) */
port_info->rx_desc_base =
(struct rx_desc_s *)ADDR_TO_P2((uintptr_t)port_info->rx_desc_alloc);
@@ -299,6 +298,9 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
cur_rx_desc--;
cur_rx_desc->rd0 |= RD_RDLE;
+ invalidate_cache(port_info->rx_buf_alloc, NUM_RX_DESC * MAX_BUF_SIZE);
+ flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
+
/* Point the controller to the rx descriptor list */
sh_eth_write(port_info, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
@@ -530,7 +532,6 @@ struct sh_ether_priv {
struct mii_dev *bus;
phys_addr_t iobase;
struct clk clk;
- struct gpio_desc reset_gpio;
};
static int sh_ether_send(struct udevice *dev, void *packet, int len)
@@ -555,15 +556,13 @@ static int sh_ether_recv(struct udevice *dev, int flags, uchar **packetp)
*packetp = packet;
return len;
- } else {
- len = 0;
+ }
- /* Restart the receiver if disabled */
- if (!(sh_eth_read(port_info, EDRRR) & EDRRR_R))
- sh_eth_write(port_info, EDRRR_R, EDRRR);
+ /* Restart the receiver if disabled */
+ if (!(sh_eth_read(port_info, EDRRR) & EDRRR_R))
+ sh_eth_write(port_info, EDRRR_R, EDRRR);
- return -EAGAIN;
- }
+ return len;
}
static int sh_ether_free_pkt(struct udevice *dev, uchar *packet, int length)
@@ -601,14 +600,11 @@ static int sh_eth_phy_config(struct udevice *dev)
int ret = 0;
struct sh_eth_info *port_info = &eth->port_info[eth->port];
struct phy_device *phydev;
- int mask = 0xffffffff;
- phydev = phy_find_by_mask(priv->bus, mask);
+ phydev = phy_connect(priv->bus, -1, dev, pdata->phy_interface);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, pdata->phy_interface);
-
port_info->phydev = phydev;
phy_config(phydev);
@@ -653,7 +649,6 @@ static int sh_ether_probe(struct udevice *udev)
struct eth_pdata *pdata = dev_get_plat(udev);
struct sh_ether_priv *priv = dev_get_priv(udev);
struct sh_eth_dev *eth = &priv->shdev;
- struct ofnode_phandle_args phandle_args;
struct mii_dev *mdiodev;
int ret;
@@ -664,18 +659,6 @@ static int sh_ether_probe(struct udevice *udev)
if (ret < 0)
return ret;
#endif
-
- ret = dev_read_phandle_with_args(udev, "phy-handle", NULL, 0, 0, &phandle_args);
- if (!ret) {
- gpio_request_by_name_nodev(phandle_args.node, "reset-gpios", 0,
- &priv->reset_gpio, GPIOD_IS_OUT);
- }
-
- if (!dm_gpio_is_valid(&priv->reset_gpio)) {
- gpio_request_by_name(udev, "reset-gpios", 0, &priv->reset_gpio,
- GPIOD_IS_OUT);
- }
-
mdiodev = mdio_alloc();
if (!mdiodev) {
ret = -ENOMEM;
@@ -738,9 +721,6 @@ static int sh_ether_remove(struct udevice *udev)
mdio_unregister(priv->bus);
mdio_free(priv->bus);
- if (dm_gpio_is_valid(&priv->reset_gpio))
- dm_gpio_free(udev, &priv->reset_gpio);
-
return 0;
}
diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c
index 014b070d9e5..f5a0d80af7a 100644
--- a/drivers/net/sni_ave.c
+++ b/drivers/net/sni_ave.c
@@ -391,14 +391,12 @@ static int ave_mdiobus_init(struct ave_private *priv, const char *name)
static int ave_phy_init(struct ave_private *priv, void *dev)
{
struct phy_device *phydev;
- int mask = GENMASK(31, 0), ret;
+ int ret;
- phydev = phy_find_by_mask(priv->bus, mask);
+ phydev = phy_connect(priv->bus, -1, dev, priv->phy_mode);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, priv->phy_mode);
-
phydev->supported &= PHY_GBIT_FEATURES;
if (priv->max_speed) {
ret = phy_set_supported(phydev, priv->max_speed);
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index ad9e1abd161..4c90d4b4981 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -248,10 +248,10 @@ static int emac_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev)
{
- int ret, mask = 0xffffffff;
+ int ret, mask = -1;
#ifdef CONFIG_PHY_ADDR
- mask = 1 << CONFIG_PHY_ADDR;
+ mask = CONFIG_PHY_ADDR;
#endif
priv->bus = mdio_alloc();
@@ -269,11 +269,10 @@ static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev)
if (ret)
return ret;
- priv->phydev = phy_find_by_mask(priv->bus, mask);
+ priv->phydev = phy_connect(priv->bus, mask, dev, PHY_INTERFACE_MODE_MII);
if (!priv->phydev)
return -ENODEV;
- phy_connect_dev(priv->phydev, dev, PHY_INTERFACE_MODE_MII);
phy_config(priv->phydev);
return 0;
diff --git a/drivers/net/ti/davinci_emac.c b/drivers/net/ti/davinci_emac.c
index 29d2fc9b54e..034877a7690 100644
--- a/drivers/net/ti/davinci_emac.c
+++ b/drivers/net/ti/davinci_emac.c
@@ -833,9 +833,9 @@ static int davinci_emac_probe(struct udevice *dev)
#endif
}
-#if defined(CONFIG_TI816X) || (defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \
- !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE))
+ !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE)
for (i = 0; i < num_phy; i++) {
if (phy[i].is_phy_connected(i))
phy[i].auto_negotiate(i);
diff --git a/drivers/nvme/Makefile b/drivers/nvme/Makefile
index fa7b6194460..fd3e68a91dc 100644
--- a/drivers/nvme/Makefile
+++ b/drivers/nvme/Makefile
@@ -4,4 +4,4 @@
obj-y += nvme-uclass.o nvme.o nvme_show.o
obj-$(CONFIG_NVME_APPLE) += nvme_apple.o
-obj-$(CONFIG_NVME_PCI) += nvme_pci.o
+obj-$(CONFIG_$(SPL_)NVME_PCI) += nvme_pci.o
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index ef328d26525..84a2ae951f7 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -40,6 +40,12 @@ config PCI_PNP
help
Enable PCI memory and I/O space resource allocation and assignment.
+config SPL_PCI_PNP
+ bool "Enable Plug & Play support for PCI"
+ help
+ Enable PCI memory and I/O space resource allocation and assignment.
+ This is required to auto configure the enumerated devices.
+
config PCI_REGION_MULTI_ENTRY
bool "Enable Multiple entries of region type MEMORY in ranges for PCI"
help
@@ -374,4 +380,11 @@ config PCIE_UNIPHIER
Say Y here if you want to enable PCIe controller support on
UniPhier SoCs.
+config PCIE_XILINX_NWL
+ bool "Xilinx NWL PCIe controller"
+ depends on ARCH_ZYNQMP
+ help
+ Say 'Y' here if you want support for Xilinx / AMD NWL PCIe
+ controller as Root Port.
+
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 49506e7ba59..11f60c6991d 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o
obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o
obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
+obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
diff --git a/drivers/pci/pcie-xilinx-nwl.c b/drivers/pci/pcie-xilinx-nwl.c
new file mode 100644
index 00000000000..7ef2bdf57b5
--- /dev/null
+++ b/drivers/pci/pcie-xilinx-nwl.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host bridge driver for Xilinx / AMD ZynqMP NWL PCIe Bridge
+ *
+ * Based on the Linux driver which is:
+ * (C) Copyright 2014 - 2015, Xilinx, Inc.
+ *
+ * Author: Stefan Roese <sr@denx.de>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <mapmem.h>
+#include <pci.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+
+/* Bridge core config registers */
+#define BRCFG_PCIE_RX0 0x00000000
+#define BRCFG_PCIE_RX1 0x00000004
+#define BRCFG_INTERRUPT 0x00000010
+#define BRCFG_PCIE_RX_MSG_FILTER 0x00000020
+
+/* Egress - Bridge translation registers */
+#define E_BREG_CAPABILITIES 0x00000200
+#define E_BREG_CONTROL 0x00000208
+#define E_BREG_BASE_LO 0x00000210
+#define E_BREG_BASE_HI 0x00000214
+#define E_ECAM_CAPABILITIES 0x00000220
+#define E_ECAM_CONTROL 0x00000228
+#define E_ECAM_BASE_LO 0x00000230
+#define E_ECAM_BASE_HI 0x00000234
+
+#define I_ISUB_CONTROL 0x000003E8
+#define SET_ISUB_CONTROL BIT(0)
+/* Rxed msg fifo - Interrupt status registers */
+#define MSGF_MISC_STATUS 0x00000400
+#define MSGF_MISC_MASK 0x00000404
+#define MSGF_LEG_STATUS 0x00000420
+#define MSGF_LEG_MASK 0x00000424
+#define MSGF_MSI_STATUS_LO 0x00000440
+#define MSGF_MSI_STATUS_HI 0x00000444
+#define MSGF_MSI_MASK_LO 0x00000448
+#define MSGF_MSI_MASK_HI 0x0000044C
+
+/* Msg filter mask bits */
+#define CFG_ENABLE_PM_MSG_FWD BIT(1)
+#define CFG_ENABLE_INT_MSG_FWD BIT(2)
+#define CFG_ENABLE_ERR_MSG_FWD BIT(3)
+#define CFG_ENABLE_MSG_FILTER_MASK (CFG_ENABLE_PM_MSG_FWD | \
+ CFG_ENABLE_INT_MSG_FWD | \
+ CFG_ENABLE_ERR_MSG_FWD)
+
+/* Misc interrupt status mask bits */
+#define MSGF_MISC_SR_RXMSG_AVAIL BIT(0)
+#define MSGF_MISC_SR_RXMSG_OVER BIT(1)
+#define MSGF_MISC_SR_SLAVE_ERR BIT(4)
+#define MSGF_MISC_SR_MASTER_ERR BIT(5)
+#define MSGF_MISC_SR_I_ADDR_ERR BIT(6)
+#define MSGF_MISC_SR_E_ADDR_ERR BIT(7)
+#define MSGF_MISC_SR_FATAL_AER BIT(16)
+#define MSGF_MISC_SR_NON_FATAL_AER BIT(17)
+#define MSGF_MISC_SR_CORR_AER BIT(18)
+#define MSGF_MISC_SR_UR_DETECT BIT(20)
+#define MSGF_MISC_SR_NON_FATAL_DEV BIT(22)
+#define MSGF_MISC_SR_FATAL_DEV BIT(23)
+#define MSGF_MISC_SR_LINK_DOWN BIT(24)
+#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25)
+#define MSGF_MSIC_SR_LINK_BWIDTH BIT(26)
+
+#define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \
+ MSGF_MISC_SR_RXMSG_OVER | \
+ MSGF_MISC_SR_SLAVE_ERR | \
+ MSGF_MISC_SR_MASTER_ERR | \
+ MSGF_MISC_SR_I_ADDR_ERR | \
+ MSGF_MISC_SR_E_ADDR_ERR | \
+ MSGF_MISC_SR_FATAL_AER | \
+ MSGF_MISC_SR_NON_FATAL_AER | \
+ MSGF_MISC_SR_CORR_AER | \
+ MSGF_MISC_SR_UR_DETECT | \
+ MSGF_MISC_SR_NON_FATAL_DEV | \
+ MSGF_MISC_SR_FATAL_DEV | \
+ MSGF_MISC_SR_LINK_DOWN | \
+ MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \
+ MSGF_MSIC_SR_LINK_BWIDTH)
+
+/* Legacy interrupt status mask bits */
+#define MSGF_LEG_SR_INTA BIT(0)
+#define MSGF_LEG_SR_INTB BIT(1)
+#define MSGF_LEG_SR_INTC BIT(2)
+#define MSGF_LEG_SR_INTD BIT(3)
+#define MSGF_LEG_SR_MASKALL (MSGF_LEG_SR_INTA | MSGF_LEG_SR_INTB | \
+ MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD)
+
+/* MSI interrupt status mask bits */
+#define MSGF_MSI_SR_LO_MASK GENMASK(31, 0)
+#define MSGF_MSI_SR_HI_MASK GENMASK(31, 0)
+
+/* Bridge config interrupt mask */
+#define BRCFG_INTERRUPT_MASK BIT(0)
+#define BREG_PRESENT BIT(0)
+#define BREG_ENABLE BIT(0)
+#define BREG_ENABLE_FORCE BIT(1)
+
+/* E_ECAM status mask bits */
+#define E_ECAM_PRESENT BIT(0)
+#define E_ECAM_CR_ENABLE BIT(0)
+#define E_ECAM_SIZE_LOC GENMASK(20, 16)
+#define E_ECAM_SIZE_SHIFT 16
+#define NWL_ECAM_VALUE_DEFAULT 12
+
+#define CFG_DMA_REG_BAR GENMASK(2, 0)
+#define CFG_PCIE_CACHE GENMASK(7, 0)
+
+/* Readin the PS_LINKUP */
+#define PS_LINKUP_OFFSET 0x00000238
+#define PCIE_PHY_LINKUP_BIT BIT(0)
+#define PHY_RDY_LINKUP_BIT BIT(1)
+
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES 10
+#define LINK_WAIT_USLEEP_MIN 90000
+#define LINK_WAIT_USLEEP_MAX 100000
+
+struct nwl_pcie {
+ struct udevice *dev;
+ void __iomem *breg_base;
+ void __iomem *pcireg_base;
+ void __iomem *ecam_base;
+ phys_addr_t phys_breg_base; /* Physical Bridge Register Base */
+ phys_addr_t phys_ecam_base; /* Physical Configuration Base */
+ u32 ecam_value;
+};
+
+static int nwl_pcie_config_address(const struct udevice *bus,
+ pci_dev_t bdf, uint offset,
+ void **paddress)
+{
+ struct nwl_pcie *pcie = dev_get_priv(bus);
+ void *addr;
+
+ addr = pcie->ecam_base;
+ addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - dev_seq(bus),
+ PCI_DEV(bdf), PCI_FUNC(bdf), offset);
+ *paddress = addr;
+
+ return 0;
+}
+
+static int nwl_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong *valuep,
+ enum pci_size_t size)
+{
+ return pci_generic_mmap_read_config(bus, nwl_pcie_config_address,
+ bdf, offset, valuep, size);
+}
+
+static int nwl_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong value,
+ enum pci_size_t size)
+{
+ return pci_generic_mmap_write_config(bus, nwl_pcie_config_address,
+ bdf, offset, value, size);
+}
+
+static const struct dm_pci_ops nwl_pcie_ops = {
+ .read_config = nwl_pcie_read_config,
+ .write_config = nwl_pcie_write_config,
+};
+
+static inline u32 nwl_bridge_readl(struct nwl_pcie *pcie, u32 off)
+{
+ return readl(pcie->breg_base + off);
+}
+
+static inline void nwl_bridge_writel(struct nwl_pcie *pcie, u32 val, u32 off)
+{
+ writel(val, pcie->breg_base + off);
+}
+
+static bool nwl_pcie_link_up(struct nwl_pcie *pcie)
+{
+ if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PCIE_PHY_LINKUP_BIT)
+ return true;
+ return false;
+}
+
+static bool nwl_phy_link_up(struct nwl_pcie *pcie)
+{
+ if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PHY_RDY_LINKUP_BIT)
+ return true;
+ return false;
+}
+
+static int nwl_wait_for_link(struct nwl_pcie *pcie)
+{
+ struct udevice *dev = pcie->dev;
+ int retries;
+
+ /* check if the link is up or not */
+ for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ if (nwl_phy_link_up(pcie))
+ return 0;
+ udelay(LINK_WAIT_USLEEP_MIN);
+ }
+
+ dev_warn(dev, "PHY link never came up\n");
+ return -ETIMEDOUT;
+}
+
+static int nwl_pcie_bridge_init(struct nwl_pcie *pcie)
+{
+ struct udevice *dev = pcie->dev;
+ u32 breg_val, ecam_val;
+ int err;
+
+ breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) & BREG_PRESENT;
+ if (!breg_val) {
+ dev_err(dev, "BREG is not present\n");
+ return breg_val;
+ }
+
+ /* Write bridge_off to breg base */
+ nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_breg_base),
+ E_BREG_BASE_LO);
+ nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_breg_base),
+ E_BREG_BASE_HI);
+
+ /* Enable BREG */
+ nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE,
+ E_BREG_CONTROL);
+
+ /* Disable DMA channel registers */
+ nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_PCIE_RX0) |
+ CFG_DMA_REG_BAR, BRCFG_PCIE_RX0);
+
+ /* Enable Ingress subtractive decode translation */
+ nwl_bridge_writel(pcie, SET_ISUB_CONTROL, I_ISUB_CONTROL);
+
+ /* Enable msg filtering details */
+ nwl_bridge_writel(pcie, CFG_ENABLE_MSG_FILTER_MASK,
+ BRCFG_PCIE_RX_MSG_FILTER);
+
+ err = nwl_wait_for_link(pcie);
+ if (err)
+ return err;
+
+ ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) & E_ECAM_PRESENT;
+ if (!ecam_val) {
+ dev_err(dev, "ECAM is not present\n");
+ return ecam_val;
+ }
+
+ /* Enable ECAM */
+ nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+ E_ECAM_CR_ENABLE, E_ECAM_CONTROL);
+
+ nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+ (pcie->ecam_value << E_ECAM_SIZE_SHIFT),
+ E_ECAM_CONTROL);
+
+ nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_ecam_base),
+ E_ECAM_BASE_LO);
+ nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_ecam_base),
+ E_ECAM_BASE_HI);
+
+ if (nwl_pcie_link_up(pcie))
+ dev_info(dev, "Link is UP\n");
+ else
+ dev_info(dev, "Link is DOWN\n");
+
+ /* Disable all misc interrupts */
+ nwl_bridge_writel(pcie, (u32)~MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
+
+ /* Clear pending misc interrupts */
+ nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MISC_STATUS) &
+ MSGF_MISC_SR_MASKALL, MSGF_MISC_STATUS);
+
+ /* Disable all legacy interrupts */
+ nwl_bridge_writel(pcie, (u32)~MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
+
+ /* Clear pending legacy interrupts */
+ nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
+ MSGF_LEG_SR_MASKALL, MSGF_LEG_STATUS);
+
+ return 0;
+}
+
+static int nwl_pcie_parse_dt(struct nwl_pcie *pcie)
+{
+ struct udevice *dev = pcie->dev;
+ struct resource res;
+ int ret;
+
+ ret = dev_read_resource_byname(dev, "breg", &res);
+ if (ret)
+ return ret;
+ pcie->breg_base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(pcie->breg_base))
+ return PTR_ERR(pcie->breg_base);
+ pcie->phys_breg_base = res.start;
+
+ ret = dev_read_resource_byname(dev, "cfg", &res);
+ if (ret)
+ return ret;
+ pcie->ecam_base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(pcie->ecam_base))
+ return PTR_ERR(pcie->ecam_base);
+ pcie->phys_ecam_base = res.start;
+
+ return 0;
+}
+
+static int nwl_pcie_probe(struct udevice *dev)
+{
+ struct nwl_pcie *pcie = dev_get_priv(dev);
+ int err;
+
+ pcie->dev = dev;
+ pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT;
+
+ err = nwl_pcie_parse_dt(pcie);
+ if (err) {
+ dev_err(dev, "Parsing DT failed\n");
+ return err;
+ }
+
+ err = nwl_pcie_bridge_init(pcie);
+ if (err) {
+ dev_err(dev, "HW Initialization failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id nwl_pcie_of_match[] = {
+ { .compatible = "xlnx,nwl-pcie-2.11", },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(nwl_pcie) = {
+ .name = "nwl-pcie",
+ .id = UCLASS_PCI,
+ .of_match = nwl_pcie_of_match,
+ .probe = nwl_pcie_probe,
+ .priv_auto = sizeof(struct nwl_pcie),
+ .ops = &nwl_pcie_ops,
+};
diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c
index e063b51c6dd..a7e0099045f 100644
--- a/drivers/phy/marvell/comphy_cp110.c
+++ b/drivers/phy/marvell/comphy_cp110.c
@@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
#define MV_SIP_COMPHY_XFI_TRAIN 0x82000004
-/* Used to distinguish between different possible callers (U-boot/Linux) */
+/* Used to distinguish between different possible callers (U-Boot/Linux) */
#define COMPHY_CALLER_UBOOT (0x1 << 21)
#define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12)
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 23397175d34..34314d0bd1e 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -256,6 +256,7 @@ enum wiz_type {
J721E_WIZ_10G,
AM64_WIZ_10G,
J784S4_WIZ_10G,
+ J721S2_WIZ_10G,
};
struct wiz_data {
@@ -307,6 +308,15 @@ static struct wiz_data j784s4_wiz_10g = {
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
};
+static struct wiz_data j721s2_10g_data = {
+ .type = J721S2_WIZ_10G,
+ .pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
+ .pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
+ .refclk_dig_sel = &refclk_dig_sel_10g,
+ .clk_mux_sel = clk_mux_sel_10g,
+ .clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
+};
+
#define WIZ_TYPEC_DIR_DEBOUNCE_MIN 100 /* ms */
#define WIZ_TYPEC_DIR_DEBOUNCE_MAX 1000
@@ -1037,8 +1047,14 @@ static int j721e_wiz_bind_of_clocks(struct wiz *wiz)
ofnode node;
int i, rc;
- if (type == AM64_WIZ_10G || type == J784S4_WIZ_10G)
+ switch (type) {
+ case AM64_WIZ_10G:
+ case J784S4_WIZ_10G:
+ case J721S2_WIZ_10G:
return j721e_wiz_bind_clocks(wiz);
+ default:
+ break;
+ };
div_clk_drv = lists_driver_lookup_name("wiz_div_clk");
if (!div_clk_drv) {
@@ -1282,6 +1298,9 @@ static const struct udevice_id j721e_wiz_ids[] = {
{
.compatible = "ti,j784s4-wiz-10g", .data = (ulong)&j784s4_wiz_10g,
},
+ {
+ .compatible = "ti,j721s2-wiz-10g", .data = (ulong)&j721s2_10g_data,
+ },
{}
};
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.h b/drivers/pinctrl/exynos/pinctrl-exynos.h
index a7788b76d90..cbc5174b48c 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.h
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.h
@@ -6,7 +6,7 @@
*/
#ifndef __PINCTRL_EXYNOS_H_
-#define __PINCTRL_EXYNOS__H_
+#define __PINCTRL_EXYNOS_H_
#define PIN_CON 0x00 /* Offset of pin function register */
#define PIN_DAT 0x04 /* Offset of pin data register */
diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
index ef02087ed23..97e574330fb 100644
--- a/drivers/pinctrl/meson/Kconfig
+++ b/drivers/pinctrl/meson/Kconfig
@@ -29,4 +29,8 @@ config PINCTRL_MESON_G12A
bool "Amlogic Meson G12a SoC pinctrl driver"
select PINCTRL_MESON_AXG_PMX
+config PINCTRL_MESON_A1
+ bool "Amlogic Meson A1 SoC pinctrl driver"
+ select PINCTRL_MESON_AXG_PMX
+
endif
diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
index 80dba65e1bd..8d10d027ac6 100644
--- a/drivers/pinctrl/meson/Makefile
+++ b/drivers/pinctrl/meson/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXBB) += pinctrl-meson-gxbb.o
obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
+obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
new file mode 100644
index 00000000000..30cf3bc0be4
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Qianggui Song <qianggui.song@amlogic.com>
+ * Copyright (C) 2023 SberDevices, Inc.
+ * Author: Igor Prusov <ivprusov@sberdevices.ru>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <dt-bindings/gpio/meson-a1-gpio.h>
+
+#include "pinctrl-meson.h"
+#include "pinctrl-meson-axg.h"
+
+/* psram */
+static const unsigned int psram_clkn_pins[] = { GPIOP_0 };
+static const unsigned int psram_clkp_pins[] = { GPIOP_1 };
+static const unsigned int psram_ce_n_pins[] = { GPIOP_2 };
+static const unsigned int psram_rst_n_pins[] = { GPIOP_3 };
+static const unsigned int psram_adq0_pins[] = { GPIOP_4 };
+static const unsigned int psram_adq1_pins[] = { GPIOP_5 };
+static const unsigned int psram_adq2_pins[] = { GPIOP_6 };
+static const unsigned int psram_adq3_pins[] = { GPIOP_7 };
+static const unsigned int psram_adq4_pins[] = { GPIOP_8 };
+static const unsigned int psram_adq5_pins[] = { GPIOP_9 };
+static const unsigned int psram_adq6_pins[] = { GPIOP_10 };
+static const unsigned int psram_adq7_pins[] = { GPIOP_11 };
+static const unsigned int psram_dqs_dm_pins[] = { GPIOP_12 };
+
+/* sdcard */
+static const unsigned int sdcard_d0_b_pins[] = { GPIOB_0 };
+static const unsigned int sdcard_d1_b_pins[] = { GPIOB_1 };
+static const unsigned int sdcard_d2_b_pins[] = { GPIOB_2 };
+static const unsigned int sdcard_d3_b_pins[] = { GPIOB_3 };
+static const unsigned int sdcard_clk_b_pins[] = { GPIOB_4 };
+static const unsigned int sdcard_cmd_b_pins[] = { GPIOB_5 };
+
+static const unsigned int sdcard_d0_x_pins[] = { GPIOX_0 };
+static const unsigned int sdcard_d1_x_pins[] = { GPIOX_1 };
+static const unsigned int sdcard_d2_x_pins[] = { GPIOX_2 };
+static const unsigned int sdcard_d3_x_pins[] = { GPIOX_3 };
+static const unsigned int sdcard_clk_x_pins[] = { GPIOX_4 };
+static const unsigned int sdcard_cmd_x_pins[] = { GPIOX_5 };
+
+/* spif */
+static const unsigned int spif_mo_pins[] = { GPIOB_0 };
+static const unsigned int spif_mi_pins[] = { GPIOB_1 };
+static const unsigned int spif_wp_n_pins[] = { GPIOB_2 };
+static const unsigned int spif_hold_n_pins[] = { GPIOB_3 };
+static const unsigned int spif_clk_pins[] = { GPIOB_4 };
+static const unsigned int spif_cs_pins[] = { GPIOB_5 };
+
+/* i2c0 */
+static const unsigned int i2c0_sck_f9_pins[] = { GPIOF_9 };
+static const unsigned int i2c0_sda_f10_pins[] = { GPIOF_10 };
+static const unsigned int i2c0_sck_f11_pins[] = { GPIOF_11 };
+static const unsigned int i2c0_sda_f12_pins[] = { GPIOF_12 };
+
+/* i2c1 */
+static const unsigned int i2c1_sda_x_pins[] = { GPIOX_9 };
+static const unsigned int i2c1_sck_x_pins[] = { GPIOX_10 };
+static const unsigned int i2c1_sda_a_pins[] = { GPIOA_10 };
+static const unsigned int i2c1_sck_a_pins[] = { GPIOA_11 };
+
+/* i2c2 */
+static const unsigned int i2c2_sck_x0_pins[] = { GPIOX_0 };
+static const unsigned int i2c2_sda_x1_pins[] = { GPIOX_1 };
+static const unsigned int i2c2_sck_x15_pins[] = { GPIOX_15 };
+static const unsigned int i2c2_sda_x16_pins[] = { GPIOX_16 };
+static const unsigned int i2c2_sck_a4_pins[] = { GPIOA_4 };
+static const unsigned int i2c2_sda_a5_pins[] = { GPIOA_5 };
+static const unsigned int i2c2_sck_a8_pins[] = { GPIOA_8 };
+static const unsigned int i2c2_sda_a9_pins[] = { GPIOA_9 };
+
+/* i2c3 */
+static const unsigned int i2c3_sck_f_pins[] = { GPIOF_4 };
+static const unsigned int i2c3_sda_f_pins[] = { GPIOF_5 };
+static const unsigned int i2c3_sck_x_pins[] = { GPIOX_11 };
+static const unsigned int i2c3_sda_x_pins[] = { GPIOX_12 };
+
+/* i2c slave */
+static const unsigned int i2c_slave_sck_a_pins[] = { GPIOA_10 };
+static const unsigned int i2c_slave_sda_a_pins[] = { GPIOA_11 };
+static const unsigned int i2c_slave_sck_f_pins[] = { GPIOF_11 };
+static const unsigned int i2c_slave_sda_f_pins[] = { GPIOF_12 };
+
+/* uart_a */
+static const unsigned int uart_a_tx_pins[] = { GPIOX_11 };
+static const unsigned int uart_a_rx_pins[] = { GPIOX_12 };
+static const unsigned int uart_a_cts_pins[] = { GPIOX_13 };
+static const unsigned int uart_a_rts_pins[] = { GPIOX_14 };
+
+/* uart_b */
+static const unsigned int uart_b_tx_x_pins[] = { GPIOX_7 };
+static const unsigned int uart_b_rx_x_pins[] = { GPIOX_8 };
+static const unsigned int uart_b_tx_f_pins[] = { GPIOF_0 };
+static const unsigned int uart_b_rx_f_pins[] = { GPIOF_1 };
+
+/* uart_c */
+static const unsigned int uart_c_tx_x0_pins[] = { GPIOX_0 };
+static const unsigned int uart_c_rx_x1_pins[] = { GPIOX_1 };
+static const unsigned int uart_c_cts_pins[] = { GPIOX_2 };
+static const unsigned int uart_c_rts_pins[] = { GPIOX_3 };
+static const unsigned int uart_c_tx_x15_pins[] = { GPIOX_15 };
+static const unsigned int uart_c_rx_x16_pins[] = { GPIOX_16 };
+
+/* pmw_a */
+static const unsigned int pwm_a_x6_pins[] = { GPIOX_6 };
+static const unsigned int pwm_a_x7_pins[] = { GPIOX_7 };
+static const unsigned int pwm_a_f6_pins[] = { GPIOF_6 };
+static const unsigned int pwm_a_f10_pins[] = { GPIOF_10 };
+static const unsigned int pwm_a_a_pins[] = { GPIOA_5 };
+
+/* pmw_b */
+static const unsigned int pwm_b_x_pins[] = { GPIOX_8 };
+static const unsigned int pwm_b_f_pins[] = { GPIOF_7 };
+static const unsigned int pwm_b_a_pins[] = { GPIOA_11 };
+
+/* pmw_c */
+static const unsigned int pwm_c_x_pins[] = { GPIOX_9 };
+static const unsigned int pwm_c_f3_pins[] = { GPIOF_3 };
+static const unsigned int pwm_c_f8_pins[] = { GPIOF_8 };
+static const unsigned int pwm_c_a_pins[] = { GPIOA_10 };
+
+/* pwm_d */
+static const unsigned int pwm_d_x10_pins[] = { GPIOX_10 };
+static const unsigned int pwm_d_x13_pins[] = { GPIOX_13 };
+static const unsigned int pwm_d_x15_pins[] = { GPIOX_15 };
+static const unsigned int pwm_d_f_pins[] = { GPIOF_11 };
+
+/* pwm_e */
+static const unsigned int pwm_e_p_pins[] = { GPIOP_3 };
+static const unsigned int pwm_e_x2_pins[] = { GPIOX_2 };
+static const unsigned int pwm_e_x14_pins[] = { GPIOX_14 };
+static const unsigned int pwm_e_x16_pins[] = { GPIOX_16 };
+static const unsigned int pwm_e_f_pins[] = { GPIOF_3 };
+static const unsigned int pwm_e_a_pins[] = { GPIOA_0 };
+
+/* pwm_f */
+static const unsigned int pwm_f_b_pins[] = { GPIOB_6 };
+static const unsigned int pwm_f_x_pins[] = { GPIOX_3 };
+static const unsigned int pwm_f_f4_pins[] = { GPIOF_4 };
+static const unsigned int pwm_f_f12_pins[] = { GPIOF_12 };
+
+/* pwm_a_hiz */
+static const unsigned int pwm_a_hiz_f8_pins[] = { GPIOF_8 };
+static const unsigned int pwm_a_hiz_f10_pins[] = { GPIOF_10 };
+static const unsigned int pmw_a_hiz_f6_pins[] = { GPIOF_6 };
+
+/* pwm_b_hiz */
+static const unsigned int pwm_b_hiz_pins[] = { GPIOF_7 };
+
+/* pmw_c_hiz */
+static const unsigned int pwm_c_hiz_pins[] = { GPIOF_8 };
+
+/* tdm_a */
+static const unsigned int tdm_a_dout1_pins[] = { GPIOX_7 };
+static const unsigned int tdm_a_dout0_pins[] = { GPIOX_8 };
+static const unsigned int tdm_a_fs_pins[] = { GPIOX_9 };
+static const unsigned int tdm_a_sclk_pins[] = { GPIOX_10 };
+static const unsigned int tdm_a_din1_pins[] = { GPIOX_7 };
+static const unsigned int tdm_a_din0_pins[] = { GPIOX_8 };
+static const unsigned int tdm_a_slv_fs_pins[] = { GPIOX_9 };
+static const unsigned int tdm_a_slv_sclk_pins[] = { GPIOX_10 };
+
+/* spi_a */
+static const unsigned int spi_a_mosi_x2_pins[] = { GPIOX_2 };
+static const unsigned int spi_a_ss0_x3_pins[] = { GPIOX_3 };
+static const unsigned int spi_a_sclk_x4_pins[] = { GPIOX_4 };
+static const unsigned int spi_a_miso_x5_pins[] = { GPIOX_5 };
+static const unsigned int spi_a_mosi_x7_pins[] = { GPIOX_7 };
+static const unsigned int spi_a_miso_x8_pins[] = { GPIOX_8 };
+static const unsigned int spi_a_ss0_x9_pins[] = { GPIOX_9 };
+static const unsigned int spi_a_sclk_x10_pins[] = { GPIOX_10 };
+
+static const unsigned int spi_a_mosi_a_pins[] = { GPIOA_6 };
+static const unsigned int spi_a_miso_a_pins[] = { GPIOA_7 };
+static const unsigned int spi_a_ss0_a_pins[] = { GPIOA_8 };
+static const unsigned int spi_a_sclk_a_pins[] = { GPIOA_9 };
+
+/* pdm */
+static const unsigned int pdm_din0_x_pins[] = { GPIOX_7 };
+static const unsigned int pdm_din1_x_pins[] = { GPIOX_8 };
+static const unsigned int pdm_din2_x_pins[] = { GPIOX_9 };
+static const unsigned int pdm_dclk_x_pins[] = { GPIOX_10 };
+
+static const unsigned int pdm_din2_a_pins[] = { GPIOA_6 };
+static const unsigned int pdm_din1_a_pins[] = { GPIOA_7 };
+static const unsigned int pdm_din0_a_pins[] = { GPIOA_8 };
+static const unsigned int pdm_dclk_pins[] = { GPIOA_9 };
+
+/* gen_clk */
+static const unsigned int gen_clk_x_pins[] = { GPIOX_7 };
+static const unsigned int gen_clk_f8_pins[] = { GPIOF_8 };
+static const unsigned int gen_clk_f10_pins[] = { GPIOF_10 };
+static const unsigned int gen_clk_a_pins[] = { GPIOA_11 };
+
+/* jtag_a */
+static const unsigned int jtag_a_clk_pins[] = { GPIOF_4 };
+static const unsigned int jtag_a_tms_pins[] = { GPIOF_5 };
+static const unsigned int jtag_a_tdi_pins[] = { GPIOF_6 };
+static const unsigned int jtag_a_tdo_pins[] = { GPIOF_7 };
+
+/* clk_32_in */
+static const unsigned int clk_32k_in_pins[] = { GPIOF_2 };
+
+/* ir in */
+static const unsigned int remote_input_f_pins[] = { GPIOF_3 };
+static const unsigned int remote_input_a_pins[] = { GPIOA_11 };
+
+/* ir out */
+static const unsigned int remote_out_pins[] = { GPIOF_5 };
+
+/* spdif */
+static const unsigned int spdif_in_f6_pins[] = { GPIOF_6 };
+static const unsigned int spdif_in_f7_pins[] = { GPIOF_7 };
+
+/* sw */
+static const unsigned int swclk_pins[] = { GPIOF_4 };
+static const unsigned int swdio_pins[] = { GPIOF_5 };
+
+/* clk_25 */
+static const unsigned int clk25_pins[] = { GPIOF_10 };
+
+/* cec_a */
+static const unsigned int cec_a_pins[] = { GPIOF_2 };
+
+/* cec_b */
+static const unsigned int cec_b_pins[] = { GPIOF_2 };
+
+/* clk12_24 */
+static const unsigned int clk12_24_pins[] = { GPIOF_10 };
+
+/* mclk_0 */
+static const unsigned int mclk_0_pins[] = { GPIOA_0 };
+
+/* tdm_b */
+static const unsigned int tdm_b_sclk_pins[] = { GPIOA_1 };
+static const unsigned int tdm_b_fs_pins[] = { GPIOA_2 };
+static const unsigned int tdm_b_dout0_pins[] = { GPIOA_3 };
+static const unsigned int tdm_b_dout1_pins[] = { GPIOA_4 };
+static const unsigned int tdm_b_dout2_pins[] = { GPIOA_5 };
+static const unsigned int tdm_b_dout3_pins[] = { GPIOA_6 };
+static const unsigned int tdm_b_dout4_pins[] = { GPIOA_7 };
+static const unsigned int tdm_b_dout5_pins[] = { GPIOA_8 };
+static const unsigned int tdm_b_slv_sclk_pins[] = { GPIOA_5 };
+static const unsigned int tdm_b_slv_fs_pins[] = { GPIOA_6 };
+static const unsigned int tdm_b_din0_pins[] = { GPIOA_7 };
+static const unsigned int tdm_b_din1_pins[] = { GPIOA_8 };
+static const unsigned int tdm_b_din2_pins[] = { GPIOA_9 };
+
+/* mclk_vad */
+static const unsigned int mclk_vad_pins[] = { GPIOA_0 };
+
+/* tdm_vad */
+static const unsigned int tdm_vad_sclk_a1_pins[] = { GPIOA_1 };
+static const unsigned int tdm_vad_fs_a2_pins[] = { GPIOA_2 };
+static const unsigned int tdm_vad_sclk_a5_pins[] = { GPIOA_5 };
+static const unsigned int tdm_vad_fs_a6_pins[] = { GPIOA_6 };
+
+/* tst_out */
+static const unsigned int tst_out0_pins[] = { GPIOA_0 };
+static const unsigned int tst_out1_pins[] = { GPIOA_1 };
+static const unsigned int tst_out2_pins[] = { GPIOA_2 };
+static const unsigned int tst_out3_pins[] = { GPIOA_3 };
+static const unsigned int tst_out4_pins[] = { GPIOA_4 };
+static const unsigned int tst_out5_pins[] = { GPIOA_5 };
+static const unsigned int tst_out6_pins[] = { GPIOA_6 };
+static const unsigned int tst_out7_pins[] = { GPIOA_7 };
+static const unsigned int tst_out8_pins[] = { GPIOA_8 };
+static const unsigned int tst_out9_pins[] = { GPIOA_9 };
+static const unsigned int tst_out10_pins[] = { GPIOA_10 };
+static const unsigned int tst_out11_pins[] = { GPIOA_11 };
+
+/* mute */
+static const unsigned int mute_key_pins[] = { GPIOA_4 };
+static const unsigned int mute_en_pins[] = { GPIOA_5 };
+
+static struct meson_pmx_group meson_a1_periphs_groups[] = {
+ GPIO_GROUP(GPIOP_0, 0),
+ GPIO_GROUP(GPIOP_1, 0),
+ GPIO_GROUP(GPIOP_2, 0),
+ GPIO_GROUP(GPIOP_3, 0),
+ GPIO_GROUP(GPIOP_4, 0),
+ GPIO_GROUP(GPIOP_5, 0),
+ GPIO_GROUP(GPIOP_6, 0),
+ GPIO_GROUP(GPIOP_7, 0),
+ GPIO_GROUP(GPIOP_8, 0),
+ GPIO_GROUP(GPIOP_9, 0),
+ GPIO_GROUP(GPIOP_10, 0),
+ GPIO_GROUP(GPIOP_11, 0),
+ GPIO_GROUP(GPIOP_12, 0),
+ GPIO_GROUP(GPIOB_0, 0),
+ GPIO_GROUP(GPIOB_1, 0),
+ GPIO_GROUP(GPIOB_2, 0),
+ GPIO_GROUP(GPIOB_3, 0),
+ GPIO_GROUP(GPIOB_4, 0),
+ GPIO_GROUP(GPIOB_5, 0),
+ GPIO_GROUP(GPIOB_6, 0),
+ GPIO_GROUP(GPIOX_0, 0),
+ GPIO_GROUP(GPIOX_1, 0),
+ GPIO_GROUP(GPIOX_2, 0),
+ GPIO_GROUP(GPIOX_3, 0),
+ GPIO_GROUP(GPIOX_4, 0),
+ GPIO_GROUP(GPIOX_5, 0),
+ GPIO_GROUP(GPIOX_6, 0),
+ GPIO_GROUP(GPIOX_7, 0),
+ GPIO_GROUP(GPIOX_8, 0),
+ GPIO_GROUP(GPIOX_9, 0),
+ GPIO_GROUP(GPIOX_10, 0),
+ GPIO_GROUP(GPIOX_11, 0),
+ GPIO_GROUP(GPIOX_12, 0),
+ GPIO_GROUP(GPIOX_13, 0),
+ GPIO_GROUP(GPIOX_14, 0),
+ GPIO_GROUP(GPIOX_15, 0),
+ GPIO_GROUP(GPIOX_16, 0),
+ GPIO_GROUP(GPIOF_0, 0),
+ GPIO_GROUP(GPIOF_1, 0),
+ GPIO_GROUP(GPIOF_2, 0),
+ GPIO_GROUP(GPIOF_3, 0),
+ GPIO_GROUP(GPIOF_4, 0),
+ GPIO_GROUP(GPIOF_5, 0),
+ GPIO_GROUP(GPIOF_6, 0),
+ GPIO_GROUP(GPIOF_7, 0),
+ GPIO_GROUP(GPIOF_8, 0),
+ GPIO_GROUP(GPIOF_9, 0),
+ GPIO_GROUP(GPIOF_10, 0),
+ GPIO_GROUP(GPIOF_11, 0),
+ GPIO_GROUP(GPIOF_12, 0),
+ GPIO_GROUP(GPIOA_0, 0),
+ GPIO_GROUP(GPIOA_1, 0),
+ GPIO_GROUP(GPIOA_2, 0),
+ GPIO_GROUP(GPIOA_3, 0),
+ GPIO_GROUP(GPIOA_4, 0),
+ GPIO_GROUP(GPIOA_5, 0),
+ GPIO_GROUP(GPIOA_6, 0),
+ GPIO_GROUP(GPIOA_7, 0),
+ GPIO_GROUP(GPIOA_8, 0),
+ GPIO_GROUP(GPIOA_9, 0),
+ GPIO_GROUP(GPIOA_10, 0),
+ GPIO_GROUP(GPIOA_11, 0),
+
+ /* bank P func1 */
+ GROUP(psram_clkn, 1),
+ GROUP(psram_clkp, 1),
+ GROUP(psram_ce_n, 1),
+ GROUP(psram_rst_n, 1),
+ GROUP(psram_adq0, 1),
+ GROUP(psram_adq1, 1),
+ GROUP(psram_adq2, 1),
+ GROUP(psram_adq3, 1),
+ GROUP(psram_adq4, 1),
+ GROUP(psram_adq5, 1),
+ GROUP(psram_adq6, 1),
+ GROUP(psram_adq7, 1),
+ GROUP(psram_dqs_dm, 1),
+
+ /* bank P func2 */
+ GROUP(pwm_e_p, 2),
+
+ /* bank B func1 */
+ GROUP(spif_mo, 1),
+ GROUP(spif_mi, 1),
+ GROUP(spif_wp_n, 1),
+ GROUP(spif_hold_n, 1),
+ GROUP(spif_clk, 1),
+ GROUP(spif_cs, 1),
+ GROUP(pwm_f_b, 1),
+
+ /* bank B func2 */
+ GROUP(sdcard_d0_b, 2),
+ GROUP(sdcard_d1_b, 2),
+ GROUP(sdcard_d2_b, 2),
+ GROUP(sdcard_d3_b, 2),
+ GROUP(sdcard_clk_b, 2),
+ GROUP(sdcard_cmd_b, 2),
+
+ /* bank X func1 */
+ GROUP(sdcard_d0_x, 1),
+ GROUP(sdcard_d1_x, 1),
+ GROUP(sdcard_d2_x, 1),
+ GROUP(sdcard_d3_x, 1),
+ GROUP(sdcard_clk_x, 1),
+ GROUP(sdcard_cmd_x, 1),
+ GROUP(pwm_a_x6, 1),
+ GROUP(tdm_a_dout1, 1),
+ GROUP(tdm_a_dout0, 1),
+ GROUP(tdm_a_fs, 1),
+ GROUP(tdm_a_sclk, 1),
+ GROUP(uart_a_tx, 1),
+ GROUP(uart_a_rx, 1),
+ GROUP(uart_a_cts, 1),
+ GROUP(uart_a_rts, 1),
+ GROUP(pwm_d_x15, 1),
+ GROUP(pwm_e_x16, 1),
+
+ /* bank X func2 */
+ GROUP(i2c2_sck_x0, 2),
+ GROUP(i2c2_sda_x1, 2),
+ GROUP(spi_a_mosi_x2, 2),
+ GROUP(spi_a_ss0_x3, 2),
+ GROUP(spi_a_sclk_x4, 2),
+ GROUP(spi_a_miso_x5, 2),
+ GROUP(tdm_a_din1, 2),
+ GROUP(tdm_a_din0, 2),
+ GROUP(tdm_a_slv_fs, 2),
+ GROUP(tdm_a_slv_sclk, 2),
+ GROUP(i2c3_sck_x, 2),
+ GROUP(i2c3_sda_x, 2),
+ GROUP(pwm_d_x13, 2),
+ GROUP(pwm_e_x14, 2),
+ GROUP(i2c2_sck_x15, 2),
+ GROUP(i2c2_sda_x16, 2),
+
+ /* bank X func3 */
+ GROUP(uart_c_tx_x0, 3),
+ GROUP(uart_c_rx_x1, 3),
+ GROUP(uart_c_cts, 3),
+ GROUP(uart_c_rts, 3),
+ GROUP(pdm_din0_x, 3),
+ GROUP(pdm_din1_x, 3),
+ GROUP(pdm_din2_x, 3),
+ GROUP(pdm_dclk_x, 3),
+ GROUP(uart_c_tx_x15, 3),
+ GROUP(uart_c_rx_x16, 3),
+
+ /* bank X func4 */
+ GROUP(pwm_e_x2, 4),
+ GROUP(pwm_f_x, 4),
+ GROUP(spi_a_mosi_x7, 4),
+ GROUP(spi_a_miso_x8, 4),
+ GROUP(spi_a_ss0_x9, 4),
+ GROUP(spi_a_sclk_x10, 4),
+
+ /* bank X func5 */
+ GROUP(uart_b_tx_x, 5),
+ GROUP(uart_b_rx_x, 5),
+ GROUP(i2c1_sda_x, 5),
+ GROUP(i2c1_sck_x, 5),
+
+ /* bank X func6 */
+ GROUP(pwm_a_x7, 6),
+ GROUP(pwm_b_x, 6),
+ GROUP(pwm_c_x, 6),
+ GROUP(pwm_d_x10, 6),
+
+ /* bank X func7 */
+ GROUP(gen_clk_x, 7),
+
+ /* bank F func1 */
+ GROUP(uart_b_tx_f, 1),
+ GROUP(uart_b_rx_f, 1),
+ GROUP(remote_input_f, 1),
+ GROUP(jtag_a_clk, 1),
+ GROUP(jtag_a_tms, 1),
+ GROUP(jtag_a_tdi, 1),
+ GROUP(jtag_a_tdo, 1),
+ GROUP(gen_clk_f8, 1),
+ GROUP(pwm_a_f10, 1),
+ GROUP(i2c0_sck_f11, 1),
+ GROUP(i2c0_sda_f12, 1),
+
+ /* bank F func2 */
+ GROUP(clk_32k_in, 2),
+ GROUP(pwm_e_f, 2),
+ GROUP(pwm_f_f4, 2),
+ GROUP(remote_out, 2),
+ GROUP(spdif_in_f6, 2),
+ GROUP(spdif_in_f7, 2),
+ GROUP(pwm_a_hiz_f8, 2),
+ GROUP(pwm_a_hiz_f10, 2),
+ GROUP(pwm_d_f, 2),
+ GROUP(pwm_f_f12, 2),
+
+ /* bank F func3 */
+ GROUP(pwm_c_f3, 3),
+ GROUP(swclk, 3),
+ GROUP(swdio, 3),
+ GROUP(pwm_a_f6, 3),
+ GROUP(pwm_b_f, 3),
+ GROUP(pwm_c_f8, 3),
+ GROUP(clk25, 3),
+ GROUP(i2c_slave_sck_f, 3),
+ GROUP(i2c_slave_sda_f, 3),
+
+ /* bank F func4 */
+ GROUP(cec_a, 4),
+ GROUP(i2c3_sck_f, 4),
+ GROUP(i2c3_sda_f, 4),
+ GROUP(pmw_a_hiz_f6, 4),
+ GROUP(pwm_b_hiz, 4),
+ GROUP(pwm_c_hiz, 4),
+ GROUP(i2c0_sck_f9, 4),
+ GROUP(i2c0_sda_f10, 4),
+
+ /* bank F func5 */
+ GROUP(cec_b, 5),
+ GROUP(clk12_24, 5),
+
+ /* bank F func7 */
+ GROUP(gen_clk_f10, 7),
+
+ /* bank A func1 */
+ GROUP(mclk_0, 1),
+ GROUP(tdm_b_sclk, 1),
+ GROUP(tdm_b_fs, 1),
+ GROUP(tdm_b_dout0, 1),
+ GROUP(tdm_b_dout1, 1),
+ GROUP(tdm_b_dout2, 1),
+ GROUP(tdm_b_dout3, 1),
+ GROUP(tdm_b_dout4, 1),
+ GROUP(tdm_b_dout5, 1),
+ GROUP(remote_input_a, 1),
+
+ /* bank A func2 */
+ GROUP(pwm_e_a, 2),
+ GROUP(tdm_b_slv_sclk, 2),
+ GROUP(tdm_b_slv_fs, 2),
+ GROUP(tdm_b_din0, 2),
+ GROUP(tdm_b_din1, 2),
+ GROUP(tdm_b_din2, 2),
+ GROUP(i2c1_sda_a, 2),
+ GROUP(i2c1_sck_a, 2),
+
+ /* bank A func3 */
+ GROUP(i2c2_sck_a4, 3),
+ GROUP(i2c2_sda_a5, 3),
+ GROUP(pdm_din2_a, 3),
+ GROUP(pdm_din1_a, 3),
+ GROUP(pdm_din0_a, 3),
+ GROUP(pdm_dclk, 3),
+ GROUP(pwm_c_a, 3),
+ GROUP(pwm_b_a, 3),
+
+ /* bank A func4 */
+ GROUP(pwm_a_a, 4),
+ GROUP(spi_a_mosi_a, 4),
+ GROUP(spi_a_miso_a, 4),
+ GROUP(spi_a_ss0_a, 4),
+ GROUP(spi_a_sclk_a, 4),
+ GROUP(i2c_slave_sck_a, 4),
+ GROUP(i2c_slave_sda_a, 4),
+
+ /* bank A func5 */
+ GROUP(mclk_vad, 5),
+ GROUP(tdm_vad_sclk_a1, 5),
+ GROUP(tdm_vad_fs_a2, 5),
+ GROUP(tdm_vad_sclk_a5, 5),
+ GROUP(tdm_vad_fs_a6, 5),
+ GROUP(i2c2_sck_a8, 5),
+ GROUP(i2c2_sda_a9, 5),
+
+ /* bank A func6 */
+ GROUP(tst_out0, 6),
+ GROUP(tst_out1, 6),
+ GROUP(tst_out2, 6),
+ GROUP(tst_out3, 6),
+ GROUP(tst_out4, 6),
+ GROUP(tst_out5, 6),
+ GROUP(tst_out6, 6),
+ GROUP(tst_out7, 6),
+ GROUP(tst_out8, 6),
+ GROUP(tst_out9, 6),
+ GROUP(tst_out10, 6),
+ GROUP(tst_out11, 6),
+
+ /* bank A func7 */
+ GROUP(mute_key, 7),
+ GROUP(mute_en, 7),
+ GROUP(gen_clk_a, 7),
+};
+
+static const char * const gpio_periphs_groups[] = {
+ "GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
+ "GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
+ "GPIOP_10", "GPIOP_11", "GPIOP_12",
+
+ "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
+ "GPIOB_5", "GPIOB_6",
+
+ "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+ "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+ "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+ "GPIOX_15", "GPIOX_16",
+
+ "GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
+ "GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
+ "GPIOF_10", "GPIOF_11", "GPIOF_12",
+
+ "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
+ "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
+ "GPIOA_10", "GPIOA_11",
+};
+
+static const char * const psram_groups[] = {
+ "psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
+ "psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
+ "psram_adq6", "psram_adq7", "psram_dqs_dm",
+};
+
+static const char * const pwm_a_groups[] = {
+ "pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
+};
+
+static const char * const pwm_b_groups[] = {
+ "pwm_b_x", "pwm_b_f", "pwm_b_a",
+};
+
+static const char * const pwm_c_groups[] = {
+ "pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
+};
+
+static const char * const pwm_d_groups[] = {
+ "pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
+};
+
+static const char * const pwm_e_groups[] = {
+ "pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
+ "pwm_e_a",
+};
+
+static const char * const pwm_f_groups[] = {
+ "pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
+};
+
+static const char * const pwm_a_hiz_groups[] = {
+ "pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
+};
+
+static const char * const pwm_b_hiz_groups[] = {
+ "pwm_b_hiz",
+};
+
+static const char * const pwm_c_hiz_groups[] = {
+ "pwm_c_hiz",
+};
+
+static const char * const spif_groups[] = {
+ "spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
+ "spif_cs",
+};
+
+static const char * const sdcard_groups[] = {
+ "sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
+ "sdcard_clk_b", "sdcard_cmd_b",
+
+ "sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
+ "sdcard_clk_x", "sdcard_cmd_x",
+};
+
+static const char * const tdm_a_groups[] = {
+ "tdm_a_din0", "tdm_a_din1", "tdm_a_fs", "tdm_a_sclk",
+ "tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
+};
+
+static const char * const uart_a_groups[] = {
+ "uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
+};
+
+static const char * const uart_b_groups[] = {
+ "uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
+};
+
+static const char * const uart_c_groups[] = {
+ "uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
+ "uart_c_tx_x15", "uart_c_rx_x16",
+};
+
+static const char * const i2c0_groups[] = {
+ "i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
+};
+
+static const char * const i2c1_groups[] = {
+ "i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
+};
+
+static const char * const i2c2_groups[] = {
+ "i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
+ "i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
+};
+
+static const char * const i2c3_groups[] = {
+ "i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
+};
+
+static const char * const spi_a_groups[] = {
+ "spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
+ "spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
+
+ "spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
+};
+
+static const char * const pdm_groups[] = {
+ "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
+ "pdm_din1_a", "pdm_din0_a", "pdm_dclk",
+};
+
+static const char * const gen_clk_groups[] = {
+ "gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
+};
+
+static const char * const remote_input_groups[] = {
+ "remote_input_f",
+ "remote_input_a",
+};
+
+static const char * const jtag_a_groups[] = {
+ "jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
+};
+
+static const char * const clk_32k_in_groups[] = {
+ "clk_32k_in",
+};
+
+static const char * const remote_out_groups[] = {
+ "remote_out",
+};
+
+static const char * const spdif_in_groups[] = {
+ "spdif_in_f6", "spdif_in_f7",
+};
+
+static const char * const sw_groups[] = {
+ "swclk", "swdio",
+};
+
+static const char * const clk25_groups[] = {
+ "clk_25",
+};
+
+static const char * const cec_a_groups[] = {
+ "cec_a",
+};
+
+static const char * const cec_b_groups[] = {
+ "cec_b",
+};
+
+static const char * const clk12_24_groups[] = {
+ "clk12_24",
+};
+
+static const char * const mclk_0_groups[] = {
+ "mclk_0",
+};
+
+static const char * const tdm_b_groups[] = {
+ "tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
+ "tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
+ "tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
+ "tdm_b_slv_sclk", "tdm_b_slv_fs",
+};
+
+static const char * const mclk_vad_groups[] = {
+ "mclk_vad",
+};
+
+static const char * const tdm_vad_groups[] = {
+ "tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
+};
+
+static const char * const tst_out_groups[] = {
+ "tst_out0", "tst_out1", "tst_out2", "tst_out3",
+ "tst_out4", "tst_out5", "tst_out6", "tst_out7",
+ "tst_out8", "tst_out9", "tst_out10", "tst_out11",
+};
+
+static const char * const mute_groups[] = {
+ "mute_key", "mute_en",
+};
+
+static struct meson_pmx_func meson_a1_periphs_functions[] = {
+ FUNCTION(gpio_periphs),
+ FUNCTION(psram),
+ FUNCTION(pwm_a),
+ FUNCTION(pwm_b),
+ FUNCTION(pwm_c),
+ FUNCTION(pwm_d),
+ FUNCTION(pwm_e),
+ FUNCTION(pwm_f),
+ FUNCTION(pwm_a_hiz),
+ FUNCTION(pwm_b_hiz),
+ FUNCTION(pwm_c_hiz),
+ FUNCTION(spif),
+ FUNCTION(sdcard),
+ FUNCTION(tdm_a),
+ FUNCTION(uart_a),
+ FUNCTION(uart_b),
+ FUNCTION(uart_c),
+ FUNCTION(i2c0),
+ FUNCTION(i2c1),
+ FUNCTION(i2c2),
+ FUNCTION(i2c3),
+ FUNCTION(spi_a),
+ FUNCTION(pdm),
+ FUNCTION(gen_clk),
+ FUNCTION(remote_input),
+ FUNCTION(jtag_a),
+ FUNCTION(clk_32k_in),
+ FUNCTION(remote_out),
+ FUNCTION(spdif_in),
+ FUNCTION(sw),
+ FUNCTION(clk25),
+ FUNCTION(cec_a),
+ FUNCTION(cec_b),
+ FUNCTION(clk12_24),
+ FUNCTION(mclk_0),
+ FUNCTION(tdm_b),
+ FUNCTION(mclk_vad),
+ FUNCTION(tdm_vad),
+ FUNCTION(tst_out),
+ FUNCTION(mute),
+};
+
+static struct meson_bank meson_a1_periphs_banks[] = {
+ /* name first last pullen pull dir out in ds */
+ BANK_DS("P", GPIOP_0, GPIOP_12, 0x3, 0, 0x4, 0, 0x2, 0, 0x1, 0, 0x0, 0, 0x5, 0),
+ BANK_DS("B", GPIOB_0, GPIOB_6, 0x13, 0, 0x14, 0, 0x12, 0, 0x11, 0, 0x10, 0, 0x15, 0),
+ BANK_DS("X", GPIOX_0, GPIOX_16, 0x23, 0, 0x24, 0, 0x22, 0, 0x21, 0, 0x20, 0, 0x25, 0),
+ BANK_DS("F", GPIOF_0, GPIOF_12, 0x33, 0, 0x34, 0, 0x32, 0, 0x31, 0, 0x30, 0, 0x35, 0),
+ BANK_DS("A", GPIOA_0, GPIOA_11, 0x43, 0, 0x44, 0, 0x42, 0, 0x41, 0, 0x40, 0, 0x45, 0),
+};
+
+static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
+ /* name first last reg offset */
+ BANK_PMX("P", GPIOP_0, GPIOP_12, 0x0, 0),
+ BANK_PMX("B", GPIOB_0, GPIOB_6, 0x2, 0),
+ BANK_PMX("X", GPIOX_0, GPIOX_16, 0x3, 0),
+ BANK_PMX("F", GPIOF_0, GPIOF_12, 0x6, 0),
+ BANK_PMX("A", GPIOA_0, GPIOA_11, 0x8, 0),
+};
+
+static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
+ .pmx_banks = meson_a1_periphs_pmx_banks,
+ .num_pmx_banks = ARRAY_SIZE(meson_a1_periphs_pmx_banks),
+};
+
+static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
+ .name = "periphs-banks",
+ .groups = meson_a1_periphs_groups,
+ .funcs = meson_a1_periphs_functions,
+ .banks = meson_a1_periphs_banks,
+ .num_pins = 62,
+ .num_groups = ARRAY_SIZE(meson_a1_periphs_groups),
+ .num_funcs = ARRAY_SIZE(meson_a1_periphs_functions),
+ .num_banks = ARRAY_SIZE(meson_a1_periphs_banks),
+ .pmx_data = &meson_a1_periphs_pmx_banks_data,
+};
+
+static const struct udevice_id meson_a1_pinctrl_match[] = {
+ {
+ .compatible = "amlogic,meson-a1-periphs-pinctrl",
+ .data = (ulong)&meson_a1_periphs_pinctrl_data,
+ },
+ { },
+};
+
+U_BOOT_DRIVER(meson_a1_pinctrl) = {
+ .name = "meson-a1-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(meson_a1_pinctrl_match),
+ .probe = meson_pinctrl_probe,
+ .priv_auto = sizeof(struct meson_pinctrl),
+ .ops = &meson_axg_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 1ad8bfbd880..92513822e70 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -1552,12 +1552,12 @@ static int npcm7xx_pinconf_set(struct udevice *dev, unsigned int pin,
setbits_le32(base + NPCM7XX_GP_N_OES, BIT(gpio));
case PIN_CONFIG_OUTPUT:
dev_dbg(dev, "set pin %d output %d\n", pin, arg);
- clrbits_le32(base + NPCM7XX_GP_N_IEM, BIT(gpio));
- setbits_le32(base + NPCM7XX_GP_N_OES, BIT(gpio));
if (arg)
setbits_le32(base + NPCM7XX_GP_N_DOUT, BIT(gpio));
else
clrbits_le32(base + NPCM7XX_GP_N_DOUT, BIT(gpio));
+ clrbits_le32(base + NPCM7XX_GP_N_IEM, BIT(gpio));
+ setbits_le32(base + NPCM7XX_GP_N_OES, BIT(gpio));
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
dev_dbg(dev, "set pin %d push pull\n", pin);
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 0ec47e9577e..f18be08518e 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -900,12 +900,12 @@ static int npcm8xx_pinconf_set(struct udevice *dev, unsigned int selector,
setbits_le32(base + GPIO_OES, BIT(gpio));
case PIN_CONFIG_OUTPUT:
dev_dbg(dev, "set pin %d output %d\n", pin, arg);
- clrbits_le32(base + GPIO_IEM, BIT(gpio));
- setbits_le32(base + GPIO_OES, BIT(gpio));
if (arg)
setbits_le32(base + GPIO_DOUT, BIT(gpio));
else
clrbits_le32(base + GPIO_DOUT, BIT(gpio));
+ clrbits_le32(base + GPIO_IEM, BIT(gpio));
+ setbits_le32(base + GPIO_OES, BIT(gpio));
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
dev_dbg(dev, "set pin %d push pull\n", pin);
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 7e1b8c072fa..411c210756a 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -68,6 +68,13 @@ config MESON_EE_POWER_DOMAIN
Enable support for manipulating Amlogic Meson Everything-Else power
domains.
+config MESON_SECURE_POWER_DOMAIN
+ bool "Enable Amlogic Secure power domain driver"
+ depends on POWER_DOMAIN && ARCH_MESON && MESON_A1
+ help
+ Enable support for manipulating Amlogic Meson Secure power domains.
+ Support for Amlogic A1 series.
+
config SANDBOX_POWER_DOMAIN
bool "Enable the sandbox power domain test driver"
depends on POWER_DOMAIN && SANDBOX
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index e6244776216..aa5a4ba57cd 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
+obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
diff --git a/drivers/power/domain/meson-secure-pwrc.c b/drivers/power/domain/meson-secure-pwrc.c
new file mode 100644
index 00000000000..f70f8e02423
--- /dev/null
+++ b/drivers/power/domain/meson-secure-pwrc.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ * Author: Alexey Romanov <avromanov@sberdevices.ru>
+ */
+
+#include <dm.h>
+#include <asm/arch/sm.h>
+#include <power-domain.h>
+#include <power-domain-uclass.h>
+#include <dt-bindings/power/meson-a1-power.h>
+
+struct meson_secure_pwrc_domain_desc {
+ char *name;
+ size_t index;
+};
+
+struct meson_secure_pwrc_domain_data {
+ unsigned int count;
+ struct meson_secure_pwrc_domain_desc *domains;
+};
+
+struct meson_secure_pwrc_priv {
+ const struct meson_secure_pwrc_domain_data *data;
+};
+
+static int meson_secure_pwrc_on(struct power_domain *power_domain)
+{
+ struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+ struct meson_secure_pwrc_domain_desc *pwrc_domain;
+ int err;
+
+ pwrc_domain = &priv->data->domains[power_domain->id];
+
+ err = meson_sm_pwrdm_on(pwrc_domain->index);
+ if (err) {
+ pr_err("meson_sm_pwrdm_on() failed (%d)\n", err);
+ return err;
+ }
+
+ pr_debug("enable %s power domain\n", pwrc_domain->name);
+
+ return 0;
+}
+
+static int meson_secure_pwrc_off(struct power_domain *power_domain)
+{
+ struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+ struct meson_secure_pwrc_domain_desc *pwrc_domain;
+ int err;
+
+ pwrc_domain = &priv->data->domains[power_domain->id];
+
+ err = meson_sm_pwrdm_off(pwrc_domain->index);
+ if (err) {
+ pr_err("meson_sm_pwrdm_off() failed (%d)\n", err);
+ return err;
+ }
+
+ pr_debug("disable %s power domain\n", pwrc_domain->name);
+
+ return 0;
+}
+
+static int meson_secure_pwrc_of_xlate(struct power_domain *power_domain,
+ struct ofnode_phandle_args *args)
+{
+ struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+ struct meson_secure_pwrc_domain_desc *pwrc_domain;
+
+ if (args->args_count < 1) {
+ pr_err("invalid args count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ power_domain->id = args->args[0];
+
+ if (power_domain->id >= priv->data->count) {
+ pr_err("domain with ID=%lu is invalid\n", power_domain->id);
+ return -EINVAL;
+ }
+
+ pwrc_domain = &priv->data->domains[power_domain->id];
+
+ if (!pwrc_domain->name) {
+ pr_err("domain with ID=%lu is invalid\n", power_domain->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define SEC_PD(__name) \
+[PWRC_##__name##_ID] = \
+{ \
+ .name = #__name, \
+ .index = PWRC_##__name##_ID, \
+}
+
+static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
+ SEC_PD(DSPA),
+ SEC_PD(DSPB),
+ SEC_PD(UART),
+ SEC_PD(DMC),
+ SEC_PD(I2C),
+ SEC_PD(PSRAM),
+ SEC_PD(ACODEC),
+ SEC_PD(AUDIO),
+ SEC_PD(OTP),
+ SEC_PD(DMA),
+ SEC_PD(SD_EMMC),
+ SEC_PD(RAMA),
+ SEC_PD(RAMB),
+ SEC_PD(IR),
+ SEC_PD(SPICC),
+ SEC_PD(SPIFC),
+ SEC_PD(USB),
+ SEC_PD(NIC),
+ SEC_PD(PDMIN),
+ SEC_PD(RSA),
+};
+
+struct power_domain_ops meson_secure_pwrc_ops = {
+ .on = meson_secure_pwrc_on,
+ .off = meson_secure_pwrc_off,
+ .of_xlate = meson_secure_pwrc_of_xlate,
+};
+
+static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
+ .count = ARRAY_SIZE(a1_pwrc_domains),
+ .domains = a1_pwrc_domains,
+};
+
+static const struct udevice_id meson_secure_pwrc_ids[] = {
+ {
+ .compatible = "amlogic,meson-a1-pwrc",
+ .data = (unsigned long)&meson_secure_a1_pwrc_data,
+ },
+ { }
+};
+
+static int meson_secure_pwrc_probe(struct udevice *dev)
+{
+ struct meson_secure_pwrc_priv *priv = dev_get_priv(dev);
+
+ priv->data = (void *)dev_get_driver_data(dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(meson_secure_pwrc) = {
+ .name = "meson_secure_pwrc",
+ .id = UCLASS_POWER_DOMAIN,
+ .of_match = meson_secure_pwrc_ids,
+ .probe = meson_secure_pwrc_probe,
+ .ops = &meson_secure_pwrc_ops,
+ .priv_auto = sizeof(struct meson_secure_pwrc_priv),
+};
diff --git a/drivers/power/domain/zynqmp-power-domain.c b/drivers/power/domain/zynqmp-power-domain.c
index adbbb5fdd93..5ee9e020fb3 100644
--- a/drivers/power/domain/zynqmp-power-domain.c
+++ b/drivers/power/domain/zynqmp-power-domain.c
@@ -23,12 +23,17 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
static int zynqmp_power_domain_request(struct power_domain *power_domain)
{
+ int ret = 0;
+
dev_dbg(power_domain->dev, "Request for id: %ld\n", power_domain->id);
- if (IS_ENABLED(CONFIG_ARCH_ZYNQMP))
- return zynqmp_pmufw_node(power_domain->id);
+ if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) {
+ ret = zynqmp_pmufw_node(power_domain->id);
+ if (ret == -ENODEV)
+ ret = 0;
+ }
- return 0;
+ return ret;
}
static int zynqmp_power_domain_free(struct power_domain *power_domain)
diff --git a/drivers/power/pmic/stpmic1.c b/drivers/power/pmic/stpmic1.c
index 2c85410b1bf..8701d4f971c 100644
--- a/drivers/power/pmic/stpmic1.c
+++ b/drivers/power/pmic/stpmic1.c
@@ -34,7 +34,9 @@ static const struct pmic_child_info stpmic1_children_info[] = {
{ .prefix = "ldo", .driver = "stpmic1_ldo" },
{ .prefix = "buck", .driver = "stpmic1_buck" },
{ .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
+ { .prefix = "vref-ddr", .driver = "stpmic1_vref_ddr" },
{ .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
+ { .prefix = "pwr-sw", .driver = "stpmic1_pwr_sw" },
{ .prefix = "boost", .driver = "stpmic1_boost" },
{ },
};
diff --git a/drivers/power/regulator/fan53555.c b/drivers/power/regulator/fan53555.c
index 5681206bbaf..815f96beef6 100644
--- a/drivers/power/regulator/fan53555.c
+++ b/drivers/power/regulator/fan53555.c
@@ -101,7 +101,7 @@ struct fan53555_priv {
static int fan53555_regulator_of_to_plat(struct udevice *dev)
{
- struct fan53555_plat *dev_pdata = dev_get_plat(dev);
+ struct fan53555_plat *plat = dev_get_plat(dev);
struct dm_regulator_uclass_plat *uc_pdata =
dev_get_uclass_plat(dev);
u32 sleep_vsel;
@@ -118,12 +118,12 @@ static int fan53555_regulator_of_to_plat(struct udevice *dev)
*/
switch (sleep_vsel) {
case FAN53555_VSEL0:
- dev_pdata->sleep_reg = FAN53555_VSEL0;
- dev_pdata->vol_reg = FAN53555_VSEL1;
+ plat->sleep_reg = FAN53555_VSEL0;
+ plat->vol_reg = FAN53555_VSEL1;
break;
case FAN53555_VSEL1:
- dev_pdata->sleep_reg = FAN53555_VSEL1;
- dev_pdata->vol_reg = FAN53555_VSEL0;
+ plat->sleep_reg = FAN53555_VSEL1;
+ plat->vol_reg = FAN53555_VSEL0;
break;
default:
pr_err("%s: invalid vsel id %d\n", dev->name, sleep_vsel);
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index 90004d1601a..ad3b4b98d66 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -24,16 +24,16 @@ struct fixed_clock_regulator_plat {
static int fixed_regulator_of_to_plat(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct regulator_common_plat *dev_pdata;
+ struct regulator_common_plat *plat;
- dev_pdata = dev_get_plat(dev);
+ plat = dev_get_plat(dev);
uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata)
return -ENXIO;
uc_pdata->type = REGULATOR_TYPE_FIXED;
- return regulator_common_of_to_plat(dev, dev_pdata, "gpio");
+ return regulator_common_of_to_plat(dev, plat, "gpio");
}
static int fixed_regulator_get_value(struct udevice *dev)
@@ -88,7 +88,7 @@ static int fixed_clock_regulator_get_enable(struct udevice *dev)
static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
{
struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
- struct regulator_common_plat *dev_pdata = dev_get_plat(dev);
+ struct regulator_common_plat *plat = dev_get_plat(dev);
int ret = 0;
if (enable) {
@@ -101,11 +101,11 @@ static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
if (ret)
return ret;
- if (enable && dev_pdata->startup_delay_us)
- udelay(dev_pdata->startup_delay_us);
+ if (enable && plat->startup_delay_us)
+ udelay(plat->startup_delay_us);
- if (!enable && dev_pdata->off_on_delay_us)
- udelay(dev_pdata->off_on_delay_us);
+ if (!enable && plat->off_on_delay_us)
+ udelay(plat->off_on_delay_us);
return ret;
}
diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c
index 9c0a68aa5af..ded7be059bb 100644
--- a/drivers/power/regulator/gpio-regulator.c
+++ b/drivers/power/regulator/gpio-regulator.c
@@ -27,12 +27,12 @@ struct gpio_regulator_plat {
static int gpio_regulator_of_to_plat(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct gpio_regulator_plat *dev_pdata;
+ struct gpio_regulator_plat *plat;
struct gpio_desc *gpio;
int ret, count, i, j;
u32 states_array[GPIO_REGULATOR_MAX_STATES * 2];
- dev_pdata = dev_get_plat(dev);
+ plat = dev_get_plat(dev);
uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata)
return -ENXIO;
@@ -47,7 +47,7 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
+ gpio = &plat->gpio;
ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
if (ret)
debug("regulator gpio - not found! Error: %d", ret);
@@ -68,21 +68,21 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
return ret;
for (i = 0, j = 0; i < count; i += 2) {
- dev_pdata->voltages[j] = states_array[i];
- dev_pdata->states[j] = states_array[i + 1];
+ plat->voltages[j] = states_array[i];
+ plat->states[j] = states_array[i + 1];
j++;
}
- return regulator_common_of_to_plat(dev, &dev_pdata->common, "enable-gpios");
+ return regulator_common_of_to_plat(dev, &plat->common, "enable-gpios");
}
static int gpio_regulator_get_value(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
int enable;
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return -ENOSYS;
uc_pdata = dev_get_uclass_plat(dev);
@@ -91,30 +91,30 @@ static int gpio_regulator_get_value(struct udevice *dev)
return -EINVAL;
}
- enable = dm_gpio_get_value(&dev_pdata->gpio);
- if (enable == dev_pdata->states[0])
- return dev_pdata->voltages[0];
+ enable = dm_gpio_get_value(&plat->gpio);
+ if (enable == plat->states[0])
+ return plat->voltages[0];
else
- return dev_pdata->voltages[1];
+ return plat->voltages[1];
}
static int gpio_regulator_set_value(struct udevice *dev, int uV)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
int ret;
bool enable;
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->voltages[0])
- enable = dev_pdata->states[0];
- else if (uV == dev_pdata->voltages[1])
- enable = dev_pdata->states[1];
+ if (uV == plat->voltages[0])
+ enable = plat->states[0];
+ else if (uV == plat->voltages[1])
+ enable = plat->states[1];
else
return -EINVAL;
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
+ ret = dm_gpio_set_value(&plat->gpio, enable);
if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
@@ -126,14 +126,14 @@ static int gpio_regulator_set_value(struct udevice *dev, int uV)
static int gpio_regulator_get_enable(struct udevice *dev)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
- return regulator_common_get_enable(dev, &dev_pdata->common);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
+ return regulator_common_get_enable(dev, &plat->common);
}
static int gpio_regulator_set_enable(struct udevice *dev, bool enable)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
- return regulator_common_set_enable(dev, &dev_pdata->common, enable);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
+ return regulator_common_set_enable(dev, &plat->common, enable);
}
static const struct dm_regulator_ops gpio_regulator_ops = {
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index d608f7c2365..3a6ba69f6d5 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -197,6 +197,12 @@ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
ret = regulator_set_enable(dev, enable);
if (ret == -ENOSYS || ret == -EACCES)
return 0;
+ /* if we want to disable but it's in use by someone else */
+ if (!enable && ret == -EBUSY)
+ return 0;
+ /* if it's already enabled/disabled */
+ if (ret == -EALREADY)
+ return 0;
return ret;
}
diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
index 93d8196b381..e26f5ebec34 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -13,7 +13,7 @@
#include "regulator_common.h"
int regulator_common_of_to_plat(struct udevice *dev,
- struct regulator_common_plat *dev_pdata,
+ struct regulator_common_plat *plat,
const char *enable_gpio_name)
{
struct gpio_desc *gpio;
@@ -26,7 +26,7 @@ int regulator_common_of_to_plat(struct udevice *dev,
flags |= GPIOD_IS_OUT_ACTIVE;
/* Get optional enable GPIO desc */
- gpio = &dev_pdata->gpio;
+ gpio = &plat->gpio;
ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags);
if (ret) {
debug("Regulator '%s' optional enable GPIO - not found! Error: %d\n",
@@ -36,12 +36,11 @@ int regulator_common_of_to_plat(struct udevice *dev,
}
/* Get optional ramp up delay */
- dev_pdata->startup_delay_us = dev_read_u32_default(dev,
- "startup-delay-us", 0);
- dev_pdata->off_on_delay_us =
- dev_read_u32_default(dev, "off-on-delay-us", 0);
- if (!dev_pdata->off_on_delay_us) {
- dev_pdata->off_on_delay_us =
+ plat->startup_delay_us = dev_read_u32_default(dev,
+ "startup-delay-us", 0);
+ plat->off_on_delay_us = dev_read_u32_default(dev, "off-on-delay-us", 0);
+ if (!plat->off_on_delay_us) {
+ plat->off_on_delay_us =
dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0);
}
@@ -49,43 +48,65 @@ int regulator_common_of_to_plat(struct udevice *dev,
}
int regulator_common_get_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata)
+ struct regulator_common_plat *plat)
{
/* Enable GPIO is optional */
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return true;
- return dm_gpio_get_value(&dev_pdata->gpio);
+ return dm_gpio_get_value(&plat->gpio);
}
int regulator_common_set_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata, bool enable)
+ struct regulator_common_plat *plat, bool enable)
{
int ret;
debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
- dev->name, enable, dev_pdata->startup_delay_us,
- dm_gpio_is_valid(&dev_pdata->gpio));
+ dev->name, enable, plat->startup_delay_us,
+ dm_gpio_is_valid(&plat->gpio));
/* Enable GPIO is optional */
- if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
+ if (!dm_gpio_is_valid(&plat->gpio)) {
if (!enable)
return -ENOSYS;
return 0;
}
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
+ /* If previously enabled, increase count */
+ if (enable && plat->enable_count > 0) {
+ plat->enable_count++;
+ return -EALREADY;
+ }
+
+ if (!enable) {
+ if (plat->enable_count > 1) {
+ /* If enabled multiple times, decrease count */
+ plat->enable_count--;
+ return -EBUSY;
+ } else if (!plat->enable_count) {
+ /* If already disabled, do nothing */
+ return -EALREADY;
+ }
+ }
+
+ ret = dm_gpio_set_value(&plat->gpio, enable);
if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
}
- if (enable && dev_pdata->startup_delay_us)
- udelay(dev_pdata->startup_delay_us);
+ if (enable && plat->startup_delay_us)
+ udelay(plat->startup_delay_us);
debug("%s: done\n", __func__);
- if (!enable && dev_pdata->off_on_delay_us)
- udelay(dev_pdata->off_on_delay_us);
+ if (!enable && plat->off_on_delay_us)
+ udelay(plat->off_on_delay_us);
+
+ if (enable)
+ plat->enable_count++;
+ else
+ plat->enable_count--;
return 0;
}
diff --git a/drivers/power/regulator/regulator_common.h b/drivers/power/regulator/regulator_common.h
index c10492f0167..d4962899d83 100644
--- a/drivers/power/regulator/regulator_common.h
+++ b/drivers/power/regulator/regulator_common.h
@@ -13,14 +13,35 @@ struct regulator_common_plat {
struct gpio_desc gpio; /* GPIO for regulator enable control */
unsigned int startup_delay_us;
unsigned int off_on_delay_us;
+ unsigned int enable_count;
};
int regulator_common_of_to_plat(struct udevice *dev,
- struct regulator_common_plat *dev_pdata, const
+ struct regulator_common_plat *plat, const
char *enable_gpio_name);
int regulator_common_get_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata);
+ struct regulator_common_plat *plat);
+/*
+ * Enable or Disable a regulator
+ *
+ * This is a reentrant function and subsequent calls that enable will
+ * increase an internal counter, and disable calls will decrease the counter.
+ * The actual resource will be enabled when the counter gets to 1 coming from 0,
+ * and disabled when it reaches 0 coming from 1.
+ *
+ * @dev: regulator device
+ * @plat: Platform data
+ * @enable: bool indicating whether to enable or disable the regulator
+ * @return:
+ * 0 on Success
+ * -EBUSY if the regulator cannot be disabled because it's requested by
+ * another device
+ * -EALREADY if the regulator has already been enabled or has already been
+ * disabled
+ * -EACCES if there is no possibility to enable/disable the regulator
+ * -ve on different error situation
+ */
int regulator_common_set_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata, bool enable);
+ struct regulator_common_plat *plat, bool enable);
#endif /* _REGULATOR_COMMON_H */
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index 2ba92bf9c48..0085113f674 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -18,6 +18,7 @@
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/iopoll.h>
#include "serial_stm32.h"
#include <dm/device_compat.h>
@@ -28,6 +29,10 @@ static void _stm32_serial_setbrg(fdt_addr_t base,
{
bool stm32f4 = uart_info->stm32f4;
u32 int_div, mantissa, fraction, oversampling;
+ u8 uart_enable_bit = uart_info->uart_enable_bit;
+
+ /* BRR register must be set when uart is disabled */
+ clrbits_le32(base + CR1_OFFSET(stm32f4), BIT(uart_enable_bit));
int_div = DIV_ROUND_CLOSEST(clock_rate, baudrate);
@@ -43,6 +48,8 @@ static void _stm32_serial_setbrg(fdt_addr_t base,
fraction = int_div % oversampling;
writel(mantissa | fraction, base + BRR_OFFSET(stm32f4));
+
+ setbits_le32(base + CR1_OFFSET(stm32f4), BIT(uart_enable_bit));
}
static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
@@ -181,9 +188,12 @@ static int stm32_serial_probe(struct udevice *dev)
struct stm32x7_serial_plat *plat = dev_get_plat(dev);
struct clk clk;
struct reset_ctl reset;
+ u32 isr;
int ret;
+ bool stm32f4;
plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev);
+ stm32f4 = plat->uart_info->stm32f4;
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0)
@@ -195,6 +205,17 @@ static int stm32_serial_probe(struct udevice *dev)
return ret;
}
+ /*
+ * before uart initialization, wait for TC bit (Transmission Complete)
+ * in case there is still chars from previous bootstage to transmit
+ */
+ ret = read_poll_timeout(readl, isr, isr & USART_ISR_TC, 10, 150,
+ plat->base + ISR_OFFSET(stm32f4));
+ if (ret) {
+ clk_disable(&clk);
+ return ret;
+ }
+
ret = reset_get_by_index(dev, 0, &reset);
if (!ret) {
reset_assert(&reset);
diff --git a/drivers/serial/serial_stm32.h b/drivers/serial/serial_stm32.h
index 5bee68fa9c2..b7e7a90b931 100644
--- a/drivers/serial/serial_stm32.h
+++ b/drivers/serial/serial_stm32.h
@@ -66,6 +66,7 @@ struct stm32x7_serial_plat {
#define USART_CR3_OVRDIS BIT(12)
#define USART_ISR_TXE BIT(7)
+#define USART_ISR_TC BIT(6)
#define USART_ISR_RXNE BIT(5)
#define USART_ISR_ORE BIT(3)
#define USART_ISR_FE BIT(1)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4f435fd2681..453a5983b2a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -382,7 +382,7 @@ config SPI_QUP
config RENESAS_RPC_SPI
bool "Renesas RPC SPI driver"
depends on RCAR_64 || RZA1
- imply SPI_FLASH_BAR
+ imply SPI_FLASH_SFDP_SUPPORT
help
Enable the Renesas RPC SPI driver, used to access SPI NOR flash
on Renesas RCar Gen3 SoCs. This uses driver model and requires a
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index 1cbb5d46fd6..ff7b55f8707 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -347,20 +347,28 @@ static void _omap3_spi_set_wordlen(struct omap3_spi_priv *priv)
omap3_spi_write_chconf(priv, confr);
}
-static void spi_reset(struct mcspi *regs)
+static void spi_reset(struct omap3_spi_priv *priv)
{
unsigned int tmp;
- writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &regs->sysconfig);
+ writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &priv->regs->sysconfig);
do {
- tmp = readl(&regs->sysstatus);
+ tmp = readl(&priv->regs->sysstatus);
} while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
- OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, &regs->sysconfig);
+ OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, &priv->regs->sysconfig);
- writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &regs->wakeupenable);
+ writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &priv->regs->wakeupenable);
+
+ /*
+ * Set the same default mode for each channel, especially CS polarity
+ * which must be common for all SPI slaves before any transfer.
+ */
+ for (priv->cs = 0 ; priv->cs < OMAP4_MCSPI_CHAN_NB ; priv->cs++)
+ _omap3_spi_set_mode(priv);
+ priv->cs = 0;
}
static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv)
@@ -430,7 +438,7 @@ static int omap3_spi_probe(struct udevice *dev)
priv->pin_dir = plat->pin_dir;
priv->wordlen = SPI_DEFAULT_WORDLEN;
- spi_reset(priv->regs);
+ spi_reset(priv);
return 0;
}
diff --git a/drivers/spi/renesas_rpc_spi.c b/drivers/spi/renesas_rpc_spi.c
index cb2b8fb64de..51c37d72eb6 100644
--- a/drivers/spi/renesas_rpc_spi.c
+++ b/drivers/spi/renesas_rpc_spi.c
@@ -17,6 +17,7 @@
#include <linux/bug.h>
#include <linux/errno.h>
#include <spi.h>
+#include <spi-mem.h>
#include <wait_bit.h>
#define RPC_CMNCR 0x0000 /* R/W */
@@ -140,6 +141,7 @@
#define PRC_PHYCNT_EXDS BIT(21)
#define RPC_PHYCNT_OCT BIT(20)
#define RPC_PHYCNT_STRTIM(v) (((v) & 0x7) << 15)
+#define RPC_PHYCNT_STRTIM2(v) ((((v) & 0x7) << 15) | (((v) & 0x8) << 24))
#define RPC_PHYCNT_WBUF2 BIT(4)
#define RPC_PHYCNT_WBUF BIT(2)
#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0)
@@ -167,10 +169,6 @@ struct rpc_spi_priv {
fdt_addr_t regs;
fdt_addr_t extr;
struct clk clk;
-
- u8 cmdcopy[8];
- u32 cmdlen;
- bool cmdstarted;
};
static int rpc_spi_wait_sslf(struct udevice *dev)
@@ -202,18 +200,35 @@ static void rpc_spi_flush_read_cache(struct udevice *dev)
}
+static u32 rpc_spi_get_strobe_delay(void)
+{
+#ifndef CONFIG_RZA1
+ u32 cpu_type = rmobile_get_cpu_type();
+
+ /*
+ * NOTE: RPC_PHYCNT_STRTIM value:
+ * 0: On H3 ES1.x (not supported in mainline U-Boot)
+ * 6: On M3 ES1.x
+ * 7: On other R-Car Gen3
+ * 15: On R-Car Gen4
+ */
+ if (cpu_type == RMOBILE_CPU_TYPE_R8A7796 && rmobile_get_cpu_rev_integer() == 1)
+ return RPC_PHYCNT_STRTIM(6);
+ else if (cpu_type == RMOBILE_CPU_TYPE_R8A779F0 ||
+ cpu_type == RMOBILE_CPU_TYPE_R8A779G0)
+ return RPC_PHYCNT_STRTIM2(15);
+ else
+#endif
+ return RPC_PHYCNT_STRTIM(7);
+}
+
static int rpc_spi_claim_bus(struct udevice *dev, bool manual)
{
struct udevice *bus = dev->parent;
struct rpc_spi_priv *priv = dev_get_priv(bus);
- /*
- * NOTE: The 0x260 are undocumented bits, but they must be set.
- * NOTE: On H3 ES1.x (not supported in mainline U-Boot), the
- * RPC_PHYCNT_STRTIM shall be 0, while on newer parts, the
- * RPC_PHYCNT_STRTIM shall be 6.
- */
- writel(RPC_PHYCNT_CAL | RPC_PHYCNT_STRTIM(6) | 0x260,
+ /* NOTE: The 0x260 are undocumented bits, but they must be set. */
+ writel(RPC_PHYCNT_CAL | rpc_spi_get_strobe_delay() | 0x260,
priv->regs + RPC_PHYCNT);
writel((manual ? RPC_CMNCR_MD : 0) | RPC_CMNCR_SFDE |
RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | RPC_CMNCR_BSZ(0),
@@ -233,79 +248,91 @@ static int rpc_spi_release_bus(struct udevice *dev)
struct rpc_spi_priv *priv = dev_get_priv(bus);
/* NOTE: The 0x260 are undocumented bits, but they must be set. */
- writel(RPC_PHYCNT_STRTIM(6) | 0x260, priv->regs + RPC_PHYCNT);
+ writel(rpc_spi_get_strobe_delay() | 0x260, priv->regs + RPC_PHYCNT);
rpc_spi_flush_read_cache(dev);
return 0;
}
-static int rpc_spi_xfer(struct udevice *dev, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
+static int rpc_spi_mem_exec_op(struct spi_slave *spi,
+ const struct spi_mem_op *op)
{
- struct udevice *bus = dev->parent;
+ struct udevice *bus = spi->dev->parent;
struct rpc_spi_priv *priv = dev_get_priv(bus);
- u32 wlen = dout ? (bitlen / 8) : 0;
- u32 rlen = din ? (bitlen / 8) : 0;
- u32 wloop = DIV_ROUND_UP(wlen, 4);
- u32 smenr, smcr, offset;
+ const void *dout = op->data.buf.out ? op->data.buf.out : NULL;
+ void *din = op->data.buf.in ? op->data.buf.in : NULL;
int ret = 0;
-
- if (!priv->cmdstarted) {
- if (!wlen || rlen)
- BUG();
-
- memcpy(priv->cmdcopy, dout, wlen);
- priv->cmdlen = wlen;
-
- /* Command transfer start */
- priv->cmdstarted = true;
- if (!(flags & SPI_XFER_END))
- return 0;
- }
-
- offset = (priv->cmdcopy[1] << 16) | (priv->cmdcopy[2] << 8) |
- (priv->cmdcopy[3] << 0);
+ u32 offset = 0;
+ u32 smenr, smcr;
smenr = 0;
+ offset = op->addr.val;
+
+ switch (op->data.dir) {
+ case SPI_MEM_DATA_IN:
+ rpc_spi_claim_bus(spi->dev, false);
+
+ writel(0, priv->regs + RPC_DRCMR);
+ writel(RPC_DRCMR_CMD(op->cmd.opcode), priv->regs + RPC_DRCMR);
+ smenr |= RPC_DRENR_CDE;
+
+ writel(0, priv->regs + RPC_DREAR);
+ if (op->addr.nbytes == 4) {
+ writel(RPC_DREAR_EAV(offset >> 25) | RPC_DREAR_EAC(1),
+ priv->regs + RPC_DREAR);
+ smenr |= RPC_DRENR_ADE(0xF);
+ } else if (op->addr.nbytes == 3) {
+ smenr |= RPC_DRENR_ADE(0x7);
+ } else {
+ smenr |= RPC_DRENR_ADE(0);
+ }
- if (wlen || (!rlen && !wlen) || flags == SPI_XFER_ONCE) {
- if (wlen && flags == SPI_XFER_END)
- smenr = RPC_SMENR_SPIDE(0xf);
+ writel(0, priv->regs + RPC_DRDMCR);
+ if (op->dummy.nbytes) {
+ writel(8 * op->dummy.nbytes - 1, priv->regs + RPC_DRDMCR);
+ smenr |= RPC_DRENR_DME;
+ }
- rpc_spi_claim_bus(dev, true);
+ writel(0, priv->regs + RPC_DROPR);
+ writel(smenr, priv->regs + RPC_DRENR);
- writel(0, priv->regs + RPC_SMCR);
+ memcpy_fromio(din, (void *)(priv->extr + offset), op->data.nbytes);
- if (priv->cmdlen >= 1) { /* Command(1) */
- writel(RPC_SMCMR_CMD(priv->cmdcopy[0]),
- priv->regs + RPC_SMCMR);
- smenr |= RPC_SMENR_CDE;
- } else {
- writel(0, priv->regs + RPC_SMCMR);
- }
+ rpc_spi_release_bus(spi->dev);
+ break;
+ case SPI_MEM_DATA_OUT:
+ case SPI_MEM_NO_DATA:
+ rpc_spi_claim_bus(spi->dev, true);
- if (priv->cmdlen >= 4) { /* Address(3) */
- writel(offset, priv->regs + RPC_SMADR);
- smenr |= RPC_SMENR_ADE(7);
- } else {
- writel(0, priv->regs + RPC_SMADR);
- }
+ writel(0, priv->regs + RPC_SMCR);
+ writel(0, priv->regs + RPC_SMCMR);
+ writel(RPC_SMCMR_CMD(op->cmd.opcode), priv->regs + RPC_SMCMR);
+ smenr |= RPC_SMENR_CDE;
+
+ writel(0, priv->regs + RPC_SMADR);
+ if (op->addr.nbytes == 4)
+ smenr |= RPC_SMENR_ADE(0xF);
+ else if (op->addr.nbytes == 3)
+ smenr |= RPC_SMENR_ADE(0x7);
+ else
+ smenr |= RPC_SMENR_ADE(0);
+ writel(offset, priv->regs + RPC_SMADR);
- if (priv->cmdlen >= 5) { /* Dummy(n) */
- writel(8 * (priv->cmdlen - 4) - 1,
- priv->regs + RPC_SMDMCR);
+ writel(0, priv->regs + RPC_SMDMCR);
+ if (op->dummy.nbytes) {
+ writel(8 * op->dummy.nbytes - 1, priv->regs + RPC_SMDMCR);
smenr |= RPC_SMENR_DME;
- } else {
- writel(0, priv->regs + RPC_SMDMCR);
}
writel(0, priv->regs + RPC_SMOPR);
-
writel(0, priv->regs + RPC_SMDRENR);
- if (wlen && flags == SPI_XFER_END) {
+ if (dout && op->data.nbytes) {
u32 *datout = (u32 *)dout;
+ u32 wloop = DIV_ROUND_UP(op->data.nbytes, 4);
+
+ smenr |= RPC_SMENR_SPIDE(0xF);
while (wloop--) {
smcr = RPC_SMCR_SPIWE | RPC_SMCR_SPIE;
@@ -314,57 +341,28 @@ static int rpc_spi_xfer(struct udevice *dev, unsigned int bitlen,
writel(smenr, priv->regs + RPC_SMENR);
writel(*datout, priv->regs + RPC_SMWDR0);
writel(smcr, priv->regs + RPC_SMCR);
- ret = rpc_spi_wait_tend(dev);
- if (ret)
- goto err;
+ ret = rpc_spi_wait_tend(spi->dev);
+ if (ret) {
+ rpc_spi_release_bus(spi->dev);
+ return ret;
+ }
datout++;
- smenr = RPC_SMENR_SPIDE(0xf);
+ smenr &= (~RPC_SMENR_CDE & ~RPC_SMENR_ADE(0xF));
}
- ret = rpc_spi_wait_sslf(dev);
-
+ ret = rpc_spi_wait_sslf(spi->dev);
} else {
writel(smenr, priv->regs + RPC_SMENR);
writel(RPC_SMCR_SPIE, priv->regs + RPC_SMCR);
- ret = rpc_spi_wait_tend(dev);
- }
- } else { /* Read data only, using DRx ext access */
- rpc_spi_claim_bus(dev, false);
-
- if (priv->cmdlen >= 1) { /* Command(1) */
- writel(RPC_DRCMR_CMD(priv->cmdcopy[0]),
- priv->regs + RPC_DRCMR);
- smenr |= RPC_DRENR_CDE;
- } else {
- writel(0, priv->regs + RPC_DRCMR);
- }
-
- if (priv->cmdlen >= 4) /* Address(3) */
- smenr |= RPC_DRENR_ADE(7);
-
- if (priv->cmdlen >= 5) { /* Dummy(n) */
- writel(8 * (priv->cmdlen - 4) - 1,
- priv->regs + RPC_DRDMCR);
- smenr |= RPC_DRENR_DME;
- } else {
- writel(0, priv->regs + RPC_DRDMCR);
+ ret = rpc_spi_wait_tend(spi->dev);
}
- writel(0, priv->regs + RPC_DROPR);
-
- writel(smenr, priv->regs + RPC_DRENR);
-
- if (rlen)
- memcpy_fromio(din, (void *)(priv->extr + offset), rlen);
- else
- readl(priv->extr); /* Dummy read */
+ rpc_spi_release_bus(spi->dev);
+ break;
+ default:
+ break;
}
-err:
- priv->cmdstarted = false;
-
- rpc_spi_release_bus(dev);
-
return ret;
}
@@ -380,6 +378,10 @@ static int rpc_spi_set_mode(struct udevice *bus, uint mode)
return 0;
}
+static const struct spi_controller_mem_ops rpc_spi_mem_ops = {
+ .exec_op = rpc_spi_mem_exec_op
+};
+
static int rpc_spi_bind(struct udevice *parent)
{
const void *fdt = gd->fdt_blob;
@@ -443,9 +445,9 @@ static int rpc_spi_of_to_plat(struct udevice *bus)
}
static const struct dm_spi_ops rpc_spi_ops = {
- .xfer = rpc_spi_xfer,
.set_speed = rpc_spi_set_speed,
.set_mode = rpc_spi_set_mode,
+ .mem_ops = &rpc_spi_mem_ops
};
static const struct udevice_id rpc_spi_ids[] = {
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index 7b64532e50b..572cef1694c 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -9,7 +9,7 @@
* Author: Robert Marko <robert.marko@sartura.hr>
* Author: Luka Kovacic <luka.kovacic@sartura.hr>
*
- * Based on stock U-boot and Linux drivers
+ * Based on stock U-Boot and Linux drivers
*/
#include <asm/gpio.h>
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 94fb32d107c..a972d87c7ad 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -126,6 +126,28 @@ config USB_HUB_DEBOUNCE_TIMEOUT
value = 1s because some usb device needs around 1.5s to be initialized
and a 2s value should solve detection issue on problematic USB keys.
+if SPL_USB_HOST
+
+comment "USB peripherals in SPL"
+
+config SPL_USB_STORAGE
+ bool "Support loading from USB"
+ help
+ Enable support for USB devices in SPL. This allows use of USB
+ devices such as hard drives and flash drivers for loading U-Boot.
+ The actual drivers are enabled separately using the normal U-Boot
+ config options. This enables loading from USB using a configured
+ device.
+
+config SYS_USB_FAT_BOOT_PARTITION
+ int "Partition on USB to use to load U-Boot from"
+ depends on SPL_USB_STORAGE
+ default 1
+ help
+ Partition on the USB storage device to load U-Boot from.
+
+endif
+
if USB_KEYBOARD
config USB_KEYBOARD_FN_KEYS
diff --git a/drivers/usb/eth/lan78xx.c b/drivers/usb/eth/lan78xx.c
index 37912a1d040..1d8267c80bb 100644
--- a/drivers/usb/eth/lan78xx.c
+++ b/drivers/usb/eth/lan78xx.c
@@ -146,11 +146,9 @@ static int lan78xx_read_otp(struct usb_device *udev, u32 offset,
ret = lan78xx_read_raw_otp(udev, 0, 1, &sig);
if (!ret) {
- if (sig == LAN78XX_OTP_INDICATOR_1)
- offset = offset;
- else if (sig == LAN78XX_OTP_INDICATOR_2)
+ if (sig == LAN78XX_OTP_INDICATOR_2)
offset += 0x100;
- else
+ else if (sig != LAN78XX_OTP_INDICATOR_1)
return -EINVAL;
ret = lan78xx_read_raw_otp(udev, offset, length, data);
if (ret)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 941f97c96d0..1cfe6022842 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -36,6 +36,12 @@ menuconfig USB_GADGET
peripheral/device side bus controller, and a "gadget driver" for
your peripheral protocol.
+config SPL_USB_GADGET
+ bool "USB Gadget Support in SPL"
+ help
+ Enable USB Gadget API which allows to enable USB device functions
+ in SPL.
+
if USB_GADGET
config USB_GADGET_MANUFACTURER
@@ -265,3 +271,85 @@ config USBNET_HOST_ADDR
endif # USB_ETHER
endif # USB_GADGET
+
+if SPL_USB_GADGET
+
+config SPL_USB_ETHER
+ bool "Support USB Ethernet drivers in SPL"
+ depends on SPL_NET
+ help
+ Enable access to the USB network subsystem and associated
+ drivers in SPL. This permits SPL to load U-Boot over a
+ USB-connected Ethernet link (such as a USB Ethernet dongle) rather
+ than from an onboard peripheral. Environment support is required
+ since the network stack uses a number of environment variables.
+ See also SPL_NET and SPL_ETH.
+
+if SPL_USB_ETHER
+
+choice
+ prompt "USB Ethernet Gadget Model in SPL"
+ default SPL_USB_ETH_RNDIS
+ help
+ There is several models (protocols) to implement Ethernet over USB
+ devices. The main ones are Microsoft's RNDIS and USB's CDC-Ethernet
+ (also called CDC-ECM). RNDIS is obviously compatible with Windows,
+ while CDC-ECM is not. Most other operating systems support both, so
+ if inter-operability is a concern, RNDIS is to be preferred.
+
+config SPL_USB_ETH_RNDIS
+ bool "RNDIS Protocol"
+ help
+ The RNDIS (Remote Network Driver Interface Specification) is a
+ Microsoft proprietary protocol to create an Ethernet device over USB.
+ Windows obviously supports it, as well as all the major operating
+ systems, so it's the best option for compatibility.
+
+endchoice
+
+endif # SPL_USB_ETHER
+
+config SPL_DFU
+ bool "Support DFU (Device Firmware Upgrade) in SPL"
+ select SPL_HASH
+ select SPL_DFU_NO_RESET
+ depends on SPL_RAM_SUPPORT
+ help
+ This feature enables the DFU (Device Firmware Upgrade) in SPL with
+ RAM memory device support. The ROM code will load and execute
+ the SPL built with dfu. The user can load binaries (u-boot/kernel) to
+ selected device partition from host-pc using dfu-utils.
+ This feature is useful to flash the binaries to factory or bare-metal
+ boards using USB interface.
+
+choice
+ bool "DFU device selection in SPL"
+ depends on SPL_DFU
+
+config SPL_DFU_RAM
+ bool "RAM device"
+ depends on SPL_DFU && SPL_RAM_SUPPORT
+ help
+ select RAM/DDR memory device for loading binary images
+ (u-boot/kernel) to the selected device partition using
+ DFU and execute the u-boot/kernel from RAM.
+
+endchoice
+
+config SPL_USB_SDP_SUPPORT
+ bool "Support SDP (Serial Download Protocol) in SPL"
+ depends on SPL_SERIAL
+ help
+ Enable Serial Download Protocol (SDP) device support in SPL. This
+ allows to download images into memory and execute (jump to) them
+ using the same protocol as implemented by the i.MX family's boot ROM.
+
+config SPL_SDP_USB_DEV
+ int "SDP USB controller index in SPL"
+ default 0
+ depends on SPL_USB_SDP_SUPPORT
+ help
+ Some boards have USB controller other than 0. Define this option
+ so it can be used in compiled environment.
+
+endif # SPL_USB_GADGET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 6cfe0f3a041..6abcce0d9c7 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -3,8 +3,9 @@
# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-obj-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o
-obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
+obj-$(CONFIG_$(SPL_TPL_)USB_GADGET) += epautoconf.o config.o usbstring.o
+obj-$(CONFIG_$(SPL_TPL_)USB_ETHER) += epautoconf.o config.o usbstring.o ether.o
+obj-$(CONFIG_$(SPL_TPL_)USB_ETH_RNDIS) += rndis.o
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_USB_GADGET) += g_dnl.o
@@ -34,9 +35,6 @@ endif
obj-$(CONFIG_CI_UDC) += ci_udc.o
-obj-$(CONFIG_USB_ETHER) += ether.o
-obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o
-
# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
# This is really only N900 and USBTTY now.
obj-$(CONFIG_USB_DEVICE) += core.o ep0.o
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6213b3c95fa..1a883babf4c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -6,6 +6,19 @@ comment "USB Host Controller Drivers"
config USB_HOST
bool
select DM_USB
+ help
+ Enable access to USB (Universal Serial Bus) host devices so that
+ SPL can load U-Boot from a connected USB peripheral, such as a USB
+ flash stick. While USB takes a little longer to start up than most
+ buses, it is very flexible since many different types of storage
+ device can be attached.
+
+config SPL_USB_HOST
+ bool "Support USB host drivers"
+ depends on SPL
+ help
+ For detailed help see USB_HOST Kconfig symbol. This option enables
+ the drivers in drivers/usb/host as part of an SPL build.
config USB_XHCI_HCD
bool "xHCI HCD (USB 3.0) support"
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1e2f4e6de4a..49762950719 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -740,14 +740,7 @@ 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 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/zynqmp/Kconfig"
source "drivers/video/nexell/Kconfig"
config CONSOLE_SCROLL_LINES
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9a53cd14187..f99d7e3c3d9 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -73,7 +73,7 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
obj-$(CONFIG_VIDEO_VESA) += vesa.o
obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
-obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp_dpsub.o
+obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp/
obj-y += bridge/
obj-y += sunxi/
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 8396bdfb11e..1b66a8061a7 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -220,14 +220,20 @@ u32 video_index_to_colour(struct video_priv *priv, unsigned int idx)
break;
case VIDEO_BPP32:
if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
- if (priv->format == VIDEO_X2R10G10B10)
+ switch (priv->format) {
+ case VIDEO_X2R10G10B10:
return (colours[idx].r << 22) |
(colours[idx].g << 12) |
(colours[idx].b << 2);
- else
+ case VIDEO_RGBA8888:
+ return (colours[idx].r << 24) |
+ (colours[idx].g << 16) |
+ (colours[idx].b << 8) | 0xff;
+ default:
return (colours[idx].r << 16) |
(colours[idx].g << 8) |
(colours[idx].b << 0);
+ }
}
break;
default:
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 47e52c4f69c..45f003c8251 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -43,6 +43,18 @@ static u32 get_bmp_col_x2r10g10b10(struct bmp_color_table_entry *cte)
}
/**
+ * get_bmp_col_rgba8888() - Convert a colour-table entry into a rgba8888 pixel value
+ *
+ * Return: value to write to the rgba8888 frame buffer for this palette entry
+ */
+static u32 get_bmp_col_rgba8888(struct bmp_color_table_entry *cte)
+{
+ return ((cte->red) |
+ (cte->green << 8U) |
+ (cte->blue << 16U) | 0xff << 24U);
+}
+
+/**
* write_pix8() - Write a pixel from a BMP image into the framebuffer
*
* This handles frame buffers with 8, 16, 24 or 32 bits per pixel
@@ -71,6 +83,8 @@ static void write_pix8(u8 *fb, uint bpix, enum video_format eformat,
*fb++ = cte->blue;
} else if (eformat == VIDEO_X2R10G10B10) {
*(u32 *)fb = get_bmp_col_x2r10g10b10(cte);
+ } else if (eformat == VIDEO_RGBA8888) {
+ *(u32 *)fb = get_bmp_col_rgba8888(cte);
} else {
*fb++ = cte->blue;
*fb++ = cte->green;
@@ -382,6 +396,17 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
*fb++ = (pix >> 8) & 0xff;
*fb++ = (pix >> 16) & 0xff;
*fb++ = pix >> 24;
+ } else if (eformat == VIDEO_RGBA8888) {
+ u32 pix;
+
+ pix = *bmap++ << 8U; /* blue */
+ pix |= *bmap++ << 16U; /* green */
+ pix |= *bmap++ << 24U; /* red */
+
+ *fb++ = (pix >> 24) & 0xff;
+ *fb++ = (pix >> 16) & 0xff;
+ *fb++ = (pix >> 8) & 0xff;
+ *fb++ = 0xff;
} else {
*fb++ = *bmap++;
*fb++ = *bmap++;
@@ -409,6 +434,17 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
*fb++ = (pix >> 8) & 0xff;
*fb++ = (pix >> 16) & 0xff;
*fb++ = pix >> 24;
+ } else if (eformat == VIDEO_RGBA8888) {
+ u32 pix;
+
+ pix = *bmap++ << 8U; /* blue */
+ pix |= *bmap++ << 16U; /* green */
+ pix |= *bmap++ << 24U; /* red */
+ bmap++;
+ *fb++ = (pix >> 24) & 0xff;
+ *fb++ = (pix >> 16) & 0xff;
+ *fb++ = (pix >> 8) & 0xff;
+ *fb++ = 0xff; /* opacity */
} else {
*fb++ = *bmap++;
*fb++ = *bmap++;
diff --git a/drivers/video/zynqmp/Kconfig b/drivers/video/zynqmp/Kconfig
new file mode 100644
index 00000000000..b35cd1fb342
--- /dev/null
+++ b/drivers/video/zynqmp/Kconfig
@@ -0,0 +1,8 @@
+
+config VIDEO_ZYNQMP_DPSUB
+ bool "Enable video support for ZynqMP Display Port"
+ depends on 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.
diff --git a/drivers/video/zynqmp/Makefile b/drivers/video/zynqmp/Makefile
new file mode 100644
index 00000000000..cc057f53560
--- /dev/null
+++ b/drivers/video/zynqmp/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2023, Advanced Micro Devices, Inc.
+
+obj-y += zynqmp_dpsub.o
diff --git a/drivers/video/zynqmp/zynqmp_dpsub.c b/drivers/video/zynqmp/zynqmp_dpsub.c
new file mode 100644
index 00000000000..def4dcf6261
--- /dev/null
+++ b/drivers/video/zynqmp/zynqmp_dpsub.c
@@ -0,0 +1,2225 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 - 2022, Xilinx Inc.
+ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
+ *
+ * Xilinx displayport(DP) Tx Subsytem driver
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <stdlib.h>
+#include <video.h>
+#include <wait_bit.h>
+#include <dm/device_compat.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <dm/device_compat.h>
+#include <asm/global_data.h>
+
+#include "zynqmp_dpsub.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Maximum supported resolution */
+#define WIDTH 1024
+#define HEIGHT 768
+
+static struct dp_dma dp_dma;
+static struct dp_dma_descriptor cur_desc __aligned(256);
+
+static void dma_init_video_descriptor(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct dp_dma_frame_buffer *frame_buffer = &dp_sub->frame_buffer;
+
+ cur_desc.control = DPDMA_DESC_PREAMBLE | DPDMA_DESC_IGNR_DONE |
+ DPDMA_DESC_LAST_FRAME;
+ cur_desc.dscr_id = 0;
+ cur_desc.xfer_size = frame_buffer->size;
+ cur_desc.line_size_stride = ((frame_buffer->stride >> 4) <<
+ DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT) |
+ (frame_buffer->line_size);
+ cur_desc.addr_ext = (((u32)(frame_buffer->address >>
+ DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH) <<
+ DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT) |
+ (upper_32_bits((u64)&cur_desc)));
+ cur_desc.next_desr = lower_32_bits((u64)&cur_desc);
+ cur_desc.src_addr = lower_32_bits((u64)gd->fb_base);
+}
+
+static void dma_set_descriptor_address(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ flush_dcache_range((u64)&cur_desc,
+ ALIGN(((u64)&cur_desc + sizeof(cur_desc)),
+ CONFIG_SYS_CACHELINE_SIZE));
+ writel(upper_32_bits((u64)&cur_desc), dp_sub->dp_dma->base_addr +
+ DPDMA_CH3_DSCR_STRT_ADDRE);
+ writel(lower_32_bits((u64)&cur_desc), dp_sub->dp_dma->base_addr +
+ DPDMA_CH3_DSCR_STRT_ADDR);
+}
+
+static void dma_setup_channel(struct udevice *dev)
+{
+ dma_init_video_descriptor(dev);
+ dma_set_descriptor_address(dev);
+}
+
+static void dma_set_channel_state(struct udevice *dev)
+{
+ u32 mask = 0, regval = 0;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ mask = DPDMA_CH_CNTL_EN_MASK | DPDMA_CH_CNTL_PAUSE_MASK;
+ regval = DPDMA_CH_CNTL_EN_MASK;
+
+ clrsetbits_le32(dp_sub->dp_dma->base_addr + DPDMA_CH3_CNTL,
+ mask, regval);
+}
+
+static void dma_trigger(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 trigger;
+
+ trigger = DPDMA_GBL_TRG_CH3_MASK;
+ dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_DONE;
+ writel(trigger, dp_sub->dp_dma->base_addr + DPDMA_GBL);
+}
+
+static void dma_vsync_intr_handler(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ dma_setup_channel(dev);
+ dma_set_channel_state(dev);
+ dma_trigger(dev);
+
+ /* Clear VSync Interrupt */
+ writel(DPDMA_ISR_VSYNC_INT_MASK, dp_sub->dp_dma->base_addr + DPDMA_ISR);
+}
+
+/**
+ * wait_phy_ready() - Wait for the DisplayPort PHY to come out of reset
+ * @dev: The DP device
+ *
+ * Return: 0 if wait succeeded, -ve if error occurred
+ */
+static int wait_phy_ready(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 timeout = 100, phy_status;
+ u8 phy_ready_mask = DP_PHY_STATUS_RESET_LANE_0_DONE_MASK |
+ DP_PHY_STATUS_GT_PLL_LOCK_MASK;
+
+ /* Wait until the PHY is ready. */
+ do {
+ udelay(20);
+ phy_status = readl(dp_sub->base_addr + DP_PHY_STATUS);
+ phy_status &= phy_ready_mask;
+ /* Protect against an infinite loop. */
+ if (!timeout--)
+ return -ETIMEDOUT;
+ } while (phy_status != phy_ready_mask);
+
+ return 0;
+}
+
+static int init_dp_tx(struct udevice *dev)
+{
+ u32 status, phyval, regval, rate;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ phyval = readl(dp_sub->base_addr + DP_PHY_CONFIG);
+ writel(DP_SOFT_RESET_EN, dp_sub->base_addr + DP_SOFT_RESET);
+ status = readl(dp_sub->base_addr + DP_SOFT_RESET);
+ writel(DP_DISABLE, dp_sub->base_addr + DP_ENABLE);
+
+ regval = (readl(dp_sub->base_addr + DP_AUX_CLK_DIVIDER) &
+ ~DP_AUX_CLK_DIVIDER_VAL_MASK) |
+ (60 << 8) |
+ (dp_sub->clock / 1000000);
+ writel(regval, dp_sub->base_addr + DP_AUX_CLK_DIVIDER);
+
+ writel(DP_PHY_CLOCK_SELECT_540GBPS, dp_sub->base_addr + DP_PHY_CLOCK_SELECT);
+
+ regval = phyval & ~DP_PHY_CONFIG_GT_ALL_RESET_MASK;
+ writel(regval, dp_sub->base_addr + DP_PHY_CONFIG);
+ status = wait_phy_ready(dev);
+ if (status)
+ return -EINVAL;
+
+ writel(DP_ENABLE, dp_sub->base_addr + DP_ENABLE);
+
+ rate = ~DP_INTR_HPD_PULSE_DETECTED_MASK & ~DP_INTR_HPD_EVENT_MASK
+ & ~DP_INTR_HPD_IRQ_MASK;
+ writel(rate, dp_sub->base_addr + DP_INTR_MASK);
+ return 0;
+}
+
+static int set_nonlive_gfx_format(struct udevice *dev, enum av_buf_video_format format)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct av_buf_vid_attribute *ptr = (struct av_buf_vid_attribute *)avbuf_supported_formats;
+
+ while (1) {
+ dev_dbg(dev, "Format %d\n", ptr->video_format);
+
+ if (!ptr->video_format)
+ return -EINVAL;
+
+ if (ptr->video_format == format) {
+ dp_sub->non_live_graphics = ptr;
+ break;
+ }
+ ptr++;
+ }
+ dev_dbg(dev, "Video format found. BPP %d\n", dp_sub->non_live_graphics->bpp);
+ return 0;
+}
+
+/* DP dma setup */
+static void set_qos(struct udevice *dev, u8 qos)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 index;
+ u32 regval = 0, mask;
+
+ regval = (((u32)qos << DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT) |
+ ((u32)qos << DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT) |
+ ((u32)qos << DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT));
+
+ mask = DPDMA_CH_CNTL_QOS_DATA_RD_MASK |
+ DPDMA_CH_CNTL_QOS_DSCR_RD_MASK |
+ DPDMA_CH_CNTL_QOS_DSCR_WR_MASK;
+ for (index = 0; index <= DPDMA_AUDIO_CHANNEL1; index++) {
+ clrsetbits_le32(dp_sub->dp_dma->base_addr +
+ DPDMA_CH0_CNTL +
+ (DPDMA_CH_OFFSET * (u32)index),
+ mask, regval);
+ }
+}
+
+static void enable_gfx_buffers(struct udevice *dev, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 regval = 0;
+
+ regval = (0xF << AVBUF_CHBUF3_BURST_LEN_SHIFT) |
+ AVBUF_CHBUF3_FLUSH_MASK;
+ writel(regval, dp_sub->base_addr + AVBUF_CHBUF3);
+ if (enable) {
+ regval = (0xF << AVBUF_CHBUF3_BURST_LEN_SHIFT) |
+ AVBUF_CHBUF0_EN_MASK;
+ writel(regval, dp_sub->base_addr + AVBUF_CHBUF3);
+ }
+}
+
+static void avbuf_video_select(struct udevice *dev, enum av_buf_video_stream vid_stream,
+ enum av_buf_gfx_stream gfx_stream)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ dp_sub->av_mode.video_src = vid_stream;
+ dp_sub->av_mode.gfx_src = gfx_stream;
+
+ clrsetbits_le32(dp_sub->base_addr +
+ AVBUF_BUF_OUTPUT_AUD_VID_SELECT,
+ AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM2_SEL_MASK |
+ AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM1_SEL_MASK,
+ vid_stream | gfx_stream);
+}
+
+static void config_gfx_pipeline(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u16 *csc_matrix, *offset_matrix;
+ u32 regval = 0, index = 0, *scaling_factors = NULL;
+ u16 rgb_coeffs[] = { 0x1000, 0x0000, 0x0000,
+ 0x0000, 0x1000, 0x0000,
+ 0x0000, 0x0000, 0x1000 };
+ u16 rgb_offset[] = { 0x0000, 0x0000, 0x0000 };
+ struct av_buf_vid_attribute *video = dp_sub->non_live_graphics;
+
+ scaling_factors = video->sf;
+
+ clrsetbits_le32(dp_sub->base_addr + AVBUF_BUF_FORMAT,
+ AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_MASK,
+ (video->value) << AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_SHIFT);
+
+ for (index = 0; index < 3; index++) {
+ writel(scaling_factors[index], dp_sub->base_addr +
+ AVBUF_BUF_GRAPHICS_COMP0_SCALE_FACTOR + (index * 4));
+ }
+ regval = (video->is_rgb << AVBUF_V_BLEND_LAYER0_CONTROL_RGB_MODE_SHIFT) |
+ video->sampling_en;
+ writel(regval, dp_sub->base_addr + AVBUF_V_BLEND_LAYER1_CONTROL);
+
+ if (video->is_rgb) {
+ csc_matrix = rgb_coeffs;
+ offset_matrix = rgb_offset;
+ }
+ /* Program Colorspace conversion coefficients */
+ for (index = 9; index < 12; index++) {
+ writel(offset_matrix[index - 9], dp_sub->base_addr +
+ AVBUF_V_BLEND_IN2CSC_COEFF0 + (index * 4));
+ }
+
+ /* Program Colorspace conversion matrix */
+ for (index = 0; index < 9; index++) {
+ writel(csc_matrix[index], dp_sub->base_addr +
+ AVBUF_V_BLEND_IN2CSC_COEFF0 + (index * 4));
+ }
+}
+
+static void set_blender_alpha(struct udevice *dev, u8 alpha, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 regval;
+
+ regval = enable;
+ regval |= alpha << AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG_VALUE_SHIFT;
+ writel(regval, dp_sub->base_addr +
+ AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG);
+}
+
+static void config_output_video(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 regval = 0, index;
+ u16 rgb_coeffs[] = { 0x1000, 0x0000, 0x0000,
+ 0x0000, 0x1000, 0x0000,
+ 0x0000, 0x0000, 0x1000 };
+ u16 rgb_offset[] = { 0x0000, 0x0000, 0x0000 };
+ u16 *matrix_coeff = rgb_coeffs, *matrix_offset = rgb_offset;
+
+ struct av_buf_vid_attribute *output_video = dp_sub->non_live_graphics;
+
+ regval |= output_video->sampling_en <<
+ AVBUF_V_BLEND_OUTPUT_VID_FORMAT_EN_DOWNSAMPLE_SHIFT;
+ regval |= output_video->value;
+ writel(regval, dp_sub->base_addr + AVBUF_V_BLEND_OUTPUT_VID_FORMAT);
+
+ for (index = 0; index < 9; index++) {
+ writel(matrix_coeff[index], dp_sub->base_addr +
+ AVBUF_V_BLEND_RGB2YCBCR_COEFF0 + (index * 4));
+ }
+
+ for (index = 0; index < 3; index++) {
+ writel((matrix_offset[index] <<
+ AVBUF_V_BLEND_LUMA_IN1CSC_OFFSET_POST_OFFSET_SHIFT),
+ dp_sub->base_addr +
+ AVBUF_V_BLEND_LUMA_OUTCSC_OFFSET
+ + (index * 4));
+ }
+
+ set_blender_alpha(dev, 0, 0);
+}
+
+static void config_msa_sync_clk_mode(struct udevice *dev, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct main_stream_attributes *msa_config;
+
+ msa_config = &dp_sub->msa_config;
+ msa_config->synchronous_clock_mode = enable;
+
+ if (enable == 1) {
+ msa_config->misc0 |= (1 <<
+ DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT);
+ } else {
+ msa_config->misc0 &= ~(1 <<
+ DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT);
+ }
+}
+
+static void av_buf_soft_reset(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ writel(AVBUF_BUF_SRST_REG_VID_RST_MASK,
+ dp_sub->base_addr + AVBUF_BUF_SRST_REG);
+ writel(0, dp_sub->base_addr + AVBUF_BUF_SRST_REG);
+}
+
+static void set_video_clk_source(struct udevice *dev, u8 video_clk, u8 audio_clk)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 regval = 0;
+
+ if (dp_sub->av_mode.video_src != AVBUF_VIDSTREAM1_LIVE &&
+ dp_sub->av_mode.gfx_src != AVBUF_VIDSTREAM2_LIVE_GFX) {
+ regval = 1 << AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_TIMING_SRC_SHIFT;
+ } else if (dp_sub->av_mode.video_src == AVBUF_VIDSTREAM1_LIVE ||
+ dp_sub->av_mode.gfx_src == AVBUF_VIDSTREAM2_LIVE_GFX) {
+ video_clk = AVBUF_PL_CLK;
+ }
+
+ regval |= (video_clk << AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT) |
+ (audio_clk << AVBUF_BUF_AUD_VID_CLK_SOURCE_AUD_CLK_SRC_SHIFT);
+ writel(regval, dp_sub->base_addr + AVBUF_BUF_AUD_VID_CLK_SOURCE);
+
+ av_buf_soft_reset(dev);
+}
+
+static int init_dpdma_subsys(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ dp_sub->dp_dma->base_addr = DPDMA_BASE_ADDRESS;
+ dp_sub->dp_dma->gfx.channel.cur = NULL;
+ dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_DONE;
+
+ set_qos(dev, 11);
+ return 0;
+}
+
+/**
+ * is_dp_connected() - Check if there is a connected RX device
+ * @dev: The DP device
+ *
+ *
+ * Return: true if a connected RX device was detected, false otherwise
+ */
+static bool is_dp_connected(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ u8 retries = 0;
+
+ do {
+ status = readl(dp_sub->base_addr +
+ DP_INTERRUPT_SIG_STATE)
+ & DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK;
+
+ if (retries > DP_IS_CONNECTED_MAX_TIMEOUT_COUNT)
+ return 0;
+
+ retries++;
+ udelay(1000);
+ } while (status == 0);
+
+ return 1;
+}
+
+/**
+ * aux_wait_ready() - Wait until another request is no longer in progress
+ * @dev: The DP device
+ *
+ * Return: 0 if wait succeeded, -ve if error occurred
+ */
+static int aux_wait_ready(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status, timeout = 100;
+
+ do {
+ status = readl(dp_sub->base_addr +
+ DP_INTERRUPT_SIG_STATE);
+ if (!timeout--)
+ return -ETIMEDOUT;
+
+ udelay(20);
+ } while (status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK);
+
+ return 0;
+}
+
+/**
+ * aux_wait_reply() - Wait for reply on AUX channel
+ * @dev: The DP device
+ *
+ * Wait for a reply indicating that the most recent AUX request
+ * has been received by the RX device.
+ *
+ * Return: 0 if wait succeeded, -ve if error occurred
+ */
+static int aux_wait_reply(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 timeout = DP_AUX_MAX_WAIT, status;
+
+ while (timeout > 0) {
+ status = readl(dp_sub->base_addr + DP_REPLY_STATUS);
+ if (status & DP_REPLY_STATUS_REPLY_ERROR_MASK)
+ return -ETIMEDOUT;
+
+ if ((status & DP_REPLY_STATUS_REPLY_RECEIVED_MASK) &&
+ !(status & DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK) &&
+ !(status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK)) {
+ return 0;
+ }
+ timeout--;
+ udelay(20);
+ }
+ return -ETIMEDOUT;
+}
+
+/**
+ * aux_request_send() - Send request on the AUX channel
+ * @dev: The DP device
+ * @request: The request to send
+ *
+ * Submit the supplied AUX request to the RX device over the AUX
+ * channel by writing the command, the destination address, (the write buffer
+ * for write commands), and the data size to the DisplayPort TX core.
+ *
+ * This is the lower-level sending routine, which is called by aux_request().
+ *
+ * Return: 0 if request was sent successfully, -ve on error
+ */
+static int aux_request_send(struct udevice *dev, struct aux_transaction *request)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 timeout_count = 0, status;
+ u8 index;
+
+ do {
+ status = readl(dp_sub->base_addr +
+ DP_REPLY_STATUS);
+
+ udelay(20);
+ timeout_count++;
+ if (timeout_count >= DP_AUX_MAX_TIMEOUT_COUNT)
+ return -ETIMEDOUT;
+
+ } while ((status & DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK) ||
+ (status & DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK));
+ /* Set the address for the request. */
+ writel(request->address, dp_sub->base_addr + DP_AUX_ADDRESS);
+
+ if (request->cmd_code == DP_AUX_CMD_WRITE ||
+ request->cmd_code == DP_AUX_CMD_I2C_WRITE ||
+ request->cmd_code == DP_AUX_CMD_I2C_WRITE_MOT) {
+ /* Feed write data into the DisplayPort TX core's write FIFO. */
+ for (index = 0; index < request->num_bytes; index++) {
+ writel(request->data[index],
+ dp_sub->base_addr +
+ DP_AUX_WRITE_FIFO);
+ }
+ }
+
+ status = ((request->cmd_code << DP_AUX_CMD_SHIFT) |
+ ((request->num_bytes - 1) &
+ DP_AUX_CMD_NBYTES_TRANSFER_MASK));
+
+ /* Submit the command and the data size. */
+ writel(((request->cmd_code << DP_AUX_CMD_SHIFT) |
+ ((request->num_bytes - 1) & DP_AUX_CMD_NBYTES_TRANSFER_MASK)),
+ dp_sub->base_addr + DP_AUX_CMD);
+
+ /* Check for a reply from the RX device to the submitted request. */
+ status = aux_wait_reply(dev);
+ if (status)
+ /* Waiting for a reply timed out. */
+ return -ETIMEDOUT;
+
+ /* Analyze the reply. */
+ status = readl(dp_sub->base_addr + DP_AUX_REPLY_CODE);
+ if (status == DP_AUX_REPLY_CODE_DEFER ||
+ status == DP_AUX_REPLY_CODE_I2C_DEFER) {
+ /* The request was deferred. */
+ return -EAGAIN;
+ } else if (status == DP_AUX_REPLY_CODE_NACK ||
+ status == DP_AUX_REPLY_CODE_I2C_NACK) {
+ /* The request was not acknowledged. */
+ return -EIO;
+ }
+
+ /* The request was acknowledged. */
+ if (request->cmd_code == DP_AUX_CMD_READ ||
+ request->cmd_code == DP_AUX_CMD_I2C_READ ||
+ request->cmd_code == DP_AUX_CMD_I2C_READ_MOT) {
+ /* Wait until all data has been received. */
+ timeout_count = 0;
+ do {
+ status = readl(dp_sub->base_addr +
+ DP_REPLY_DATA_COUNT);
+ udelay(100);
+ timeout_count++;
+ if (timeout_count >= DP_AUX_MAX_TIMEOUT_COUNT)
+ return -ETIMEDOUT;
+ } while (status != request->num_bytes);
+
+ /* Obtain the read data from the reply FIFO. */
+ for (index = 0; index < request->num_bytes; index++) {
+ request->data[index] = readl(dp_sub->base_addr +
+ DP_AUX_REPLY_DATA);
+ }
+ }
+ return 0;
+}
+
+/**
+ * aux_request() - Submit request on the AUX channel
+ * @dev: The DP device
+ * @request: The request to submit
+ *
+ * Submit the supplied AUX request to the RX device over the AUX
+ * channel. If waiting for a reply times out, or if the DisplayPort TX core
+ * indicates that the request was deferred, the request is sent again (up to a
+ * maximum specified by DP_AUX_MAX_DEFER_COUNT|DP_AUX_MAX_TIMEOUT_COUNT).
+ *
+ * Return: 0 if request was submitted successfully, -ve on error
+ */
+static int aux_request(struct udevice *dev, struct aux_transaction *request)
+{
+ u32 status, defer_count = 0, timeout_count = 0;
+
+ do {
+ status = aux_wait_ready(dev);
+ if (status) {
+ /* The RX device isn't ready yet. */
+ timeout_count++;
+ continue;
+ }
+ /* Send the request. */
+ status = aux_request_send(dev, request);
+ if (status == -EAGAIN) {
+ /* The request was deferred. */
+ defer_count++;
+ } else if (status == -ETIMEDOUT) {
+ /* Waiting for a reply timed out. */
+ timeout_count++;
+ } else {
+ return status;
+ }
+
+ udelay(100);
+ } while ((defer_count < DP_AUX_MAX_DEFER_COUNT) &&
+ (timeout_count < DP_AUX_MAX_TIMEOUT_COUNT));
+
+ /* The request was not successfully received by the RX device. */
+ return -ETIMEDOUT;
+}
+
+/**
+ * aux_common() - Common (read/write) AUX communication transmission
+ * @dev: The DP device
+ * @cmd_type: Command code of the transaction
+ * @address: The DPCD address of the transaction
+ * @num_bytes: Number of bytes in the payload data
+ * @data: The payload data of the AUX command
+ *
+ * Common sequence of submitting an AUX command for AUX read, AUX write,
+ * I2C-over-AUX read, and I2C-over-AUX write transactions. If required, the
+ * reads and writes are split into multiple requests, each acting on a maximum
+ * of 16 bytes.
+ *
+ * Return: 0 if OK, -ve on error
+ */
+static int aux_common(struct udevice *dev, u32 cmd_type, u32 address,
+ u32 num_bytes, u8 *data)
+{
+ u32 status, bytes_left;
+ struct aux_transaction request;
+
+ if (!is_dp_connected(dev))
+ return -ENODEV;
+
+ /*
+ * Set the start address for AUX transactions. For I2C transactions,
+ * this is the address of the I2C bus.
+ */
+ request.address = address;
+ bytes_left = num_bytes;
+ while (bytes_left > 0) {
+ request.cmd_code = cmd_type;
+
+ if (cmd_type == DP_AUX_CMD_READ ||
+ cmd_type == DP_AUX_CMD_WRITE) {
+ /* Increment address for normal AUX transactions. */
+ request.address = address + (num_bytes - bytes_left);
+ }
+
+ /* Increment the pointer to the supplied data buffer. */
+ request.data = &data[num_bytes - bytes_left];
+
+ if (bytes_left > 16)
+ request.num_bytes = 16;
+ else
+ request.num_bytes = bytes_left;
+
+ bytes_left -= request.num_bytes;
+
+ if (cmd_type == DP_AUX_CMD_I2C_READ && bytes_left > 0) {
+ /*
+ * Middle of a transaction I2C read request. Override
+ * the command code that was set to CmdType.
+ */
+ request.cmd_code = DP_AUX_CMD_I2C_READ_MOT;
+ } else if (cmd_type == DP_AUX_CMD_I2C_WRITE && bytes_left > 0) {
+ /*
+ * Middle of a transaction I2C write request. Override
+ * the command code that was set to CmdType.
+ */
+ request.cmd_code = DP_AUX_CMD_I2C_WRITE_MOT;
+ }
+
+ status = aux_request(dev, &request);
+ if (status)
+ return status;
+ }
+ return 0;
+}
+
+/**
+ * aux_write() - Issue AUX write request
+ * @dev: The DP device
+ * @dpcd_address: The DPCD address to write to
+ * @bytes_to_write: Number of bytes to write
+ * @write_data: Buffer containig data to be written
+ *
+ * Issue a write request over the AUX channel that will write to
+ * the RX device's DisplayPort Configuration data (DPCD) address space. The
+ * write message will be divided into multiple transactions which write a
+ * maximum of 16 bytes each.
+ *
+ * Return: 0 if write operation was successful, -ve on error
+ */
+static int aux_write(struct udevice *dev, u32 dpcd_address, u32 bytes_to_write,
+ void *write_data)
+{
+ return aux_common(dev, DP_AUX_CMD_WRITE, dpcd_address,
+ bytes_to_write, (u8 *)write_data);
+}
+
+/**
+ * aux_read() - Issue AUX read request
+ * @dev: The DP device
+ * @dpcd_address: The DPCD address to read from
+ * @bytes_to_read: Number of bytes to read
+ * @read_data: Buffer to receive the read data
+ *
+ * Issue a read request over the AUX channel that will read from the RX
+ * device's DisplayPort Configuration data (DPCD) address space. The read
+ * message will be divided into multiple transactions which read a maximum of
+ * 16 bytes each.
+ *
+ * Return: 0 if read operation was successful, -ve on error
+ */
+static int aux_read(struct udevice *dev, u32 dpcd_address, u32 bytes_to_read, void *read_data)
+{
+ return aux_common(dev, DP_AUX_CMD_READ, dpcd_address,
+ bytes_to_read, (u8 *)read_data);
+}
+
+static int dp_tx_wakeup(struct udevice *dev)
+{
+ u32 status;
+ u8 aux_data;
+
+ aux_data = 0x1;
+ status = aux_write(dev, DP_DPCD_SET_POWER_DP_PWR_VOLTAGE, 1, &aux_data);
+ if (status)
+ debug("! 1st power wake-up - AUX write failed.\n");
+ status = aux_write(dev, DP_DPCD_SET_POWER_DP_PWR_VOLTAGE, 1, &aux_data);
+ if (status)
+ debug("! 2nd power wake-up - AUX write failed.\n");
+
+ return status;
+}
+
+/**
+ * enable_main_link() - Switch on main link for a device
+ * @dev: The DP device
+ */
+static void enable_main_link(struct udevice *dev, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ /* Reset the scrambler. */
+ writel(1, dp_sub->base_addr + DP_FORCE_SCRAMBLER_RESET);
+ /* Enable the main stream. */
+ writel(enable, dp_sub->base_addr + DP_ENABLE_MAIN_STREAM);
+}
+
+/**
+ * get_rx_capabilities() - Check if capabilities of RX device are valid for TX
+ * device
+ * @dev: The DP device
+ *
+ * Return: 0 if the capabilities of the RX device are valid for the TX device,
+ * -ve if not, of an error occurred during capability determination
+ */
+static int get_rx_capabilities(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 rx_max_link_rate, rx_max_lane_count, *dpcd = NULL;
+ u32 status;
+ struct link_config *link_config = NULL;
+
+ dpcd = dp_sub->dpcd_rx_caps;
+ link_config = &dp_sub->link_config;
+
+ status = aux_read(dev, DP_DPCD_RECEIVER_CAP_FIELD_START, 16, dpcd);
+ if (status)
+ return status;
+
+ rx_max_link_rate = dpcd[DP_DPCD_MAX_LINK_RATE];
+ rx_max_lane_count = dpcd[DP_DPCD_MAX_LANE_COUNT] & DP_DPCD_MAX_LANE_COUNT_MASK;
+ link_config->max_link_rate = (rx_max_link_rate > DP_0_LINK_RATE) ?
+ DP_0_LINK_RATE : rx_max_link_rate;
+ link_config->max_lane_count = (rx_max_lane_count > DP_0_LANE_COUNT) ?
+ DP_0_LANE_COUNT : rx_max_lane_count;
+ link_config->support_enhanced_framing_mode = dpcd[DP_DPCD_MAX_LANE_COUNT] &
+ DP_DPCD_ENHANCED_FRAME_SUPPORT_MASK;
+ link_config->support_downspread_control = dpcd[DP_DPCD_MAX_DOWNSPREAD] &
+ DP_DPCD_MAX_DOWNSPREAD_MASK;
+
+ return 0;
+}
+
+/**
+ * set_enhanced_frame_mode() - Enable/Disable enhanced frame mode
+ * @dev: The DP device
+ * @enable: Flag to determine whether to enable (1) or disable (0) the enhanced
+ * frame mode
+ *
+ * Enable or disable the enhanced framing symbol sequence for
+ * both the DisplayPort TX core and the RX device.
+ *
+ * Return: 0 if enabling/disabling the enhanced frame mode was successful, -ve
+ * on error
+ */
+static int set_enhanced_frame_mode(struct udevice *dev, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ u8 regval;
+
+ dp_sub->link_config.enhanced_framing_mode = enable;
+ /* Write enhanced frame mode enable to the DisplayPort TX core. */
+ writel(dp_sub->link_config.enhanced_framing_mode,
+ dp_sub->base_addr + DP_ENHANCED_FRAME_EN);
+
+ /* Preserve the current RX device settings. */
+ status = aux_read(dev, DP_DPCD_LANE_COUNT_SET, 0x1, &regval);
+ if (status)
+ return status;
+
+ if (dp_sub->link_config.enhanced_framing_mode)
+ regval |= DP_DPCD_ENHANCED_FRAME_EN_MASK;
+ else
+ regval &= ~DP_DPCD_ENHANCED_FRAME_EN_MASK;
+
+ /* Write enhanced frame mode enable to the RX device. */
+ return aux_write(dev, DP_DPCD_LANE_COUNT_SET, 0x1, &regval);
+}
+
+/**
+ * set_lane_count() - Set the lane count
+ * @dev: The DP device
+ * @lane_count: Lane count to set
+ *
+ * Set the number of lanes to be used by the main link for both
+ * the DisplayPort TX core and the RX device.
+ *
+ * Return: 0 if setting the lane count was successful, -ve on error
+ */
+static int set_lane_count(struct udevice *dev, u8 lane_count)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ u8 regval;
+
+ dp_sub->link_config.lane_count = lane_count;
+ /* Write the new lane count to the DisplayPort TX core. */
+ writel(dp_sub->link_config.lane_count,
+ dp_sub->base_addr + DP_LANE_COUNT_SET);
+
+ /* Preserve the current RX device settings. */
+ status = aux_read(dev, DP_DPCD_LANE_COUNT_SET, 0x1, &regval);
+ if (status)
+ return status;
+
+ regval &= ~DP_DPCD_LANE_COUNT_SET_MASK;
+ regval |= dp_sub->link_config.lane_count;
+
+ /* Write the new lane count to the RX device. */
+ return aux_write(dev, DP_DPCD_LANE_COUNT_SET, 0x1, &regval);
+}
+
+/**
+ * set_clk_speed() - Set DP phy clock speed
+ * @dev: The DP device
+ * @speed: The clock frquency to set (one of PHY_CLOCK_SELECT_*)
+ *
+ * Set the clock frequency for the DisplayPort PHY corresponding to a desired
+ * data rate.
+ *
+ * Return: 0 if setting the DP phy clock speed was successful, -ve on error
+ */
+static int set_clk_speed(struct udevice *dev, u32 speed)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 regval;
+
+ /* Disable the DisplayPort TX core first. */
+ regval = readl(dp_sub->base_addr + DP_ENABLE);
+ writel(0, dp_sub->base_addr + DP_ENABLE);
+
+ /* Change speed of the feedback clock. */
+ writel(speed, dp_sub->base_addr + DP_PHY_CLOCK_SELECT);
+
+ /* Re-enable the DisplayPort TX core if it was previously enabled. */
+ if (regval)
+ writel(regval, dp_sub->base_addr + DP_ENABLE);
+
+ /* Wait until the PHY is ready. */
+ return wait_phy_ready(dev);
+}
+
+/**
+ * set_link_rate() - Set the link rate
+ * @dev: The DP device
+ * @link_rate: The link rate to set (one of LINK_BW_SET_*)
+ *
+ * Set the data rate to be used by the main link for both the DisplayPort TX
+ * core and the RX device.
+ *
+ * Return: 0 if setting the link rate was successful, -ve on error
+ */
+static int set_link_rate(struct udevice *dev, u8 link_rate)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+
+ /* Write a corresponding clock frequency to the DisplayPort TX core. */
+ switch (link_rate) {
+ case DP_LINK_BW_SET_162GBPS:
+ status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_162GBPS);
+ break;
+ case DP_LINK_BW_SET_270GBPS:
+ status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_270GBPS);
+ break;
+ case DP_LINK_BW_SET_540GBPS:
+ status = set_clk_speed(dev, DP_PHY_CLOCK_SELECT_540GBPS);
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ }
+ if (status)
+ return status;
+
+ dp_sub->link_config.link_rate = link_rate;
+ /* Write new link rate to the DisplayPort TX core. */
+ writel(dp_sub->link_config.link_rate,
+ dp_sub->base_addr +
+ DP_LINK_BW_SET);
+
+ /* Write new link rate to the RX device. */
+ return aux_write(dev, DP_DPCD_LINK_BW_SET, 0x1,
+ &dp_sub->link_config.link_rate);
+}
+
+static int set_downspread(struct udevice *dev, u8 enable)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ u8 regval;
+
+ dp_sub->link_config.support_downspread_control = enable;
+ /* Write downspread enable to the DisplayPort TX core. */
+ writel(dp_sub->link_config.support_downspread_control,
+ dp_sub->base_addr + DP_DOWNSPREAD_CTRL);
+
+ /* Preserve the current RX device settings. */
+ status = aux_read(dev, DP_DPCD_DOWNSPREAD_CTRL, 0x1, &regval);
+ if (status)
+ return status;
+
+ if (dp_sub->link_config.support_downspread_control)
+ regval |= DP_DPCD_SPREAD_AMP_MASK;
+ else
+ regval &= ~DP_DPCD_SPREAD_AMP_MASK;
+
+ /* Write downspread enable to the RX device. */
+ return aux_write(dev, DP_DPCD_DOWNSPREAD_CTRL, 0x1, &regval);
+}
+
+static void set_serdes_vswing_preemp(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 index;
+ u8 vs_level_rx = dp_sub->link_config.vs_level;
+ u8 pe_level_rx = dp_sub->link_config.pe_level;
+
+ for (index = 0; index < dp_sub->link_config.lane_count; index++) {
+ /* Write new voltage swing levels to the TX registers. */
+ writel(vs[pe_level_rx][vs_level_rx], (ulong)SERDES_BASEADDR +
+ SERDES_L0_TX_MARGININGF + index * SERDES_LANE_OFFSET);
+ /* Write new pre-emphasis levels to the TX registers. */
+ writel(pe[pe_level_rx][vs_level_rx], (ulong)SERDES_BASEADDR +
+ SERDES_L0_TX_DEEMPHASIS + index * SERDES_LANE_OFFSET);
+ }
+}
+
+/**
+ * set_vswing_preemp() - Build AUX data to set voltage swing and pre-emphasis
+ * @dev: The DP device
+ * @aux_data: Buffer to receive the built AUX data
+ *
+ * Build AUX data to set current voltage swing and pre-emphasis level settings;
+ * the necessary data is taken from the link_config structure.
+ */
+static void set_vswing_preemp(struct udevice *dev, u8 *aux_data)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 data = 0;
+ u8 vs_level_rx = dp_sub->link_config.vs_level;
+ u8 pe_level_rx = dp_sub->link_config.pe_level;
+
+ if (vs_level_rx >= DP_MAXIMUM_VS_LEVEL)
+ data |= DP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK;
+
+ /* The maximum pre-emphasis level has been reached. */
+ if (pe_level_rx >= DP_MAXIMUM_PE_LEVEL)
+ data |= DP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK;
+
+ /* Set up the data buffer for writing to the RX device. */
+ data |= (pe_level_rx << DP_DPCD_TRAINING_LANEX_SET_PE_SHIFT) |
+ vs_level_rx;
+ memset(aux_data, data, 4);
+
+ set_serdes_vswing_preemp(dev);
+}
+
+static int set_training_pattern(struct udevice *dev, u32 pattern)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 aux_data[5];
+
+ writel(pattern, dp_sub->base_addr + TRAINING_PATTERN_SET);
+
+ aux_data[0] = pattern;
+ switch (pattern) {
+ case TRAINING_PATTERN_SET_OFF:
+ writel(0, dp_sub->base_addr + SCRAMBLING_DISABLE);
+ dp_sub->link_config.scrambler_en = 1;
+ break;
+ case TRAINING_PATTERN_SET_TP1:
+ case TRAINING_PATTERN_SET_TP2:
+ case TRAINING_PATTERN_SET_TP3:
+ aux_data[0] |= DP_DPCD_TP_SET_SCRAMB_DIS_MASK;
+ writel(1, dp_sub->base_addr + SCRAMBLING_DISABLE);
+ dp_sub->link_config.scrambler_en = 0;
+ break;
+ default:
+ break;
+ }
+ /*
+ * Make the adjustments to both the DisplayPort TX core and the RX
+ * device.
+ */
+ set_vswing_preemp(dev, &aux_data[1]);
+ /*
+ * Write the voltage swing and pre-emphasis levels for each lane to the
+ * RX device.
+ */
+ if (pattern == TRAINING_PATTERN_SET_OFF)
+ return aux_write(dev, DP_DPCD_TP_SET, 1, aux_data);
+ else
+ return aux_write(dev, DP_DPCD_TP_SET, 5, aux_data);
+}
+
+static int get_lane_status_adj_reqs(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ u8 aux_data[8];
+
+ status = aux_read(dev, DP_DPCD_SINK_COUNT, 8, aux_data);
+ if (status)
+ return status;
+
+ /* Save XDPPSU_DPCD_SINK_COUNT contents. */
+ dp_sub->sink_count =
+ ((aux_data[0] & DP_DPCD_SINK_COUNT_HIGH_MASK) >>
+ DP_DPCD_SINK_COUNT_HIGH_LOW_SHIFT) |
+ (aux_data[0] & DP_DPCD_SINK_COUNT_LOW_MASK);
+ memcpy(dp_sub->lane_status_ajd_reqs, &aux_data[2], 6);
+ return 0;
+}
+
+/**
+ * check_clock_recovery() - Check clock recovery success
+ * @dev: The LogiCore DP TX device in question
+ * @lane_count: The number of lanes for which to check clock recovery success
+ *
+ * Check if the RX device's DisplayPort Configuration data (DPCD) indicates
+ * that the clock recovery sequence during link training was successful - the
+ * RX device's link clock and data recovery unit has realized and maintained
+ * the frequency lock for all lanes currently in use.
+ *
+ * Return: 0 if clock recovery was successful on all lanes in question, -ve if
+ * not
+ */
+static int check_clock_recovery(struct udevice *dev, u8 lane_count)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 *lane_status = dp_sub->lane_status_ajd_reqs;
+
+ switch (lane_count) {
+ case DP_LANE_COUNT_SET_2:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_CR_DONE_MASK))
+ return -EINVAL;
+ case DP_LANE_COUNT_SET_1:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_CR_DONE_MASK))
+ return -EINVAL;
+ default:
+ /* All (LaneCount) lanes have achieved clock recovery. */
+ break;
+ }
+ return 0;
+}
+
+/**
+ * adj_vswing_preemp() - Adjust voltage swing and pre-emphasis
+ * @dev: The DP device
+ *
+ * Set new voltage swing and pre-emphasis levels using the
+ * adjustment requests obtained from the RX device.
+ *
+ * Return: 0 if voltage swing and pre-emphasis could be adjusted successfully,
+ * -ve on error
+ */
+static int adj_vswing_preemp(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 index, vs_level_adj_req[4], pe_level_adj_req[4];
+ u8 aux_data[4];
+ u8 *adj_reqs = &dp_sub->lane_status_ajd_reqs[4];
+
+ /*
+ * Analyze the adjustment requests for changes in voltage swing and
+ * pre-emphasis levels.
+ */
+ vs_level_adj_req[0] = adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK;
+ vs_level_adj_req[1] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >>
+ DP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT;
+ pe_level_adj_req[0] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >>
+ DP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT;
+ pe_level_adj_req[1] = (adj_reqs[0] & DP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >>
+ DP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT;
+
+ /*
+ * Change the drive settings to match the adjustment requests. Use the
+ * greatest level requested.
+ */
+ dp_sub->link_config.vs_level = 0;
+ dp_sub->link_config.pe_level = 0;
+ for (index = 0; index < dp_sub->link_config.lane_count; index++) {
+ if (vs_level_adj_req[index] > dp_sub->link_config.vs_level)
+ dp_sub->link_config.vs_level = vs_level_adj_req[index];
+
+ if (pe_level_adj_req[index] > dp_sub->link_config.pe_level)
+ dp_sub->link_config.pe_level = pe_level_adj_req[index];
+ }
+
+ if (dp_sub->link_config.pe_level > DP_MAXIMUM_PE_LEVEL)
+ dp_sub->link_config.pe_level = DP_MAXIMUM_PE_LEVEL;
+
+ if (dp_sub->link_config.vs_level > DP_MAXIMUM_VS_LEVEL)
+ dp_sub->link_config.vs_level = DP_MAXIMUM_VS_LEVEL;
+
+ if (dp_sub->link_config.pe_level >
+ (4 - dp_sub->link_config.vs_level)) {
+ dp_sub->link_config.pe_level =
+ 4 - dp_sub->link_config.vs_level;
+ }
+ /*
+ * Make the adjustments to both the DisplayPort TX core and the RX
+ * device.
+ */
+ set_vswing_preemp(dev, aux_data);
+ /*
+ * Write the voltage swing and pre-emphasis levels for each lane to the
+ * RX device.
+ */
+ return aux_write(dev, DP_DPCD_TRAINING_LANE0_SET, 2, aux_data);
+}
+
+/**
+ * get_training_delay() - Get training delay
+ * @dev: The DP device
+ * @training_state: The training state for which the required training delay
+ * should be queried
+ *
+ * Determine what the RX device's required training delay is for
+ * link training.
+ *
+ * Return: The training delay in us
+ */
+static u32 get_training_delay(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 *dpcd = dp_sub->dpcd_rx_caps;
+
+ if (dpcd[DP_DPCD_TRAIN_AUX_RD_INTERVAL])
+ return 400 * dpcd[DP_DPCD_TRAIN_AUX_RD_INTERVAL] * 10;
+
+ return 400;
+}
+
+/**
+ * training_state_clock_recovery() - Run clock recovery part of link training
+ * @dev: The DP device
+ *
+ * Run the clock recovery sequence as part of link training. The
+ * sequence is as follows:
+ *
+ * 0) Start signaling at the minimum voltage swing, pre-emphasis, and
+ * post- cursor levels.
+ * 1) Transmit training pattern 1 over the main link with symbol
+ * scrambling disabled.
+ * 2) The clock recovery loop. If clock recovery is unsuccessful after
+ * MaxIterations loop iterations, return.
+ * 2a) Wait for at least the period of time specified in the RX device's
+ * DisplayPort Configuration data (DPCD) register,
+ * TRAINING_AUX_RD_INTERVAL.
+ * 2b) Check if all lanes have achieved clock recovery lock. If so,
+ * return.
+ * 2c) Check if the same voltage swing level has been used 5 consecutive
+ * times or if the maximum level has been reached. If so, return.
+ * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as
+ * requested by the RX device.
+ * 2e) Loop back to 2a.
+ *
+ * For a more detailed description of the clock recovery sequence, see section
+ * 3.5.1.2.1 of the DisplayPort 1.2a specification document.
+ *
+ * Return: The next state machine state to advance to
+ */
+static enum link_training_states training_state_clock_recovery(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status, delay_us;
+ u8 prev_vs_level = 0, same_vs_level_count = 0;
+ struct link_config *link_config = &dp_sub->link_config;
+
+ delay_us = get_training_delay(dev);
+ /* Start CRLock. */
+ /* Start from minimal voltage swing and pre-emphasis levels. */
+ dp_sub->link_config.vs_level = 0;
+ dp_sub->link_config.pe_level = 0;
+ /* Transmit training pattern 1. */
+ status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP1);
+ if (status)
+ return TS_FAILURE;
+
+ while (1) {
+ /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */
+ udelay(delay_us);
+ /* Get lane and adjustment requests. */
+ status = get_lane_status_adj_reqs(dev);
+ if (status)
+ /* The AUX read failed. */
+ return TS_FAILURE;
+
+ /*
+ * Check if all lanes have realized and maintained the frequency
+ * lock and get adjustment requests.
+ */
+ status = check_clock_recovery(dev, dp_sub->link_config.lane_count);
+ if (status == 0)
+ return TS_CHANNEL_EQUALIZATION;
+ /*
+ * Check if the same voltage swing for each lane has been used 5
+ * consecutive times.
+ */
+ if (prev_vs_level == link_config->vs_level) {
+ same_vs_level_count++;
+ } else {
+ same_vs_level_count = 0;
+ prev_vs_level = link_config->vs_level;
+ }
+ if (same_vs_level_count >= 5)
+ break;
+
+ /* Only try maximum voltage swing once. */
+ if (link_config->vs_level == DP_MAXIMUM_VS_LEVEL)
+ break;
+
+ /* Adjust the drive settings as requested by the RX device. */
+ status = adj_vswing_preemp(dev);
+ if (status)
+ /* The AUX write failed. */
+ return TS_FAILURE;
+ }
+ return TS_ADJUST_LINK_RATE;
+}
+
+/**
+ * check_channel_equalization() - Check channel equalization success
+ * @dev: The DP device
+ * @lane_count: The number of lanes for which to check channel equalization
+ * success
+ *
+ * Check if the RX device's DisplayPort Configuration data (DPCD) indicates
+ * that the channel equalization sequence during link training was successful -
+ * the RX device has achieved channel equalization, symbol lock, and interlane
+ * alignment for all lanes currently in use.
+ *
+ * Return: 0 if channel equalization was successful on all lanes in question,
+ * -ve if not
+ */
+static int check_channel_equalization(struct udevice *dev, u8 lane_count)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 *lane_status = dp_sub->lane_status_ajd_reqs;
+
+ /* Check that all LANEx_CHANNEL_EQ_DONE bits are set. */
+ switch (lane_count) {
+ case DP_LANE_COUNT_SET_2:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_CE_DONE_MASK))
+ return -EINVAL;
+ case DP_LANE_COUNT_SET_1:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_CE_DONE_MASK))
+ return -EINVAL;
+ default:
+ /* All (LaneCount) lanes have achieved channel equalization. */
+ break;
+ }
+
+ /* Check that all LANEx_SYMBOL_LOCKED bits are set. */
+ switch (lane_count) {
+ case DP_LANE_COUNT_SET_2:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_1_SL_DONE_MASK))
+ return -EINVAL;
+ case DP_LANE_COUNT_SET_1:
+ if (!(lane_status[0] & DP_DPCD_STATUS_LANE_0_SL_DONE_MASK))
+ return -EINVAL;
+ default:
+ /* All (LaneCount) lanes have achieved symbol lock. */
+ break;
+ }
+
+ /* Check that interlane alignment is done. */
+ if (!(lane_status[2] & DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK))
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * training_state_channel_equalization() - Run channel equalization part of
+ * link training
+ * @dev: The DP device
+ *
+ * Run the channel equalization sequence as part of link
+ * training. The sequence is as follows:
+ *
+ * 0) Start signaling with the same drive settings used at the end of the
+ * clock recovery sequence.
+ * 1) Transmit training pattern 2 (or 3) over the main link with symbol
+ * scrambling disabled.
+ * 2) The channel equalization loop. If channel equalization is
+ * unsuccessful after 5 loop iterations, return.
+ * 2a) Wait for at least the period of time specified in the RX device's
+ * DisplayPort Configuration data (DPCD) register,
+ * TRAINING_AUX_RD_INTERVAL.
+ * 2b) Check if all lanes have achieved channel equalization, symbol lock,
+ * and interlane alignment. If so, return.
+ * 2c) Check if the same voltage swing level has been used 5 consecutive
+ * times or if the maximum level has been reached. If so, return.
+ * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as
+ * requested by the RX device.
+ * 2e) Loop back to 2a.
+ *
+ * For a more detailed description of the channel equalization sequence, see
+ * section 3.5.1.2.2 of the DisplayPort 1.2a specification document.
+ *
+ * Return: The next state machine state to advance to
+ */
+static enum link_training_states training_state_channel_equalization(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status, delay_us = 400, iteration_count = 0;
+
+ /* Write the current drive settings. */
+ /* Transmit training pattern 2/3. */
+ if (dp_sub->dpcd_rx_caps[DP_DPCD_MAX_LANE_COUNT] &
+ DP_DPCD_TPS3_SUPPORT_MASK)
+ status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP3);
+ else
+ status = set_training_pattern(dev, TRAINING_PATTERN_SET_TP2);
+
+ if (status)
+ return TS_FAILURE;
+
+ while (iteration_count < 5) {
+ /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */
+ udelay(delay_us);
+
+ /* Get lane and adjustment requests. */
+ status = get_lane_status_adj_reqs(dev);
+ if (status)
+ /* The AUX read failed. */
+ return TS_FAILURE;
+
+ /* Adjust the drive settings as requested by the RX device. */
+ status = adj_vswing_preemp(dev);
+ if (status)
+ /* The AUX write failed. */
+ return TS_FAILURE;
+
+ /* Check that all lanes still have their clocks locked. */
+ status = check_clock_recovery(dev, dp_sub->link_config.lane_count);
+ if (status)
+ break;
+ /*
+ * Check that all lanes have accomplished channel
+ * equalization, symbol lock, and interlane alignment.
+ */
+ status = check_channel_equalization(dev, dp_sub->link_config.lane_count);
+ if (status == 0)
+ return TS_SUCCESS;
+ iteration_count++;
+ }
+
+ /*
+ * Tried 5 times with no success. Try a reduced bitrate first, then
+ * reduce the number of lanes.
+ */
+ return TS_ADJUST_LINK_RATE;
+}
+
+static int check_lane_align(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u8 *lane_status = dp_sub->lane_status_ajd_reqs;
+
+ if (!(lane_status[2] & DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK))
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * check_link_status() - Check status of link
+ * @dev: The DP device
+ * @lane_count: The lane count to use for the check
+ *
+ * Check if the receiver's DisplayPort Configuration data (DPCD) indicates the
+ * receiver has achieved and maintained clock recovery, channel equalization,
+ * symbol lock, and interlane alignment for all lanes currently in use.
+ *
+ * Return: 0 if the link status is OK, -ve if a error occurred during checking
+ */
+static int check_link_status(struct udevice *dev, u8 lane_count)
+{
+ u32 status;
+
+ status = get_lane_status_adj_reqs(dev);
+ if (status)
+ /* The AUX read failed. */
+ return status;
+
+ /* Check if the link needs training. */
+ if ((check_clock_recovery(dev, lane_count) == 0) &&
+ (check_channel_equalization(dev, lane_count) == 0) &&
+ (check_lane_align(dev) == 0)) {
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/**
+ * run_training() - Run link training
+ * @dev: The DP device
+ *
+ * Run the link training process. It is implemented as a state machine, with
+ * each state returning the next state. First, the clock recovery sequence will
+ * be run; if successful, the channel equalization sequence will run. If either
+ * the clock recovery or channel equalization sequence failed, the link rate or
+ * the number of lanes used will be reduced and training will be re-attempted.
+ * If training fails at the minimal data rate, 1.62 Gbps with a single lane,
+ * training will no longer re-attempt and fail.
+ *
+ * There are undocumented timeout constraints in the link training process. In
+ * DP v1.2a spec, Chapter 3.5.1.2.2 a 10ms limit for the complete training
+ * process is mentioned. Which individual timeouts are derived and implemented
+ * by sink manufacturers is unknown. So each step should be as short as
+ * possible and link training should start as soon as possible after HPD.
+ *
+ * Return: 0 if the training sequence ran successfully, -ve if a error occurred
+ * or the training failed
+ */
+static int run_training(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status;
+ enum link_training_states training_state = TS_CLOCK_RECOVERY;
+
+ while (1) {
+ switch (training_state) {
+ case TS_CLOCK_RECOVERY:
+ training_state = training_state_clock_recovery(dev);
+ break;
+ case TS_CHANNEL_EQUALIZATION:
+ training_state = training_state_channel_equalization(dev);
+ break;
+ default:
+ break;
+ }
+
+ if (training_state == TS_SUCCESS)
+ break;
+ else if (training_state == TS_FAILURE)
+ return -EINVAL;
+
+ if (training_state == TS_ADJUST_LANE_COUNT ||
+ training_state == TS_ADJUST_LINK_RATE) {
+ status = set_training_pattern(dev, TRAINING_PATTERN_SET_OFF);
+ if (status)
+ return -EINVAL;
+ }
+ }
+
+ /* Final status check. */
+ return check_link_status(dev, dp_sub->link_config.lane_count);
+}
+
+void reset_dp_phy(struct udevice *dev, u32 reset)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 phyval, regval;
+
+ writel(0, dp_sub->base_addr + DP_ENABLE);
+ phyval = readl(dp_sub->base_addr + DP_PHY_CONFIG);
+ regval = phyval | reset;
+ writel(regval, dp_sub->base_addr + DP_PHY_CONFIG);
+ /* Remove the reset. */
+ writel(phyval, dp_sub->base_addr + DP_PHY_CONFIG);
+ /* Wait for the PHY to be ready. */
+ wait_phy_ready(dev);
+
+ writel(1, dp_sub->base_addr + DP_ENABLE);
+}
+
+/**
+ * establish_link() - Establish a link
+ * @dev: The DP device
+ *
+ * Check if the link needs training and run the training sequence if training
+ * is required.
+ *
+ * Return: 0 if the link was established successfully, -ve on error
+ */
+static int establish_link(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 status, re_enable_main_link;
+
+ reset_dp_phy(dev, DP_PHY_CONFIG_TX_PHY_8B10BEN_MASK |
+ DP_PHY_CONFIG_PHY_RESET_MASK);
+
+ re_enable_main_link = readl(dp_sub->base_addr + DP_ENABLE_MAIN_STREAM);
+ if (re_enable_main_link)
+ enable_main_link(dev, 0);
+
+ status = run_training(dev);
+ if (status)
+ return status;
+
+ status = set_training_pattern(dev, TRAINING_PATTERN_SET_OFF);
+ if (status)
+ return status;
+
+ if (re_enable_main_link)
+ enable_main_link(dev, 1);
+
+ return check_link_status(dev, dp_sub->link_config.lane_count);
+}
+
+static int dp_hpd_train(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct link_config *link_config = &dp_sub->link_config;
+ u32 status;
+
+ status = get_rx_capabilities(dev);
+ if (status) {
+ debug("! Error getting RX caps.\n");
+ return status;
+ }
+
+ status = set_enhanced_frame_mode(dev, link_config->support_enhanced_framing_mode ? 1 : 0);
+ if (status) {
+ debug("! EFM set failed.\n");
+ return status;
+ }
+
+ status = set_lane_count(dev, (dp_sub->use_max_lane_count) ?
+ link_config->max_lane_count : dp_sub->lane_count);
+ if (status) {
+ debug("! Lane count set failed.\n");
+ return status;
+ }
+
+ status = set_link_rate(dev, (dp_sub->use_max_link_rate) ?
+ link_config->max_link_rate : dp_sub->link_rate);
+ if (status) {
+ debug("! Link rate set failed.\n");
+ return status;
+ }
+
+ status = set_downspread(dev, link_config->support_downspread_control);
+ if (status) {
+ debug("! Setting downspread failed.\n");
+ return status;
+ }
+
+ debug("Lane count =%d\n", dp_sub->link_config.lane_count);
+ debug("Link rate =%d\n", dp_sub->link_config.link_rate);
+
+ debug("Starting Training...\n");
+ status = establish_link(dev);
+ if (status == 0)
+ debug("! Training succeeded.\n");
+ else
+ debug("! Training failed.\n");
+
+ return status;
+}
+
+static void display_gfx_frame_buffer(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ if (!dp_sub->dp_dma->gfx.channel.cur)
+ dp_sub->dp_dma->gfx.trigger_status = DPDMA_TRIGGER_EN;
+}
+
+static void set_color_encode(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct main_stream_attributes *msa_config = &dp_sub->msa_config;
+
+ msa_config->y_cb_cr_colorimetry = 0;
+ msa_config->dynamic_range = 0;
+ msa_config->component_format = 0;
+ msa_config->misc0 = 0;
+ msa_config->misc1 = 0;
+ msa_config->component_format = DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_RGB;
+}
+
+static void config_msa_recalculate(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ u32 video_bw, link_bw, words_per_line;
+ u8 bits_per_pixel;
+ struct main_stream_attributes *msa_config;
+ struct link_config *link_config;
+
+ msa_config = &dp_sub->msa_config;
+ link_config = &dp_sub->link_config;
+
+ msa_config->user_pixel_width = 1;
+
+ /* Compute the rest of the MSA values. */
+ msa_config->n_vid = 27 * 1000 * link_config->link_rate;
+ msa_config->h_start = msa_config->vid_timing_mode.video_timing.h_sync_width +
+ msa_config->vid_timing_mode.video_timing.h_back_porch;
+ msa_config->v_start = msa_config->vid_timing_mode.video_timing.f0_pv_sync_width +
+ msa_config->vid_timing_mode.video_timing.f0_pv_back_porch;
+
+ /* Miscellaneous attributes. */
+ if (msa_config->bits_per_color == 6)
+ msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_6BPC;
+ else if (msa_config->bits_per_color == 8)
+ msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_8BPC;
+ else if (msa_config->bits_per_color == 10)
+ msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_10BPC;
+ else if (msa_config->bits_per_color == 12)
+ msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_12BPC;
+ else if (msa_config->bits_per_color == 16)
+ msa_config->misc0 = DP_MAIN_STREAM_MISC0_BDC_16BPC;
+
+ msa_config->misc0 <<= DP_MAIN_STREAM_MISC0_BDC_SHIFT;
+
+ /* Need to set this. */
+ msa_config->misc0 |= msa_config->component_format <<
+ DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT;
+
+ msa_config->misc0 |= msa_config->dynamic_range <<
+ DP_MAIN_STREAM_MISC0_DYNAMIC_RANGE_SHIFT;
+
+ msa_config->misc0 |= msa_config->y_cb_cr_colorimetry <<
+ DP_MAIN_STREAM_MISC0_YCBCR_COLORIMETRY_SHIFT;
+
+ msa_config->misc0 |= msa_config->synchronous_clock_mode;
+ /*
+ * Determine the number of bits per pixel for the specified color
+ * component format.
+ */
+ if (msa_config->misc1 == DP_MAIN_STREAM_MISC1_Y_ONLY_EN_MASK)
+ bits_per_pixel = msa_config->bits_per_color;
+ else if (msa_config->component_format ==
+ DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_YCBCR422)
+ /* YCbCr422 color component format. */
+ bits_per_pixel = msa_config->bits_per_color * 2;
+ else
+ /* RGB or YCbCr 4:4:4 color component format. */
+ bits_per_pixel = msa_config->bits_per_color * 3;
+
+ /* Calculate the data per lane. */
+ words_per_line = msa_config->vid_timing_mode.video_timing.h_active * bits_per_pixel;
+ if (words_per_line % 16)
+ words_per_line += 16;
+
+ words_per_line /= 16;
+ msa_config->data_per_lane = words_per_line - link_config->lane_count;
+ if (words_per_line % link_config->lane_count)
+ msa_config->data_per_lane += (words_per_line % link_config->lane_count);
+
+ /* Allocate a fixed size for single-stream transport (SST) operation. */
+ msa_config->transfer_unit_size = 64;
+
+ /*
+ * Calculate the average number of bytes per transfer unit.
+ * Note: Both the integer and the fractional part is stored in
+ * AvgBytesPerTU.
+ */
+ video_bw = ((msa_config->pixel_clock_hz / 1000) * bits_per_pixel) / 8;
+ link_bw = (link_config->lane_count * link_config->link_rate * 27);
+ msa_config->avg_bytes_per_tu = ((10 *
+ (video_bw * msa_config->transfer_unit_size)
+ / link_bw) + 5) / 10;
+ /*
+ * The number of initial wait cycles at the start of a new line by the
+ * framing logic. This allows enough data to be buffered in the input
+ * FIFO before video is sent.
+ */
+ if ((msa_config->avg_bytes_per_tu / 1000) <= 4)
+ msa_config->init_wait = 64;
+ else
+ msa_config->init_wait = msa_config->transfer_unit_size -
+ (msa_config->avg_bytes_per_tu / 1000);
+}
+
+static void set_msa_bpc(struct udevice *dev, u8 bits_per_color)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ dp_sub->msa_config.bits_per_color = bits_per_color;
+ /* Calculate the rest of the MSA values. */
+ config_msa_recalculate(dev);
+}
+
+const struct video_timing_mode *get_video_mode_data(enum video_mode vm_id)
+{
+ if (vm_id < VIDC_VM_NUM_SUPPORTED)
+ return &vidc_video_timing_modes[vm_id];
+
+ return NULL;
+}
+
+static u64 get_pixelclk_by_vmid(enum video_mode vm_id)
+{
+ const struct video_timing_mode *vm;
+ u64 clk_hz;
+
+ vm = get_video_mode_data(vm_id);
+ /* For progressive mode, use only frame 0 vertical total. */
+ clk_hz = vm->video_timing.f0_pv_total;
+ /* Multiply the number of pixels by the frame rate. */
+ clk_hz *= vm->frame_rate;
+
+ /*
+ * Multiply the vertical total by the horizontal total for number of
+ * pixels.
+ */
+ clk_hz *= vm->video_timing.h_total;
+
+ return clk_hz;
+}
+
+/**
+ * config_msa_video_mode() - Enable video output
+ * @dev: The DP device
+ * @msa: The MSA values to set for the device
+ *
+ * Return: 0 if the video was enabled successfully, -ve on error
+ */
+static void config_msa_video_mode(struct udevice *dev, enum video_mode videomode)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct main_stream_attributes *msa_config;
+
+ msa_config = &dp_sub->msa_config;
+
+ /* Configure the MSA values from the display monitor DMT table. */
+ msa_config->vid_timing_mode.vid_mode = vidc_video_timing_modes[videomode].vid_mode;
+ msa_config->vid_timing_mode.frame_rate = vidc_video_timing_modes[videomode].frame_rate;
+ msa_config->vid_timing_mode.video_timing.h_active =
+ vidc_video_timing_modes[videomode].video_timing.h_active;
+ msa_config->vid_timing_mode.video_timing.h_front_porch =
+ vidc_video_timing_modes[videomode].video_timing.h_front_porch;
+ msa_config->vid_timing_mode.video_timing.h_sync_width =
+ vidc_video_timing_modes[videomode].video_timing.h_sync_width;
+ msa_config->vid_timing_mode.video_timing.h_back_porch =
+ vidc_video_timing_modes[videomode].video_timing.h_back_porch;
+ msa_config->vid_timing_mode.video_timing.h_total =
+ vidc_video_timing_modes[videomode].video_timing.h_total;
+ msa_config->vid_timing_mode.video_timing.h_sync_polarity =
+ vidc_video_timing_modes[videomode].video_timing.h_sync_polarity;
+ msa_config->vid_timing_mode.video_timing.v_active =
+ vidc_video_timing_modes[videomode].video_timing.v_active;
+ msa_config->vid_timing_mode.video_timing.f0_pv_front_porch =
+ vidc_video_timing_modes[videomode].video_timing.f0_pv_front_porch;
+ msa_config->vid_timing_mode.video_timing.f0_pv_sync_width =
+ vidc_video_timing_modes[videomode].video_timing.f0_pv_sync_width;
+ msa_config->vid_timing_mode.video_timing.f0_pv_back_porch =
+ vidc_video_timing_modes[videomode].video_timing.f0_pv_back_porch;
+ msa_config->vid_timing_mode.video_timing.f0_pv_total =
+ vidc_video_timing_modes[videomode].video_timing.f0_pv_total;
+ msa_config->vid_timing_mode.video_timing.f1_v_front_porch =
+ vidc_video_timing_modes[videomode].video_timing.f1_v_front_porch;
+ msa_config->vid_timing_mode.video_timing.f1_v_sync_width =
+ vidc_video_timing_modes[videomode].video_timing.f1_v_sync_width;
+ msa_config->vid_timing_mode.video_timing.f1_v_back_porch =
+ vidc_video_timing_modes[videomode].video_timing.f1_v_back_porch;
+ msa_config->vid_timing_mode.video_timing.f1_v_total =
+ vidc_video_timing_modes[videomode].video_timing.f1_v_total;
+ msa_config->vid_timing_mode.video_timing.v_sync_polarity =
+ vidc_video_timing_modes[videomode].video_timing.v_sync_polarity;
+ msa_config->pixel_clock_hz = get_pixelclk_by_vmid(msa_config->vid_timing_mode.vid_mode);
+
+ /* Calculate the rest of the MSA values. */
+ config_msa_recalculate(dev);
+}
+
+static void set_pixel_clock(u64 freq_hz)
+{
+ u64 ext_divider, vco, vco_int_frac;
+ u32 pll_assigned, frac_int_fb_div, fraction, regpll = 0;
+ u8 pll;
+
+ pll_assigned = readl(CLK_FPD_BASEADDR + VIDEO_REF_CTRL) & VIDEO_REF_CTRL_SRCSEL_MASK;
+ if (pll_assigned)
+ pll = VPLL;
+
+ ext_divider = PLL_OUT_FREQ / freq_hz;
+ vco = freq_hz * ext_divider * 2;
+ vco_int_frac = (vco * INPUT_FREQ_PRECISION * SHIFT_DECIMAL) /
+ AVBUF_INPUT_REF_CLK;
+ frac_int_fb_div = vco_int_frac >> PRECISION;
+ fraction = vco_int_frac & AVBUF_DECIMAL;
+
+ regpll |= ENABLE_BIT << PLL_CTRL_BYPASS_SHIFT;
+ regpll |= frac_int_fb_div << PLL_CTRL_FBDIV_SHIFT;
+ regpll |= (1 << PLL_CTRL_DIV2_SHIFT);
+ regpll |= (PSS_REF_CLK << PLL_CTRL_PRE_SRC_SHIFT);
+ writel(regpll, CLK_FPD_BASEADDR + VPLL_CTRL);
+
+ regpll = 0;
+ regpll |= VPLL_CFG_CP << PLL_CFG_CP_SHIFT;
+ regpll |= VPLL_CFG_RES << PLL_CFG_RES_SHIFT;
+ regpll |= VPLL_CFG_LFHF << PLL_CFG_LFHF_SHIFT;
+ regpll |= VPLL_CFG_LOCK_DLY << PLL_CFG_LOCK_DLY_SHIFT;
+ regpll |= VPLL_CFG_LOCK_CNT << PLL_CFG_LOCK_CNT_SHIFT;
+ writel(regpll, CLK_FPD_BASEADDR + VPLL_CFG);
+
+ regpll = (1U << PLL_FRAC_CFG_ENABLED_SHIFT) |
+ (fraction << PLL_FRAC_CFG_DATA_SHIFT);
+ writel(regpll, CLK_FPD_BASEADDR + VPLL_FRAC_CFG);
+
+ clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL,
+ PLL_CTRL_RESET_MASK,
+ (ENABLE_BIT << PLL_CTRL_RESET_SHIFT));
+
+ /* Deassert reset to the PLL. */
+ clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL,
+ PLL_CTRL_RESET_MASK,
+ (DISABLE_BIT << PLL_CTRL_RESET_SHIFT));
+
+ while (!(readl(CLK_FPD_BASEADDR + PLL_STATUS) &
+ (1 << PLL_STATUS_VPLL_LOCK)))
+ ;
+
+ /* Deassert Bypass. */
+ clrsetbits_le32(CLK_FPD_BASEADDR + VPLL_CTRL,
+ PLL_CTRL_BYPASS_MASK,
+ (DISABLE_BIT << PLL_CTRL_BYPASS_SHIFT));
+ udelay(1);
+
+ clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL,
+ VIDEO_REF_CTRL_CLKACT_MASK,
+ (DISABLE_BIT << VIDEO_REF_CTRL_CLKACT_SHIFT));
+
+ clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL,
+ VIDEO_REF_CTRL_DIVISOR1_MASK,
+ (ENABLE_BIT << VIDEO_REF_CTRL_DIVISOR1_SHIFT));
+
+ clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL,
+ VIDEO_REF_CTRL_DIVISOR0_MASK,
+ (ext_divider << VIDEO_REF_CTRL_DIVISOR0_SHIFT));
+
+ clrsetbits_le32(CLK_FPD_BASEADDR + VIDEO_REF_CTRL,
+ VIDEO_REF_CTRL_CLKACT_MASK,
+ (ENABLE_BIT << VIDEO_REF_CTRL_CLKACT_SHIFT));
+}
+
+/**
+ * set_msa_values() - Set MSA values
+ * @dev: The DP device
+ *
+ * Set the main stream attributes registers of the DisplayPort TX
+ * core with the values specified in the main stream attributes configuration
+ * structure.
+ */
+static void set_msa_values(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct main_stream_attributes *msa_config;
+
+ msa_config = &dp_sub->msa_config;
+
+ /*
+ * Set the main stream attributes to the associated DisplayPort TX core
+ * registers.
+ */
+ writel(msa_config->vid_timing_mode.video_timing.h_total,
+ dp_sub->base_addr + DP_MAIN_STREAM_HTOTAL);
+ writel(msa_config->vid_timing_mode.video_timing.f0_pv_total,
+ dp_sub->base_addr + DP_MAIN_STREAM_VTOTAL);
+ writel(msa_config->vid_timing_mode.video_timing.h_sync_polarity |
+ (msa_config->vid_timing_mode.video_timing.v_sync_polarity
+ << DP_MAIN_STREAM_POLARITY_VSYNC_POL_SHIFT),
+ dp_sub->base_addr + DP_MAIN_STREAM_POLARITY);
+ writel(msa_config->vid_timing_mode.video_timing.h_sync_width,
+ dp_sub->base_addr + DP_MAIN_STREAM_HSWIDTH);
+ writel(msa_config->vid_timing_mode.video_timing.f0_pv_sync_width,
+ dp_sub->base_addr + DP_MAIN_STREAM_VSWIDTH);
+ writel(msa_config->vid_timing_mode.video_timing.h_active,
+ dp_sub->base_addr + DP_MAIN_STREAM_HRES);
+ writel(msa_config->vid_timing_mode.video_timing.v_active,
+ dp_sub->base_addr + DP_MAIN_STREAM_VRES);
+ writel(msa_config->h_start, dp_sub->base_addr + DP_MAIN_STREAM_HSTART);
+ writel(msa_config->v_start, dp_sub->base_addr + DP_MAIN_STREAM_VSTART);
+ writel(msa_config->misc0, dp_sub->base_addr + DP_MAIN_STREAM_MISC0);
+ writel(msa_config->misc1, dp_sub->base_addr + DP_MAIN_STREAM_MISC1);
+ writel(msa_config->pixel_clock_hz / 1000, dp_sub->base_addr + DP_M_VID);
+ writel(msa_config->n_vid, dp_sub->base_addr + DP_N_VID);
+ writel(msa_config->user_pixel_width, dp_sub->base_addr + DP_USER_PIXEL_WIDTH);
+ writel(msa_config->data_per_lane, dp_sub->base_addr + DP_USER_DATA_COUNT_PER_LANE);
+ /*
+ * Set the transfer unit values to the associated DisplayPort TX core
+ * registers.
+ */
+ writel(msa_config->transfer_unit_size, dp_sub->base_addr + DP_TU_SIZE);
+ writel(msa_config->avg_bytes_per_tu / 1000,
+ dp_sub->base_addr + DP_MIN_BYTES_PER_TU);
+ writel((msa_config->avg_bytes_per_tu % 1000) * 1000,
+ dp_sub->base_addr + DP_FRAC_BYTES_PER_TU);
+ writel(msa_config->init_wait, dp_sub->base_addr + DP_INIT_WAIT);
+}
+
+static void setup_video_stream(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+ struct main_stream_attributes *msa_config = &dp_sub->msa_config;
+
+ set_color_encode(dev);
+ set_msa_bpc(dev, dp_sub->bpc);
+ config_msa_video_mode(dev, dp_sub->video_mode);
+
+ /* Set pixel clock. */
+ dp_sub->pix_clk = msa_config->pixel_clock_hz;
+ set_pixel_clock(dp_sub->pix_clk);
+
+ /* Reset the transmitter. */
+ writel(1, dp_sub->base_addr + DP_SOFT_RESET);
+ udelay(10);
+ writel(0, dp_sub->base_addr + DP_SOFT_RESET);
+
+ set_msa_values(dev);
+
+ /* Issuing a soft-reset (AV_BUF_SRST_REG). */
+ writel(3, dp_sub->base_addr + AVBUF_BUF_SRST_REG); // Assert reset.
+ udelay(10);
+ writel(0, dp_sub->base_addr + AVBUF_BUF_SRST_REG); // De-ssert reset.
+
+ enable_main_link(dev, 1);
+
+ debug("DONE!\n");
+}
+
+static int dp_tx_start_link_training(struct udevice *dev)
+{
+ u32 status;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ enable_main_link(dev, 0);
+
+ if (!is_dp_connected(dev)) {
+ debug("! Disconnected.\n");
+ return -ENODEV;
+ }
+
+ status = dp_tx_wakeup(dev);
+ if (status) {
+ debug("! Wakeup failed.\n");
+ return -EIO;
+ }
+
+ do {
+ mdelay(100);
+ status = dp_hpd_train(dev);
+ if (status == -EINVAL) {
+ debug("Lost connection\n\r");
+ return -EIO;
+ } else if (status) {
+ continue;
+ }
+ display_gfx_frame_buffer(dev);
+ setup_video_stream(dev);
+ status = check_link_status(dev, dp_sub->link_config.lane_count);
+ if (status == -EINVAL)
+ return -EIO;
+ } while (status != 0);
+
+ return 0;
+}
+
+static void init_run_config(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ dp_sub->dp_dma = &dp_dma;
+ dp_sub->video_mode = VIDC_VM_1024x768_60_P;
+ dp_sub->bpc = VIDC_BPC_8;
+ dp_sub->color_encode = DP_CENC_RGB;
+ dp_sub->use_max_cfg_caps = 1;
+ dp_sub->lane_count = LANE_COUNT_1;
+ dp_sub->link_rate = LINK_RATE_540GBPS;
+ dp_sub->en_sync_clk_mode = 0;
+ dp_sub->use_max_lane_count = 1;
+ dp_sub->use_max_link_rate = 1;
+}
+
+static int dpdma_setup(struct udevice *dev)
+{
+ int status;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ writel(DPDMA_ISR_VSYNC_INT_MASK, dp_sub->dp_dma->base_addr + DPDMA_IEN);
+ status = wait_for_bit_le32((u32 *)dp_sub->dp_dma->base_addr + DPDMA_ISR,
+ DPDMA_ISR_VSYNC_INT_MASK, false, 1000, false);
+ if (status) {
+ debug("%s: INTR TIMEDOUT\n", __func__);
+ return status;
+ }
+ debug("INTR dma_vsync_intr_handler called...\n");
+ dma_vsync_intr_handler(dev);
+
+ return 0;
+}
+
+static int zynqmp_dpsub_init(struct udevice *dev)
+{
+ int status;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ /* Initialize the dpdma configuration */
+ status = init_dpdma_subsys(dev);
+ if (status)
+ return -EINVAL;
+
+ config_msa_sync_clk_mode(dev, dp_sub->en_sync_clk_mode);
+ set_video_clk_source(dev, AVBUF_PS_CLK, AVBUF_PS_CLK);
+
+ return 0;
+}
+
+static int dp_tx_run(struct udevice *dev)
+{
+ u32 interrupt_signal_state, interrupt_status, hpd_state, hpd_event;
+ u32 hpd_pulse_detected, hpd_duration, status;
+ int attempts = 0;
+ struct zynqmp_dpsub_priv *dp_sub = dev_get_priv(dev);
+
+ /* Continuously poll for HPD events. */
+ while (attempts < 5) {
+ /* Read interrupt registers. */
+ interrupt_signal_state = readl(dp_sub->base_addr + DP_INTERRUPT_SIG_STATE);
+ interrupt_status = readl(dp_sub->base_addr + DP_INTR_STATUS);
+ /* Check for HPD events. */
+ hpd_state = interrupt_signal_state & DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK;
+ hpd_event = interrupt_status & DP_INTR_HPD_EVENT_MASK;
+ hpd_pulse_detected = interrupt_status & DP_INTR_HPD_PULSE_DETECTED_MASK;
+ if (hpd_pulse_detected)
+ hpd_duration = readl(dp_sub->base_addr + DP_HPD_DURATION);
+ else
+ attempts++;
+
+ /* HPD event handling. */
+ if (hpd_state && hpd_event) {
+ debug("+===> HPD connection event detected.\n");
+ /* Initiate link training. */
+ status = dp_tx_start_link_training(dev);
+ if (status) {
+ debug("Link training failed\n");
+ return status;
+ }
+ return 0;
+ } else if (hpd_state && hpd_pulse_detected && (hpd_duration >= 250)) {
+ debug("===> HPD pulse detected.\n");
+ /* Re-train if needed. */
+ status = dp_tx_start_link_training(dev);
+ if (status) {
+ debug("HPD pulse detection failed\n");
+ return status;
+ }
+ return 0;
+ } else if (!hpd_state && hpd_event) {
+ debug("+===> HPD disconnection event detected.\n\n");
+ /* Disable main link. */
+ enable_main_link(dev, 0);
+ break;
+ }
+ }
+ return -EINVAL;
+}
+
+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);
+ struct clk clk;
+ int ret;
+ int mode = RGBA8888;
+
+ ret = clk_get_by_name(dev, "dp_apb_clk", &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ priv->clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(priv->clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return priv->clock;
+ }
+
+ ret = clk_enable(&clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "Base addr 0x%x, clock %d\n", (u32)priv->base_addr,
+ priv->clock);
+
+ /* Initialize the DisplayPort TX core. */
+ ret = init_dp_tx(dev);
+ if (ret)
+ return -EINVAL;
+
+ /* Initialize the runtime configuration */
+ init_run_config(dev);
+ /* Set the format graphics frame for Video Pipeline */
+ ret = set_nonlive_gfx_format(dev, mode);
+ if (ret)
+ return ret;
+
+ uc_priv->bpix = ffs(priv->non_live_graphics->bpp) - 1;
+ dev_dbg(dev, "BPP in bits %d, bpix %d\n",
+ priv->non_live_graphics->bpp, uc_priv->bpix);
+
+ uc_priv->fb = (void *)gd->fb_base;
+ uc_priv->xsize = vidc_video_timing_modes[priv->video_mode].video_timing.h_active;
+ uc_priv->ysize = vidc_video_timing_modes[priv->video_mode].video_timing.v_active;
+ /* Calculated by core but need it for my own setup */
+ uc_priv->line_length = uc_priv->xsize * VNBYTES(uc_priv->bpix);
+ /* Will be calculated again in video_post_probe() but I need that value now */
+ uc_priv->fb_size = uc_priv->line_length * uc_priv->ysize;
+
+ switch (mode) {
+ case RGBA8888:
+ uc_priv->format = VIDEO_RGBA8888;
+ break;
+ default:
+ debug("Unsupported mode\n");
+ return -EINVAL;
+ }
+
+ video_set_flush_dcache(dev, true);
+ debug("Video: WIDTH[%d]xHEIGHT[%d]xBPP[%d/%d] -- line length %d\n", uc_priv->xsize,
+ uc_priv->ysize, uc_priv->bpix, VNBYTES(uc_priv->bpix), uc_priv->line_length);
+
+ enable_gfx_buffers(dev, 1);
+ avbuf_video_select(dev, AVBUF_VIDSTREAM1_NONE, AVBUF_VIDSTREAM2_NONLIVE_GFX);
+ config_gfx_pipeline(dev);
+ config_output_video(dev);
+
+ ret = zynqmp_dpsub_init(dev);
+ if (ret)
+ return ret;
+
+ /* Populate the FrameBuffer structure with the frame attributes */
+ priv->frame_buffer.stride = uc_priv->line_length;
+ priv->frame_buffer.line_size = priv->frame_buffer.stride;
+ priv->frame_buffer.size = priv->frame_buffer.line_size * uc_priv->ysize;
+
+ ret = dp_tx_run(dev);
+ if (ret)
+ return ret;
+
+ return dpdma_setup(dev);
+}
+
+static int zynqmp_dpsub_bind(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ /* This is maximum size to allocate - it depends on BPP setting */
+ plat->size = WIDTH * HEIGHT * 4;
+ /* plat->align is not defined that's why 1MB alignment is used */
+
+ /*
+ * plat->base can be used for allocating own location for FB
+ * if not defined then it is allocated by u-boot itself
+ */
+
+ return 0;
+}
+
+static int zynqmp_dpsub_of_to_plat(struct udevice *dev)
+{
+ struct zynqmp_dpsub_priv *priv = dev_get_priv(dev);
+ struct resource res;
+ int ret;
+
+ ret = dev_read_resource_byname(dev, "dp", &res);
+ if (ret)
+ return ret;
+
+ priv->base_addr = res.start;
+
+ return 0;
+}
+
+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,
+ .plat_auto = sizeof(struct video_uc_plat),
+ .bind = zynqmp_dpsub_bind,
+ .probe = zynqmp_dpsub_probe,
+ .priv_auto = sizeof(struct zynqmp_dpsub_priv),
+ .of_to_plat = zynqmp_dpsub_of_to_plat,
+};
diff --git a/drivers/video/zynqmp/zynqmp_dpsub.h b/drivers/video/zynqmp/zynqmp_dpsub.h
new file mode 100644
index 00000000000..7d2737e31aa
--- /dev/null
+++ b/drivers/video/zynqmp/zynqmp_dpsub.h
@@ -0,0 +1,680 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ */
+
+#ifndef _VIDEO_ZYNQMP_DPSUB_H
+#define _VIDEO_ZYNQMP_DPSUB_H
+
+enum video_mode {
+ VIDC_VM_640x480_60_P = 0,
+ VIDC_VM_1024x768_60_P = 1,
+};
+
+enum {
+ LANE_COUNT_1 = 1,
+ LANE_COUNT_2 = 2,
+};
+
+enum {
+ LINK_RATE_162GBPS = 0x06,
+ LINK_RATE_270GBPS = 0x0A,
+ LINK_RATE_540GBPS = 0x14,
+};
+
+enum video_color_depth {
+ VIDC_BPC_6 = 6,
+ VIDC_BPC_8 = 8,
+ VIDC_BPC_10 = 10,
+ VIDC_BPC_12 = 12,
+ VIDC_BPC_14 = 14,
+ VIDC_BPC_16 = 16,
+ VIDC_BPC_NUM_SUPPORTED = 6,
+ VIDC_BPC_UNKNOWN
+};
+
+enum video_color_encoding {
+ DP_CENC_RGB = 0,
+ DP_CENC_YONLY,
+};
+
+enum dp_dma_channel_type {
+ VIDEO_CHAN,
+ GRAPHICS_CHAN,
+};
+
+enum dp_dma_channel_state {
+ DPDMA_DISABLE,
+ DPDMA_ENABLE,
+ DPDMA_IDLE,
+ DPDMA_PAUSE
+};
+
+enum link_training_states {
+ TS_CLOCK_RECOVERY,
+ TS_CHANNEL_EQUALIZATION,
+ TS_ADJUST_LINK_RATE,
+ TS_ADJUST_LANE_COUNT,
+ TS_FAILURE,
+ TS_SUCCESS
+};
+
+enum video_frame_rate {
+ VIDC_FR_60HZ = 60,
+ VIDC_FR_NUM_SUPPORTED = 2,
+ VIDC_FR_UNKNOWN
+};
+
+enum av_buf_video_modes {
+ INTERLEAVED,
+ SEMIPLANAR
+};
+
+enum av_buf_video_format {
+ RGBA8888 = 1,
+};
+
+enum av_buf_video_stream {
+ AVBUF_VIDSTREAM1_LIVE,
+ AVBUF_VIDSTREAM1_NONLIVE,
+ AVBUF_VIDSTREAM1_TPG,
+ AVBUF_VIDSTREAM1_NONE,
+};
+
+enum av_buf_gfx_stream {
+ AVBUF_VIDSTREAM2_DISABLEGFX = 0x0,
+ AVBUF_VIDSTREAM2_NONLIVE_GFX = 0x4,
+ AVBUF_VIDSTREAM2_LIVE_GFX = 0x8,
+ AVBUF_VIDSTREAM2_NONE = 0xC0,
+};
+
+/**
+ * struct aux_transaction - Description of an AUX channel transaction
+ * @cmd_code: Command code of the transaction
+ * @num_bytes: The number of bytes in the transaction's payload data
+ * @address: The DPCD address of the transaction
+ * @data: Payload data of the AUX channel transaction
+ */
+struct aux_transaction {
+ u16 cmd_code;
+ u8 num_bytes;
+ u32 address;
+ u8 *data;
+};
+
+/**
+ * struct link_config - Description of link configuration
+ * @lane_count: Currently selected lane count for this link
+ * @link_rate: Currently selected link rate for this link
+ * @scrambler_en: Flag to determine whether the scrambler is
+ * enabled for this link
+ * @enhanced_framing_mode: Flag to determine whether enhanced framing
+ * mode is active for this link
+ * @max_lane_count: Maximum lane count for this link
+ * @max_link_rate: Maximum link rate for this link
+ * @support_enhanced_framing_mode: Flag to indicate whether the link supports
+ * enhanced framing mode
+ * @vs_level: Voltage swing for each lane
+ * @pe_level: Pre-emphasis/cursor level for each lane
+ * @pattern: The current pattern currently in use over the main link
+ */
+struct link_config {
+ u8 lane_count;
+ u8 link_rate;
+ u8 scrambler_en;
+ u8 enhanced_framing_mode;
+ u8 max_lane_count;
+ u8 max_link_rate;
+ u8 support_enhanced_framing_mode;
+ u8 support_downspread_control;
+ u8 vs_level;
+ u8 pe_level;
+ u8 pattern;
+};
+
+struct video_timing {
+ u16 h_active;
+ u16 h_front_porch;
+ u16 h_sync_width;
+ u16 h_back_porch;
+ u16 h_total;
+ bool h_sync_polarity;
+ u16 v_active;
+ u16 f0_pv_front_porch;
+ u16 f0_pv_sync_width;
+ u16 f0_pv_back_porch;
+ u16 f0_pv_total;
+ u16 f1_v_front_porch;
+ u16 f1_v_sync_width;
+ u16 f1_v_back_porch;
+ u16 f1_v_total;
+ bool v_sync_polarity;
+};
+
+struct video_timing_mode {
+ enum video_mode vid_mode;
+ char name[21];
+ enum video_frame_rate frame_rate;
+ struct video_timing video_timing;
+};
+
+/*
+ * struct main_stream_attributes - Main Stream Attributes (MSA)
+ * @pixel_clock_hz: The pixel clock of the stream (in Hz)
+ * @h_start: Horizontal blank start (in pixels)
+ * @v_start: Vertical blank start (in lines).
+ * @misc0: Miscellaneous stream attributes 0
+ * @misc1: Miscellaneous stream attributes 1
+ * @n_vid N value for the video stream
+ * @user_pixel_width: The width of the user data input port.
+ * @data_per_plane: Used to translate the number of pixels per
+ * line to the native internal 16-bit datapath.
+ * @avg_bytes_per_tu: Average number of bytes per transfer unit,
+ * scaled up by a factor of 1000.
+ * @transfer_unit_size: Size of the transfer unit in the
+ * framing logic.
+ * @init_wait: Number of initial wait cycles at the start
+ * of a new line by the framing logic.
+ * @bits_per_color: Number of bits per color component.
+ * @component_format: The component format currently in
+ * use by the video stream.
+ * @dynamic_range: The dynamic range currently in use
+ * by the video stream.
+ * @y_cb_cr_colorimetry: The YCbCr colorimetry currently in
+ * use by the video stream.
+ * @synchronous_clock_mode: Synchronous clock mode is currently
+ * in use by the video stream.
+ */
+struct main_stream_attributes {
+ struct video_timing_mode vid_timing_mode;
+ u32 pixel_clock_hz;
+ u32 h_start;
+ u32 v_start;
+ u32 misc0;
+ u32 misc1;
+ u32 n_vid;
+ u32 user_pixel_width;
+ u32 data_per_lane;
+ u32 avg_bytes_per_tu;
+ u32 transfer_unit_size;
+ u32 init_wait;
+ u32 bits_per_color;
+ u8 component_format;
+ u8 dynamic_range;
+ u8 y_cb_cr_colorimetry;
+ u8 synchronous_clock_mode;
+};
+
+struct av_buf_vid_attribute {
+ enum av_buf_video_format video_format;
+ u8 value;
+ enum av_buf_video_modes mode;
+ u32 sf[3];
+ u8 sampling_en;
+ u8 is_rgb;
+ u8 swap;
+ u8 bpp;
+};
+
+struct av_buf_mode {
+ enum av_buf_video_stream video_src;
+ enum av_buf_gfx_stream gfx_src;
+ u8 video_clk;
+};
+
+struct dp_dma_descriptor {
+ u32 control;
+ u32 dscr_id;
+ u32 xfer_size;
+ u32 line_size_stride;
+ u32 lsb_timestamp;
+ u32 msb_timestamp;
+ u32 addr_ext;
+ u32 next_desr;
+ u32 src_addr;
+ u32 addr_ext_23;
+ u32 addr_ext_45;
+ u32 src_addr2;
+ u32 src_addr3;
+ u32 src_addr4;
+ u32 src_addr5;
+ u32 crc;
+};
+
+struct dp_dma_channel {
+ struct dp_dma_descriptor *cur;
+};
+
+struct dp_dma_frame_buffer {
+ u64 address;
+ u32 size;
+ u32 stride;
+ u32 line_size;
+};
+
+struct dp_dma_gfx_channel {
+ struct dp_dma_channel channel;
+ u8 trigger_status;
+ u8 av_buf_en;
+ struct dp_dma_frame_buffer *frame_buffer;
+};
+
+struct dp_dma {
+ phys_addr_t base_addr;
+ struct dp_dma_gfx_channel gfx;
+};
+
+/**
+ * struct zynqmp_dpsub_priv - Private structure
+ * @dev: Device uclass for video_ops
+ */
+struct zynqmp_dpsub_priv {
+ phys_addr_t base_addr;
+ u32 clock;
+ struct av_buf_vid_attribute *non_live_graphics;
+ struct av_buf_mode av_mode;
+ struct dp_dma_frame_buffer frame_buffer;
+
+ struct link_config link_config;
+ struct main_stream_attributes msa_config;
+ struct dp_dma *dp_dma;
+ enum video_mode video_mode;
+ enum video_color_depth bpc;
+ enum video_color_encoding color_encode;
+ u32 pix_clk;
+ u8 dpcd_rx_caps[16];
+ u8 lane_status_ajd_reqs[6];
+ u8 sink_count;
+ u8 use_max_lane_count;
+ u8 use_max_link_rate;
+ u8 lane_count;
+ u8 link_rate;
+ u8 use_max_cfg_caps;
+ u8 en_sync_clk_mode;
+};
+
+/**************************** Variable Definitions ****************************/
+#define TRAINING_PATTERN_SET 0x000C
+#define TRAINING_PATTERN_SET_OFF 0x0
+#define SCRAMBLING_DISABLE 0x0014
+#define TRAINING_PATTERN_SET_TP1 0x1
+#define TRAINING_PATTERN_SET_TP2 0x2
+#define TRAINING_PATTERN_SET_TP3 0x3
+
+#define AVBUF_BUF_4BIT_SF 0x11111
+#define AVBUF_BUF_5BIT_SF 0x10842
+#define AVBUF_BUF_6BIT_SF 0x10410
+#define AVBUF_BUF_8BIT_SF 0x10101
+#define AVBUF_BUF_10BIT_SF 0x10040
+#define AVBUF_BUF_12BIT_SF 0x10000
+#define AVBUF_BUF_6BPC 0x000
+#define AVBUF_BUF_8BPC 0x001
+#define AVBUF_BUF_10BPC 0x010
+#define AVBUF_BUF_12BPC 0x011
+#define AVBUF_CHBUF3 0x0000B01C
+#define AVBUF_CHBUF3_BURST_LEN_SHIFT 2
+#define AVBUF_CHBUF3_FLUSH_MASK 0x00000002
+#define AVBUF_CHBUF0_EN_MASK 0x00000001
+#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT 0x0000B070
+#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM2_SEL_MASK 0x0000000C
+#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT_VID_STREAM1_SEL_MASK 0x00000003
+#define AVBUF_BUF_OUTPUT_AUD_VID_SELECT 0x0000B070
+#define AVBUF_BUF_GRAPHICS_COMP0_SCALE_FACTOR 0x0000B200
+#define AVBUF_V_BLEND_LAYER1_CONTROL 0x0000A01C
+#define AVBUF_V_BLEND_IN2CSC_COEFF0 0x0000A080
+#define AVBUF_BUF_FORMAT 0x0000B000
+#define AVBUF_BUF_FORMAT_NL_VID_FORMAT_MASK 0x0000001F
+#define AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_MASK 0x00000F00
+#define AVBUF_BUF_FORMAT_NL_GRAPHX_FORMAT_SHIFT 8
+#define AVBUF_V_BLEND_LAYER0_CONTROL_RGB_MODE_SHIFT 1
+#define AVBUF_V_BLEND_OUTPUT_VID_FORMAT_EN_DOWNSAMPLE_SHIFT 4
+#define AVBUF_V_BLEND_OUTPUT_VID_FORMAT 0x0000A014
+#define AVBUF_V_BLEND_RGB2YCBCR_COEFF0 0x0000A020
+#define AVBUF_V_BLEND_LUMA_OUTCSC_OFFSET 0x0000A074
+#define AVBUF_V_BLEND_LUMA_IN1CSC_OFFSET_POST_OFFSET_SHIFT 16
+#define AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG_VALUE_SHIFT 1
+#define AVBUF_V_BLEND_SET_GLOBAL_ALPHA_REG 0x0000A00C
+#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_SHIFT 1
+#define DP_MAIN_STREAM_MISC0_DYNAMIC_RANGE_SHIFT 3
+#define DP_MAIN_STREAM_MISC0_YCBCR_COLORIMETRY_SHIFT 4
+#define DP_MAIN_STREAM_MISC1_Y_ONLY_EN_MASK 0x00000080
+#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_YCBCR422 0x1
+#define AVBUF_PL_CLK 0x0
+#define AVBUF_PS_CLK 0x1
+#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_TIMING_SRC_SHIFT 2
+#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT 0
+#define AVBUF_BUF_AUD_VID_CLK_SOURCE_AUD_CLK_SRC_SHIFT 1
+#define AVBUF_BUF_AUD_VID_CLK_SOURCE 0x0000B120
+#define AVBUF_BUF_SRST_REG 0x0000B124
+#define AVBUF_BUF_SRST_REG_VID_RST_MASK 0x00000002
+#define AVBUF_CLK_FPD_BASEADDR 0xFD1A0000
+#define AVBUF_CLK_LPD_BASEADDR 0xFF5E0000
+#define AVBUF_LPD_CTRL_OFFSET 16
+#define AVBUF_FPD_CTRL_OFFSET 12
+#define AVBUF_EXTERNAL_DIVIDER 2
+#define AVBUF_VIDEO_REF_CTRL 0x00000070
+#define AVBUF_VIDEO_REF_CTRL_SRCSEL_MASK 0x00000007
+#define AVBUF_VPLL_SRC_SEL 0
+#define AVBUF_DPLL_SRC_SEL 2
+#define AVBUF_RPLL_TO_FPD_SRC_SEL 3
+#define AVBUF_INPUT_REF_CLK 3333333333
+#define AVBUF_PLL_OUT_FREQ 1450000000
+#define AVBUF_INPUT_FREQ_PRECISION 100
+#define AVBUF_PRECISION 16
+#define AVBUF_SHIFT_DECIMAL BIT(16)
+#define AVBUF_DECIMAL (AVBUF_SHIFT_DECIMAL - 1)
+#define AVBUF_ENABLE_BIT 1
+#define AVBUF_DISABLE_BIT 0
+#define AVBUF_PLL_CTRL_BYPASS_SHIFT 3
+#define AVBUF_PLL_CTRL_FBDIV_SHIFT 8
+#define AVBUF_PLL_CTRL_DIV2_SHIFT 16
+#define AVBUF_PLL_CTRL_PRE_SRC_SHIFT 20
+#define AVBUF_PLL_CTRL 0x00000020
+#define AVBUF_PLL_CFG_CP_SHIFT 5
+#define AVBUF_PLL_CFG_RES_SHIFT 0
+#define AVBUF_PLL_CFG_LFHF_SHIFT 10
+#define AVBUF_PLL_CFG_LOCK_DLY_SHIFT 25
+#define AVBUF_PLL_CFG_LOCK_CNT_SHIFT 13
+#define AVBUF_PLL_FRAC_CFG 0x00000028
+#define AVBUF_PLL_FRAC_CFG_ENABLED_SHIFT 31
+#define AVBUF_PLL_FRAC_CFG_DATA_SHIFT 0
+#define AVBUF_PLL_CTRL_RESET_MASK 0x00000001
+#define AVBUF_PLL_CTRL_RESET_SHIFT 0
+#define AVBUF_PLL_STATUS 0x00000044
+#define AVBUF_REG_OFFSET 4
+#define AVBUF_PLL_CTRL_BYPASS_MASK 0x00000008
+#define AVBUF_PLL_CTRL_BYPASS_SHIFT 3
+#define AVBUF_DOMAIN_SWITCH_CTRL 0x00000044
+#define AVBUF_DOMAIN_SWITCH_DIVISOR0_MASK 0x00003F00
+#define AVBUF_DOMAIN_SWITCH_DIVISOR0_SHIFT 8
+#define AVBUF_PLL_CFG 0x00000024
+#define AVBUF_BUF_AUD_VID_CLK_SOURCE_VID_CLK_SRC_SHIFT 0
+#define AVBUF_VIDEO_REF_CTRL_CLKACT_MASK 0x01000000
+#define AVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT 24
+#define AVBUF_VIDEO_REF_CTRL_DIVISOR1_MASK 0x003F0000
+#define AVBUF_VIDEO_REF_CTRL_DIVISOR1_SHIFT 16
+#define AVBUF_VIDEO_REF_CTRL_DIVISOR0_MASK 0x00003F00
+#define AVBUF_VIDEO_REF_CTRL_DIVISOR0_SHIFT 8
+#define AVBUF_VIDEO_REF_CTRL_CLKACT_MASK 0x01000000
+#define AVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT 24
+
+#define DP_INTERRUPT_SIG_STATE 0x0130
+#define DP_INTR_STATUS 0x03A0
+#define DP_INTERRUPT_SIG_STATE_HPD_STATE_MASK 0x00000001
+#define DP_INTR_HPD_EVENT_MASK 0x00000002
+#define DP_INTR_HPD_PULSE_DETECTED_MASK 0x00000010
+#define DP_HPD_DURATION 0x0150
+#define DP_FORCE_SCRAMBLER_RESET 0x00C0
+#define DP_ENABLE_MAIN_STREAM 0x0084
+#define DP_IS_CONNECTED_MAX_TIMEOUT_COUNT 50
+#define DP_0_LINK_RATE 20
+#define DP_0_LANE_COUNT 1
+#define DP_ENHANCED_FRAME_EN 0x0008
+#define DP_LANE_COUNT_SET 0x0004
+#define DP_LINK_BW_SET_162GBPS 0x06
+#define DP_LINK_BW_SET_270GBPS 0x0A
+#define DP_LINK_BW_SET_540GBPS 0x14
+#define DP_LINK_BW_SET 0x0000
+#define DP_DOWNSPREAD_CTRL 0x0018
+#define DP_SCRAMBLING_DISABLE 0x0014
+#define DP_AUX_CMD_READ 0x9
+#define DP_AUX_CMD_WRITE 0x8
+#define DP_AUX_CMD_I2C_READ 0x1
+#define DP_AUX_CMD_I2C_READ_MOT 0x5
+#define DP_AUX_CMD_I2C_WRITE 0x0
+#define DP_AUX_CMD_I2C_WRITE_MOT 0x4
+#define DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK 0x00000002
+#define DP_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK 0x00000004
+#define DP_REPLY_STATUS 0x014C
+#define DP_AUX_MAX_TIMEOUT_COUNT 50
+#define DP_AUX_MAX_DEFER_COUNT 50
+#define DP_AUX_ADDRESS 0x0108
+#define DP_AUX_WRITE_FIFO 0x0104
+#define DP_AUX_CMD 0x0100
+#define DP_AUX_CMD_SHIFT 8
+#define DP_AUX_CMD_NBYTES_TRANSFER_MASK 0x0000000F
+#define DP_AUX_REPLY_CODE 0x0138
+#define DP_AUX_REPLY_CODE_DEFER 0x2
+#define DP_AUX_REPLY_CODE_I2C_DEFER 0x8
+#define DP_AUX_REPLY_CODE_NACK 0x1
+#define DP_AUX_REPLY_CODE_I2C_NACK 0x4
+#define DP_REPLY_DATA_COUNT 0x0148
+#define DP_AUX_REPLY_DATA 0x0134
+#define DP_LANE_COUNT_SET_1 0x01
+#define DP_LANE_COUNT_SET_2 0x02
+#define DP_MAXIMUM_PE_LEVEL 2
+#define DP_MAXIMUM_VS_LEVEL 3
+#define DP_MAIN_STREAM_MISC0_COMPONENT_FORMAT_RGB 0x0
+#define DP_MAIN_STREAM_MISC0_BDC_6BPC 0x0
+#define DP_MAIN_STREAM_MISC0_BDC_8BPC 0x1
+#define DP_MAIN_STREAM_MISC0_BDC_10BPC 0x2
+#define DP_MAIN_STREAM_MISC0_BDC_12BPC 0x3
+#define DP_MAIN_STREAM_MISC0_BDC_16BPC 0x4
+#define DP_MAIN_STREAM_MISC0_BDC_SHIFT 5
+#define DP_PHY_CONFIG_TX_PHY_8B10BEN_MASK 0x0010000
+#define DP_PHY_CONFIG_PHY_RESET_MASK 0x0000001
+#define DP_ENABLE_MAIN_STREAM 0x0084
+#define DP_SOFT_RESET 0x001C
+#define DP_MAIN_STREAM_HTOTAL 0x0180
+#define DP_MAIN_STREAM_VTOTAL 0x0184
+#define DP_MAIN_STREAM_POLARITY 0x0188
+#define DP_MAIN_STREAM_POLARITY_VSYNC_POL_SHIFT 1
+#define DP_MAIN_STREAM_HSWIDTH 0x018C
+#define DP_MAIN_STREAM_VSWIDTH 0x0190
+#define DP_MAIN_STREAM_HRES 0x0194
+#define DP_MAIN_STREAM_VRES 0x0198
+#define DP_MAIN_STREAM_HSTART 0x019C
+#define DP_MAIN_STREAM_VSTART 0x01A0
+#define DP_MAIN_STREAM_MISC0 0x01A4
+#define DP_MAIN_STREAM_MISC1 0x01A8
+#define DP_M_VID 0x01AC
+#define DP_N_VID 0x01B4
+#define DP_USER_PIXEL_WIDTH 0x01B8
+#define DP_USER_DATA_COUNT_PER_LANE 0x01BC
+#define DP_TU_SIZE 0x01B0
+#define DP_MIN_BYTES_PER_TU 0x01C4
+#define DP_FRAC_BYTES_PER_TU 0x01C8
+#define DP_INIT_WAIT 0x01CC
+#define DP_PHY_CLOCK_SELECT_162GBPS 0x1
+#define DP_PHY_CLOCK_SELECT_270GBPS 0x3
+#define DP_PHY_CLOCK_SELECT_540GBPS 0x5
+#define DP_PHY_STATUS 0x0280
+#define DP_PHY_STATUS_ALL_LANES_READY_MASK 0x00000013
+#define DP_PHY_STATUS_GT_PLL_LOCK_MASK 0x00000010
+#define DP_PHY_STATUS_RESET_LANE_0_DONE_MASK 0x00000001
+#define DP_INTR_HPD_IRQ_MASK 0x00000001
+#define DP_INTR_MASK 0x03A4
+#define DP_DP_ENABLE 0x1
+#define DP_PHY_CONFIG_GT_ALL_RESET_MASK 0x0000003
+#define DP_PHY_CLOCK_SELECT 0x0234
+#define DP_AUX_CLK_DIVIDER_VAL_MASK 0x000000FF
+#define DP_AUX_CLK_DIVIDER 0x010C
+#define DP_DISABLE 0x0
+#define DP_ENABLE 0x0080
+#define DP_SOFT_RESET_EN 0x1
+#define DP_PHY_CONFIG 0x0200
+#define DP_REPLY_STATUS_REPLY_RECEIVED_MASK 0x00000001
+#define DP_REPLY_STATUS_REPLY_IN_PROGRESS_MASK 0x00000002
+#define DP_REPLY_STATUS_REPLY_ERROR_MASK 0x00000008
+#define DP_AUX_MAX_WAIT 20000
+
+#define DP_DPCD_SINK_COUNT 0x00200
+#define DP_DPCD_TP_SET_SCRAMB_DIS_MASK 0x20
+#define DP_DPCD_STATUS_LANE_1_CR_DONE_MASK 0x10
+#define DP_DPCD_STATUS_LANE_0_CR_DONE_MASK 0x01
+#define DP_DPCD_STATUS_LANE_1_CE_DONE_MASK 0x20
+#define DP_DPCD_STATUS_LANE_0_CE_DONE_MASK 0x02
+#define DP_DPCD_STATUS_LANE_1_SL_DONE_MASK 0x40
+#define DP_DPCD_STATUS_LANE_0_SL_DONE_MASK 0x04
+#define DP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK 0x01
+#define DP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK 0x03
+#define DP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK 0x30
+#define DP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT 4
+#define DP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK 0x0C
+#define DP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT 2
+#define DP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK 0xC0
+#define DP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT 6
+#define DP_DPCD_TRAINING_LANE0_SET 0x00103
+#define DP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK 0x04
+#define DP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK 0x20
+#define DP_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3
+#define DP_DPCD_SET_POWER_DP_PWR_VOLTAGE 0x00600
+#define DP_DPCD_RECEIVER_CAP_FIELD_START 0x00000
+#define DP_DPCD_MAX_LINK_RATE 0x00001
+#define DP_DPCD_MAX_LANE_COUNT 0x00002
+#define DP_DPCD_MAX_LANE_COUNT_MASK 0x1F
+#define DP_DPCD_ENHANCED_FRAME_SUPPORT_MASK 0x80
+#define DP_DPCD_MAX_DOWNSPREAD 0x00003
+#define DP_DPCD_MAX_DOWNSPREAD_MASK 0x01
+#define DP_DPCD_LANE_COUNT_SET 0x00101
+#define DP_DPCD_ENHANCED_FRAME_EN_MASK 0x80
+#define DP_DPCD_LINK_BW_SET 0x00100
+#define DP_DPCD_DOWNSPREAD_CTRL 0x00107
+#define DP_DPCD_SPREAD_AMP_MASK 0x10
+#define DP_DPCD_LANE_COUNT_SET_MASK 0x1F
+#define DP_DPCD_TPS3_SUPPORT_MASK 0x40
+#define DP_DPCD_TRAIN_AUX_RD_INTERVAL 0x0000E
+#define DP_DPCD_SINK_COUNT_HIGH_MASK 0x80
+#define DP_DPCD_SINK_COUNT_HIGH_LOW_SHIFT 1
+#define DP_DPCD_SINK_COUNT_LOW_MASK 0x3F
+#define DP_DPCD_TP_SET 0x00102
+
+#define SERDES_BASEADDR 0xFD400000
+#define SERDES_L0_TX_MARGININGF 0x0CC0
+#define SERDES_L0_TX_DEEMPHASIS 0x0048
+#define SERDES_LANE_OFFSET 0x4000
+
+#define DPDMA_TRIGGER_EN 1U
+#define DPDMA_RETRIGGER_EN 2U
+#define DPDMA_DESC_PREAMBLE 0xA5U
+#define DPDMA_DESC_IGNR_DONE 0x400U
+#define DPDMA_DESC_LAST_FRAME 0x200000U
+#define DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT 18
+#define DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH 32U
+#define DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT 16U
+#define DPDMA_CH0_DSCR_STRT_ADDR 0X0204U
+#define DPDMA_CH_OFFSET 0x100U
+#define DPDMA_CH0_CNTL 0x0218U
+#define DPDMA_CH3_CNTL 0x0518U
+#define DPDMA_CH0_DSCR_STRT_ADDRE 0x0200U
+#define DPDMA_CH3_DSCR_STRT_ADDR 0x0504
+#define DPDMA_CH3_DSCR_STRT_ADDRE 0x0500
+#define DPDMA_CH_CNTL_EN_MASK 0x1U
+#define DPDMA_CH_CNTL_PAUSE_MASK 0x2U
+#define DPDMA_GBL 0x0104U
+#define DPDMA_GBL_TRG_CH3_MASK 0x8
+#define DPDMA_TRIGGER_DONE 0U
+#define DPDMA_CH_CNTL_EN_MASK 0x1U
+#define DPDMA_CH_CNTL_PAUSE_MASK 0x2U
+#define DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT 10U
+#define DPDMA_CH_CNTL_QOS_DATA_RD_MASK 0x3C00U
+#define DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT 6U
+#define DPDMA_CH_CNTL_QOS_DSCR_RD_MASK 0x03C0U
+#define DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT 2U
+#define DPDMA_CH_CNTL_QOS_DSCR_WR_MASK 0x3CU
+#define DPDMA_CH_OFFSET 0x100U
+#define DPDMA_WAIT_TIMEOUT 10000U
+#define DPDMA_AUDIO_ALIGNMENT 128U
+#define DPDMA_VIDEO_CHANNEL0 0U
+#define DPDMA_VIDEO_CHANNEL1 1U
+#define DPDMA_VIDEO_CHANNEL2 2U
+#define DPDMA_GRAPHICS_CHANNEL 3U
+#define DPDMA_AUDIO_CHANNEL0 4U
+#define DPDMA_AUDIO_CHANNEL1 5U
+#define DPDMA_DESC_PREAMBLE 0xA5U
+#define DPDMA_DESC_IGNR_DONE 0x400U
+#define DPDMA_DESC_UPDATE 0x200U
+#define DPDMA_DESC_COMP_INTR 0x100U
+#define DPDMA_DESC_LAST_FRAME 0x200000U
+#define DPDMA_DESC_DONE_SHIFT 31U
+#define DPDMA_QOS_MIN 4U
+#define DPDMA_QOS_MAX 11U
+#define DPDMA_BASE_ADDRESS 0xFD4C0000
+#define DPDMA_ISR 0x0004U
+#define DPDMA_IEN 0x000CU
+#define DPDMA_ISR_VSYNC_INT_MASK 0x08000000
+
+#define CLK_FPD_BASEADDR 0xFD1A0000
+#define VIDEO_REF_CTRL 0x00000070
+#define VIDEO_REF_CTRL_SRCSEL_MASK 0x00000007
+#define PLL_OUT_FREQ 1450000000
+#define INPUT_FREQ_PRECISION 100
+#define PRECISION 16
+#define SHIFT_DECIMAL BIT(16)
+#define ENABLE_BIT 1
+#define DISABLE_BIT 0
+#define PLL_CTRL_BYPASS_SHIFT 3
+#define PLL_CTRL_FBDIV_SHIFT 8
+#define PLL_CTRL_DIV2_SHIFT 16
+#define PLL_CTRL_PRE_SRC_SHIFT 20
+#define PLL_CTRL 0x00000020
+#define VPLL_CTRL 0x00000038
+#define PLL_CFG 0x00000024
+#define VPLL 2
+#define VPLL_CFG 0x0000003C
+#define VPLL_CFG_CP 4
+#define VPLL_CFG_RES 6
+#define VPLL_CFG_LFHF 3
+#define VPLL_CFG_LOCK_DLY 63
+#define VPLL_CFG_LOCK_CNT 600
+#define PLL_STATUS_VPLL_LOCK 2
+#define PLL_CFG_CP_SHIFT 5
+#define PLL_CFG_RES_SHIFT 0
+#define PLL_CFG_LFHF_SHIFT 10
+#define PLL_CFG_LOCK_DLY_SHIFT 25
+#define PLL_CFG_LOCK_CNT_SHIFT 13
+#define PLL_FRAC_CFG 0x00000028
+#define VPLL_FRAC_CFG 0x00000040
+#define PLL_FRAC_CFG_ENABLED_SHIFT 31
+#define PLL_FRAC_CFG_DATA_SHIFT 0
+#define PLL_CTRL_RESET_MASK 0x00000001
+#define PLL_CTRL_RESET_SHIFT 0
+#define PLL_STATUS 0x00000044
+#define REG_OFFSET 4
+#define PLL_CTRL_BYPASS_MASK 0x00000008
+#define PLL_CTRL_BYPASS_SHIFT 3
+#define DOMAIN_SWITCH_CTRL 0x00000044
+#define DOMAIN_SWITCH_DIVISOR0_MASK 0x00003F00
+#define DOMAIN_SWITCH_DIVISOR0_SHIFT 8
+#define VIDEO_REF_CTRL_CLKACT_MASK 0x01000000
+#define VIDEO_REF_CTRL_CLKACT_SHIFT 24
+#define VIDEO_REF_CTRL_DIVISOR1_MASK 0x003F0000
+#define VIDEO_REF_CTRL_DIVISOR1_SHIFT 16
+#define VIDEO_REF_CTRL_DIVISOR0_MASK 0x00003F00
+#define VIDEO_REF_CTRL_DIVISOR0_SHIFT 8
+#define PSS_REF_CLK 0
+#define FPD_CTRL_OFFSET 12
+#define VIDC_VM_NUM_SUPPORTED 2
+
+static const u32 vs[4][4] = {
+ { 0x2a, 0x27, 0x24, 0x20 },
+ { 0x27, 0x23, 0x20, 0xff },
+ { 0x24, 0x20, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0xff },
+};
+
+static const u32 pe[4][4] = {
+ { 0x02, 0x02, 0x02, 0x02 },
+ { 0x01, 0x01, 0x01, 0xff },
+ { 0x00, 0x00, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0xff },
+};
+
+const struct video_timing_mode vidc_video_timing_modes[VIDC_VM_NUM_SUPPORTED] = {
+ { VIDC_VM_640x480_60_P, "640x480@60Hz", VIDC_FR_60HZ,
+ {640, 16, 96, 48, 800, 0,
+ 480, 10, 2, 33, 525, 0, 0, 0, 0, 0} },
+ { VIDC_VM_1024x768_60_P, "1024x768@60Hz", VIDC_FR_60HZ,
+ {1024, 24, 136, 160, 1344, 0,
+ 768, 3, 6, 29, 806, 0, 0, 0, 0, 0} },
+};
+
+const struct av_buf_vid_attribute avbuf_supported_formats[] = {
+ /* Non-Live Graphics formats */
+ { RGBA8888, 0, INTERLEAVED,
+ {AVBUF_BUF_8BIT_SF, AVBUF_BUF_8BIT_SF, AVBUF_BUF_8BIT_SF},
+ 0, 1, 0, 32},
+};
+
+#endif
diff --git a/drivers/video/zynqmp_dpsub.c b/drivers/video/zynqmp_dpsub.c
deleted file mode 100644
index 4ead663cd59..00000000000
--- a/drivers/video/zynqmp_dpsub.c
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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),
-};