aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/blk-uclass.c2
-rw-r--r--drivers/block/sandbox.c11
-rw-r--r--drivers/bootcount/Kconfig7
-rw-r--r--drivers/bootcount/Makefile1
-rw-r--r--drivers/bootcount/pmic_pfuze100.c161
-rw-r--r--drivers/clk/at91/pmc.c57
-rw-r--r--drivers/clk/clk-uclass.c37
-rw-r--r--drivers/clk/clk.c65
-rw-r--r--drivers/clk/clk_sandbox.c6
-rw-r--r--drivers/clk/clk_sandbox_test.c9
-rw-r--r--drivers/clk/clk_scmi.c96
-rw-r--r--drivers/clk/imx/clk-imx6q.c73
-rw-r--r--drivers/clk/imx/clk-imx8mm.c88
-rw-r--r--drivers/clk/imx/clk-imx8mn.c88
-rw-r--r--drivers/clk/imx/clk-imx8mp.c90
-rw-r--r--drivers/clk/imx/clk-imxrt1020.c65
-rw-r--r--drivers/clk/imx/clk-imxrt1050.c85
-rw-r--r--drivers/clk/microchip/mpfs_clk.c67
-rw-r--r--drivers/core/Kconfig10
-rw-r--r--drivers/core/device-remove.c8
-rw-r--r--drivers/core/device.c9
-rw-r--r--drivers/core/ofnode.c36
-rw-r--r--drivers/core/root.c5
-rw-r--r--drivers/ddr/fsl/Kconfig4
-rw-r--r--drivers/ddr/marvell/axp/ddr3_axp.h2
-rw-r--r--drivers/ddr/marvell/axp/ddr3_axp_config.h2
-rw-r--r--drivers/dma/Kconfig7
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/bcm6348-iudma.c6
-rw-r--r--drivers/dma/xilinx_dpdma.c43
-rw-r--r--drivers/firmware/firmware-zynqmp.c51
-rw-r--r--drivers/firmware/scmi/sandbox-scmi_agent.c228
-rw-r--r--drivers/firmware/scmi/sandbox-scmi_devices.c4
-rw-r--r--drivers/firmware/scmi/scmi_agent-uclass.c17
-rw-r--r--drivers/gpio/Kconfig22
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-aspeed.c299
-rw-r--r--drivers/gpio/gpio_slg7xl45106.c115
-rw-r--r--drivers/i2c/i2c-cdns.c18
-rw-r--r--drivers/led/Kconfig7
-rw-r--r--drivers/led/Makefile1
-rw-r--r--drivers/led/led_bcm6753.c270
-rw-r--r--drivers/mmc/omap_hsmmc.c1
-rw-r--r--drivers/mmc/zynq_sdhci.c110
-rw-r--r--drivers/mtd/Kconfig7
-rw-r--r--drivers/mtd/nand/raw/Kconfig6
-rw-r--r--drivers/mtd/nand/raw/brcmnand/Makefile1
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c124
-rw-r--r--drivers/mtd/nand/raw/zynq_nand.c9
-rw-r--r--drivers/net/Kconfig10
-rw-r--r--drivers/net/bcm6348-eth.c6
-rw-r--r--drivers/net/bcm6368-eth.c6
-rw-r--r--drivers/net/fec_mxc.c255
-rw-r--r--drivers/net/mcfmii.c4
-rw-r--r--drivers/net/phy/Kconfig20
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/ethernet_id.c69
-rw-r--r--drivers/net/phy/phy.c13
-rw-r--r--drivers/pci/pci-aardvark.c2
-rw-r--r--drivers/pci/pci-rcar-gen3.c2
-rw-r--r--drivers/pci/pci_mpc85xx.c1
-rw-r--r--drivers/pci/pci_mvebu.c2
-rw-r--r--drivers/pci/pci_rom.c1
-rw-r--r--drivers/pci/pci_tegra.c4
-rw-r--r--drivers/pci/pcie_dw_mvebu.c4
-rw-r--r--drivers/pci/pcie_fsl.c2
-rw-r--r--drivers/pci/pcie_imx.c4
-rw-r--r--drivers/pci/pcie_iproc.c2
-rw-r--r--drivers/pci/pcie_rockchip.c2
-rw-r--r--drivers/phy/bcm6318-usbh-phy.c4
-rw-r--r--drivers/phy/bcm6348-usbh-phy.c4
-rw-r--r--drivers/phy/bcm6368-usbh-phy.c8
-rw-r--r--drivers/pinctrl/Kconfig10
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/aspeed/pinctrl_ast2600.c120
-rw-r--r--drivers/pinctrl/pinctrl-zynqmp.c644
-rw-r--r--drivers/power/domain/zynqmp-power-domain.c29
-rw-r--r--drivers/power/regulator/scmi_regulator.c10
-rw-r--r--drivers/pwm/Kconfig8
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-aspeed.c251
-rw-r--r--drivers/ram/aspeed/Kconfig91
-rw-r--r--drivers/reset/reset-scmi.c4
-rw-r--r--drivers/rtc/Kconfig8
-rw-r--r--drivers/rtc/mcfrtc.c4
-rw-r--r--drivers/serial/Kconfig39
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial-uclass.c26
-rw-r--r--drivers/serial/serial.c2
-rw-r--r--drivers/serial/serial_semihosting.c156
-rw-r--r--drivers/spi/bcm63xx_hsspi.c8
-rw-r--r--drivers/spi/bcm63xx_spi.c4
-rw-r--r--drivers/spi/designware_spi.c2
-rw-r--r--drivers/timer/Kconfig8
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/atmel_tcb_timer.c161
-rw-r--r--drivers/video/Kconfig158
-rw-r--r--drivers/video/Makefile6
-rw-r--r--drivers/video/cfb_console.c1865
-rw-r--r--drivers/video/da8xx-fb.c1048
-rw-r--r--drivers/video/da8xx-fb.h115
-rw-r--r--drivers/video/formike.c513
-rw-r--r--drivers/video/fsl_dcu_fb.c549
-rw-r--r--drivers/video/fsl_diu_fb.c416
-rw-r--r--drivers/video/imx/mxc_ipuv3_fb.c1
-rw-r--r--drivers/video/mxsfb.c90
-rw-r--r--drivers/video/nexell_display.c17
-rw-r--r--drivers/video/omap3_dss.c29
-rw-r--r--drivers/video/sunxi/sunxi_display.c1
-rw-r--r--drivers/video/video-uclass.c2
-rw-r--r--drivers/video/zynqmp_dpsub.c66
-rw-r--r--drivers/watchdog/Kconfig3
112 files changed, 3393 insertions, 5934 deletions
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index bee1cd6..f9f05f4 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -712,7 +712,7 @@ int blk_unbind_all(int if_type)
static int blk_post_probe(struct udevice *dev)
{
- if (IS_ENABLED(CONFIG_PARTITIONS) &&
+ if (CONFIG_IS_ENABLED(PARTITIONS) &&
IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) {
struct blk_desc *desc = dev_get_uclass_plat(dev);
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index 53925ce..1388498 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -125,9 +125,14 @@ int host_dev_bind(int devnum, char *filename, bool removable)
fd = os_open(filename, OS_O_RDWR);
if (fd == -1) {
- printf("Failed to access host backing file '%s'\n", filename);
- ret = -ENOENT;
- goto err;
+ printf("Failed to access host backing file '%s', trying read-only\n",
+ filename);
+ fd = os_open(filename, OS_O_RDONLY);
+ if (fd == -1) {
+ printf("- still failed\n");
+ ret = -ENOENT;
+ goto err;
+ }
}
ret = blk_create_device(gd->dm_root, "sandbox_host_blk", str,
IF_TYPE_HOST, devnum, 512,
diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index 65c052f..66ce4cc 100644
--- a/drivers/bootcount/Kconfig
+++ b/drivers/bootcount/Kconfig
@@ -127,6 +127,13 @@ config DM_BOOTCOUNT_I2C_EEPROM
pointing to the underlying i2c eeprom device) and an optional 'offset'
property are supported.
+config DM_BOOTCOUNT_PMIC_PFUZE100
+ bool "Enable Bootcount driver for PMIC PFUZE100"
+ depends on DM_PMIC_PFUZE100
+ help
+ Enable support for the bootcounter using PMIC PFUZE100 registers.
+ This works only, if the PMIC is not connected.
+
config DM_BOOTCOUNT_SPI_FLASH
bool "Support SPI flash devices as a backing store for bootcount"
depends on DM_SPI_FLASH
diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile
index 3a784bb..b65959a 100644
--- a/drivers/bootcount/Makefile
+++ b/drivers/bootcount/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_BOOTCOUNT_EXT) += bootcount_ext.o
obj-$(CONFIG_BOOTCOUNT_AM33XX_NVMEM) += bootcount_nvmem.o
obj-$(CONFIG_DM_BOOTCOUNT) += bootcount-uclass.o
+obj-$(CONFIG_DM_BOOTCOUNT_PMIC_PFUZE100) += pmic_pfuze100.o
obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o
obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o
obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o
diff --git a/drivers/bootcount/pmic_pfuze100.c b/drivers/bootcount/pmic_pfuze100.c
new file mode 100644
index 0000000..ad3bc03
--- /dev/null
+++ b/drivers/bootcount/pmic_pfuze100.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018-2022 Denx Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ * Philip Oberfichtner <pro@denx.de>
+ *
+ * A bootcount driver using the registers MEMA - MEMD on the PFUZE100.
+ * This works only, if the PMIC is not connected.
+ */
+
+#include <common.h>
+#include <bootcount.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PFUZE_BC_MAGIC 0xdead
+
+struct bootcount_pmic_priv {
+ struct udevice *pmic;
+};
+
+static int pfuze100_get_magic(struct udevice *dev, u32 *magic)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev, PFUZE100_MEMA);
+ if (ret < 0)
+ return ret;
+ *magic = ret;
+
+ ret = pmic_reg_read(dev, PFUZE100_MEMB);
+ if (ret < 0)
+ return ret;
+ *magic += ret << 8;
+
+ return 0;
+}
+
+static int pfuze100_set_magic(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_write(dev, PFUZE100_MEMA, PFUZE_BC_MAGIC & 0xff);
+ if (ret)
+ return ret;
+
+ ret = pmic_reg_write(dev, PFUZE100_MEMB, (PFUZE_BC_MAGIC >> 8) & 0xff);
+ return ret;
+}
+
+static int pfuze100_get_value(struct udevice *dev, u32 *a)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev, PFUZE100_MEMC);
+ if (ret < 0)
+ return ret;
+ *a = ret;
+
+ ret = pmic_reg_read(dev, PFUZE100_MEMD);
+ if (ret < 0)
+ return ret;
+ *a += ret << 8;
+
+ return 0;
+}
+
+static int pfuze100_set_value(struct udevice *dev, u32 val)
+{
+ int ret;
+
+ ret = pmic_reg_write(dev, PFUZE100_MEMC, val & 0xff);
+ if (ret)
+ return ret;
+
+ ret = pmic_reg_write(dev, PFUZE100_MEMD, (val >> 8) & 0xff);
+ return ret;
+}
+
+static int bootcount_pmic_set(struct udevice *dev, const u32 a)
+{
+ struct bootcount_pmic_priv *priv = dev_get_priv(dev);
+
+ if (pfuze100_set_magic(priv->pmic)) {
+ debug("%s: writing magic failed\n", __func__);
+ return -EIO;
+ }
+
+ if (pfuze100_set_value(priv->pmic, a)) {
+ debug("%s: writing value failed\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int bootcount_pmic_get(struct udevice *dev, u32 *a)
+{
+ struct bootcount_pmic_priv *priv = dev_get_priv(dev);
+ u32 magic;
+
+ if (pfuze100_get_magic(priv->pmic, &magic)) {
+ debug("%s: reading magic failed\n", __func__);
+ return -EIO;
+ }
+
+ if (magic != PFUZE_BC_MAGIC) {
+ *a = 0;
+ return 0;
+ }
+
+ if (pfuze100_get_value(priv->pmic, a)) {
+ debug("%s: reading value failed\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int bootcount_pmic_probe(struct udevice *dev)
+{
+ struct ofnode_phandle_args phandle_args;
+ struct bootcount_pmic_priv *priv = dev_get_priv(dev);
+ struct udevice *pmic;
+
+ if (dev_read_phandle_with_args(dev, "pmic", NULL, 0, 0, &phandle_args)) {
+ debug("%s: pmic backing device not specified\n", dev->name);
+ return -ENOENT;
+ }
+
+ if (uclass_get_device_by_ofnode(UCLASS_PMIC, phandle_args.node, &pmic)) {
+ debug("%s: could not get backing device\n", dev->name);
+ return -ENODEV;
+ }
+
+ priv->pmic = pmic;
+
+ return 0;
+}
+
+static const struct bootcount_ops bootcount_pmic_ops = {
+ .get = bootcount_pmic_get,
+ .set = bootcount_pmic_set,
+};
+
+static const struct udevice_id bootcount_pmic_ids[] = {
+ { .compatible = "u-boot,bootcount-pmic" },
+ { }
+};
+
+U_BOOT_DRIVER(bootcount_pmic) = {
+ .name = "bootcount-pmic",
+ .id = UCLASS_BOOTCOUNT,
+ .priv_auto = sizeof(struct bootcount_pmic_priv),
+ .probe = bootcount_pmic_probe,
+ .of_match = bootcount_pmic_ids,
+ .ops = &bootcount_pmic_ops,
+};
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 1fa42d7..2708925 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <asm/io.h>
#include <clk-uclass.h>
+#include <linux/clk-provider.h>
#include "pmc.h"
static int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
@@ -21,60 +22,12 @@ static int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
return 0;
}
-static ulong at91_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong at91_clk_set_rate(struct clk *clk, ulong rate)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int at91_clk_enable(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_enable(c);
-}
-
-static int at91_clk_disable(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_disable(c);
-}
-
const struct clk_ops at91_clk_ops = {
.of_xlate = at91_clk_of_xlate,
- .set_rate = at91_clk_set_rate,
- .get_rate = at91_clk_get_rate,
- .enable = at91_clk_enable,
- .disable = at91_clk_disable,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
/**
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index c20c928..b89c77b 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -138,14 +138,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
{
- struct ofnode_phandle_args args;
- int ret;
-
- ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
- index, &args);
-
- return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
- index, clk);
+ return clk_get_by_index_nodev(dev_ofnode(dev), index, clk);
}
int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
@@ -400,18 +393,7 @@ int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage)
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
{
- int index;
-
- debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
- clk->dev = NULL;
-
- index = dev_read_stringlist_search(dev, "clock-names", name);
- if (index < 0) {
- debug("fdt_stringlist_search() failed: %d\n", index);
- return index;
- }
-
- return clk_get_by_index(dev, index, clk);
+ return clk_get_by_name_nodev(dev_ofnode(dev), name, clk);
}
#endif /* OF_REAL */
@@ -447,9 +429,7 @@ int clk_release_all(struct clk *clk, int count)
if (ret && ret != -ENOSYS)
return ret;
- ret = clk_free(&clk[i]);
- if (ret && ret != -ENOSYS)
- return ret;
+ clk_free(&clk[i]);
}
return 0;
@@ -472,19 +452,18 @@ int clk_request(struct udevice *dev, struct clk *clk)
return ops->request(clk);
}
-int clk_free(struct clk *clk)
+void clk_free(struct clk *clk)
{
const struct clk_ops *ops;
debug("%s(clk=%p)\n", __func__, clk);
if (!clk_valid(clk))
- return 0;
+ return;
ops = clk_dev_ops(clk->dev);
- if (!ops->rfree)
- return 0;
-
- return ops->rfree(clk);
+ if (ops->rfree)
+ ops->rfree(clk);
+ return;
}
ulong clk_get_rate(struct clk *clk)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index eff0fa1..a5a3461 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -74,3 +74,68 @@ bool clk_dev_binded(struct clk *clk)
return false;
}
+
+/* Helper functions for clock ops */
+
+ulong ccf_clk_get_rate(struct clk *clk)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_get_rate(c);
+}
+
+ulong ccf_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_set_rate(c, rate);
+}
+
+int ccf_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk *c, *p;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+
+ err = clk_get_by_id(parent->id, &p);
+ if (err)
+ return err;
+
+ return clk_set_parent(c, p);
+}
+
+static int ccf_clk_endisable(struct clk *clk, bool enable)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return enable ? clk_enable(c) : clk_disable(c);
+}
+
+int ccf_clk_enable(struct clk *clk)
+{
+ return ccf_clk_endisable(clk, true);
+}
+
+int ccf_clk_disable(struct clk *clk)
+{
+ return ccf_clk_endisable(clk, false);
+}
+
+const struct clk_ops ccf_clk_ops = {
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .set_parent = ccf_clk_set_parent,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
+};
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 57acf7d..636914d 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -101,15 +101,15 @@ static int sandbox_clk_request(struct clk *clk)
return 0;
}
-static int sandbox_clk_free(struct clk *clk)
+static void sandbox_clk_free(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id >= SANDBOX_CLK_ID_COUNT)
- return -EINVAL;
+ return;
priv->requested[clk->id] = false;
- return 0;
+ return;
}
static struct clk_ops sandbox_clk_ops = {
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index f665fd3..5807a45 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -137,14 +137,11 @@ int sandbox_clk_test_disable_bulk(struct udevice *dev)
int sandbox_clk_test_free(struct udevice *dev)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
- int i, ret;
+ int i;
devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]);
- for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
- ret = clk_free(&sbct->clks[i]);
- if (ret)
- return ret;
- }
+ for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++)
+ clk_free(&sbct->clks[i]);
return 0;
}
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
index 9a0a6f6..5702268 100644
--- a/drivers/clk/clk_scmi.c
+++ b/drivers/clk/clk_scmi.c
@@ -11,6 +11,52 @@
#include <scmi_agent.h>
#include <scmi_protocols.h>
#include <asm/types.h>
+#include <linux/clk-provider.h>
+
+static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
+{
+ struct scmi_clk_protocol_attr_out out;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
+ .message_id = SCMI_PROTOCOL_ATTRIBUTES,
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ *num_clocks = out.attributes & SCMI_CLK_PROTO_ATTR_COUNT_MASK;
+
+ return 0;
+}
+
+static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
+{
+ struct scmi_clk_attribute_in in = {
+ .clock_id = clkid,
+ };
+ struct scmi_clk_attribute_out out;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
+ .message_id = SCMI_CLOCK_ATTRIBUTES,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ *name = out.clock_name;
+
+ return 0;
+}
static int scmi_clk_gate(struct clk *clk, int enable)
{
@@ -24,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev->parent, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret)
return ret;
@@ -52,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev->parent, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret < 0)
return ret;
@@ -77,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
in, out);
int ret;
- ret = devm_scmi_process_msg(clk->dev->parent, &msg);
+ ret = devm_scmi_process_msg(clk->dev, &msg);
if (ret < 0)
return ret;
@@ -88,6 +134,49 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
return scmi_clk_get_rate(clk);
}
+static int scmi_clk_probe(struct udevice *dev)
+{
+ struct clk *clk;
+ size_t num_clocks, i;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(CLK_CCF))
+ return 0;
+
+ /* register CCF children: CLK UCLASS, no probed again */
+ if (device_get_uclass_id(dev->parent) == UCLASS_CLK)
+ return 0;
+
+ ret = scmi_clk_get_num_clock(dev, &num_clocks);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < num_clocks; i++) {
+ char *name;
+
+ if (!scmi_clk_get_attibute(dev, i, &name)) {
+ char *clock_name = strdup(name);
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk || !clock_name)
+ ret = -ENOMEM;
+ else
+ ret = clk_register(clk, dev->driver->name,
+ clock_name, dev->name);
+
+ if (ret) {
+ free(clk);
+ free(clock_name);
+ return ret;
+ }
+
+ clk_dm(i, clk);
+ }
+ }
+
+ return 0;
+}
+
static const struct clk_ops scmi_clk_ops = {
.enable = scmi_clk_enable,
.disable = scmi_clk_disable,
@@ -99,4 +188,5 @@ U_BOOT_DRIVER(scmi_clock) = {
.name = "scmi_clk",
.id = UCLASS_CLK,
.ops = &scmi_clk_ops,
+ .probe = &scmi_clk_probe,
};
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 5343036..67825af 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -14,79 +14,22 @@
#include "clk.h"
-static int imx6q_check_id(ulong id)
+static int imx6q_clk_request(struct clk *clk)
{
- if (id < IMX6QDL_CLK_DUMMY || id >= IMX6QDL_CLK_END) {
- printf("%s: Invalid clk ID #%lu\n", __func__, id);
+ if (clk->id < IMX6QDL_CLK_DUMMY || clk->id >= IMX6QDL_CLK_END) {
+ printf("%s: Invalid clk ID #%lu\n", __func__, clk->id);
return -EINVAL;
}
return 0;
}
-static ulong imx6q_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = imx6q_check_id(clk->id);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx6q_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- return rate;
-}
-
-static int __imx6q_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret = 0;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = imx6q_check_id(clk->id);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx6q_clk_disable(struct clk *clk)
-{
- return __imx6q_clk_enable(clk, 0);
-}
-
-static int imx6q_clk_enable(struct clk *clk)
-{
- return __imx6q_clk_enable(clk, 1);
-}
-
static struct clk_ops imx6q_clk_ops = {
- .set_rate = imx6q_clk_set_rate,
- .get_rate = imx6q_clk_get_rate,
- .enable = imx6q_clk_enable,
- .disable = imx6q_clk_disable,
+ .request = imx6q_clk_request,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 3aa8c64..443bbda 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -140,92 +140,6 @@ static const char *imx8mm_ecspi2_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sy
static const char *imx8mm_ecspi3_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
"sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
-static ulong imx8mm_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mm_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mm_clk_disable(struct clk *clk)
-{
- return __imx8mm_clk_enable(clk, 0);
-}
-
-static int imx8mm_clk_enable(struct clk *clk)
-{
- return __imx8mm_clk_enable(clk, 1);
-}
-
-static int imx8mm_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mm_clk_ops = {
- .set_rate = imx8mm_clk_set_rate,
- .get_rate = imx8mm_clk_get_rate,
- .enable = imx8mm_clk_enable,
- .disable = imx8mm_clk_disable,
- .set_parent = imx8mm_clk_set_parent,
-};
-
static int imx8mm_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -470,7 +384,7 @@ U_BOOT_DRIVER(imx8mm_clk) = {
.name = "clk_imx8mm",
.id = UCLASS_CLK,
.of_match = imx8mm_clk_ids,
- .ops = &imx8mm_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mm_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index e398d7d..bb62138 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -148,92 +148,6 @@ static const char * const imx8mn_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
-static ulong imx8mn_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mn_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mn_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mn_clk_disable(struct clk *clk)
-{
- return __imx8mn_clk_enable(clk, 0);
-}
-
-static int imx8mn_clk_enable(struct clk *clk)
-{
- return __imx8mn_clk_enable(clk, 1);
-}
-
-static int imx8mn_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mn_clk_ops = {
- .set_rate = imx8mn_clk_set_rate,
- .get_rate = imx8mn_clk_get_rate,
- .enable = imx8mn_clk_enable,
- .disable = imx8mn_clk_disable,
- .set_parent = imx8mn_clk_set_parent,
-};
-
static int imx8mn_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -481,7 +395,7 @@ U_BOOT_DRIVER(imx8mn_clk) = {
.name = "clk_imx8mn",
.id = UCLASS_CLK,
.of_match = imx8mn_clk_ids,
- .ops = &imx8mn_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mn_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index c77500b..ad84ce3 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -186,94 +186,6 @@ static const char *imx8mp_enet_phy_ref_sels[] = {"clock-osc-24m", "sys_pll2_50m"
static const char *imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
-
-static ulong imx8mp_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imx8mp_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imx8mp_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imx8mp_clk_disable(struct clk *clk)
-{
- return __imx8mp_clk_enable(clk, 0);
-}
-
-static int imx8mp_clk_enable(struct clk *clk)
-{
- return __imx8mp_clk_enable(clk, 1);
-}
-
-static int imx8mp_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- ret = clk_set_parent(c, cp);
-
- c->dev->parent = cp->dev;
-
- return ret;
-}
-
-static struct clk_ops imx8mp_clk_ops = {
- .set_rate = imx8mp_clk_set_rate,
- .get_rate = imx8mp_clk_get_rate,
- .enable = imx8mp_clk_enable,
- .disable = imx8mp_clk_disable,
- .set_parent = imx8mp_clk_set_parent,
-};
-
static int imx8mp_clk_probe(struct udevice *dev)
{
void __iomem *base;
@@ -409,7 +321,7 @@ U_BOOT_DRIVER(imx8mp_clk) = {
.name = "clk_imx8mp",
.id = UCLASS_CLK,
.of_match = imx8mp_clk_ids,
- .ops = &imx8mp_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imx8mp_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/imx/clk-imxrt1020.c b/drivers/clk/imx/clk-imxrt1020.c
index 840f783..3f8b4df 100644
--- a/drivers/clk/imx/clk-imxrt1020.c
+++ b/drivers/clk/imx/clk-imxrt1020.c
@@ -14,68 +14,11 @@
#include "clk.h"
-static ulong imxrt1020_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imxrt1020_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imxrt1020_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imxrt1020_clk_disable(struct clk *clk)
-{
- return __imxrt1020_clk_enable(clk, 0);
-}
-
-static int imxrt1020_clk_enable(struct clk *clk)
-{
- return __imxrt1020_clk_enable(clk, 1);
-}
-
static struct clk_ops imxrt1020_clk_ops = {
- .set_rate = imxrt1020_clk_set_rate,
- .get_rate = imxrt1020_clk_get_rate,
- .enable = imxrt1020_clk_enable,
- .disable = imxrt1020_clk_disable,
+ .set_rate = ccf_clk_set_rate,
+ .get_rate = ccf_clk_get_rate,
+ .enable = ccf_clk_enable,
+ .disable = ccf_clk_disable,
};
static const char * const pll2_bypass_sels[] = {"pll2_sys", "osc", };
diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
index 3e17161..5cb5e3b 100644
--- a/drivers/clk/imx/clk-imxrt1050.c
+++ b/drivers/clk/imx/clk-imxrt1050.c
@@ -15,89 +15,6 @@
#include "clk.h"
-static ulong imxrt1050_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu)\n", __func__, clk->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_get_rate(c);
-}
-
-static ulong imxrt1050_clk_set_rate(struct clk *clk, ulong rate)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- return clk_set_rate(c, rate);
-}
-
-static int __imxrt1050_clk_enable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int ret;
-
- debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- if (enable)
- ret = clk_enable(c);
- else
- ret = clk_disable(c);
-
- return ret;
-}
-
-static int imxrt1050_clk_disable(struct clk *clk)
-{
- return __imxrt1050_clk_enable(clk, 0);
-}
-
-static int imxrt1050_clk_enable(struct clk *clk)
-{
- return __imxrt1050_clk_enable(clk, 1);
-}
-
-static int imxrt1050_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *cp;
- int ret;
-
- debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
-
- ret = clk_get_by_id(clk->id, &c);
- if (ret)
- return ret;
-
- ret = clk_get_by_id(parent->id, &cp);
- if (ret)
- return ret;
-
- return clk_set_parent(c, cp);
-}
-
-static struct clk_ops imxrt1050_clk_ops = {
- .set_rate = imxrt1050_clk_set_rate,
- .get_rate = imxrt1050_clk_get_rate,
- .enable = imxrt1050_clk_enable,
- .disable = imxrt1050_clk_disable,
- .set_parent = imxrt1050_clk_set_parent,
-};
-
static const char * const pll_ref_sels[] = {"osc", "dummy", };
static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
@@ -317,7 +234,7 @@ U_BOOT_DRIVER(imxrt1050_clk) = {
.name = "clk_imxrt1050",
.id = UCLASS_CLK,
.of_match = imxrt1050_clk_ids,
- .ops = &imxrt1050_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = imxrt1050_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c
index 05d7647..67828c9 100644
--- a/drivers/clk/microchip/mpfs_clk.c
+++ b/drivers/clk/microchip/mpfs_clk.c
@@ -15,63 +15,6 @@
#include "mpfs_clk.h"
-/* All methods are delegated to CCF clocks */
-
-static ulong mpfs_clk_get_rate(struct clk *clk)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return clk_get_rate(c);
-}
-
-static ulong mpfs_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return clk_set_rate(c, rate);
-}
-
-static int mpfs_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct clk *c, *p;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
-
- err = clk_get_by_id(parent->id, &p);
- if (err)
- return err;
-
- return clk_set_parent(c, p);
-}
-
-static int mpfs_clk_endisable(struct clk *clk, bool enable)
-{
- struct clk *c;
- int err = clk_get_by_id(clk->id, &c);
-
- if (err)
- return err;
- return enable ? clk_enable(c) : clk_disable(c);
-}
-
-static int mpfs_clk_enable(struct clk *clk)
-{
- return mpfs_clk_endisable(clk, true);
-}
-
-static int mpfs_clk_disable(struct clk *clk)
-{
- return mpfs_clk_endisable(clk, false);
-}
-
static int mpfs_clk_probe(struct udevice *dev)
{
int ret;
@@ -100,14 +43,6 @@ static int mpfs_clk_probe(struct udevice *dev)
return ret;
}
-static const struct clk_ops mpfs_clk_ops = {
- .set_rate = mpfs_clk_set_rate,
- .get_rate = mpfs_clk_get_rate,
- .set_parent = mpfs_clk_set_parent,
- .enable = mpfs_clk_enable,
- .disable = mpfs_clk_disable,
-};
-
static const struct udevice_id mpfs_of_match[] = {
{ .compatible = "microchip,mpfs-clkcfg" },
{ }
@@ -117,7 +52,7 @@ U_BOOT_DRIVER(mpfs_clk) = {
.name = "mpfs_clk",
.id = UCLASS_CLK,
.of_match = mpfs_of_match,
- .ops = &mpfs_clk_ops,
+ .ops = &ccf_clk_ops,
.probe = mpfs_clk_probe,
.priv_auto = sizeof(struct clk),
.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 8f7703c..5c34004 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -77,6 +77,16 @@ config DM_DEVICE_REMOVE
it causes unplugged devices to linger around in the dm-tree, and it
causes USB host controllers to not be stopped when booting the OS.
+config DM_EVENT
+ bool "Support events with driver model"
+ depends on DM
+ imply EVENT
+ default y if SANDBOX
+ help
+ This enables support for generating events related to driver model
+ operations, such as prbing or removing a device. Subsystems can
+ register a 'spy' function that is called when the event occurs.
+
config SPL_DM_DEVICE_REMOVE
bool "Support device removal in SPL"
depends on SPL_DM
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index e6ec6ff..73d2e9e 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -207,6 +207,10 @@ int device_remove(struct udevice *dev, uint flags)
if (!(dev_get_flags(dev) & DM_FLAG_ACTIVATED))
return 0;
+ ret = device_notify(dev, EVT_DM_PRE_REMOVE);
+ if (ret)
+ return ret;
+
/*
* If the child returns EKEYREJECTED, continue. It just means that it
* didn't match the flags.
@@ -256,6 +260,10 @@ int device_remove(struct udevice *dev, uint flags)
dev_bic_flags(dev, DM_FLAG_ACTIVATED);
+ ret = device_notify(dev, EVT_DM_POST_REMOVE);
+ if (ret)
+ goto err_remove;
+
return 0;
err_remove:
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 901c1e2..1b356f1 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <event.h>
#include <log.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -493,6 +494,10 @@ int device_probe(struct udevice *dev)
if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
return 0;
+ ret = device_notify(dev, EVT_DM_PRE_PROBE);
+ if (ret)
+ return ret;
+
drv = dev->driver;
assert(drv);
@@ -597,6 +602,10 @@ int device_probe(struct udevice *dev)
dev->name, ret, errno_str(ret));
}
+ ret = device_notify(dev, EVT_DM_POST_PROBE);
+ if (ret)
+ return ret;
+
return 0;
fail_uclass:
if (device_remove(dev, DM_REMOVE_NORMAL)) {
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 709bea2..8042847 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -898,6 +898,42 @@ int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
return -ENOENT;
}
+int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
+{
+ const char *list, *end;
+ int len;
+
+ list = ofnode_get_property(node, "compatible", &len);
+
+ if (!list)
+ return -ENOENT;
+
+ end = list + len;
+ while (list < end) {
+ len = strlen(list);
+
+ if (len >= strlen("ethernet-phy-idVVVV,DDDD")) {
+ char *s = strstr(list, "ethernet-phy-id");
+
+ /*
+ * check if the string is something like
+ * ethernet-phy-idVVVV,DDDD
+ */
+ if (s && s[19] == '.') {
+ s += strlen("ethernet-phy-id");
+ *vendor = simple_strtol(s, NULL, 16);
+ s += 5;
+ *device = simple_strtol(s, NULL, 16);
+
+ return 0;
+ }
+ }
+ list += (len + 1);
+ }
+
+ return -ENOENT;
+}
+
int ofnode_read_addr_cells(ofnode node)
{
if (ofnode_is_np(node)) {
diff --git a/drivers/core/root.c b/drivers/core/root.c
index e3f8795..8efb425 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -404,6 +404,11 @@ int dm_init_and_scan(bool pre_reloc_only)
return ret;
}
}
+ if (CONFIG_IS_ENABLED(DM_EVENT)) {
+ ret = event_notify_null(EVT_DM_POST_INIT);
+ if (ret)
+ return log_msg_ret("ev", ret);
+ }
return 0;
}
diff --git a/drivers/ddr/fsl/Kconfig b/drivers/ddr/fsl/Kconfig
index b0e6df8..2771670 100644
--- a/drivers/ddr/fsl/Kconfig
+++ b/drivers/ddr/fsl/Kconfig
@@ -49,6 +49,10 @@ config SYS_NUM_DDR_CTLRS
ARCH_LX2162A
default 1
+config CHIP_SELECTS_PER_CTRL
+ int "Number of chip selects per controller"
+ default 4
+
config SYS_FSL_DDR_VER
int
default 50 if SYS_FSL_DDR_VER_50
diff --git a/drivers/ddr/marvell/axp/ddr3_axp.h b/drivers/ddr/marvell/axp/ddr3_axp.h
index 970651f..a14c766 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp.h
@@ -37,7 +37,7 @@
#define ECC_SUPPORT
#endif
#define NEW_FABRIC_TWSI_ADDR 0x4E
-#ifdef CONFIG_DB_784MP_GP
+#ifdef CONFIG_TARGET_DB_MV784MP_GP
#define BUS_WIDTH_ECC_TWSI_ADDR 0x4E
#else
#define BUS_WIDTH_ECC_TWSI_ADDR 0x4F
diff --git a/drivers/ddr/marvell/axp/ddr3_axp_config.h b/drivers/ddr/marvell/axp/ddr3_axp_config.h
index 437a02e..ab09e726 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp_config.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp_config.h
@@ -138,7 +138,7 @@
* Enables I2C auto detection different options
*/
#if defined(CONFIG_DB_88F78X60) || defined(CONFIG_DB_88F78X60_REV2) || \
- defined(CONFIG_DB_784MP_GP)
+ defined(CONFIG_TARGET_DB_MV784MP_GP)
#define AUTO_DETECTION_SUPPORT
#endif
#endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 9cacea8..0af5460 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -68,6 +68,13 @@ config APBH_DMA
help
Enable APBH DMA driver.
+config XILINX_DPDMA
+ bool "Enable ZynqMP Display Port DMA driver"
+ depends on DMA && ZYNQMP_POWER_DOMAIN
+ help
+ Enable support for Xilinx ZynqMP Display DMA driver. Currently
+ this file is used as placeholder for driver. The main reason is
+ to record compatible string and calling power domain driver.
if APBH_DMA
config APBH_DMA_BURST
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index afab324..a75572f 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -13,5 +13,6 @@ obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
+obj-$(CONFIG_XILINX_DPDMA) += xilinx_dpdma.o
obj-y += ti/
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
index c04aa55..4fc6502 100644
--- a/drivers/dma/bcm6348-iudma.c
+++ b/drivers/dma/bcm6348-iudma.c
@@ -596,11 +596,7 @@ static int bcm6348_iudma_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("error freeing clock %d\n", i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/dma/xilinx_dpdma.c b/drivers/dma/xilinx_dpdma.c
new file mode 100644
index 0000000..d4ee21d
--- /dev/null
+++ b/drivers/dma/xilinx_dpdma.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Xilinx Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <dma.h>
+#include <dma-uclass.h>
+#include <errno.h>
+#include <dm/device_compat.h>
+
+/**
+ * struct zynqmp_dpdma_priv - Private structure
+ * @dev: Device uclass for video_ops
+ */
+struct zynqmp_dpdma_priv {
+ struct udevice *dev;
+};
+
+static int zynqmp_dpdma_probe(struct udevice *dev)
+{
+ /* Only placeholder for power domain driver */
+ return 0;
+}
+
+static const struct dma_ops zynqmp_dpdma_ops = {
+};
+
+static const struct udevice_id zynqmp_dpdma_ids[] = {
+ { .compatible = "xlnx,zynqmp-dpdma" },
+ { }
+};
+
+U_BOOT_DRIVER(zynqmp_dpdma) = {
+ .name = "zynqmp_dpdma",
+ .id = UCLASS_DMA,
+ .of_match = zynqmp_dpdma_ids,
+ .ops = &zynqmp_dpdma_ops,
+ .probe = zynqmp_dpdma_probe,
+ .priv_auto = sizeof(struct zynqmp_dpdma_priv),
+};
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index 8d8492d..8916c55 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -140,6 +140,57 @@ unsigned int zynqmp_firmware_version(void)
return pm_api_version;
};
+int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
+{
+ int ret;
+
+ ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_SD_CONFIG,
+ config, value, NULL);
+ if (ret)
+ printf("%s: node %d: set_sd_config %d failed\n",
+ __func__, node, config);
+
+ return ret;
+}
+
+int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
+{
+ int ret;
+ u32 *bit_mask;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ /* Input arguments validation */
+ if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
+ return -EINVAL;
+
+ /* Check feature check API version */
+ ret = xilinx_pm_request(PM_FEATURE_CHECK, PM_FEATURE_CHECK, 0, 0, 0,
+ ret_payload);
+ if (ret)
+ return ret;
+
+ /* Check if feature check version 2 is supported or not */
+ if ((ret_payload[1] & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
+ /*
+ * Call feature check for IOCTL/QUERY API to get IOCTL ID or
+ * QUERY ID feature status.
+ */
+
+ ret = xilinx_pm_request(PM_FEATURE_CHECK, api_id, 0, 0, 0,
+ ret_payload);
+ if (ret)
+ return ret;
+
+ bit_mask = &ret_payload[2];
+ if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0)
+ return -EOPNOTSUPP;
+ } else {
+ return -ENODATA;
+ }
+
+ return 0;
+}
+
/**
* Send a configuration object to the PMU firmware.
*
diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
index 4b96820..c555164 100644
--- a/drivers/firmware/scmi/sandbox-scmi_agent.c
+++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
@@ -19,51 +19,36 @@
* The sandbox SCMI agent driver simulates to some extend a SCMI message
* processing. It simulates few of the SCMI services for some of the
* SCMI protocols embedded in U-Boot. Currently:
- * - SCMI clock protocol: emulate 2 agents each exposing few clocks
- * - SCMI reset protocol: emulate 1 agent exposing a reset controller
- * - SCMI voltage domain protocol: emulate 1 agent exposing 2 regulators
+ * - SCMI clock protocol emulates an agent exposing 2 clocks
+ * - SCMI reset protocol emulates an agent exposing a reset controller
+ * - SCMI voltage domain protocol emulates an agent exposing 2 regulators
*
- * Agent #0 simulates 2 clocks, 1 reset domain and 1 voltage domain.
- * See IDs in scmi0_clk[]/scmi0_reset[] and "sandbox-scmi-agent@0" in test.dts.
- *
- * Agent #1 simulates 1 clock.
- * See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts.
+ * As per DT bindings, the device node name shall be scmi.
*
* All clocks and regulators are default disabled and reset controller down.
*
- * This Driver exports sandbox_scmi_service_ctx() for the test sequence to
+ * This driver exports sandbox_scmi_service_ctx() for the test sequence to
* get the state of the simulated services (clock state, rate, ...) and
* check back-end device state reflects the request send through the
* various uclass devices, as clocks and reset controllers.
*/
-#define SANDBOX_SCMI_AGENT_COUNT 2
-
-static struct sandbox_scmi_clk scmi0_clk[] = {
- { .id = 7, .rate = 1000 },
- { .id = 3, .rate = 333 },
+static struct sandbox_scmi_clk scmi_clk[] = {
+ { .rate = 333 },
+ { .rate = 200 },
+ { .rate = 1000 },
};
-static struct sandbox_scmi_reset scmi0_reset[] = {
+static struct sandbox_scmi_reset scmi_reset[] = {
{ .id = 3 },
};
-static struct sandbox_scmi_voltd scmi0_voltd[] = {
+static struct sandbox_scmi_voltd scmi_voltd[] = {
{ .id = 0, .voltage_uv = 3300000 },
{ .id = 1, .voltage_uv = 1800000 },
};
-static struct sandbox_scmi_clk scmi1_clk[] = {
- { .id = 1, .rate = 44 },
-};
-
-/* The list saves to simulted end devices references for test purpose */
-struct sandbox_scmi_agent *sandbox_scmi_agent_list[SANDBOX_SCMI_AGENT_COUNT];
-
-static struct sandbox_scmi_service sandbox_scmi_service_state = {
- .agent = sandbox_scmi_agent_list,
- .agent_count = SANDBOX_SCMI_AGENT_COUNT,
-};
+static struct sandbox_scmi_service sandbox_scmi_service_state;
struct sandbox_scmi_service *sandbox_scmi_service_ctx(void)
{
@@ -74,9 +59,8 @@ static void debug_print_agent_state(struct udevice *dev, char *str)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
- dev_dbg(dev, "Dump sandbox_scmi_agent %u: %s\n", agent->idx, str);
- dev_dbg(dev, " scmi%u_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n",
- agent->idx,
+ dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str);
+ dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n",
agent->clk_count,
agent->clk_count ? agent->clk[0].enabled : -1,
agent->clk_count ? agent->clk[0].rate : -1,
@@ -84,13 +68,11 @@ static void debug_print_agent_state(struct udevice *dev, char *str)
agent->clk_count > 1 ? agent->clk[1].rate : -1,
agent->clk_count > 2 ? agent->clk[2].enabled : -1,
agent->clk_count > 2 ? agent->clk[2].rate : -1);
- dev_dbg(dev, " scmi%u_reset (%zu): %d, %d, ...\n",
- agent->idx,
+ dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n",
agent->reset_count,
agent->reset_count ? agent->reset[0].asserted : -1,
agent->reset_count > 1 ? agent->reset[1].asserted : -1);
- dev_dbg(dev, " scmi%u_voltd (%zu): %u/%d, %u/%d, ...\n",
- agent->idx,
+ dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n",
agent->voltd_count,
agent->voltd_count ? agent->voltd[0].enabled : -1,
agent->voltd_count ? agent->voltd[0].voltage_uv : -1,
@@ -98,56 +80,32 @@ static void debug_print_agent_state(struct udevice *dev, char *str)
agent->voltd_count ? agent->voltd[1].voltage_uv : -1);
};
-static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id)
+static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id)
{
- struct sandbox_scmi_clk *target = NULL;
- size_t target_count = 0;
- size_t n;
-
- switch (agent_id) {
- case 0:
- target = scmi0_clk;
- target_count = ARRAY_SIZE(scmi0_clk);
- break;
- case 1:
- target = scmi1_clk;
- target_count = ARRAY_SIZE(scmi1_clk);
- break;
- default:
- return NULL;
- }
-
- for (n = 0; n < target_count; n++)
- if (target[n].id == clock_id)
- return target + n;
+ if (clock_id < ARRAY_SIZE(scmi_clk))
+ return scmi_clk + clock_id;
return NULL;
}
-static struct sandbox_scmi_reset *get_scmi_reset_state(uint agent_id,
- uint reset_id)
+static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id)
{
size_t n;
- if (agent_id == 0) {
- for (n = 0; n < ARRAY_SIZE(scmi0_reset); n++)
- if (scmi0_reset[n].id == reset_id)
- return scmi0_reset + n;
- }
+ for (n = 0; n < ARRAY_SIZE(scmi_reset); n++)
+ if (scmi_reset[n].id == reset_id)
+ return scmi_reset + n;
return NULL;
}
-static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id,
- uint domain_id)
+static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id)
{
size_t n;
- if (agent_id == 0) {
- for (n = 0; n < ARRAY_SIZE(scmi0_voltd); n++)
- if (scmi0_voltd[n].id == domain_id)
- return scmi0_voltd + n;
- }
+ for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++)
+ if (scmi_voltd[n].id == domain_id)
+ return scmi_voltd + n;
return NULL;
}
@@ -156,10 +114,58 @@ static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id,
* Sandbox SCMI agent ops
*/
+static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
+ struct scmi_msg *msg)
+{
+ struct scmi_clk_protocol_attr_out *out = NULL;
+
+ if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ out = (struct scmi_clk_protocol_attr_out *)msg->out_msg;
+ out->attributes = ARRAY_SIZE(scmi_clk);
+ out->status = SCMI_SUCCESS;
+
+ return 0;
+}
+
+static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg)
+{
+ struct scmi_clk_attribute_in *in = NULL;
+ struct scmi_clk_attribute_out *out = NULL;
+ struct sandbox_scmi_clk *clk_state = NULL;
+ int ret;
+
+ if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
+ !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+ return -EINVAL;
+
+ in = (struct scmi_clk_attribute_in *)msg->in_msg;
+ out = (struct scmi_clk_attribute_out *)msg->out_msg;
+
+ clk_state = get_scmi_clk_state(in->clock_id);
+ if (!clk_state) {
+ dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
+
+ out->status = SCMI_NOT_FOUND;
+ } else {
+ memset(out, 0, sizeof(*out));
+
+ if (clk_state->enabled)
+ out->attributes = 1;
+
+ ret = snprintf(out->clock_name, sizeof(out->clock_name),
+ "clk%u", in->clock_id);
+ assert(ret > 0 && ret < sizeof(out->clock_name));
+
+ out->status = SCMI_SUCCESS;
+ }
+
+ return 0;
+}
static int sandbox_scmi_clock_rate_set(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_clk_rate_set_in *in = NULL;
struct scmi_clk_rate_set_out *out = NULL;
struct sandbox_scmi_clk *clk_state = NULL;
@@ -171,7 +177,7 @@ static int sandbox_scmi_clock_rate_set(struct udevice *dev,
in = (struct scmi_clk_rate_set_in *)msg->in_msg;
out = (struct scmi_clk_rate_set_out *)msg->out_msg;
- clk_state = get_scmi_clk_state(agent->idx, in->clock_id);
+ clk_state = get_scmi_clk_state(in->clock_id);
if (!clk_state) {
dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
@@ -190,7 +196,6 @@ static int sandbox_scmi_clock_rate_set(struct udevice *dev,
static int sandbox_scmi_clock_rate_get(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_clk_rate_get_in *in = NULL;
struct scmi_clk_rate_get_out *out = NULL;
struct sandbox_scmi_clk *clk_state = NULL;
@@ -202,7 +207,7 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev,
in = (struct scmi_clk_rate_get_in *)msg->in_msg;
out = (struct scmi_clk_rate_get_out *)msg->out_msg;
- clk_state = get_scmi_clk_state(agent->idx, in->clock_id);
+ clk_state = get_scmi_clk_state(in->clock_id);
if (!clk_state) {
dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
@@ -219,7 +224,6 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev,
static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_clk_state_in *in = NULL;
struct scmi_clk_state_out *out = NULL;
struct sandbox_scmi_clk *clk_state = NULL;
@@ -231,7 +235,7 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
in = (struct scmi_clk_state_in *)msg->in_msg;
out = (struct scmi_clk_state_out *)msg->out_msg;
- clk_state = get_scmi_clk_state(agent->idx, in->clock_id);
+ clk_state = get_scmi_clk_state(in->clock_id);
if (!clk_state) {
dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
@@ -249,7 +253,6 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_rd_attr_in *in = NULL;
struct scmi_rd_attr_out *out = NULL;
struct sandbox_scmi_reset *reset_state = NULL;
@@ -261,7 +264,7 @@ static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
in = (struct scmi_rd_attr_in *)msg->in_msg;
out = (struct scmi_rd_attr_out *)msg->out_msg;
- reset_state = get_scmi_reset_state(agent->idx, in->domain_id);
+ reset_state = get_scmi_reset_state(in->domain_id);
if (!reset_state) {
dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
@@ -278,7 +281,6 @@ static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_rd_reset_in *in = NULL;
struct scmi_rd_reset_out *out = NULL;
struct sandbox_scmi_reset *reset_state = NULL;
@@ -290,7 +292,7 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
in = (struct scmi_rd_reset_in *)msg->in_msg;
out = (struct scmi_rd_reset_out *)msg->out_msg;
- reset_state = get_scmi_reset_state(agent->idx, in->domain_id);
+ reset_state = get_scmi_reset_state(in->domain_id);
if (!reset_state) {
dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id);
@@ -321,7 +323,6 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_attr_in *in = NULL;
struct scmi_voltd_attr_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
@@ -333,7 +334,7 @@ static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
in = (struct scmi_voltd_attr_in *)msg->in_msg;
out = (struct scmi_voltd_attr_out *)msg->out_msg;
- voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
+ voltd_state = get_scmi_voltd_state(in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
@@ -351,7 +352,6 @@ static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
static int sandbox_scmi_voltd_config_set(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_config_set_in *in = NULL;
struct scmi_voltd_config_set_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
@@ -363,7 +363,7 @@ static int sandbox_scmi_voltd_config_set(struct udevice *dev,
in = (struct scmi_voltd_config_set_in *)msg->in_msg;
out = (struct scmi_voltd_config_set_out *)msg->out_msg;
- voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
+ voltd_state = get_scmi_voltd_state(in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
@@ -388,7 +388,6 @@ static int sandbox_scmi_voltd_config_set(struct udevice *dev,
static int sandbox_scmi_voltd_config_get(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_config_get_in *in = NULL;
struct scmi_voltd_config_get_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
@@ -400,7 +399,7 @@ static int sandbox_scmi_voltd_config_get(struct udevice *dev,
in = (struct scmi_voltd_config_get_in *)msg->in_msg;
out = (struct scmi_voltd_config_get_out *)msg->out_msg;
- voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
+ voltd_state = get_scmi_voltd_state(in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
@@ -420,7 +419,6 @@ static int sandbox_scmi_voltd_config_get(struct udevice *dev,
static int sandbox_scmi_voltd_level_set(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_level_set_in *in = NULL;
struct scmi_voltd_level_set_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
@@ -432,7 +430,7 @@ static int sandbox_scmi_voltd_level_set(struct udevice *dev,
in = (struct scmi_voltd_level_set_in *)msg->in_msg;
out = (struct scmi_voltd_level_set_out *)msg->out_msg;
- voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
+ voltd_state = get_scmi_voltd_state(in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
@@ -448,7 +446,6 @@ static int sandbox_scmi_voltd_level_set(struct udevice *dev,
static int sandbox_scmi_voltd_level_get(struct udevice *dev,
struct scmi_msg *msg)
{
- struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_level_get_in *in = NULL;
struct scmi_voltd_level_get_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
@@ -460,7 +457,7 @@ static int sandbox_scmi_voltd_level_get(struct udevice *dev,
in = (struct scmi_voltd_level_get_in *)msg->in_msg;
out = (struct scmi_voltd_level_get_out *)msg->out_msg;
- voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
+ voltd_state = get_scmi_voltd_state(in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
@@ -479,6 +476,10 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
switch (msg->protocol_id) {
case SCMI_PROTOCOL_ID_CLOCK:
switch (msg->message_id) {
+ case SCMI_PROTOCOL_ATTRIBUTES:
+ return sandbox_scmi_clock_protocol_attribs(dev, msg);
+ case SCMI_CLOCK_ATTRIBUTES:
+ return sandbox_scmi_clock_attribs(dev, msg);
case SCMI_CLOCK_RATE_SET:
return sandbox_scmi_clock_rate_set(dev, msg);
case SCMI_CLOCK_RATE_GET:
@@ -541,52 +542,37 @@ static int sandbox_scmi_test_remove(struct udevice *dev)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
+ if (agent != sandbox_scmi_service_ctx()->agent)
+ return -EINVAL;
+
debug_print_agent_state(dev, "removed");
/* We only need to dereference the agent in the context */
- sandbox_scmi_service_ctx()->agent[agent->idx] = NULL;
+ sandbox_scmi_service_ctx()->agent = NULL;
return 0;
}
static int sandbox_scmi_test_probe(struct udevice *dev)
{
- static const char basename[] = "sandbox-scmi-agent@";
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
- const size_t basename_size = sizeof(basename) - 1;
-
- if (strncmp(basename, dev->name, basename_size))
- return -ENOENT;
-
- switch (dev->name[basename_size]) {
- case '0':
- *agent = (struct sandbox_scmi_agent){
- .idx = 0,
- .clk = scmi0_clk,
- .clk_count = ARRAY_SIZE(scmi0_clk),
- .reset = scmi0_reset,
- .reset_count = ARRAY_SIZE(scmi0_reset),
- .voltd = scmi0_voltd,
- .voltd_count = ARRAY_SIZE(scmi0_voltd),
- };
- break;
- case '1':
- *agent = (struct sandbox_scmi_agent){
- .idx = 1,
- .clk = scmi1_clk,
- .clk_count = ARRAY_SIZE(scmi1_clk),
- };
- break;
- default:
- dev_err(dev, "%s(): Unexpected agent ID %s\n",
- __func__, dev->name + basename_size);
- return -ENOENT;
- }
+
+ if (sandbox_scmi_service_ctx()->agent)
+ return -EINVAL;
+
+ *agent = (struct sandbox_scmi_agent){
+ .clk = scmi_clk,
+ .clk_count = ARRAY_SIZE(scmi_clk),
+ .reset = scmi_reset,
+ .reset_count = ARRAY_SIZE(scmi_reset),
+ .voltd = scmi_voltd,
+ .voltd_count = ARRAY_SIZE(scmi_voltd),
+ };
debug_print_agent_state(dev, "probed");
/* Save reference for tests purpose */
- sandbox_scmi_service_ctx()->agent[agent->idx] = agent;
+ sandbox_scmi_service_ctx()->agent = agent;
return 0;
};
diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c
index 66a6792..9baeb46 100644
--- a/drivers/firmware/scmi/sandbox-scmi_devices.c
+++ b/drivers/firmware/scmi/sandbox-scmi_devices.c
@@ -23,7 +23,7 @@
* and reset controllers.
*/
-#define SCMI_TEST_DEVICES_CLK_COUNT 3
+#define SCMI_TEST_DEVICES_CLK_COUNT 2
#define SCMI_TEST_DEVICES_RD_COUNT 1
#define SCMI_TEST_DEVICES_VOLTD_COUNT 2
@@ -135,7 +135,7 @@ U_BOOT_DRIVER(sandbox_scmi_devices) = {
.name = "sandbox-scmi_devices",
.id = UCLASS_MISC,
.of_match = sandbox_scmi_devices_ids,
- .priv_auto = sizeof(struct sandbox_scmi_device_priv),
+ .priv_auto = sizeof(struct sandbox_scmi_device_priv),
.remove = sandbox_scmi_devices_remove,
.probe = sandbox_scmi_devices_probe,
};
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 4f5870b..3819f2f 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -116,10 +116,23 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
{
- const struct scmi_agent_ops *ops = transport_dev_ops(dev);
+ const struct scmi_agent_ops *ops;
+ struct udevice *parent = dev;
+
+ /* Find related SCMI agent device */
+ do {
+ parent = dev_get_parent(parent);
+ } while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT);
+
+ if (!parent) {
+ dev_err(dev, "Invalid SCMI device, agent not found\n");
+ return -ENODEV;
+ }
+
+ ops = transport_dev_ops(parent);
if (ops->process_msg)
- return ops->process_msg(dev, msg);
+ return ops->process_msg(parent, msg);
return -EPROTONOSUPPORT;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 522dfc1..a55e368 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -84,10 +84,15 @@ config ALTERA_PIO
Select this to enable PIO for Altera devices. Please find
details on the "Embedded Peripherals IP User Guide" of Altera.
+config BCM2835_GPIO
+ bool "BCM2835 GPIO driver"
+ depends on DM_GPIO
+
config BCM6345_GPIO
bool "BCM6345 GPIO driver"
depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM68360 || \
- ARCH_BCM6858 || ARCH_BCM63158)
+ ARCH_BCM6858 || ARCH_BCM63158 || \
+ ARCH_BCM6753)
help
This driver supports the GPIO banks on BCM6345 SoCs.
@@ -126,6 +131,13 @@ config ATMEL_PIO4
may be dedicated as a general purpose I/O or be assigned to
a function of an embedded peripheral.
+config ASPEED_GPIO
+ bool "Aspeed GPIO Driver"
+ help
+ Say yes here to support the Aspeed GPIO driver. The controller
+ is found in the AST2400, AST2500 and AST2600 BMC SoCs and
+ provides access to over 200 GPIOs on each chip.
+
config DA8XX_GPIO
bool "DA8xx GPIO Driver"
help
@@ -550,4 +562,12 @@ config SL28CPLD_GPIO
help
Support GPIO access on Kontron sl28cpld board management controllers.
+config SLG7XL45106_I2C_GPO
+ bool "slg7xl45106 i2c gpo expander"
+ depends on DM_GPIO
+ help
+ Support for slg7xl45106 i2c gpo expander. It is an i2c based
+ 8-bit gpo expander, all gpo lines are controlled by writing
+ value into data register.
+
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 33f7d41..b39dde1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o
obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o
+obj-$(CONFIG_ASPEED_GPIO) += gpio-aspeed.o
obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o
obj-$(CONFIG_BCM6345_GPIO) += bcm6345_gpio.o
@@ -72,3 +73,4 @@ obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
+obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
new file mode 100644
index 0000000..a8a2afc
--- /dev/null
+++ b/drivers/gpio/gpio-aspeed.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2015 IBM Corp.
+ * Joel Stanley <joel@jms.id.au>
+ * Ryan Chen <ryan_chen@aspeedtech.com>
+ *
+ * Implementation extracted from the Linux kernel and adapted for u-boot.
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#include <config.h>
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/bug.h>
+#include <linux/sizes.h>
+
+struct aspeed_gpio_priv {
+ void *regs;
+};
+
+struct aspeed_gpio_bank {
+ u16 val_regs; /* +0: Rd: read input value, Wr: set write latch
+ * +4: Rd/Wr: Direction (0=in, 1=out)
+ */
+ u16 rdata_reg; /* Rd: read write latch, Wr: <none> */
+ u16 irq_regs;
+ u16 debounce_regs;
+ u16 tolerance_regs;
+ u16 cmdsrc_regs;
+ const char names[4][3];
+};
+
+static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
+ {
+ .val_regs = 0x0000,
+ .rdata_reg = 0x00c0,
+ .irq_regs = 0x0008,
+ .debounce_regs = 0x0040,
+ .tolerance_regs = 0x001c,
+ .cmdsrc_regs = 0x0060,
+ .names = { "A", "B", "C", "D" },
+ },
+ {
+ .val_regs = 0x0020,
+ .rdata_reg = 0x00c4,
+ .irq_regs = 0x0028,
+ .debounce_regs = 0x0048,
+ .tolerance_regs = 0x003c,
+ .cmdsrc_regs = 0x0068,
+ .names = { "E", "F", "G", "H" },
+ },
+ {
+ .val_regs = 0x0070,
+ .rdata_reg = 0x00c8,
+ .irq_regs = 0x0098,
+ .debounce_regs = 0x00b0,
+ .tolerance_regs = 0x00ac,
+ .cmdsrc_regs = 0x0090,
+ .names = { "I", "J", "K", "L" },
+ },
+ {
+ .val_regs = 0x0078,
+ .rdata_reg = 0x00cc,
+ .irq_regs = 0x00e8,
+ .debounce_regs = 0x0100,
+ .tolerance_regs = 0x00fc,
+ .cmdsrc_regs = 0x00e0,
+ .names = { "M", "N", "O", "P" },
+ },
+ {
+ .val_regs = 0x0080,
+ .rdata_reg = 0x00d0,
+ .irq_regs = 0x0118,
+ .debounce_regs = 0x0130,
+ .tolerance_regs = 0x012c,
+ .cmdsrc_regs = 0x0110,
+ .names = { "Q", "R", "S", "T" },
+ },
+ {
+ .val_regs = 0x0088,
+ .rdata_reg = 0x00d4,
+ .irq_regs = 0x0148,
+ .debounce_regs = 0x0160,
+ .tolerance_regs = 0x015c,
+ .cmdsrc_regs = 0x0140,
+ .names = { "U", "V", "W", "X" },
+ },
+ {
+ .val_regs = 0x01E0,
+ .rdata_reg = 0x00d8,
+ .irq_regs = 0x0178,
+ .debounce_regs = 0x0190,
+ .tolerance_regs = 0x018c,
+ .cmdsrc_regs = 0x0170,
+ .names = { "Y", "Z", "AA", "AB" },
+ },
+ {
+ .val_regs = 0x01e8,
+ .rdata_reg = 0x00dc,
+ .irq_regs = 0x01a8,
+ .debounce_regs = 0x01c0,
+ .tolerance_regs = 0x01bc,
+ .cmdsrc_regs = 0x01a0,
+ .names = { "AC", "", "", "" },
+ },
+};
+
+enum aspeed_gpio_reg {
+ reg_val,
+ reg_rdata,
+ reg_dir,
+ reg_irq_enable,
+ reg_irq_type0,
+ reg_irq_type1,
+ reg_irq_type2,
+ reg_irq_status,
+ reg_debounce_sel1,
+ reg_debounce_sel2,
+ reg_tolerance,
+ reg_cmdsrc0,
+ reg_cmdsrc1,
+};
+
+#define GPIO_VAL_VALUE 0x00
+#define GPIO_VAL_DIR 0x04
+
+#define GPIO_IRQ_ENABLE 0x00
+#define GPIO_IRQ_TYPE0 0x04
+#define GPIO_IRQ_TYPE1 0x08
+#define GPIO_IRQ_TYPE2 0x0c
+#define GPIO_IRQ_STATUS 0x10
+
+#define GPIO_DEBOUNCE_SEL1 0x00
+#define GPIO_DEBOUNCE_SEL2 0x04
+
+#define GPIO_CMDSRC_0 0x00
+#define GPIO_CMDSRC_1 0x04
+#define GPIO_CMDSRC_ARM 0
+#define GPIO_CMDSRC_LPC 1
+#define GPIO_CMDSRC_COLDFIRE 2
+#define GPIO_CMDSRC_RESERVED 3
+
+/* This will be resolved at compile time */
+static inline void __iomem *bank_reg(struct aspeed_gpio_priv *gpio,
+ const struct aspeed_gpio_bank *bank,
+ const enum aspeed_gpio_reg reg)
+{
+ switch (reg) {
+ case reg_val:
+ return gpio->regs + bank->val_regs + GPIO_VAL_VALUE;
+ case reg_rdata:
+ return gpio->regs + bank->rdata_reg;
+ case reg_dir:
+ return gpio->regs + bank->val_regs + GPIO_VAL_DIR;
+ case reg_irq_enable:
+ return gpio->regs + bank->irq_regs + GPIO_IRQ_ENABLE;
+ case reg_irq_type0:
+ return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE0;
+ case reg_irq_type1:
+ return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE1;
+ case reg_irq_type2:
+ return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE2;
+ case reg_irq_status:
+ return gpio->regs + bank->irq_regs + GPIO_IRQ_STATUS;
+ case reg_debounce_sel1:
+ return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL1;
+ case reg_debounce_sel2:
+ return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL2;
+ case reg_tolerance:
+ return gpio->regs + bank->tolerance_regs;
+ case reg_cmdsrc0:
+ return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_0;
+ case reg_cmdsrc1:
+ return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_1;
+ }
+ BUG();
+}
+
+#define GPIO_BANK(x) ((x) >> 5)
+#define GPIO_OFFSET(x) ((x) & 0x1f)
+#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
+
+static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
+{
+ unsigned int bank = GPIO_BANK(offset);
+
+ WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks));
+ return &aspeed_gpio_banks[bank];
+}
+
+static int
+aspeed_gpio_direction_input(struct udevice *dev, unsigned int offset)
+{
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ u32 dir = readl(bank_reg(priv, bank, reg_dir));
+
+ dir &= ~GPIO_BIT(offset);
+ writel(dir, bank_reg(priv, bank, reg_dir));
+
+ return 0;
+}
+
+static int aspeed_gpio_direction_output(struct udevice *dev, unsigned int offset,
+ int value)
+{
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ u32 dir = readl(bank_reg(priv, bank, reg_dir));
+ u32 output = readl(bank_reg(priv, bank, reg_val));
+
+ dir |= GPIO_BIT(offset);
+ writel(dir, bank_reg(priv, bank, reg_dir));
+
+ if (value)
+ output |= GPIO_BIT(offset);
+ else
+ output &= ~GPIO_BIT(offset);
+
+ writel(output, bank_reg(priv, bank, reg_val));
+
+ return 0;
+}
+
+static int aspeed_gpio_get_value(struct udevice *dev, unsigned int offset)
+{
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+
+ return !!(readl(bank_reg(priv, bank, reg_val)) & GPIO_BIT(offset));
+}
+
+static int
+aspeed_gpio_set_value(struct udevice *dev, unsigned int offset, int value)
+{
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ u32 data = readl(bank_reg(priv, bank, reg_val));
+
+ if (value)
+ data |= GPIO_BIT(offset);
+ else
+ data &= ~GPIO_BIT(offset);
+
+ writel(data, bank_reg(priv, bank, reg_val));
+
+ return 0;
+}
+
+static int aspeed_gpio_get_function(struct udevice *dev, unsigned int offset)
+{
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+
+ if (readl(bank_reg(priv, bank, reg_dir)) & GPIO_BIT(offset))
+ return GPIOF_OUTPUT;
+
+ return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops aspeed_gpio_ops = {
+ .direction_input = aspeed_gpio_direction_input,
+ .direction_output = aspeed_gpio_direction_output,
+ .get_value = aspeed_gpio_get_value,
+ .set_value = aspeed_gpio_set_value,
+ .get_function = aspeed_gpio_get_function,
+};
+
+static int aspeed_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct aspeed_gpio_priv *priv = dev_get_priv(dev);
+
+ uc_priv->bank_name = dev->name;
+ ofnode_read_u32(dev_ofnode(dev), "ngpios", &uc_priv->gpio_count);
+ priv->regs = devfdt_get_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct udevice_id aspeed_gpio_ids[] = {
+ { .compatible = "aspeed,ast2400-gpio", },
+ { .compatible = "aspeed,ast2500-gpio", },
+ { .compatible = "aspeed,ast2600-gpio", },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_aspeed) = {
+ .name = "gpio-aspeed",
+ .id = UCLASS_GPIO,
+ .of_match = aspeed_gpio_ids,
+ .ops = &aspeed_gpio_ops,
+ .probe = aspeed_gpio_probe,
+ .priv_auto = sizeof(struct aspeed_gpio_priv),
+};
diff --git a/drivers/gpio/gpio_slg7xl45106.c b/drivers/gpio/gpio_slg7xl45106.c
new file mode 100644
index 0000000..2cbf748
--- /dev/null
+++ b/drivers/gpio/gpio_slg7xl45106.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * slg7xl45106_i2c_gpo driver
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm/arch/hardware.h>
+
+#define SLG7XL45106_REG 0xdb
+
+static int slg7xl45106_i2c_gpo_direction_input(struct udevice *dev,
+ unsigned int offset)
+{
+ return 0;
+}
+
+static int slg7xl45106_i2c_gpo_xlate(struct udevice *dev,
+ struct gpio_desc *desc,
+ struct ofnode_phandle_args *args)
+{
+ desc->offset = (unsigned int)args->args[0];
+
+ return 0;
+}
+
+static int slg7xl45106_i2c_gpo_set_value(struct udevice *dev,
+ unsigned int offset, int value)
+{
+ int ret;
+ u8 val;
+
+ ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
+ if (ret)
+ return ret;
+
+ if (value)
+ val |= BIT(offset);
+ else
+ val &= ~BIT(offset);
+
+ return dm_i2c_write(dev, SLG7XL45106_REG, &val, 1);
+}
+
+static int slg7xl45106_i2c_gpo_direction_output(struct udevice *dev,
+ unsigned int offset, int value)
+{
+ return slg7xl45106_i2c_gpo_set_value(dev, offset, value);
+}
+
+static int slg7xl45106_i2c_gpo_get_value(struct udevice *dev,
+ unsigned int offset)
+{
+ int ret;
+ u8 val;
+
+ ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
+ if (ret)
+ return ret;
+
+ return !!(val & BIT(offset));
+}
+
+static int slg7xl45106_i2c_gpo_get_function(struct udevice *dev,
+ unsigned int offset)
+{
+ return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops slg7xl45106_i2c_gpo_ops = {
+ .direction_input = slg7xl45106_i2c_gpo_direction_input,
+ .direction_output = slg7xl45106_i2c_gpo_direction_output,
+ .get_value = slg7xl45106_i2c_gpo_get_value,
+ .set_value = slg7xl45106_i2c_gpo_set_value,
+ .get_function = slg7xl45106_i2c_gpo_get_function,
+ .xlate = slg7xl45106_i2c_gpo_xlate,
+};
+
+static int slg7xl45106_i2c_gpo_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ const void *label_ptr;
+
+ label_ptr = dev_read_prop(dev, "label", NULL);
+ if (label_ptr) {
+ uc_priv->bank_name = strdup(label_ptr);
+ if (!uc_priv->bank_name)
+ return -ENOMEM;
+ } else {
+ uc_priv->bank_name = dev->name;
+ }
+
+ uc_priv->gpio_count = 8;
+
+ return 0;
+}
+
+static const struct udevice_id slg7xl45106_i2c_gpo_ids[] = {
+ { .compatible = "dlg,slg7xl45106",},
+ { }
+};
+
+U_BOOT_DRIVER(slg7xl45106_i2c_gpo) = {
+ .name = "slg7xl45106_i2c_gpo",
+ .id = UCLASS_GPIO,
+ .ops = &slg7xl45106_i2c_gpo_ops,
+ .of_match = slg7xl45106_i2c_gpo_ids,
+ .probe = slg7xl45106_i2c_gpo_probe,
+};
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
index a650dd6..0da9f6f 100644
--- a/drivers/i2c/i2c-cdns.c
+++ b/drivers/i2c/i2c-cdns.c
@@ -251,24 +251,32 @@ static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
u8 *cur_data = data;
struct cdns_i2c_regs *regs = i2c_bus->regs;
u32 ret;
+ bool start = 1;
/* Set the controller in Master transmit mode and clear FIFO */
setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO);
clrbits_le32(&regs->control, CDNS_I2C_CONTROL_RW);
- /* Check message size against FIFO depth, and set hold bus bit
- * if it is greater than FIFO depth
+ /*
+ * For sequential data load hold the bus.
*/
- if (len > CDNS_I2C_FIFO_DEPTH)
+ if (len > 1)
setbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
/* Clear the interrupts in status register */
writel(CDNS_I2C_INTERRUPTS_MASK, &regs->interrupt_status);
- writel(addr, &regs->address);
+ /* In case of Probe (i.e no data), start the transfer */
+ if (!len)
+ writel(addr, &regs->address);
while (len-- && !is_arbitration_lost(regs)) {
writel(*(cur_data++), &regs->data);
+ /* Trigger write only after loading data */
+ if (start) {
+ writel(addr, &regs->address);
+ start = 0;
+ }
if (len && readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
CDNS_I2C_INTERRUPT_ARBLOST);
@@ -375,7 +383,6 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
curr_recv_count = recv_count;
}
} else if (recv_count && !hold_quirk && !curr_recv_count) {
- writel(addr, &regs->address);
if (recv_count > CDNS_I2C_TRANSFER_SIZE) {
writel(CDNS_I2C_TRANSFER_SIZE,
&regs->transfer_size);
@@ -384,6 +391,7 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
writel(recv_count, &regs->transfer_size);
curr_recv_count = recv_count;
}
+ writel(addr, &regs->address);
}
}
diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
index cc87fbf..430d076 100644
--- a/drivers/led/Kconfig
+++ b/drivers/led/Kconfig
@@ -28,6 +28,13 @@ config LED_BCM6358
LED HW controller accessed via MMIO registers.
HW has no blinking capabilities and up to 32 LEDs can be controlled.
+config LED_BCM6753
+ bool "LED Support for BCM6753"
+ depends on LED && ARCH_BCM6753
+ help
+ This option enables support for LEDs connected to the BCM6753
+ HW has blinking and fading capabilities and up to 32 LEDs can be controlled.
+
config LED_BCM6858
bool "LED Support for BCM6858"
depends on LED && (ARCH_BCM68360 || ARCH_BCM6858 || ARCH_BCM63158)
diff --git a/drivers/led/Makefile b/drivers/led/Makefile
index 8e3ae7f..2aa2c21 100644
--- a/drivers/led/Makefile
+++ b/drivers/led/Makefile
@@ -6,6 +6,7 @@
obj-y += led-uclass.o
obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o
obj-$(CONFIG_LED_BCM6358) += led_bcm6358.o
+obj-$(CONFIG_LED_BCM6753) += led_bcm6753.o
obj-$(CONFIG_LED_BCM6858) += led_bcm6858.o
obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o
obj-$(CONFIG_LED_CORTINA) += led_cortina.o
diff --git a/drivers/led/led_bcm6753.c b/drivers/led/led_bcm6753.c
new file mode 100644
index 0000000..a32bd82
--- /dev/null
+++ b/drivers/led/led_bcm6753.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Philippe Reynes <philippe.reynes@softathome.com>
+ *
+ * based on:
+ * drivers/led/led_bcm6858.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/bitops.h>
+
+#define LEDS_MAX 32
+#define LEDS_WAIT 100
+
+/* LED Mode register */
+#define LED_MODE_REG 0x0
+#define LED_MODE_OFF 0
+#define LED_MODE_ON 1
+#define LED_MODE_MASK 1
+
+/* LED Controller Global settings register */
+#define CLED_CTRL_REG 0x00
+#define CLED_CTRL_SERIAL_LED_DATA_PPOL BIT(1)
+#define CLED_CTRL_SERIAL_LED_CLK_POL BIT(2)
+#define CLED_CTRL_SERIAL_LED_EN_POL BIT(3)
+#define CLED_CTRL_SERIAL_LED_MSB_FIRST BIT(4)
+#define CLED_CTRL_MASK 0x1E
+/* LED Controller IP LED source select register */
+#define CLED_HW_LED_EN_REG 0x04
+/* Hardware LED Polarity register */
+#define CLED_HW_LED_IP_PPOL_REG 0x0c
+/* Soft LED Set Register */
+#define CLED_SW_LED_IP_SET_REG 0x10
+/* Parallel LED Output Polarity Register */
+#define CLED_PLED_OP_PPOL_REG 0x18
+/* LED Channel activate register */
+#define CLED_LED_CH_ACTIVATE_REG 0x1c
+/* LED 0 Config 0 reg */
+#define CLED_LED_0_CONFIG_0 0x20
+/* Soft LED Clear Register */
+#define CLED_SW_LED_IP_CLEAR_REG 0x444
+/* Soft LED Status Register */
+#define CLED_SW_LED_IP_STATUS_REG 0x448
+
+/* Size of all registers used for the config of one LED */
+#define CLED_CONFIG_SIZE (4 * sizeof(u32))
+
+#define CLED_CONFIG0_MODE 0
+#define CLED_CONFIG0_MODE_MASK (BIT(0) | BIT(1))
+#define CLED_CONFIG0_MODE_STEADY 0
+#define CLED_CONFIG0_MODE_FADING 1
+#define CLED_CONFIG0_MODE_PULSATING 2
+
+#define CLED_CONFIG0_FLASH_CTRL_SHIFT 3
+#define CLED_CONFIG0_FLASH_CTRL_MASK (BIT(3) | BIT(4) | BIT(5))
+
+struct bcm6753_led_priv {
+ void __iomem *regs;
+ u8 pin;
+};
+
+/*
+ * The value for flash rate are:
+ * 0 : no blinking
+ * 1 : rate is 25 Hz => 40 ms (period)
+ * 2 : rate is 12.5 Hz => 80 ms (period)
+ * 3 : rate is 6.25 Hz => 160 ms (period)
+ * 4 : rate is 3.125 Hz => 320 ms (period)
+ * 5 : rate is 1.5625 Hz => 640 ms (period)
+ * 6 : rate is 0.7815 Hz => 1280 ms (period)
+ * 7 : rate is 0.390625 Hz => 2560 ms (period)
+ */
+static const int bcm6753_flash_rate[8] = {
+ 0, 40, 80, 160, 320, 640, 1280, 2560
+};
+
+static u32 bcm6753_flash_rate_value(int period_ms)
+{
+ unsigned long value = 7;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bcm6753_flash_rate); i++) {
+ if (period_ms <= bcm6753_flash_rate[i]) {
+ value = i;
+ break;
+ }
+ }
+
+ return value;
+}
+
+static int bcm6753_led_set_period(struct udevice *dev, int period_ms)
+{
+ struct bcm6753_led_priv *priv = dev_get_priv(dev);
+ u32 offset, shift, value;
+
+ offset = CLED_LED_0_CONFIG_0 + (CLED_CONFIG_SIZE * priv->pin);
+ value = bcm6753_flash_rate_value(period_ms);
+ shift = CLED_CONFIG0_FLASH_CTRL_SHIFT;
+
+ /* set mode steady */
+ clrbits_32(priv->regs + offset, CLED_CONFIG0_MODE_MASK);
+ setbits_32(priv->regs + offset, CLED_CONFIG0_MODE_STEADY);
+
+ /* set flash rate */
+ clrbits_32(priv->regs + offset, CLED_CONFIG0_FLASH_CTRL_MASK);
+ setbits_32(priv->regs + offset, value << shift);
+
+ /* enable config */
+ setbits_32(priv->regs + CLED_LED_CH_ACTIVATE_REG, 1 << priv->pin);
+
+ return 0;
+}
+
+static enum led_state_t bcm6753_led_get_state(struct udevice *dev)
+{
+ struct bcm6753_led_priv *priv = dev_get_priv(dev);
+ enum led_state_t state = LEDST_OFF;
+ u32 sw_led_ip_status;
+
+ sw_led_ip_status = readl(priv->regs + CLED_SW_LED_IP_STATUS_REG);
+ if (sw_led_ip_status & (1 << priv->pin))
+ state = LEDST_ON;
+
+ return state;
+}
+
+static int bcm6753_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct bcm6753_led_priv *priv = dev_get_priv(dev);
+
+ switch (state) {
+ case LEDST_OFF:
+ setbits_32(priv->regs + CLED_SW_LED_IP_CLEAR_REG, (1 << priv->pin));
+ if (IS_ENABLED(CONFIG_LED_BLINK))
+ bcm6753_led_set_period(dev, 0);
+ break;
+ case LEDST_ON:
+ setbits_32(priv->regs + CLED_SW_LED_IP_SET_REG, (1 << priv->pin));
+ if (IS_ENABLED(CONFIG_LED_BLINK))
+ bcm6753_led_set_period(dev, 0);
+ break;
+ case LEDST_TOGGLE:
+ if (bcm6753_led_get_state(dev) == LEDST_OFF)
+ return bcm6753_led_set_state(dev, LEDST_ON);
+ else
+ return bcm6753_led_set_state(dev, LEDST_OFF);
+ break;
+#ifdef CONFIG_LED_BLINK
+ case LEDST_BLINK:
+ setbits_32(priv->regs + CLED_SW_LED_IP_SET_REG, (1 << priv->pin));
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct led_ops bcm6753_led_ops = {
+ .get_state = bcm6753_led_get_state,
+ .set_state = bcm6753_led_set_state,
+#ifdef CONFIG_LED_BLINK
+ .set_period = bcm6753_led_set_period,
+#endif
+};
+
+static int bcm6753_led_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ void __iomem *regs;
+ u32 set_bits = 0;
+
+ regs = dev_remap_addr(dev);
+ if (!regs)
+ return -EINVAL;
+
+ if (dev_read_bool(dev, "brcm,serial-led-msb-first"))
+ set_bits |= CLED_CTRL_SERIAL_LED_MSB_FIRST;
+ if (dev_read_bool(dev, "brcm,serial-led-en-pol"))
+ set_bits |= CLED_CTRL_SERIAL_LED_EN_POL;
+ if (dev_read_bool(dev, "brcm,serial-led-clk-pol"))
+ set_bits |= CLED_CTRL_SERIAL_LED_CLK_POL;
+ if (dev_read_bool(dev, "brcm,serial-led-data-ppol"))
+ set_bits |= CLED_CTRL_SERIAL_LED_DATA_PPOL;
+
+ clrsetbits_32(regs + CLED_CTRL_REG, CLED_CTRL_MASK, set_bits);
+ } else {
+ struct bcm6753_led_priv *priv = dev_get_priv(dev);
+ void __iomem *regs;
+ unsigned int pin;
+
+ regs = dev_remap_addr(dev_get_parent(dev));
+ if (!regs)
+ return -EINVAL;
+
+ pin = dev_read_u32_default(dev, "reg", LEDS_MAX);
+ if (pin >= LEDS_MAX)
+ return -EINVAL;
+
+ priv->regs = regs;
+ priv->pin = pin;
+
+ /* this led is managed by software */
+ clrbits_32(regs + CLED_HW_LED_EN_REG, 1 << pin);
+
+ /* configure the polarity */
+ if (dev_read_bool(dev, "active-low"))
+ clrbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin);
+ else
+ setbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin);
+ }
+
+ return 0;
+}
+
+static int bcm6753_led_bind(struct udevice *parent)
+{
+ ofnode node;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ struct udevice *dev;
+ const char *label;
+ int ret;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "bcm6753-led",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id bcm6753_led_ids[] = {
+ { .compatible = "brcm,bcm6753-leds" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6753_led) = {
+ .name = "bcm6753-led",
+ .id = UCLASS_LED,
+ .of_match = bcm6753_led_ids,
+ .bind = bcm6753_led_bind,
+ .probe = bcm6753_led_probe,
+ .priv_auto = sizeof(struct bcm6753_led_priv),
+ .ops = &bcm6753_led_ops,
+};
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 8200658..b2f4a4e 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -2019,6 +2019,7 @@ static const struct udevice_id omap_hsmmc_ids[] = {
{ .compatible = "ti,omap3-hsmmc" },
{ .compatible = "ti,omap4-hsmmc" },
{ .compatible = "ti,am33xx-hsmmc" },
+ { .compatible = "ti,am335-sdhci" },
{ .compatible = "ti,dra7-hsmmc", .data = (ulong)&dra7_mmc_of_data },
{ }
};
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 5cea4c6..d96f5d5 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -12,9 +12,12 @@
#include <linux/delay.h>
#include "mmc_private.h"
#include <log.h>
+#include <reset.h>
#include <dm/device_compat.h>
#include <linux/err.h>
#include <linux/libfdt.h>
+#include <asm/types.h>
+#include <linux/math64.h>
#include <asm/cache.h>
#include <malloc.h>
#include <sdhci.h>
@@ -61,6 +64,7 @@ struct arasan_sdhci_priv {
u8 deviceid;
u8 bank;
u8 no_1p8;
+ struct reset_ctl_bulk resets;
};
/* For Versal platforms zynqmp_mmio_write() won't be available */
@@ -243,7 +247,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
- debug("%s\n", __func__);
+ dev_dbg(mmc->dev, "%s\n", __func__);
host = priv->host;
@@ -703,6 +707,87 @@ static const struct sdhci_ops arasan_ops = {
};
#endif
+#if defined(CONFIG_ARCH_ZYNQMP)
+static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
+ struct udevice *dev)
+{
+ int ret;
+ u32 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
+ struct clk clk;
+ unsigned long clock, mhz;
+
+ ret = xilinx_pm_request(PM_REQUEST_NODE, node_id, ZYNQMP_PM_CAPABILITY_ACCESS,
+ ZYNQMP_PM_MAX_QOS, ZYNQMP_PM_REQUEST_ACK_NO, NULL);
+ if (ret) {
+ dev_err(dev, "Request node failed for %d\n", node_id);
+ return ret;
+ }
+
+ ret = reset_get_bulk(dev, &priv->resets);
+ if (ret == -ENOTSUPP || ret == -ENOENT) {
+ dev_err(dev, "Reset not found\n");
+ return 0;
+ } else if (ret) {
+ dev_err(dev, "Reset failed\n");
+ return ret;
+ }
+
+ ret = reset_assert_bulk(&priv->resets);
+ if (ret) {
+ dev_err(dev, "Reset assert failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_FIXED, 0);
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_FIXED failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_EMMC_SEL,
+ dev_read_bool(dev, "non-removable"));
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
+ return ret;
+ }
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return clock;
+ }
+
+ mhz = DIV64_U64_ROUND_UP(clock, 1000000);
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz);
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_BASECLK failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_8BIT,
+ (dev_read_u32_default(dev, "bus-width", 1) == 8));
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_8BIT failed\n");
+ return ret;
+ }
+
+ ret = reset_deassert_bulk(&priv->resets);
+ if (ret) {
+ dev_err(dev, "Reset release failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
static int arasan_sdhci_probe(struct udevice *dev)
{
struct arasan_sdhci_plat *plat = dev_get_plat(dev);
@@ -715,6 +800,18 @@ static int arasan_sdhci_probe(struct udevice *dev)
host = priv->host;
+#if defined(CONFIG_ARCH_ZYNQMP)
+ if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+ ret = zynqmp_pm_is_function_supported(PM_IOCTL,
+ IOCTL_SET_SD_CONFIG);
+ if (!ret) {
+ ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
+ if (ret)
+ return ret;
+ }
+ }
+#endif
+
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0) {
dev_err(dev, "failed to get clock\n");
@@ -727,7 +824,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
return clock;
}
- debug("%s: CLK %ld\n", __func__, clock);
+ dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
ret = clk_enable(&clk);
if (ret) {
@@ -769,12 +866,13 @@ static int arasan_sdhci_probe(struct udevice *dev)
* causing sd card timeout error. Workaround this by adding a wait for
* 1000msec till the card detect state gets stable.
*/
- if (IS_ENABLED(CONFIG_ARCH_VERSAL)) {
- u32 timeout = 1000;
+ if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
+ u32 timeout = 1000000;
while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
- SDHCI_CARD_STATE_STABLE) == 0) && timeout--) {
- mdelay(1);
+ SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
+ udelay(1);
+ timeout--;
}
if (!timeout) {
dev_err(dev, "Sdhci card detect state not stable\n");
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index bde3004..588ebe9 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -52,6 +52,13 @@ config CFI_FLASH
option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
for more information on CFI.
+config CFI_FLASH_USE_WEAK_ACCESSORS
+ bool "Allow read/write functions to be overridden"
+ depends on FLASH_CFI_DRIVER
+ help
+ Enable this option to allow for the flash_{read,write}{8,16,32,64}
+ functions to be overridden by the platform.
+
config SYS_FLASH_USE_BUFFER_WRITE
bool "Enable buffered writes to flash"
depends on FLASH_CFI_DRIVER
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 0e826c1..1eab21e 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -91,6 +91,12 @@ config NAND_BRCMNAND_6368
help
Enable support for broadcom nand driver on bcm6368.
+config NAND_BRCMNAND_6753
+ bool "Support Broadcom NAND controller on bcm6753"
+ depends on NAND_BRCMNAND && ARCH_BCM6753
+ help
+ Enable support for broadcom nand driver on bcm6753.
+
config NAND_BRCMNAND_68360
bool "Support Broadcom NAND controller on bcm68360"
depends on NAND_BRCMNAND && ARCH_BCM68360
diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile
index 5d9e7e3..f46a7ed 100644
--- a/drivers/mtd/nand/raw/brcmnand/Makefile
+++ b/drivers/mtd/nand/raw/brcmnand/Makefile
@@ -2,6 +2,7 @@
obj-$(CONFIG_NAND_BRCMNAND_6368) += bcm6368_nand.o
obj-$(CONFIG_NAND_BRCMNAND_63158) += bcm63158_nand.o
+obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6753_nand.o
obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o
obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o
obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o
diff --git a/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c
new file mode 100644
index 0000000..feae66e
--- /dev/null
+++ b/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <asm/io.h>
+#include <memalign.h>
+#include <nand.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <dm.h>
+
+#include "brcmnand.h"
+
+struct bcm6753_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *base;
+};
+
+#define BCM6753_NAND_INT 0x00
+#define BCM6753_NAND_STATUS_SHIFT 0
+#define BCM6753_NAND_STATUS_MASK (0xfff << BCM6753_NAND_STATUS_SHIFT)
+
+#define BCM6753_NAND_INT_EN 0x04
+#define BCM6753_NAND_ENABLE_SHIFT 0
+#define BCM6753_NAND_ENABLE_MASK (0xffff << BCM6753_NAND_ENABLE_SHIFT)
+
+enum {
+ BCM6753_NP_READ = BIT(0),
+ BCM6753_BLOCK_ERASE = BIT(1),
+ BCM6753_COPY_BACK = BIT(2),
+ BCM6753_PAGE_PGM = BIT(3),
+ BCM6753_CTRL_READY = BIT(4),
+ BCM6753_DEV_RBPIN = BIT(5),
+ BCM6753_ECC_ERR_UNC = BIT(6),
+ BCM6753_ECC_ERR_CORR = BIT(7),
+};
+
+static bool bcm6753_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct bcm6753_nand_soc *priv =
+ container_of(soc, struct bcm6753_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM6753_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & (BCM6753_CTRL_READY << BCM6753_NAND_STATUS_SHIFT)) {
+ /* Ack interrupt */
+ val &= ~BCM6753_NAND_STATUS_MASK;
+ val |= BCM6753_CTRL_READY << BCM6753_NAND_STATUS_SHIFT;
+ brcmnand_writel(val, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void bcm6753_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct bcm6753_nand_soc *priv =
+ container_of(soc, struct bcm6753_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM6753_NAND_INT_EN;
+ u32 val = brcmnand_readl(mmio);
+
+ /* Don't ack any interrupts */
+ val &= ~BCM6753_NAND_STATUS_MASK;
+
+ if (en)
+ val |= BCM6753_CTRL_READY << BCM6753_NAND_ENABLE_SHIFT;
+ else
+ val &= ~(BCM6753_CTRL_READY << BCM6753_NAND_ENABLE_SHIFT);
+
+ brcmnand_writel(val, mmio);
+}
+
+static int bcm6753_nand_probe(struct udevice *dev)
+{
+ struct udevice *pdev = dev;
+ struct bcm6753_nand_soc *priv = dev_get_priv(dev);
+ struct brcmnand_soc *soc;
+ struct resource res;
+
+ soc = &priv->soc;
+
+ dev_read_resource_byname(pdev, "nand-int-base", &res);
+ priv->base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ soc->ctlrdy_ack = bcm6753_nand_intc_ack;
+ soc->ctlrdy_set_enabled = bcm6753_nand_intc_set;
+
+ /* Disable and ack all interrupts */
+ brcmnand_writel(0, priv->base + BCM6753_NAND_INT_EN);
+ brcmnand_writel(0, priv->base + BCM6753_NAND_INT);
+
+ return brcmnand_probe(pdev, soc);
+}
+
+static const struct udevice_id bcm6753_nand_dt_ids[] = {
+ {
+ .compatible = "brcm,nand-bcm6753",
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6753_nand) = {
+ .name = "bcm6753-nand",
+ .id = UCLASS_MTD,
+ .of_match = bcm6753_nand_dt_ids,
+ .probe = bcm6753_nand_probe,
+ .priv_auto = sizeof(struct bcm6753_nand_soc),
+};
+
+void board_nand_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MTD,
+ DM_DRIVER_GET(bcm6753_nand), &dev);
+ if (ret && ret != -ENODEV)
+ pr_err("Failed to initialize %s. (error %d)\n", dev->name,
+ ret);
+}
diff --git a/drivers/mtd/nand/raw/zynq_nand.c b/drivers/mtd/nand/raw/zynq_nand.c
index d792528..10e9cd1 100644
--- a/drivers/mtd/nand/raw/zynq_nand.c
+++ b/drivers/mtd/nand/raw/zynq_nand.c
@@ -1086,10 +1086,13 @@ static int zynq_nand_probe(struct udevice *dev)
int is_16bit_bw;
smc->reg = (struct zynq_nand_smc_regs *)dev_read_addr(dev);
- of_nand = dev_read_subnode(dev, "flash@e1000000");
+ of_nand = dev_read_subnode(dev, "nand-controller@0,0");
if (!ofnode_valid(of_nand)) {
- printf("Failed to find nand node in dt\n");
- return -ENODEV;
+ of_nand = dev_read_subnode(dev, "flash@e1000000");
+ if (!ofnode_valid(of_nand)) {
+ printf("Failed to find nand node in dt\n");
+ return -ENODEV;
+ }
}
if (!ofnode_is_available(of_nand)) {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 71e0cba..a6171a7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -423,6 +423,11 @@ config KSZ9477
This driver implements a DSA switch driver for the KSZ9477 family
of GbE switches using the I2C interface.
+config LPC32XX_ETH
+ bool "LPC32xx Ethernet MAC interface driver"
+ depends on ARCH_LPC32XX
+ default y
+
config MVGBE
bool "Marvell Orion5x/Kirkwood network interface support"
depends on ARCH_KIRKWOOD || ARCH_ORION5X
@@ -535,6 +540,11 @@ config MII
help
Enable support of the Media-Independent Interface (MII)
+config RMII
+ bool "Enable RMII"
+ help
+ Enable support of the Reduced Media-Independent Interface (MII)
+
config PCNET
bool "AMD PCnet series Ethernet controller driver"
help
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
index aad7b61..06e0dd7 100644
--- a/drivers/net/bcm6348-eth.c
+++ b/drivers/net/bcm6348-eth.c
@@ -461,11 +461,7 @@ static int bcm6348_eth_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("%s: error freeing clock %d\n", __func__, i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
index 29abe7f..c2a8b9f 100644
--- a/drivers/net/bcm6368-eth.c
+++ b/drivers/net/bcm6368-eth.c
@@ -546,11 +546,7 @@ static int bcm6368_eth_probe(struct udevice *dev)
return ret;
}
- ret = clk_free(&clk);
- if (ret < 0) {
- pr_err("%s: error freeing clock %d\n", __func__, i);
- return ret;
- }
+ clk_free(&clk);
}
/* try to perform resets */
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 985b038..e8ebef0 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -54,10 +54,6 @@ DECLARE_GLOBAL_DATA_PTR;
#error "CONFIG_MII has to be defined!"
#endif
-#ifndef CONFIG_FEC_XCV_TYPE
-#define CONFIG_FEC_XCV_TYPE MII100
-#endif
-
/*
* The i.MX28 operates with packets in big endian. We need to swap them before
* sending and after receiving.
@@ -408,20 +404,11 @@ static int fec_get_hwaddr(int dev_id, unsigned char *mac)
return !is_valid_ethaddr(mac);
}
-#ifdef CONFIG_DM_ETH
static int fecmxc_set_hwaddr(struct udevice *dev)
-#else
-static int fec_set_hwaddr(struct eth_device *dev)
-#endif
{
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
struct eth_pdata *pdata = dev_get_plat(dev);
uchar *mac = pdata->enetaddr;
-#else
- uchar *mac = dev->enetaddr;
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
writel(0, &fec->eth->iaddr1);
writel(0, &fec->eth->iaddr2);
@@ -468,17 +455,9 @@ static void fec_reg_setup(struct fec_priv *fec)
* Start the FEC engine
* @param[in] dev Our device to handle
*/
-#ifdef CONFIG_DM_ETH
static int fec_open(struct udevice *dev)
-#else
-static int fec_open(struct eth_device *edev)
-#endif
{
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
-#else
- struct fec_priv *fec = (struct fec_priv *)edev->priv;
-#endif
int speed;
ulong addr, size;
int i;
@@ -589,27 +568,15 @@ static int fec_open(struct eth_device *edev)
return 0;
}
-#ifdef CONFIG_DM_ETH
static int fecmxc_init(struct udevice *dev)
-#else
-static int fec_init(struct eth_device *dev, struct bd_info *bd)
-#endif
{
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
-#else
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
u8 *i;
ulong addr;
/* Initialize MAC address */
-#ifdef CONFIG_DM_ETH
fecmxc_set_hwaddr(dev);
-#else
- fec_set_hwaddr(dev);
-#endif
/* Setup transmit descriptors, there are two in total. */
fec_tbd_init(fec);
@@ -661,17 +628,9 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd)
* Halt the FEC engine
* @param[in] dev Our device to handle
*/
-#ifdef CONFIG_DM_ETH
static void fecmxc_halt(struct udevice *dev)
-#else
-static void fec_halt(struct eth_device *dev)
-#endif
{
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
-#else
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
int counter = 0xffff;
/* issue graceful stop command to the FEC transmitter if necessary */
@@ -705,11 +664,7 @@ static void fec_halt(struct eth_device *dev)
* @param[in] length Data count in bytes
* Return: 0 on success
*/
-#ifdef CONFIG_DM_ETH
static int fecmxc_send(struct udevice *dev, void *packet, int length)
-#else
-static int fec_send(struct eth_device *dev, void *packet, int length)
-#endif
{
unsigned int status;
u32 size;
@@ -721,11 +676,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
* This routine transmits one frame. This routine only accepts
* 6-byte Ethernet addresses.
*/
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
-#else
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
/*
* Check for valid length of data.
@@ -856,17 +807,9 @@ out:
* @param[in] dev Our ethernet device to handle
* Return: Length of packet read
*/
-#ifdef CONFIG_DM_ETH
static int fecmxc_recv(struct udevice *dev, int flags, uchar **packetp)
-#else
-static int fec_recv(struct eth_device *dev)
-#endif
{
-#ifdef CONFIG_DM_ETH
struct fec_priv *fec = dev_get_priv(dev);
-#else
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
-#endif
struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
unsigned long ievent;
int frame_length, len = 0;
@@ -874,28 +817,19 @@ static int fec_recv(struct eth_device *dev)
ulong addr, size, end;
int i;
-#ifdef CONFIG_DM_ETH
*packetp = memalign(ARCH_DMA_MINALIGN, FEC_MAX_PKT_SIZE);
if (*packetp == 0) {
printf("%s: error allocating packetp\n", __func__);
return -ENOMEM;
}
-#else
- ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
-#endif
/* Check if any critical events have happened */
ievent = readl(&fec->eth->ievent);
writel(ievent, &fec->eth->ievent);
debug("fec_recv: ievent 0x%lx\n", ievent);
if (ievent & FEC_IEVENT_BABR) {
-#ifdef CONFIG_DM_ETH
fecmxc_halt(dev);
fecmxc_init(dev);
-#else
- fec_halt(dev);
- fec_init(dev, fec->bd);
-#endif
printf("some error: 0x%08lx\n", ievent);
return 0;
}
@@ -907,18 +841,10 @@ static int fec_recv(struct eth_device *dev)
if (ievent & FEC_IEVENT_GRA) {
/* Graceful stop complete */
if (readl(&fec->eth->x_cntrl) & 0x00000001) {
-#ifdef CONFIG_DM_ETH
fecmxc_halt(dev);
-#else
- fec_halt(dev);
-#endif
writel(~0x00000001 & readl(&fec->eth->x_cntrl),
&fec->eth->x_cntrl);
-#ifdef CONFIG_DM_ETH
fecmxc_init(dev);
-#else
- fec_init(dev, fec->bd);
-#endif
}
}
@@ -959,12 +885,7 @@ static int fec_recv(struct eth_device *dev)
swap_packet((uint32_t *)addr, frame_length);
#endif
-#ifdef CONFIG_DM_ETH
memcpy(*packetp, (char *)addr, frame_length);
-#else
- memcpy(buff, (char *)addr, frame_length);
- net_process_received_packet(buff, frame_length);
-#endif
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR)
@@ -1104,175 +1025,6 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
return bus;
}
-#ifndef CONFIG_DM_ETH
-#ifdef CONFIG_PHYLIB
-int fec_probe(struct bd_info *bd, int dev_id, uint32_t base_addr,
- struct mii_dev *bus, struct phy_device *phydev)
-#else
-static int fec_probe(struct bd_info *bd, int dev_id, uint32_t base_addr,
- struct mii_dev *bus, int phy_id)
-#endif
-{
- struct eth_device *edev;
- struct fec_priv *fec;
- unsigned char ethaddr[6];
- char mac[16];
- uint32_t start;
- int ret = 0;
-
- /* create and fill edev struct */
- edev = (struct eth_device *)malloc(sizeof(struct eth_device));
- if (!edev) {
- puts("fec_mxc: not enough malloc memory for eth_device\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
- if (!fec) {
- puts("fec_mxc: not enough malloc memory for fec_priv\n");
- ret = -ENOMEM;
- goto err2;
- }
-
- memset(edev, 0, sizeof(*edev));
- memset(fec, 0, sizeof(*fec));
-
- ret = fec_alloc_descs(fec);
- if (ret)
- goto err3;
-
- edev->priv = fec;
- edev->init = fec_init;
- edev->send = fec_send;
- edev->recv = fec_recv;
- edev->halt = fec_halt;
- edev->write_hwaddr = fec_set_hwaddr;
-
- fec->eth = (struct ethernet_regs *)(ulong)base_addr;
- fec->bd = bd;
-
- fec->xcv_type = CONFIG_FEC_XCV_TYPE;
-
- /* Reset chip. */
- writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
- start = get_timer(0);
- while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
- if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
- printf("FEC MXC: Timeout resetting chip\n");
- goto err4;
- }
- udelay(10);
- }
-
- fec_reg_setup(fec);
- fec_set_dev_name(edev->name, dev_id);
- fec->dev_id = (dev_id == -1) ? 0 : dev_id;
- fec->bus = bus;
- fec_mii_setspeed(bus->priv);
-#ifdef CONFIG_PHYLIB
- fec->phydev = phydev;
- phy_connect_dev(phydev, edev);
- /* Configure phy */
- phy_config(phydev);
-#else
- fec->phy_id = phy_id;
-#endif
- eth_register(edev);
- /* only support one eth device, the index number pointed by dev_id */
- edev->index = fec->dev_id;
-
- if (fec_get_hwaddr(fec->dev_id, ethaddr) == 0) {
- debug("got MAC%d address from fuse: %pM\n", fec->dev_id, ethaddr);
- memcpy(edev->enetaddr, ethaddr, 6);
- if (fec->dev_id)
- sprintf(mac, "eth%daddr", fec->dev_id);
- else
- strcpy(mac, "ethaddr");
- if (!env_get(mac))
- eth_env_set_enetaddr(mac, ethaddr);
- }
- return ret;
-err4:
- fec_free_descs(fec);
-err3:
- free(fec);
-err2:
- free(edev);
-err1:
- return ret;
-}
-
-int fecmxc_initialize_multi(struct bd_info *bd, int dev_id, int phy_id,
- uint32_t addr)
-{
- uint32_t base_mii;
- struct mii_dev *bus = NULL;
-#ifdef CONFIG_PHYLIB
- struct phy_device *phydev = NULL;
-#endif
- int ret;
-
- if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
- if (enet_fused((ulong)addr)) {
- printf("SoC fuse indicates Ethernet@0x%x is unavailable.\n", addr);
- return -ENODEV;
- }
- }
-
-#ifdef CONFIG_FEC_MXC_MDIO_BASE
- /*
- * The i.MX28 has two ethernet interfaces, but they are not equal.
- * Only the first one can access the MDIO bus.
- */
- base_mii = CONFIG_FEC_MXC_MDIO_BASE;
-#else
- base_mii = addr;
-#endif
- debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
- bus = fec_get_miibus(base_mii, dev_id);
- if (!bus)
- return -ENOMEM;
-#ifdef CONFIG_PHYLIB
- phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
- if (!phydev) {
- mdio_unregister(bus);
- free(bus);
- return -ENOMEM;
- }
- ret = fec_probe(bd, dev_id, addr, bus, phydev);
-#else
- ret = fec_probe(bd, dev_id, addr, bus, phy_id);
-#endif
- if (ret) {
-#ifdef CONFIG_PHYLIB
- free(phydev);
-#endif
- mdio_unregister(bus);
- free(bus);
- }
- return ret;
-}
-
-#ifdef CONFIG_FEC_MXC_PHYADDR
-int fecmxc_initialize(struct bd_info *bd)
-{
- return fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,
- IMX_FEC_BASE);
-}
-#endif
-
-#ifndef CONFIG_PHYLIB
-int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
-{
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
- fec->mii_postcall = cb;
- return 0;
-}
-#endif
-
-#else
-
static int fecmxc_read_rom_hwaddr(struct udevice *dev)
{
struct fec_priv *priv = dev_get_priv(dev);
@@ -1513,9 +1265,9 @@ static int fecmxc_probe(struct udevice *dev)
priv->xcv_type = RGMII;
break;
default:
- priv->xcv_type = CONFIG_FEC_XCV_TYPE;
- printf("Unsupported interface type %d defaulting to %d\n",
- priv->interface, priv->xcv_type);
+ priv->xcv_type = MII100;
+ printf("Unsupported interface type %d defaulting to MII100\n",
+ priv->interface);
break;
}
@@ -1626,4 +1378,3 @@ U_BOOT_DRIVER(fecmxc_gem) = {
.priv_auto = sizeof(struct fec_priv),
.plat_auto = sizeof(struct eth_pdata),
};
-#endif
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index ca06b35..e2c8f41 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -200,9 +200,7 @@ int mii_discover_phy(fec_info_t *info)
}
#endif /* CONFIG_SYS_DISCOVER_PHY */
-void mii_init(void) __attribute__((weak,alias("__mii_init")));
-
-void __mii_init(void)
+__weak void mii_init(void)
{
#ifdef CONFIG_DM_ETH
struct udevice *dev;
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 4f8d33c..014a4de 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -2,6 +2,10 @@
config BITBANGMII
bool "Bit-banged ethernet MII management channel support"
+config BITBANGMII_MULTI
+ bool "Enable the multi bus support"
+ depends on BITBANGMII
+
config MV88E6352_SWITCH
bool "Marvell 88E6352 switch support"
@@ -307,6 +311,14 @@ config PHY_XILINX_GMII2RGMII
as bridge between MAC connected over GMII and external phy that
is connected over RGMII interface.
+config PHY_ETHERNET_ID
+ bool "Read ethernet PHY id"
+ depends on DM_GPIO
+ default y if ZYNQ_GEM
+ help
+ Enable this config to read ethernet phy id from the phy node of DT
+ and create a phy device using id.
+
config PHY_FIXED
bool "Fixed-Link PHY"
depends on DM_ETH
@@ -322,3 +334,11 @@ config PHY_NCSI
depends on DM_ETH
endif #PHYLIB
+
+config PHY_RESET_DELAY
+ int "Extra delay after reset before MII register access"
+ default 0
+ help
+ Some PHYs need extra delay after reset before any MII register access
+ is possible. For such PHY, set this option to the usec delay
+ required.
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 77f7f60..b28440b 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o
obj-$(CONFIG_PHY_TI_DP83869) += dp83869.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+obj-$(CONFIG_PHY_ETHERNET_ID) += ethernet_id.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
obj-$(CONFIG_PHY_MSCC) += mscc.o
obj-$(CONFIG_PHY_FIXED) += fixed.o
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
new file mode 100644
index 0000000..5617ac3
--- /dev/null
+++ b/drivers/net/phy/ethernet_id.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx ethernet phy reset driver
+ *
+ * Copyright (C) 2022 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <dm/device_compat.h>
+#include <phy.h>
+#include <linux/delay.h>
+#include <asm/gpio.h>
+
+struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
+ phy_interface_t interface)
+{
+ struct phy_device *phydev;
+ struct ofnode_phandle_args phandle_args;
+ struct gpio_desc gpio;
+ ofnode node;
+ u32 id, assert, deassert;
+ u16 vendor, device;
+ int ret;
+
+ if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+ &phandle_args))
+ return NULL;
+
+ if (!ofnode_valid(phandle_args.node))
+ return NULL;
+
+ node = phandle_args.node;
+
+ ret = ofnode_read_eth_phy_id(node, &vendor, &device);
+ if (ret) {
+ dev_err(dev, "Failed to read eth PHY id, err: %d\n", ret);
+ return NULL;
+ }
+
+ ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
+ GPIOD_ACTIVE_LOW);
+ if (!ret) {
+ assert = ofnode_read_u32_default(node, "reset-assert-us", 0);
+ deassert = ofnode_read_u32_default(node,
+ "reset-deassert-us", 0);
+ ret = dm_gpio_set_value(&gpio, 1);
+ if (ret) {
+ dev_err(dev, "Failed assert gpio, err: %d\n", ret);
+ return NULL;
+ }
+
+ udelay(assert);
+
+ ret = dm_gpio_set_value(&gpio, 0);
+ if (ret) {
+ dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
+ return NULL;
+ }
+
+ udelay(deassert);
+ }
+
+ id = vendor << 16 | device;
+ phydev = phy_device_create(bus, 0, id, false, interface);
+ if (phydev)
+ phydev->node = node;
+
+ return phydev;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c9fc208..92fff5b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -659,9 +659,9 @@ static struct phy_driver *get_phy_driver(struct phy_device *phydev,
return generic_for_interface(interface);
}
-static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
- u32 phy_id, bool is_c45,
- phy_interface_t interface)
+struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
+ u32 phy_id, bool is_c45,
+ phy_interface_t interface)
{
struct phy_device *dev;
@@ -872,7 +872,7 @@ int phy_reset(struct phy_device *phydev)
return -1;
}
-#ifdef CONFIG_PHY_RESET_DELAY
+#if CONFIG_PHY_RESET_DELAY > 0
udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
#endif
/*
@@ -1047,6 +1047,11 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
phydev = phy_device_create(bus, 0, PHY_NCSI_ID, false, interface);
#endif
+#ifdef CONFIG_PHY_ETHERNET_ID
+ if (!phydev)
+ phydev = phy_connect_phy_id(bus, dev, interface);
+#endif
+
#ifdef CONFIG_PHY_XILINX_GMII2RGMII
if (!phydev)
phydev = phy_connect_gmii2rgmii(bus, dev, interface);
diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c
index 4f7e61e..b0fc9ca 100644
--- a/drivers/pci/pci-aardvark.c
+++ b/drivers/pci/pci-aardvark.c
@@ -800,7 +800,7 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
*/
reg = advk_readl(pcie, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
reg &= ~0xffffff00;
- reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
+ reg |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
advk_writel(pcie, reg, ADVK_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
/* Enable generation and checking of ECRC on PCIe Root Port */
diff --git a/drivers/pci/pci-rcar-gen3.c b/drivers/pci/pci-rcar-gen3.c
index 34a561e..4902923 100644
--- a/drivers/pci/pci-rcar-gen3.c
+++ b/drivers/pci/pci-rcar-gen3.c
@@ -289,7 +289,7 @@ static int rcar_gen3_pcie_hw_init(struct udevice *dev)
* class to match. Hardware takes care of propagating the IDSETR
* settings, so there is no need to bother with a quirk.
*/
- writel(PCI_CLASS_BRIDGE_PCI << 16, priv->regs + IDSETR1);
+ writel(PCI_CLASS_BRIDGE_PCI_NORMAL << 8, priv->regs + IDSETR1);
/*
* Setup Secondary Bus Number & Subordinate Bus Number, even though
diff --git a/drivers/pci/pci_mpc85xx.c b/drivers/pci/pci_mpc85xx.c
index 1e180ee..8a81a74 100644
--- a/drivers/pci/pci_mpc85xx.c
+++ b/drivers/pci/pci_mpc85xx.c
@@ -6,7 +6,6 @@
*/
#include <common.h>
#include <asm/bitops.h>
-#include <asm/cpm_85xx.h>
#include <pci.h>
#include <dm.h>
#include <asm/fsl_law.h>
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index f076693..d80f87e 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -440,7 +440,7 @@ static int mvebu_pcie_probe(struct udevice *dev)
*/
reg = readl(pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
reg &= ~0xffffff00;
- reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
+ reg |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
writel(reg, pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
/*
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index f8b1930..73d15e7 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -36,7 +36,6 @@
#include <pci_rom.h>
#include <vbe.h>
#include <video.h>
-#include <video_fb.h>
#include <acpi/acpi_s3.h>
#include <asm/global_data.h>
#include <linux/screen_info.h>
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index fc05ee0..f8d66c0 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -325,8 +325,8 @@ static int pci_tegra_read_config(const struct udevice *bus, pci_dev_t bdf,
/* fixup root port class */
if (PCI_BUS(bdf) == 0) {
if ((offset & ~3) == PCI_CLASS_REVISION) {
- value &= ~0x00ff0000;
- value |= PCI_CLASS_BRIDGE_PCI << 16;
+ value &= ~0x00ffff00;
+ value |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
}
}
#endif
diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c
index 0490fd3..99891dc 100644
--- a/drivers/pci/pcie_dw_mvebu.c
+++ b/drivers/pci/pcie_dw_mvebu.c
@@ -539,9 +539,9 @@ static int pcie_dw_mvebu_probe(struct udevice *dev)
PCIE_ATU_TYPE_MEM, pcie->mem.phys_start,
pcie->mem.bus_start, pcie->mem.size);
- /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
+ /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI_NORMAL */
clrsetbits_le32(pcie->ctrl_base + PCI_CLASS_REVISION,
- 0xffff << 16, PCI_CLASS_BRIDGE_PCI << 16);
+ 0xffffff << 8, PCI_CLASS_BRIDGE_PCI_NORMAL << 8);
pcie_dw_set_host_bars(pcie->ctrl_base);
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c
index cc6efdd..f5ba349 100644
--- a/drivers/pci/pcie_fsl.c
+++ b/drivers/pci/pcie_fsl.c
@@ -532,7 +532,7 @@ static int fsl_pcie_fixup_classcode(struct fsl_pcie *pcie)
fsl_pcie_hose_read_config_dword(pcie, classcode_reg, &val);
val &= 0xff;
- val |= PCI_CLASS_BRIDGE_PCI << 16;
+ val |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
fsl_pcie_hose_write_config_dword(pcie, classcode_reg, val);
if (pcie->block_rev >= PEX_IP_BLK_REV_3_0)
diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index 756166f..2cec390 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -300,9 +300,9 @@ static int imx_pcie_regions_setup(struct imx_pcie_priv *priv)
setbits_le32(priv->dbi_base + PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
+ /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI_NORMAL */
setbits_le32(priv->dbi_base + PCI_CLASS_REVISION,
- PCI_CLASS_BRIDGE_PCI << 16);
+ PCI_CLASS_BRIDGE_PCI_NORMAL << 8);
/* Region #0 is used for Outbound CFG space access. */
writel(0, priv->dbi_base + PCIE_ATU_VIEWPORT);
diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c
index 85dfab5..d6d3a9e 100644
--- a/drivers/pci/pcie_iproc.c
+++ b/drivers/pci/pcie_iproc.c
@@ -1123,7 +1123,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie)
PCI_BRIDGE_CTRL_REG_OFFSET,
4, &class);
class &= ~PCI_BRIDGE_CTRL_REG_CLASS_MASK;
- class |= (PCI_CLASS_BRIDGE_PCI << 8);
+ class |= PCI_CLASS_BRIDGE_PCI_NORMAL;
iproc_pci_raw_config_write32(pcie, 0,
PCI_BRIDGE_CTRL_REG_OFFSET,
4, class);
diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c
index 67039d2..72b4139 100644
--- a/drivers/pci/pcie_rockchip.c
+++ b/drivers/pci/pcie_rockchip.c
@@ -351,7 +351,7 @@ static int rockchip_pcie_init_port(struct udevice *dev)
/* Initialize Root Complex registers. */
writel(PCIE_LM_VENDOR_ROCKCHIP, priv->apb_base + PCIE_LM_VENDOR_ID);
- writel(PCI_CLASS_BRIDGE_PCI << 16,
+ writel(PCI_CLASS_BRIDGE_PCI_NORMAL << 8,
priv->apb_base + PCIE_RC_BASE + PCI_CLASS_REVISION);
writel(PCIE_LM_RCBARPIE | PCIE_LM_RCBARPIS,
priv->apb_base + PCIE_LM_RCBAR);
diff --git a/drivers/phy/bcm6318-usbh-phy.c b/drivers/phy/bcm6318-usbh-phy.c
index 60608a5..1c10853 100644
--- a/drivers/phy/bcm6318-usbh-phy.c
+++ b/drivers/phy/bcm6318-usbh-phy.c
@@ -98,9 +98,7 @@ static int bcm6318_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* enable power domain */
ret = power_domain_get(dev, &pwr_dom);
diff --git a/drivers/phy/bcm6348-usbh-phy.c b/drivers/phy/bcm6348-usbh-phy.c
index 1b6b5ad..ce6be3d 100644
--- a/drivers/phy/bcm6348-usbh-phy.c
+++ b/drivers/phy/bcm6348-usbh-phy.c
@@ -62,9 +62,7 @@ static int bcm6348_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/phy/bcm6368-usbh-phy.c b/drivers/phy/bcm6368-usbh-phy.c
index 4d3a63f..d057f1f 100644
--- a/drivers/phy/bcm6368-usbh-phy.c
+++ b/drivers/phy/bcm6368-usbh-phy.c
@@ -137,9 +137,7 @@ static int bcm6368_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
#if defined(CONFIG_POWER_DOMAIN)
/* enable power domain */
@@ -176,9 +174,7 @@ static int bcm6368_usbh_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
}
mdelay(100);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0394624..d7477d7 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -318,6 +318,16 @@ config PINCTRL_K210
Support pin multiplexing on the K210. The "FPIOA" can remap any
supported function to any multifunctional IO pin. It can also perform
basic GPIO functions, such as reading the current value of a pin.
+
+config PINCTRL_ZYNQMP
+ bool "Xilinx ZynqMP pin control driver"
+ depends on DM && PINCTRL_GENERIC && ARCH_ZYNQMP
+ default y
+ help
+ Support pin multiplexing control on Xilinx ZynqMP. The driver uses
+ Generic Pinctrl framework and is compatible with the Linux driver,
+ i.e. it uses the same device tree configuration.
+
endif
source "drivers/pinctrl/broadcom/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index df37c32..030c38f 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
obj-$(CONFIG_$(SPL_)PINCTRL_STMFX) += pinctrl-stmfx.o
obj-y += broadcom/
+obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2600.c b/drivers/pinctrl/aspeed/pinctrl_ast2600.c
index 12cba83..97e8b4e 100644
--- a/drivers/pinctrl/aspeed/pinctrl_ast2600.c
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2600.c
@@ -335,6 +335,102 @@ static struct aspeed_sig_desc pcie1rc_link[] = {
{ 0x500, BIT(24), 0 }, /* dedicate rc reset */
};
+static struct aspeed_sig_desc pwm0[] = {
+ {0x41c, BIT(16), 0},
+};
+
+static struct aspeed_sig_desc pwm1[] = {
+ {0x41c, BIT(17), 0},
+};
+
+static struct aspeed_sig_desc pwm2[] = {
+ {0x41c, BIT(18), 0},
+};
+
+static struct aspeed_sig_desc pwm3[] = {
+ {0x41c, BIT(19), 0},
+};
+
+static struct aspeed_sig_desc pwm4[] = {
+ {0x41c, BIT(20), 0},
+};
+
+static struct aspeed_sig_desc pwm5[] = {
+ {0x41c, BIT(21), 0},
+};
+
+static struct aspeed_sig_desc pwm6[] = {
+ {0x41c, BIT(22), 0},
+};
+
+static struct aspeed_sig_desc pwm7[] = {
+ {0x41c, BIT(23), 0},
+};
+
+static struct aspeed_sig_desc pwm8g0[] = {
+ {0x4B4, BIT(8), 0},
+};
+
+static struct aspeed_sig_desc pwm8g1[] = {
+ {0x41c, BIT(24), 0},
+};
+
+static struct aspeed_sig_desc pwm9g0[] = {
+ {0x4B4, BIT(9), 0},
+};
+
+static struct aspeed_sig_desc pwm9g1[] = {
+ {0x41c, BIT(25), 0},
+};
+
+static struct aspeed_sig_desc pwm10g0[] = {
+ {0x4B4, BIT(10), 0},
+};
+
+static struct aspeed_sig_desc pwm10g1[] = {
+ {0x41c, BIT(26), 0},
+};
+
+static struct aspeed_sig_desc pwm11g0[] = {
+ {0x4B4, BIT(11), 0},
+};
+
+static struct aspeed_sig_desc pwm11g1[] = {
+ {0x41c, BIT(27), 0},
+};
+
+static struct aspeed_sig_desc pwm12g0[] = {
+ {0x4B4, BIT(12), 0},
+};
+
+static struct aspeed_sig_desc pwm12g1[] = {
+ {0x41c, BIT(28), 0},
+};
+
+static struct aspeed_sig_desc pwm13g0[] = {
+ {0x4B4, BIT(13), 0},
+};
+
+static struct aspeed_sig_desc pwm13g1[] = {
+ {0x41c, BIT(29), 0},
+};
+
+static struct aspeed_sig_desc pwm14g0[] = {
+ {0x4B4, BIT(14), 0},
+};
+
+static struct aspeed_sig_desc pwm14g1[] = {
+ {0x41c, BIT(30), 0},
+};
+
+static struct aspeed_sig_desc pwm15g0[] = {
+ {0x4B4, BIT(15), 0},
+};
+
+static struct aspeed_sig_desc pwm15g1[] = {
+ {0x41c, BIT(31), 0},
+};
+
static const struct aspeed_group_config ast2600_groups[] = {
{ "MAC1LINK", ARRAY_SIZE(mac1_link), mac1_link },
{ "MAC2LINK", ARRAY_SIZE(mac2_link), mac2_link },
@@ -394,6 +490,30 @@ static const struct aspeed_group_config ast2600_groups[] = {
{ "USB2BH", ARRAY_SIZE(usb2bh_link), usb2bh_link },
{ "PCIE0RC", ARRAY_SIZE(pcie0rc_link), pcie0rc_link },
{ "PCIE1RC", ARRAY_SIZE(pcie1rc_link), pcie1rc_link },
+ { "PWM0", ARRAY_SIZE(pwm0), pwm0 },
+ { "PWM1", ARRAY_SIZE(pwm1), pwm1 },
+ { "PWM2", ARRAY_SIZE(pwm2), pwm2 },
+ { "PWM3", ARRAY_SIZE(pwm3), pwm3 },
+ { "PWM4", ARRAY_SIZE(pwm4), pwm4 },
+ { "PWM5", ARRAY_SIZE(pwm5), pwm5 },
+ { "PWM6", ARRAY_SIZE(pwm6), pwm6 },
+ { "PWM7", ARRAY_SIZE(pwm7), pwm7 },
+ { "PWM8G0", ARRAY_SIZE(pwm8g0), pwm8g0 },
+ { "PWM8G1", ARRAY_SIZE(pwm8g1), pwm8g1 },
+ { "PWM9G0", ARRAY_SIZE(pwm9g0), pwm9g0 },
+ { "PWM9G1", ARRAY_SIZE(pwm9g1), pwm9g1 },
+ { "PWM10G0", ARRAY_SIZE(pwm10g0), pwm10g0 },
+ { "PWM10G1", ARRAY_SIZE(pwm10g1), pwm10g1 },
+ { "PWM11G0", ARRAY_SIZE(pwm11g0), pwm11g0 },
+ { "PWM11G1", ARRAY_SIZE(pwm11g1), pwm11g1 },
+ { "PWM12G0", ARRAY_SIZE(pwm12g0), pwm12g0 },
+ { "PWM12G1", ARRAY_SIZE(pwm12g1), pwm12g1 },
+ { "PWM13G0", ARRAY_SIZE(pwm13g0), pwm13g0 },
+ { "PWM13G1", ARRAY_SIZE(pwm13g1), pwm13g1 },
+ { "PWM14G0", ARRAY_SIZE(pwm14g0), pwm14g0 },
+ { "PWM14G1", ARRAY_SIZE(pwm14g1), pwm14g1 },
+ { "PWM15G0", ARRAY_SIZE(pwm15g0), pwm15g0 },
+ { "PWM15G1", ARRAY_SIZE(pwm15g1), pwm15g1 },
};
static int ast2600_pinctrl_get_groups_count(struct udevice *dev)
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
new file mode 100644
index 0000000..7c5a02d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
@@ -0,0 +1,644 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx pinctrl driver for ZynqMP
+ *
+ * Author(s): Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * Copyright (C) 2021 Xilinx, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <zynqmp_firmware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/pinctrl.h>
+#include <linux/compat.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+
+#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12
+#define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12
+#define NUM_GROUPS_PER_RESP 6
+#define NA_GROUP -1
+#define RESERVED_GROUP -2
+#define MAX_GROUP_PIN 50
+#define MAX_PIN_GROUPS 50
+#define MAX_GROUP_NAME_LEN 32
+#define MAX_FUNC_NAME_LEN 16
+
+#define DRIVE_STRENGTH_2MA 2
+#define DRIVE_STRENGTH_4MA 4
+#define DRIVE_STRENGTH_8MA 8
+#define DRIVE_STRENGTH_12MA 12
+
+/*
+ * This driver works with very simple configuration that has the same name
+ * for group and function. This way it is compatible with the Linux Kernel
+ * driver.
+ */
+struct zynqmp_pinctrl_priv {
+ u32 npins;
+ u32 nfuncs;
+ u32 ngroups;
+ struct zynqmp_pmux_function *funcs;
+ struct zynqmp_pctrl_group *groups;
+};
+
+/**
+ * struct zynqmp_pinctrl_config - pinconfig parameters
+ * @slew: Slew rate slow or fast
+ * @bias: Bias enabled or disabled
+ * @pull_ctrl: Pull control pull up or pull down
+ * @input_type: CMOS or Schmitt
+ * @drive_strength: Drive strength 2mA/4mA/8mA/12mA
+ * @volt_sts: Voltage status 1.8V or 3.3V
+ * @tri_state: Tristate enabled or disabled
+ *
+ * This structure holds information about pin control config
+ * option that can be set for each pin.
+ */
+struct zynqmp_pinctrl_config {
+ u32 slew;
+ u32 bias;
+ u32 pull_ctrl;
+ u32 input_type;
+ u32 drive_strength;
+ u32 volt_sts;
+ u32 tri_state;
+};
+
+/**
+ * enum zynqmp_pin_config_param - possible pin configuration parameters
+ * @PIN_CONFIG_IOSTANDARD: if the pin can select an IO standard,
+ * the argument to this parameter (on a
+ * custom format) tells the driver which
+ * alternative IO standard to use
+ * @PIN_CONFIG_SCHMITTCMOS: this parameter (on a custom format) allows
+ * to select schmitt or cmos input for MIO pins
+ */
+enum zynqmp_pin_config_param {
+ PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1,
+ PIN_CONFIG_SCHMITTCMOS,
+};
+
+/**
+ * struct zynqmp_pmux_function - a pinmux function
+ * @name: Name of the pinmux function
+ * @groups: List of pingroups for this function
+ * @ngroups: Number of entries in @groups
+ *
+ * This structure holds information about pin control function
+ * and function group names supporting that function.
+ */
+struct zynqmp_pmux_function {
+ char name[MAX_FUNC_NAME_LEN];
+ const char * const *groups;
+ unsigned int ngroups;
+};
+
+/**
+ * struct zynqmp_pctrl_group - Pin control group info
+ * @name: Group name
+ * @pins: Group pin numbers
+ * @npins: Number of pins in group
+ */
+struct zynqmp_pctrl_group {
+ const char *name;
+ unsigned int pins[MAX_GROUP_PIN];
+ unsigned int npins;
+};
+
+static char pin_name[PINNAME_SIZE];
+
+/**
+ * zynqmp_pm_query_data() - Get query data from firmware
+ * @qid: Value of enum pm_query_id
+ * @arg1: Argument 1
+ * @arg2: Argument 2
+ * @out: Returned output value
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_query_data(enum pm_query_id qid, u32 arg1, u32 arg2, u32 *out)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ ret = xilinx_pm_request(PM_QUERY_DATA, qid, arg1, arg2, 0, ret_payload);
+ if (ret)
+ return ret;
+
+ *out = ret_payload[1];
+
+ return ret;
+}
+
+static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, u32 *value)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ /* Get config for the pin */
+ ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 0, 0, ret_payload);
+ if (ret) {
+ printf("%s failed\n", __func__);
+ return ret;
+ }
+
+ *value = ret_payload[1];
+
+ return ret;
+}
+
+static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, u32 value)
+{
+ int ret;
+
+ /* Request the pin first */
+ ret = xilinx_pm_request(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
+ if (ret) {
+ printf("%s: pin request failed\n", __func__);
+ return ret;
+ }
+
+ /* Set config for the pin */
+ ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, pin, param, value, 0, NULL);
+ if (ret) {
+ printf("%s failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+ fid, index, 0, ret_payload);
+ if (ret) {
+ printf("%s failed\n", __func__);
+ return ret;
+ }
+
+ memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN);
+
+ return ret;
+}
+
+static int zynqmp_pinctrl_prepare_func_groups(u32 fid,
+ struct zynqmp_pmux_function *func,
+ struct zynqmp_pctrl_group *groups)
+{
+ const char **fgroups;
+ char name[MAX_GROUP_NAME_LEN];
+ u16 resp[NUM_GROUPS_PER_RESP] = {0};
+ int ret, index, i;
+
+ fgroups = kcalloc(func->ngroups, sizeof(*fgroups), GFP_KERNEL);
+ if (!fgroups)
+ return -ENOMEM;
+
+ for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) {
+ ret = zynqmp_pinctrl_get_function_groups(fid, index, resp);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+ if (resp[i] == (u16)NA_GROUP)
+ goto done;
+ if (resp[i] == (u16)RESERVED_GROUP)
+ continue;
+
+ snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
+ func->name, index + i);
+ fgroups[index + i] = strdup(name);
+
+ snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
+ func->name, index + i);
+ groups[resp[i]].name = strdup(name);
+ }
+ }
+done:
+ func->groups = fgroups;
+
+ return ret;
+}
+
+static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_PIN_GROUPS,
+ pin, index, 0, ret_payload);
+ if (ret) {
+ printf("%s failed to get pin groups\n", __func__);
+ return ret;
+ }
+
+ memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN);
+
+ return ret;
+}
+
+static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group,
+ unsigned int pin)
+{
+ group->pins[group->npins++] = pin;
+}
+
+static int zynqmp_pinctrl_create_pin_groups(struct zynqmp_pctrl_group *groups,
+ unsigned int pin)
+{
+ u16 resp[NUM_GROUPS_PER_RESP] = {0};
+ int ret, i, index = 0;
+
+ do {
+ ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+ if (resp[i] == (u16)NA_GROUP)
+ goto done;
+ if (resp[i] == (u16)RESERVED_GROUP)
+ continue;
+ zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin);
+ }
+ index += NUM_GROUPS_PER_RESP;
+ } while (index <= MAX_PIN_GROUPS);
+
+done:
+ return ret;
+}
+
+static int zynqmp_pinctrl_probe(struct udevice *dev)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+ int ret, i;
+ u32 pin;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ /* Get number of pins first */
+ ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_PINS, 0, 0, &priv->npins);
+ if (ret) {
+ printf("%s failed to get no of pins\n", __func__);
+ return ret;
+ }
+
+ /* Get number of functions available */
+ ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_FUNCTIONS, 0, 0, &priv->nfuncs);
+ if (ret) {
+ printf("%s failed to get no of functions\n", __func__);
+ return ret;
+ }
+
+ /* Allocating structures for functions and its groups */
+ priv->funcs = kzalloc(sizeof(*priv->funcs) * priv->nfuncs, GFP_KERNEL);
+ if (!priv->funcs)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->nfuncs; i++) {
+ /* Get function name for the function and fill */
+ xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_NAME,
+ i, 0, 0, ret_payload);
+
+ memcpy((void *)priv->funcs[i].name, ret_payload, MAX_FUNC_NAME_LEN);
+
+ /* And fill number of groups available for certain function */
+ xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+ i, 0, 0, ret_payload);
+
+ priv->funcs[i].ngroups = ret_payload[1];
+ priv->ngroups += priv->funcs[i].ngroups;
+ }
+
+ /* Prepare all groups */
+ priv->groups = kzalloc(sizeof(*priv->groups) * priv->ngroups,
+ GFP_KERNEL);
+ if (!priv->groups)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->nfuncs; i++) {
+ ret = zynqmp_pinctrl_prepare_func_groups(i, &priv->funcs[i],
+ priv->groups);
+ if (ret) {
+ printf("Failed to prepare_func_groups\n");
+ return ret;
+ }
+ }
+
+ for (pin = 0; pin < priv->npins; pin++) {
+ ret = zynqmp_pinctrl_create_pin_groups(priv->groups, pin);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zynqmp_pinctrl_get_functions_count(struct udevice *dev)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->nfuncs;
+}
+
+static const char *zynqmp_pinctrl_get_function_name(struct udevice *dev,
+ unsigned int selector)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->funcs[selector].name;
+}
+
+static int zynqmp_pinmux_set(struct udevice *dev, unsigned int selector,
+ unsigned int func_selector)
+{
+ int ret;
+
+ /* Request the pin first */
+ ret = xilinx_pm_request(PM_PINCTRL_REQUEST, selector, 0, 0, 0, NULL);
+ if (ret) {
+ printf("%s: pin request failed\n", __func__);
+ return ret;
+ }
+
+ /* Set the pin function */
+ ret = xilinx_pm_request(PM_PINCTRL_SET_FUNCTION, selector, func_selector,
+ 0, 0, NULL);
+ if (ret) {
+ printf("%s: Failed to set pinmux function\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zynqmp_pinmux_group_set(struct udevice *dev, unsigned int selector,
+ unsigned int func_selector)
+{
+ int i;
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct zynqmp_pctrl_group *pgrp = &priv->groups[selector];
+
+ for (i = 0; i < pgrp->npins; i++)
+ zynqmp_pinmux_set(dev, pgrp->pins[i], func_selector);
+
+ return 0;
+}
+
+static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
+ unsigned int param, unsigned int arg)
+{
+ int ret = 0;
+ unsigned int value;
+
+ switch (param) {
+ case PIN_CONFIG_SLEW_RATE:
+ param = PM_PINCTRL_CONFIG_SLEW_RATE;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ param = PM_PINCTRL_CONFIG_PULL_CTRL;
+ arg = PM_PINCTRL_BIAS_PULL_UP;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ param = PM_PINCTRL_CONFIG_PULL_CTRL;
+ arg = PM_PINCTRL_BIAS_PULL_DOWN;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ param = PM_PINCTRL_CONFIG_BIAS_STATUS;
+ arg = PM_PINCTRL_BIAS_DISABLE;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_SCHMITTCMOS:
+ param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ switch (arg) {
+ case DRIVE_STRENGTH_2MA:
+ value = PM_PINCTRL_DRIVE_STRENGTH_2MA;
+ break;
+ case DRIVE_STRENGTH_4MA:
+ value = PM_PINCTRL_DRIVE_STRENGTH_4MA;
+ break;
+ case DRIVE_STRENGTH_8MA:
+ value = PM_PINCTRL_DRIVE_STRENGTH_8MA;
+ break;
+ case DRIVE_STRENGTH_12MA:
+ value = PM_PINCTRL_DRIVE_STRENGTH_12MA;
+ break;
+ default:
+ /* Invalid drive strength */
+ dev_warn(dev, "Invalid drive strength for pin %d\n", pin);
+ return -EINVAL;
+ }
+
+ param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, value);
+ break;
+ case PIN_CONFIG_IOSTANDARD:
+ param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
+ ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
+ if (arg != value)
+ dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
+ pin);
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
+ ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
+ if (arg != value)
+ dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
+ pin);
+ break;
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ case PIN_CONFIG_LOW_POWER_MODE:
+ /*
+ * This cases are mentioned in dts but configurable
+ * registers are unknown. So falling through to ignore
+ * boot time warnings as of now.
+ */
+ ret = 0;
+ break;
+ default:
+ dev_warn(dev, "unsupported configuration parameter '%u'\n",
+ param);
+ ret = -ENOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int zynqmp_pinconf_group_set(struct udevice *dev,
+ unsigned int group_selector,
+ unsigned int param, unsigned int arg)
+{
+ int i;
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct zynqmp_pctrl_group *pgrp = &priv->groups[group_selector];
+
+ for (i = 0; i < pgrp->npins; i++)
+ zynqmp_pinconf_set(dev, pgrp->pins[i], param, arg);
+
+ return 0;
+}
+
+static int zynqmp_pinctrl_get_pins_count(struct udevice *dev)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->npins;
+}
+
+static const char *zynqmp_pinctrl_get_pin_name(struct udevice *dev,
+ unsigned int selector)
+{
+ snprintf(pin_name, PINNAME_SIZE, "MIO%d", selector);
+
+ return pin_name;
+}
+
+static int zynqmp_pinctrl_get_pin_muxing(struct udevice *dev,
+ unsigned int selector,
+ char *buf,
+ int size)
+{
+ struct zynqmp_pinctrl_config pinmux;
+
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SLEW_RATE,
+ &pinmux.slew);
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_BIAS_STATUS,
+ &pinmux.bias);
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_PULL_CTRL,
+ &pinmux.pull_ctrl);
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+ &pinmux.input_type);
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
+ &pinmux.drive_strength);
+ zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
+ &pinmux.volt_sts);
+
+ switch (pinmux.drive_strength) {
+ case PM_PINCTRL_DRIVE_STRENGTH_2MA:
+ pinmux.drive_strength = DRIVE_STRENGTH_2MA;
+ break;
+ case PM_PINCTRL_DRIVE_STRENGTH_4MA:
+ pinmux.drive_strength = DRIVE_STRENGTH_4MA;
+ break;
+ case PM_PINCTRL_DRIVE_STRENGTH_8MA:
+ pinmux.drive_strength = DRIVE_STRENGTH_8MA;
+ break;
+ case PM_PINCTRL_DRIVE_STRENGTH_12MA:
+ pinmux.drive_strength = DRIVE_STRENGTH_12MA;
+ break;
+ default:
+ /* Invalid drive strength */
+ dev_warn(dev, "Invalid drive strength\n");
+ return -EINVAL;
+ }
+
+ snprintf(buf, size, "slew:%s\tbias:%s\tpull:%s\tinput:%s\tdrive:%dmA\tvolt:%s",
+ pinmux.slew ? "slow" : "fast",
+ pinmux.bias ? "enabled" : "disabled",
+ pinmux.pull_ctrl ? "up" : "down",
+ pinmux.input_type ? "schmitt" : "cmos",
+ pinmux.drive_strength,
+ pinmux.volt_sts ? "1.8" : "3.3");
+
+ return 0;
+}
+
+static int zynqmp_pinctrl_get_groups_count(struct udevice *dev)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->ngroups;
+}
+
+static const char *zynqmp_pinctrl_get_group_name(struct udevice *dev,
+ unsigned int selector)
+{
+ struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->groups[selector].name;
+}
+
+static const struct pinconf_param zynqmp_conf_params[] = {
+ { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+ { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+ { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
+ { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+ { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
+ { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
+ { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+ { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+ { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
+ { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+ { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+ { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
+ { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
+ { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
+ { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
+ { "output-high", PIN_CONFIG_OUTPUT, 1, },
+ { "output-low", PIN_CONFIG_OUTPUT, 0, },
+ { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
+ { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
+ { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
+ { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
+ /* zynqmp specific */
+ {"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18},
+ {"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, PM_PINCTRL_INPUT_TYPE_SCHMITT},
+};
+
+static struct pinctrl_ops zynqmp_pinctrl_ops = {
+ .get_pins_count = zynqmp_pinctrl_get_pins_count,
+ .get_pin_name = zynqmp_pinctrl_get_pin_name,
+ .get_pin_muxing = zynqmp_pinctrl_get_pin_muxing,
+ .set_state = pinctrl_generic_set_state,
+ .get_groups_count = zynqmp_pinctrl_get_groups_count,
+ .get_group_name = zynqmp_pinctrl_get_group_name,
+ .get_functions_count = zynqmp_pinctrl_get_functions_count,
+ .get_function_name = zynqmp_pinctrl_get_function_name,
+ .pinmux_group_set = zynqmp_pinmux_group_set,
+ .pinmux_set = zynqmp_pinmux_set,
+ .pinconf_params = zynqmp_conf_params,
+ .pinconf_group_set = zynqmp_pinconf_group_set,
+ .pinconf_set = zynqmp_pinconf_set,
+ .pinconf_num_params = ARRAY_SIZE(zynqmp_conf_params),
+};
+
+static const struct udevice_id zynqmp_pinctrl_ids[] = {
+ { .compatible = "xlnx,zynqmp-pinctrl" },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_zynqmp) = {
+ .name = "zynqmp-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = zynqmp_pinctrl_ids,
+ .priv_auto = sizeof(struct zynqmp_pinctrl_priv),
+ .ops = &zynqmp_pinctrl_ops,
+ .probe = zynqmp_pinctrl_probe,
+};
diff --git a/drivers/power/domain/zynqmp-power-domain.c b/drivers/power/domain/zynqmp-power-domain.c
index 5383d09..6943658 100644
--- a/drivers/power/domain/zynqmp-power-domain.c
+++ b/drivers/power/domain/zynqmp-power-domain.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <log.h>
#include <malloc.h>
#include <misc.h>
@@ -13,25 +14,6 @@
#include <zynqmp_firmware.h>
-#define NODE_ID_LOCATION 5
-
-static unsigned int xpm_configobject[] = {
- /* HEADER */
- 2, /* Number of remaining words in the header */
- 1, /* Number of sections included in config object */
- PM_CONFIG_OBJECT_TYPE_OVERLAY, /* Type of Config object as overlay */
- /* SLAVE SECTION */
-
- PM_CONFIG_SLAVE_SECTION_ID, /* Section ID */
- 1, /* Number of slaves */
-
- 0, /* Node ID which will be changed below */
- PM_SLAVE_FLAG_IS_SHAREABLE,
- PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK |
- PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK |
- PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK, /* IPI Mask */
-};
-
static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
const u32 qos, const enum zynqmp_pm_request_ack ack)
{
@@ -41,12 +23,9 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
static int zynqmp_power_domain_request(struct power_domain *power_domain)
{
- /* Record power domain id */
- xpm_configobject[NODE_ID_LOCATION] = power_domain->id;
-
- zynqmp_pmufw_load_config_object(xpm_configobject, sizeof(xpm_configobject));
+ dev_dbg(power_domain->dev, "Request for id: %ld\n", power_domain->id);
- return 0;
+ return zynqmp_pmufw_node(power_domain->id);
}
static int zynqmp_power_domain_free(struct power_domain *power_domain)
@@ -57,6 +36,8 @@ static int zynqmp_power_domain_free(struct power_domain *power_domain)
static int zynqmp_power_domain_on(struct power_domain *power_domain)
{
+ dev_dbg(power_domain->dev, "Domain ON for id: %ld\n", power_domain->id);
+
return zynqmp_pm_request_node(power_domain->id,
ZYNQMP_PM_CAPABILITY_ACCESS,
ZYNQMP_PM_MAX_QOS,
diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
index 3ddeaf4..2966bdc 100644
--- a/drivers/power/regulator/scmi_regulator.c
+++ b/drivers/power/regulator/scmi_regulator.c
@@ -38,7 +38,7 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev->parent->parent, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret)
return ret;
@@ -61,7 +61,7 @@ static int scmi_voltd_get_enable(struct udevice *dev)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev->parent->parent, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -85,7 +85,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev->parent->parent, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -104,7 +104,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev)
in, out);
int ret;
- ret = devm_scmi_process_msg(dev->parent->parent, &msg);
+ ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
@@ -147,7 +147,7 @@ static int scmi_regulator_probe(struct udevice *dev)
/* Check voltage domain is known from SCMI server */
in.domain_id = pdata->domain_id;
- ret = devm_scmi_process_msg(dev->parent->parent, &scmi_msg);
+ ret = devm_scmi_process_msg(dev, &scmi_msg);
if (ret) {
dev_err(dev, "Failed to query voltage domain %u: %d\n",
pdata->domain_id, ret);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 669d3fa..6be612d 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -9,6 +9,14 @@ config DM_PWM
frequency/period can be controlled along with the proportion of that
time that the signal is high.
+config PWM_ASPEED
+ bool "Enable support for the Aspeed PWM"
+ depends on DM_PWM
+ help
+ This PWM is found on Ast2600 SoCs. It supports a programmable period
+ and duty cycle. It provides 16 channels which can be independently
+ programmed.
+
config PWM_AT91
bool "Enable support for PWM found on AT91 SoC's"
depends on DM_PWM && ARCH_AT91
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 55f2bc0..5d31812 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -10,6 +10,7 @@
obj-$(CONFIG_DM_PWM) += pwm-uclass.o
+obj-$(CONFIG_PWM_ASPEED) += pwm-aspeed.o
obj-$(CONFIG_PWM_AT91) += pwm-at91.o
obj-$(CONFIG_PWM_CROS_EC) += cros_ec_pwm.o
obj-$(CONFIG_PWM_EXYNOS) += exynos_pwm.o
diff --git a/drivers/pwm/pwm-aspeed.c b/drivers/pwm/pwm-aspeed.c
new file mode 100644
index 0000000..ba98641
--- /dev/null
+++ b/drivers/pwm/pwm-aspeed.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Aspeed Technology Inc.
+ *
+ * PWM controller driver for Aspeed ast2600 SoCs.
+ * This drivers doesn't support earlier version of the IP.
+ *
+ * The formula of pwm period duration:
+ * period duration = ((DIV_L + 1) * (PERIOD + 1) << DIV_H) / input-clk
+ *
+ * The formula of pwm duty cycle duration:
+ * duty cycle duration = period duration * DUTY_CYCLE_FALLING_POINT / (PERIOD + 1)
+ * = ((DIV_L + 1) * DUTY_CYCLE_FALLING_POINT << DIV_H) / input-clk
+ *
+ * The software driver fixes the period to 255, which causes the high-frequency
+ * precision of the PWM to be coarse, in exchange for the fineness of the duty cycle.
+ *
+ * Register usage:
+ * PIN_ENABLE: When it is unset the pwm controller will always output low to the extern.
+ * Use to determine whether the PWM channel is enabled or disabled
+ * CLK_ENABLE: When it is unset the pwm controller will reset the duty counter to 0 and
+ * output low to the PIN_ENABLE mux after that the driver can still change the pwm period
+ * and duty and the value will apply when CLK_ENABLE be set again.
+ * Use to determine whether duty_cycle bigger than 0.
+ * PWM_ASPEED_CTRL_INVERSE: When it is toggled the output value will inverse immediately.
+ * PWM_ASPEED_DUTY_CYCLE_FALLING_POINT/PWM_ASPEED_DUTY_CYCLE_RISING_POINT: When these two
+ * values are equal it means the duty cycle = 100%.
+ *
+ * Limitations:
+ * - When changing both duty cycle and period, we cannot prevent in
+ * software that the output might produce a period with mixed
+ * settings.
+ * - Disabling the PWM doesn't complete the current period.
+ *
+ * Improvements:
+ * - When only changing one of duty cycle or period, our pwm controller will not
+ * generate the glitch, the configure will change at next cycle of pwm.
+ * This improvement can disable/enable through PWM_ASPEED_CTRL_DUTY_SYNC_DISABLE.
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <pwm.h>
+#include <clk.h>
+#include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dm/device_compat.h>
+#include <linux/math64.h>
+#include <linux/bitfield.h>
+#include <asm/io.h>
+
+/* The channel number of Aspeed pwm controller */
+#define PWM_ASPEED_NR_PWMS 16
+
+/* PWM Control Register */
+#define PWM_ASPEED_CTRL(ch) ((ch) * 0x10 + 0x00)
+#define PWM_ASPEED_CTRL_LOAD_SEL_RISING_AS_WDT BIT(19)
+#define PWM_ASPEED_CTRL_DUTY_LOAD_AS_WDT_ENABLE BIT(18)
+#define PWM_ASPEED_CTRL_DUTY_SYNC_DISABLE BIT(17)
+#define PWM_ASPEED_CTRL_CLK_ENABLE BIT(16)
+#define PWM_ASPEED_CTRL_LEVEL_OUTPUT BIT(15)
+#define PWM_ASPEED_CTRL_INVERSE BIT(14)
+#define PWM_ASPEED_CTRL_OPEN_DRAIN_ENABLE BIT(13)
+#define PWM_ASPEED_CTRL_PIN_ENABLE BIT(12)
+#define PWM_ASPEED_CTRL_CLK_DIV_H GENMASK(11, 8)
+#define PWM_ASPEED_CTRL_CLK_DIV_L GENMASK(7, 0)
+
+/* PWM Duty Cycle Register */
+#define PWM_ASPEED_DUTY_CYCLE(ch) ((ch) * 0x10 + 0x04)
+#define PWM_ASPEED_DUTY_CYCLE_PERIOD GENMASK(31, 24)
+#define PWM_ASPEED_DUTY_CYCLE_POINT_AS_WDT GENMASK(23, 16)
+#define PWM_ASPEED_DUTY_CYCLE_FALLING_POINT GENMASK(15, 8)
+#define PWM_ASPEED_DUTY_CYCLE_RISING_POINT GENMASK(7, 0)
+
+/* PWM fixed value */
+#define PWM_ASPEED_FIXED_PERIOD 0xff
+
+#define NSEC_PER_SEC 1000000000L
+
+struct aspeed_pwm_priv {
+ struct clk clk;
+ struct regmap *regmap;
+ struct reset_ctl reset;
+};
+
+static int aspeed_pwm_set_invert(struct udevice *dev, uint channel, bool polarity)
+{
+ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
+
+ if (channel >= PWM_ASPEED_NR_PWMS)
+ return -EINVAL;
+
+ regmap_update_bits(priv->regmap, PWM_ASPEED_CTRL(channel),
+ PWM_ASPEED_CTRL_INVERSE,
+ FIELD_PREP(PWM_ASPEED_CTRL_INVERSE,
+ polarity));
+ return 0;
+}
+
+static int aspeed_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
+
+ if (channel >= PWM_ASPEED_NR_PWMS)
+ return -EINVAL;
+
+ regmap_update_bits(priv->regmap, PWM_ASPEED_CTRL(channel),
+ PWM_ASPEED_CTRL_PIN_ENABLE,
+ enable ? PWM_ASPEED_CTRL_PIN_ENABLE : 0);
+ return 0;
+}
+
+static int aspeed_pwm_set_config(struct udevice *dev, uint channel,
+ uint period_ns, uint duty_ns)
+{
+ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
+ u32 duty_pt;
+ unsigned long rate;
+ u64 div_h, div_l, divisor;
+ bool clk_en;
+
+ if (channel >= PWM_ASPEED_NR_PWMS)
+ return -EINVAL;
+ dev_dbg(dev, "expect period: %dns, duty_cycle: %dns\n", period_ns,
+ duty_ns);
+
+ rate = clk_get_rate(&priv->clk);
+ /*
+ * Pick the smallest value for div_h so that div_l can be the biggest
+ * which results in a finer resolution near the target period value.
+ */
+ divisor = (u64)NSEC_PER_SEC * (PWM_ASPEED_FIXED_PERIOD + 1) *
+ (PWM_ASPEED_CTRL_CLK_DIV_L + 1);
+ div_h = order_base_2(div64_u64((u64)rate * period_ns + divisor - 1, divisor));
+ if (div_h > 0xf)
+ div_h = 0xf;
+
+ divisor = ((u64)NSEC_PER_SEC * (PWM_ASPEED_FIXED_PERIOD + 1)) << div_h;
+ div_l = div64_u64((u64)rate * period_ns, divisor);
+
+ if (div_l == 0)
+ return -ERANGE;
+
+ div_l -= 1;
+
+ if (div_l > 255)
+ div_l = 255;
+
+ dev_dbg(dev, "clk source: %ld div_h %lld, div_l : %lld\n", rate, div_h,
+ div_l);
+ /* duty_pt = duty_cycle * (PERIOD + 1) / period */
+ duty_pt = div64_u64(duty_ns * (u64)rate,
+ (u64)NSEC_PER_SEC * (div_l + 1) << div_h);
+ dev_dbg(dev, "duty_cycle = %d, duty_pt = %d\n", duty_ns,
+ duty_pt);
+
+ if (duty_pt == 0) {
+ clk_en = 0;
+ } else {
+ clk_en = 1;
+ if (duty_pt >= (PWM_ASPEED_FIXED_PERIOD + 1))
+ duty_pt = 0;
+ /*
+ * Fixed DUTY_CYCLE_PERIOD to its max value to get a
+ * fine-grained resolution for duty_cycle at the expense of a
+ * coarser period resolution.
+ */
+ regmap_update_bits(priv->regmap, PWM_ASPEED_DUTY_CYCLE(channel),
+ PWM_ASPEED_DUTY_CYCLE_PERIOD |
+ PWM_ASPEED_DUTY_CYCLE_RISING_POINT |
+ PWM_ASPEED_DUTY_CYCLE_FALLING_POINT,
+ FIELD_PREP(PWM_ASPEED_DUTY_CYCLE_PERIOD,
+ PWM_ASPEED_FIXED_PERIOD) |
+ FIELD_PREP(PWM_ASPEED_DUTY_CYCLE_FALLING_POINT,
+ duty_pt));
+ }
+
+ regmap_update_bits(priv->regmap, PWM_ASPEED_CTRL(channel),
+ PWM_ASPEED_CTRL_CLK_DIV_H |
+ PWM_ASPEED_CTRL_CLK_DIV_L |
+ PWM_ASPEED_CTRL_CLK_ENABLE,
+ FIELD_PREP(PWM_ASPEED_CTRL_CLK_DIV_H, div_h) |
+ FIELD_PREP(PWM_ASPEED_CTRL_CLK_DIV_L, div_l) |
+ FIELD_PREP(PWM_ASPEED_CTRL_CLK_ENABLE, clk_en));
+ return 0;
+}
+
+static int aspeed_pwm_probe(struct udevice *dev)
+{
+ int ret;
+ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
+ struct udevice *parent_dev = dev_get_parent(dev);
+
+ priv->regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
+ if (IS_ERR(priv->regmap)) {
+ dev_err(dev, "Couldn't get regmap\n");
+ return PTR_ERR(priv->regmap);
+ }
+
+ ret = clk_get_by_index(parent_dev, 0, &priv->clk);
+ if (ret < 0) {
+ dev_err(dev, "get clock failed\n");
+ return ret;
+ }
+
+ ret = reset_get_by_index(parent_dev, 0, &priv->reset);
+ if (ret) {
+ dev_err(dev, "get reset failed\n");
+ return ret;
+ }
+ ret = reset_deassert(&priv->reset);
+ if (ret) {
+ dev_err(dev, "cannot deassert reset control: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aspeed_pwm_remove(struct udevice *dev)
+{
+ struct aspeed_pwm_priv *priv = dev_get_priv(dev);
+
+ reset_assert(&priv->reset);
+
+ return 0;
+}
+
+static const struct pwm_ops aspeed_pwm_ops = {
+ .set_invert = aspeed_pwm_set_invert,
+ .set_config = aspeed_pwm_set_config,
+ .set_enable = aspeed_pwm_set_enable,
+};
+
+static const struct udevice_id aspeed_pwm_ids[] = {
+ { .compatible = "aspeed,ast2600-pwm" },
+ { }
+};
+
+U_BOOT_DRIVER(aspeed_pwm) = {
+ .name = "aspeed_pwm",
+ .id = UCLASS_PWM,
+ .of_match = aspeed_pwm_ids,
+ .ops = &aspeed_pwm_ops,
+ .probe = aspeed_pwm_probe,
+ .remove = aspeed_pwm_remove,
+ .priv_auto = sizeof(struct aspeed_pwm_priv),
+};
diff --git a/drivers/ram/aspeed/Kconfig b/drivers/ram/aspeed/Kconfig
index 576d5af..0deab86 100644
--- a/drivers/ram/aspeed/Kconfig
+++ b/drivers/ram/aspeed/Kconfig
@@ -1,66 +1,77 @@
-if RAM || SPL_RAM
+menuconfig ASPEED_RAM
+ bool "ASPEED SDRAM configuration"
+ depends on RAM && ARCH_ASPEED
+ default ARCH_ASPEED
+ help
+ Configuration options for DDR SDRAM on ASPEED systems.
+
+ RAM initialisation is always built in for the platform. This menu
+ allows customisation of the configuration used.
+
+if ASPEED_RAM
config ASPEED_DDR4_DUALX8
bool "Enable Dual X8 DDR4 die"
- depends on DM && OF_CONTROL && ARCH_ASPEED
+ depends on ASPEED_RAM
+ help
+ Say Y if dual X8 DDR4 die is used on the board. The ASPEED DDRM
+ SRAM controller needs to know if the memory chip mounted on the
+ board is dual x8 die or not, otherwise it may get the wrong
+ size of the memory space.
+
+config ASPEED_BYPASS_SELFTEST
+ depends on ASPEED_RAM
+ depends on ASPEED_AST2600
+ bool "Bypass self test during initialization"
+ help
+ Say Y here to bypass DRAM self test to speed up the boot time.
+
+config ASPEED_ECC
+ bool "ASPEED SDRAM ECC"
+ depends on ASPEED_RAM
+ depends on ASPEED_AST2600
help
- Say Y if dual X8 DDR4 die is used on the board. The aspeed ddr sdram
- controller needs to know if the memory chip mounted on the board is dual
- x8 die or not. Or it may get the wrong size of the memory space.
+ Enable SDRAM ECC function. This configures the SDRAM controller to
+ perform error detection and correction, sacrificing 1/9th of the
+ installed RAM to do so.
-if ASPEED_AST2600
+
+config ASPEED_ECC_SIZE
+ int "ECC size: 0=driver auto-caluated"
+ depends on ASPEED_ECC
+ default 0
+ help
+ SDRAM size with the error correcting code enabled. The unit is
+ in Megabytes. Noted that only the 8/9 of the configured size
+ can be used by the system. The remaining 1/9 will be used by
+ the ECC engine. If the size is set to 0, the sdram driver will
+ calculate the SDRAM size and set the whole range be ECC enabled.
choice
- prompt "DDR4 target date rate"
+ prompt "AST2600 DDR4 target date rate"
default ASPEED_DDR4_1600
+ depends on ASPEED_RAM
+ depends on ASPEED_AST2600
config ASPEED_DDR4_400
- bool "DDR4 targets at 400Mbps"
- depends on DM && OF_CONTROL && ARCH_ASPEED
+ bool "400Mbps"
help
select DDR4 target data rate at 400M
config ASPEED_DDR4_800
- bool "DDR4 targets at 800Mbps"
- depends on DM && OF_CONTROL && ARCH_ASPEED
+ bool "800Mbps"
help
select DDR4 target data rate at 800M
config ASPEED_DDR4_1333
- bool "DDR4 targets at 1333Mbps"
- depends on DM && OF_CONTROL && ARCH_ASPEED
+ bool "1333Mbps"
help
select DDR4 target data rate at 1333M
config ASPEED_DDR4_1600
- bool "DDR4 targets at 1600Mbps"
- depends on DM && OF_CONTROL && ARCH_ASPEED
+ bool "1600Mbps"
help
select DDR4 target data rate at 1600M
endchoice
-config ASPEED_BYPASS_SELFTEST
- bool "bypass self test during DRAM initialization"
- help
- Say Y here to bypass DRAM self test to speed up the boot time
-
-config ASPEED_ECC
- bool "aspeed SDRAM error correcting code"
- depends on DM && OF_CONTROL && ARCH_ASPEED
- help
- enable SDRAM ECC function
-
-if ASPEED_ECC
-config ASPEED_ECC_SIZE
- int "ECC size: 0=driver auto-caluated"
- depends on ASPEED_ECC
- default 0
- help
- SDRAM size with the error correcting code enabled. The unit is
- in Megabytes. Noted that only the 8/9 of the configured size
- can be used by the system. The remaining 1/9 will be used by
- the ECC engine. If the size is set to 0, the sdram driver will
- calculate the SDRAM size and set the whole range be ECC enabled.
-endif # end of ASPEED_ECC
-endif # end of ASPEED_AST2600
-endif # end of RAM || SPL_RAM
+endif # End of ASPEED_RAM
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
index ca0135a..850cb18 100644
--- a/drivers/reset/reset-scmi.c
+++ b/drivers/reset/reset-scmi.c
@@ -26,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert)
in, out);
int ret;
- ret = devm_scmi_process_msg(rst->dev->parent, &msg);
+ ret = devm_scmi_process_msg(rst->dev, &msg);
if (ret)
return ret;
@@ -58,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst)
* We don't really care about the attribute, just check
* the reset domain exists.
*/
- ret = devm_scmi_process_msg(rst->dev->parent, &msg);
+ ret = devm_scmi_process_msg(rst->dev, &msg);
if (ret)
return ret;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 71777cd..7a6c6ef 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -168,6 +168,14 @@ config RTC_MC146818
clock with a wide array of features and 50 bytes of general-purpose,
battery-backed RAM. The driver supports access to the clock and RAM.
+config MCFRTC
+ bool "Use common CF RTC driver"
+ depends on M68K
+
+config SYS_MCFRTC_BASE
+ hex "Base address for RTC in immap.h"
+ depends on MCFRTC
+
config RTC_M41T62
bool "Enable M41T62 driver"
help
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c
index e10638e..d2ac889 100644
--- a/drivers/rtc/mcfrtc.c
+++ b/drivers/rtc/mcfrtc.c
@@ -13,10 +13,6 @@
#undef RTC_DEBUG
-#ifndef CONFIG_SYS_MCFRTC_BASE
-#error RTC_BASE is not defined!
-#endif
-
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
#define STARTOFTIME 1970
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 345d188..76171e7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -133,6 +133,19 @@ config SERIAL_RX_BUFFER_SIZE
help
The size of the RX buffer (needs to be power of 2)
+config SERIAL_PUTS
+ bool "Enable printing strings all at once"
+ depends on DM_SERIAL
+ help
+ Some serial drivers are much more efficient when printing multiple
+ characters at once rather than printing characters individually. This
+ can be because they can load a fifo, or because individual print
+ calls have a constant overhead. With this option set, the serial
+ subsystem will try to provide serial drivers with as many characters
+ at once as possible, instead of printing characters one by one. Most
+ serial drivers do not need this config to print efficiently. If
+ unsure, say N.
+
config SERIAL_SEARCH_ALL
bool "Search for serial devices after default one failed"
depends on DM_SERIAL
@@ -399,6 +412,15 @@ config DEBUG_UART_SANDBOX
start up driver model. The driver will be available until the real
driver model serial is running.
+config DEBUG_UART_SEMIHOSTING
+ bool "semihosting"
+ depends on SEMIHOSTING_SERIAL
+ help
+ Select this to enable the debug UART using the semihosting driver.
+ This provides basic serial output from the console without needing to
+ start up driver model. The driver will be available until the real
+ driver model serial is running.
+
config DEBUG_UART_SIFIVE
bool "SiFive UART"
depends on SIFIVE_SERIAL
@@ -647,6 +669,10 @@ config FSL_LPUART
Select this to enable a Low Power UART for Freescale VF610 and
QorIQ Layerscape devices.
+config LPUART
+ bool "Use the LPUART as console"
+ depends on FSL_LPUART
+
config MVEBU_A3700_UART
bool "UART support for Armada 3700"
help
@@ -778,6 +804,19 @@ config SCIF_CONSOLE
on systems with RCar or SH SoCs, say Y to this option. If unsure,
say N.
+config SEMIHOSTING_SERIAL
+ bool "Semihosting UART support"
+ depends on SEMIHOSTING && !SERIAL_RX_BUFFER
+ help
+ Select this to enable a serial UART using semihosting. Special halt
+ instructions will be issued which an external debugger (such as a
+ JTAG emulator) may interpret. The debugger will display U-Boot's
+ console output on the host system.
+
+ Enable this option only if you are using a debugger which supports
+ semihosting. If you are not using a debugger, this driver will halt
+ the boot.
+
config UNIPHIER_SERIAL
bool "Support for UniPhier on-chip UART"
depends on ARCH_UNIPHIER
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 52e70aa..b68b5e7 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -52,6 +52,7 @@ endif
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+obj-$(CONFIG_SEMIHOSTING_SERIAL) += serial_semihosting.o
obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index f30f352..10d6b80 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -200,8 +200,30 @@ static void _serial_putc(struct udevice *dev, char ch)
static void _serial_puts(struct udevice *dev, const char *str)
{
- while (*str)
- _serial_putc(dev, *str++);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (!CONFIG_IS_ENABLED(SERIAL_PUTS) || !ops->puts) {
+ while (*str)
+ _serial_putc(dev, *str++);
+ return;
+ }
+
+ do {
+ const char *newline = strchrnul(str, '\n');
+ size_t len = newline - str + !!*newline;
+
+ do {
+ ssize_t written = ops->puts(dev, str, len);
+
+ if (written < 0)
+ return;
+ str += written;
+ len -= written;
+ } while (len);
+
+ if (*newline)
+ _serial_putc(dev, '\r');
+ } while (*str);
}
static int __serial_getc(struct udevice *dev)
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index ebbd219..6cdbb89 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -126,6 +126,7 @@ serial_initfunc(mxc_serial_initialize);
serial_initfunc(ns16550_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
serial_initfunc(pxa_serial_initialize);
+serial_initfunc(smh_serial_initialize);
serial_initfunc(sh_serial_initialize);
serial_initfunc(mtk_serial_initialize);
@@ -180,6 +181,7 @@ int serial_initialize(void)
ns16550_serial_initialize();
pl01x_serial_initialize();
pxa_serial_initialize();
+ smh_serial_initialize();
sh_serial_initialize();
mtk_serial_initialize();
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
new file mode 100644
index 0000000..62b1b22
--- /dev/null
+++ b/drivers/serial/serial_semihosting.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <semihosting.h>
+
+/**
+ * struct smh_serial_priv - Semihosting serial private data
+ * @infd: stdin file descriptor (or error)
+ */
+struct smh_serial_priv {
+ int infd;
+ int outfd;
+};
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+static int smh_serial_getc(struct udevice *dev)
+{
+ char ch = 0;
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ if (priv->infd < 0)
+ return smh_getc();
+
+ smh_read(priv->infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_putc(struct udevice *dev, const char ch)
+{
+ smh_putc(ch);
+ return 0;
+}
+
+static const struct dm_serial_ops smh_serial_ops = {
+ .putc = smh_serial_putc,
+ .getc = smh_serial_getc,
+};
+
+static int smh_serial_bind(struct udevice *dev)
+{
+ if (semihosting_enabled())
+ return 0;
+ return -ENOENT;
+}
+
+static int smh_serial_probe(struct udevice *dev)
+{
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ priv->infd = smh_open(":tt", MODE_READ);
+ return 0;
+}
+
+U_BOOT_DRIVER(smh_serial) = {
+ .name = "serial_semihosting",
+ .id = UCLASS_SERIAL,
+ .bind = smh_serial_bind,
+ .probe = smh_serial_probe,
+ .priv_auto = sizeof(struct smh_serial_priv),
+ .ops = &smh_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(smh_serial) = {
+ .name = "serial_semihosting",
+};
+#else /* DM_SERIAL */
+static int infd = -ENODEV;
+static int outfd = -ENODEV;
+
+static int smh_serial_start(void)
+{
+ infd = smh_open(":tt", MODE_READ);
+ outfd = smh_open(":tt", MODE_WRITE);
+ return 0;
+}
+
+static int smh_serial_stop(void)
+{
+ if (outfd >= 0)
+ smh_close(outfd);
+ return 0;
+}
+
+static void smh_serial_setbrg(void)
+{
+}
+
+static int smh_serial_getc(void)
+{
+ char ch = 0;
+
+ if (infd < 0)
+ return smh_getc();
+
+ smh_read(infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_tstc(void)
+{
+ return 1;
+}
+
+static void smh_serial_puts(const char *s)
+{
+ ulong unused;
+
+ if (outfd < 0)
+ smh_puts(s);
+ else
+ smh_write(outfd, s, strlen(s), &unused);
+}
+
+struct serial_device serial_smh_device = {
+ .name = "serial_smh",
+ .start = smh_serial_start,
+ .stop = smh_serial_stop,
+ .setbrg = smh_serial_setbrg,
+ .getc = smh_serial_getc,
+ .tstc = smh_serial_tstc,
+ .putc = smh_putc,
+ .puts = smh_serial_puts,
+};
+
+void smh_serial_initialize(void)
+{
+ if (semihosting_enabled())
+ serial_register(&serial_smh_device);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &serial_smh_device;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_UART_SEMIHOSTING
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ smh_putc(c);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c
index 85108df..47002f8 100644
--- a/drivers/spi/bcm63xx_hsspi.c
+++ b/drivers/spi/bcm63xx_hsspi.c
@@ -355,9 +355,7 @@ static int bcm63xx_hsspi_probe(struct udevice *dev)
if (ret < 0 && ret != -ENOSYS)
return ret;
- ret = clk_free(&clk);
- if (ret < 0 && ret != -ENOSYS)
- return ret;
+ clk_free(&clk);
/* get clock rate */
ret = clk_get_by_name(dev, "pll", &clk);
@@ -366,9 +364,7 @@ static int bcm63xx_hsspi_probe(struct udevice *dev)
priv->clk_rate = clk_get_rate(&clk);
- ret = clk_free(&clk);
- if (ret < 0 && ret != -ENOSYS)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
index dd5e62b..0600d56 100644
--- a/drivers/spi/bcm63xx_spi.c
+++ b/drivers/spi/bcm63xx_spi.c
@@ -391,9 +391,7 @@ static int bcm63xx_spi_probe(struct udevice *dev)
if (ret < 0)
return ret;
- ret = clk_free(&clk);
- if (ret < 0)
- return ret;
+ clk_free(&clk);
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 47bea0b..1c7d0ca 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -732,7 +732,7 @@ static int dw_spi_remove(struct udevice *bus)
if (ret)
return ret;
- ret = clk_free(&priv->clk);
+ clk_free(&priv->clk);
if (ret)
return ret;
#endif
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 8913142..8fad59b 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -96,6 +96,14 @@ config ATMEL_PIT_TIMER
it is designed to offer maximum accuracy and efficient management,
even for systems with long response time.
+config ATMEL_TCB_TIMER
+ bool "Atmel timer counter support"
+ depends on TIMER
+ depends on ARCH_AT91
+ help
+ Select this to enable the use of the timer counter as a monotonic
+ counter.
+
config CADENCE_TTC_TIMER
bool "Cadence TTC (Triple Timer Counter)"
depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index e2bd530..58da6c1 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARC_TIMER) += arc_timer.o
obj-$(CONFIG_AST_TIMER) += ast_timer.o
obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
+obj-$(CONFIG_ATMEL_TCB_TIMER) += atmel_tcb_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
diff --git a/drivers/timer/atmel_tcb_timer.c b/drivers/timer/atmel_tcb_timer.c
new file mode 100644
index 0000000..8c17987
--- /dev/null
+++ b/drivers/timer/atmel_tcb_timer.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Microchip Corporation
+ *
+ * Author: Clément Léger <clement.leger@bootlin.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+#define TCB_CHAN(chan) ((chan) * 0x40)
+
+#define TCB_CCR(chan) (0x0 + TCB_CHAN(chan))
+#define TCB_CCR_CLKEN (1 << 0)
+
+#define TCB_CMR(chan) (0x4 + TCB_CHAN(chan))
+#define TCB_CMR_WAVE (1 << 15)
+#define TCB_CMR_TIMER_CLOCK2 1
+#define TCB_CMR_XC1 6
+#define TCB_CMR_ACPA_SET (1 << 16)
+#define TCB_CMR_ACPC_CLEAR (2 << 18)
+
+#define TCB_CV(chan) (0x10 + TCB_CHAN(chan))
+
+#define TCB_RA(chan) (0x14 + TCB_CHAN(chan))
+#define TCB_RC(chan) (0x1c + TCB_CHAN(chan))
+
+#define TCB_IDR(chan) (0x28 + TCB_CHAN(chan))
+
+#define TCB_BCR 0xc0
+#define TCB_BCR_SYNC (1 << 0)
+
+#define TCB_BMR 0xc4
+#define TCB_BMR_TC1XC1S_TIOA0 (2 << 2)
+
+#define TCB_WPMR 0xe4
+#define TCB_WPMR_WAKEY 0x54494d
+
+#define TCB_CLK_DIVISOR 8
+struct atmel_tcb_plat {
+ void __iomem *base;
+};
+
+static u64 atmel_tcb_get_count(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+ u64 cv0 = 0;
+ u64 cv1 = 0;
+
+ do {
+ cv1 = readl(plat->base + TCB_CV(1));
+ cv0 = readl(plat->base + TCB_CV(0));
+ } while (readl(plat->base + TCB_CV(1)) != cv1);
+
+ cv0 |= cv1 << 32;
+
+ return cv0;
+}
+
+static void atmel_tcb_configure(void __iomem *base)
+{
+ /* Disable write protection */
+ writel(TCB_WPMR_WAKEY, base + TCB_WPMR);
+
+ /* Disable all irqs for both channel 0 & 1 */
+ writel(0xff, base + TCB_IDR(0));
+ writel(0xff, base + TCB_IDR(1));
+
+ /*
+ * In order to avoid wrapping, use a 64 bit counter by chaining
+ * two channels.
+ * Channel 0 is configured to generate a clock on TIOA0 which is cleared
+ * when reaching 0x80000000 and set when reaching 0.
+ */
+ writel(TCB_CMR_TIMER_CLOCK2 | TCB_CMR_WAVE | TCB_CMR_ACPA_SET
+ | TCB_CMR_ACPC_CLEAR, base + TCB_CMR(0));
+ writel(0x80000000, base + TCB_RC(0));
+ writel(0x1, base + TCB_RA(0));
+ writel(TCB_CCR_CLKEN, base + TCB_CCR(0));
+
+ /* Channel 1 is configured to use TIOA0 as input */
+ writel(TCB_CMR_XC1 | TCB_CMR_WAVE, base + TCB_CMR(1));
+ writel(TCB_CCR_CLKEN, base + TCB_CCR(1));
+
+ /* Set XC1 input to be TIOA0 (ie output of Channel 0) */
+ writel(TCB_BMR_TC1XC1S_TIOA0, base + TCB_BMR);
+
+ /* Sync & start all timers */
+ writel(TCB_BCR_SYNC, base + TCB_BCR);
+}
+
+static int atmel_tcb_probe(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct clk clk;
+ ulong clk_rate;
+ int ret;
+
+ if (!device_is_compatible(dev->parent, "atmel,sama5d2-tcb"))
+ return -EINVAL;
+
+ /* Currently, we only support channel 0 and 1 to be chained */
+ if (dev_read_addr_index(dev, 0) != 0 &&
+ dev_read_addr_index(dev, 1) != 1) {
+ printf("Error: only chained timers 0 and 1 are supported\n");
+ return -EINVAL;
+ }
+
+ ret = clk_get_by_name(dev->parent, "t0_clk", &clk);
+ if (ret)
+ return -EINVAL;
+
+ ret = clk_enable(&clk);
+ if (ret)
+ return ret;
+
+ clk_rate = clk_get_rate(&clk);
+ if (!clk_rate) {
+ clk_disable(&clk);
+ return -EINVAL;
+ }
+
+ uc_priv->clock_rate = clk_rate / TCB_CLK_DIVISOR;
+
+ atmel_tcb_configure(plat->base);
+
+ return 0;
+}
+
+static int atmel_tcb_of_to_plat(struct udevice *dev)
+{
+ struct atmel_tcb_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_read_addr_ptr(dev->parent);
+
+ return 0;
+}
+
+static const struct timer_ops atmel_tcb_ops = {
+ .get_count = atmel_tcb_get_count,
+};
+
+static const struct udevice_id atmel_tcb_ids[] = {
+ { .compatible = "atmel,tcb-timer" },
+ { }
+};
+
+U_BOOT_DRIVER(atmel_tcb) = {
+ .name = "atmel_tcb",
+ .id = UCLASS_TIMER,
+ .of_match = atmel_tcb_ids,
+ .of_to_plat = atmel_tcb_of_to_plat,
+ .plat_auto = sizeof(struct atmel_tcb_plat),
+ .probe = atmel_tcb_probe,
+ .ops = &atmel_tcb_ops,
+};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index ff8e11f..965b587 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -421,6 +421,23 @@ config VIDEO_LCD_ANX9804
from a parallel LCD interface and translate it on the fy into a DP
interface for driving eDP TFT displays. It uses I2C for configuration.
+config ATMEL_LCD
+ bool "Atmel LCD panel support"
+ depends on LCD && ARCH_AT91
+
+config ATMEL_LCD_BGR555
+ bool "Display in BGR555 mode"
+ help
+ Use the BGR555 output mode. Otherwise RGB565 is used.
+
+config VIDEO_BCM2835
+ bool "Display support for BCM2835"
+ help
+ The graphics processor already sets up the display so this driver
+ simply checks the resolution and then sets up the frame buffer with
+ that same resolution (or as near as possible) and 32bpp depth, so
+ that U-Boot can access it with full colour depth.
+
config VIDEO_LCD_ORISETECH_OTM8009A
bool "OTM8009A DSI LCD panel support"
depends on DM_VIDEO
@@ -601,21 +618,6 @@ config VIDEO_IVYBRIDGE_IGD
a special tool which configures the VGA ROM, but the graphics
resolution can be selected in U-Boot.
-config VIDEO_FSL_DCU_FB
- bool "Enable Freescale Display Control Unit"
- depends on VIDEO || DM_VIDEO
- help
- This enables support for Freescale Display Control Unit (DCU4)
- module found on Freescale Vybrid and QorIQ family of SoCs.
-
-config VIDEO_FSL_DCU_MAX_FB_SIZE_MB
- int "Freescale DCU framebuffer size"
- depends on VIDEO_FSL_DCU_FB
- default 4194304
- help
- Set maximum framebuffer size to be used for Freescale Display
- Controller Unit (DCU4).
-
source "drivers/video/rockchip/Kconfig"
config VIDEO_ARM_MALIDP
@@ -680,6 +682,14 @@ config VIDEO_SEPS525
Enable support for the Syncoam PM-OLED display driver (RGB 160x128).
Currently driver is supporting only SPI interface.
+config VIDEO_ZYNQMP_DPSUB
+ bool "Enable video support for ZynqMP Display Port"
+ depends on DM_VIDEO && ZYNQMP_POWER_DOMAIN
+ help
+ Enable support for Xilinx ZynqMP Display Port. Currently this file
+ is used as placeholder for driver. The main reason is to record
+ compatible string and calling power domain driver.
+
source "drivers/video/nexell/Kconfig"
config VIDEO
@@ -691,89 +701,9 @@ config VIDEO
model. Video drivers typically provide a colour text console and
cursor.
-config CFB_CONSOLE
- bool "Enable colour frame buffer console"
- depends on VIDEO || ARCH_OMAP2PLUS
- default y if VIDEO
- help
- Enables the colour frame buffer driver. This supports colour
- output on a bitmap display from an in-memory frame buffer.
- Several colour devices are supported along with various options to
- adjust the supported features. The driver is implemented in
- cfb_console.c
-
- The following defines are needed (cf. smiLynxEM, i8042)
- VIDEO_FB_LITTLE_ENDIAN graphic memory organisation
- (default big endian)
- VIDEO_HW_RECTFILL graphic chip supports
- rectangle fill (cf. smiLynxEM)
- VIDEO_HW_BITBLT graphic chip supports
- bit-blit (cf. smiLynxEM)
- VIDEO_VISIBLE_COLS visible pixel columns (cols=pitch)
- VIDEO_VISIBLE_ROWS visible pixel rows
- VIDEO_PIXEL_SIZE bytes per pixel
- VIDEO_DATA_FORMAT graphic data format
- (0-5, cf. cfb_console.c)
- VIDEO_FB_ADRS framebuffer address
- VIDEO_KBD_INIT_FCT keyboard int fct (i.e. rx51_kp_init())
- VIDEO_TSTC_FCT test char fct (i.e. rx51_kp_tstc)
- VIDEO_GETC_FCT get char fct (i.e. rx51_kp_getc)
- CONFIG_VIDEO_LOGO display Linux logo in upper left corner
- CONFIG_VIDEO_BMP_LOGO use bmp_logo.h instead of linux_logo.h
- for logo. Requires CONFIG_VIDEO_LOGO
- CONFIG_CONSOLE_EXTRA_INFO
- additional board info beside
- the logo
- CONFIG_HIDE_LOGO_VERSION
- do not display bootloader
- version string
-
- When CONFIG_CFB_CONSOLE is defined, the video console is the
- default console. The serial console can be forced by setting the
- environment 'console=serial'.
-
-config CFB_CONSOLE_ANSI
- bool "Support ANSI escape sequences"
- depends on CFB_CONSOLE
- help
- This allows the colour buffer frame buffer driver to support
- a limited number of ANSI escape sequences (cursor control,
- erase functions and limited graphics rendition control). Normal
- output from U-Boot will pass through this filter.
-
-config VGA_AS_SINGLE_DEVICE
- bool "Set the video as an output-only device"
- depends on CFB_CONSOLE
- default y
- help
- If enable the framebuffer device will be initialized as an
- output-only device. The Keyboard driver will not be set up. This
- may be used if you have no keyboard device, or more than one
- (USB Keyboard, AT Keyboard).
-
-config VIDEO_SW_CURSOR
- bool "Enable a software cursor"
- depends on CFB_CONSOLE
- default y if CFB_CONSOLE
- help
- This draws a cursor after the last character. No blinking is
- provided. This makes it possible to see the current cursor
- position when entering text on the console. It is recommended to
- enable this.
-
-config CONSOLE_EXTRA_INFO
- bool "Display additional board information"
- depends on CFB_CONSOLE
- help
- Display additional board information strings that normally go to
- the serial port. When this option is enabled, a board-specific
- function video_get_info_str() is called to get the string for
- each line of the display. The function should return the string,
- which can be empty if there is nothing to display for that line.
-
config CONSOLE_SCROLL_LINES
int "Number of lines to scroll the console by"
- depends on CFB_CONSOLE || DM_VIDEO || LCD
+ depends on DM_VIDEO || LCD
default 1
help
When the console need to be scrolled, this is the number of
@@ -781,28 +711,6 @@ config CONSOLE_SCROLL_LINES
console jump but can help speed up operation when scrolling
is slow.
-config SYS_CONSOLE_BG_COL
- hex "Background colour"
- depends on CFB_CONSOLE
- default 0x00
- help
- Defines the background colour for the console. The value is from
- 0x00 to 0xff and the meaning depends on the graphics card.
- Typically, 0x00 means black and 0xff means white. Do not set
- the background and foreground to the same colour or you will see
- nothing.
-
-config SYS_CONSOLE_FG_COL
- hex "Foreground colour"
- depends on CFB_CONSOLE
- default 0xa0
- help
- Defines the foreground colour for the console. The value is from
- 0x00 to 0xff and the meaning depends on the graphics card.
- Typically, 0x00 means black and 0xff means white. Do not set
- the background and foreground to the same colour or you will see
- nothing.
-
config LCD
bool "Enable legacy LCD support"
help
@@ -811,6 +719,18 @@ config LCD
CONFIG option. See the README for details. Drives which have been
converted to driver model will instead used CONFIG_DM_VIDEO.
+config LCD_INFO
+ bool "Show LCD info on-screen"
+ depends on LCD
+
+config LCD_LOGO
+ bool "Show a logo on screen"
+ depends on LCD
+
+config LCD_INFO_BELOW_LOGO
+ bool "Show LCD info below the on-screen logo"
+ depends on LCD_INFO && LCD_LOGO
+
config VIDEO_DW_HDMI
bool
help
@@ -988,7 +908,7 @@ config VIDEO_BMP_GZIP
config VIDEO_BMP_RLE8
bool "Run length encoded BMP image (RLE8) support"
- depends on DM_VIDEO || CFB_CONSOLE
+ depends on DM_VIDEO
help
If this option is set, the 8-bit RLE compressed BMP images
is supported.
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 4038395..2596580 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -30,9 +30,6 @@ obj-y += ti/
obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o
obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o
-obj-$(CONFIG_CFB_CONSOLE) += cfb_console.o
-obj-$(CONFIG_FORMIKE) += formike.o
-obj-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o
obj-$(CONFIG_IHS_VIDEO_OUT) += ihs_video_out.o
obj-$(CONFIG_LD9040) += ld9040.o
obj-$(CONFIG_LG4573) += lg4573.o
@@ -47,11 +44,9 @@ obj-$(CONFIG_VIDEO_ARM_MALIDP) += mali_dp.o
obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o
obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
-obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
obj-$(CONFIG_VIDEO_DW_MIPI_DSI) += dw_mipi_dsi.o
obj-$(CONFIG_VIDEO_EFI) += efi.o
-obj-$(CONFIG_VIDEO_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o
obj-$(CONFIG_VIDEO_IPUV3) += imx/
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
@@ -74,6 +69,7 @@ obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
obj-$(CONFIG_VIDEO_VESA) += vesa.o
obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
+obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp_dpsub.o
obj-y += bridge/
obj-y += sunxi/
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
deleted file mode 100644
index 52b109f..0000000
--- a/drivers/video/cfb_console.c
+++ /dev/null
@@ -1,1865 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2002 ELTEC Elektronik AG
- * Frank Gottschling <fgottschling@eltec.de>
- */
-
-/*
- * cfb_console.c
- *
- * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
- *
- * At the moment only the 8x16 font is tested and the font fore- and
- * background color is limited to black/white/gray colors. The Linux
- * logo can be placed in the upper left corner and additional board
- * information strings (that normally goes to serial port) can be drawn.
- *
- * The console driver can use a keyboard interface for character input
- * but this is deprecated. Only rk51 uses it.
- *
- * Character output goes to a memory-mapped video
- * framebuffer with little or big-endian organisation.
- * With environment setting 'console=serial' the console i/o can be
- * forced to serial port.
- *
- * The driver uses graphic specific defines/parameters/functions:
- *
- * (for SMI LynxE graphic chip)
- *
- * VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
- * VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
- * VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
- *
- * Console Parameters are set by graphic drivers global struct:
- *
- * VIDEO_VISIBLE_COLS - x resolution
- * VIDEO_VISIBLE_ROWS - y resolution
- * VIDEO_PIXEL_SIZE - storage size in byte per pixel
- * VIDEO_DATA_FORMAT - graphical data format GDF
- * VIDEO_FB_ADRS - start of video memory
- *
- * VIDEO_KBD_INIT_FCT - init function for keyboard
- * VIDEO_TSTC_FCT - keyboard_tstc function
- * VIDEO_GETC_FCT - keyboard_getc function
- *
- * CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
- * CONFIG_CONSOLE_EXTRA_INFO - display additional board information
- * strings that normaly goes to serial
- * port. This define requires a board
- * specific function:
- * video_drawstring (VIDEO_INFO_X,
- * VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
- * info);
- * that fills a info buffer at i=row.
- * s.a: board/eltec/bab7xx.
- *
- * CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last
- * character. No blinking is provided.
- * Uses the macros CURSOR_SET and
- * CURSOR_OFF.
- */
-
-#include <common.h>
-#include <command.h>
-#include <cpu_func.h>
-#include <env.h>
-#include <fdtdec.h>
-#include <gzip.h>
-#include <log.h>
-#include <version_string.h>
-#include <malloc.h>
-#include <video.h>
-#include <asm/global_data.h>
-#include <dm/ofnode.h>
-#include <linux/compiler.h>
-
-/*
- * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
- */
-#include <video_fb.h>
-
-#include <splash.h>
-
-/*
- * some Macros
- */
-#define VIDEO_VISIBLE_COLS (pGD->winSizeX)
-#define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
-#define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
-#define VIDEO_DATA_FORMAT (pGD->gdfIndex)
-#define VIDEO_FB_ADRS (pGD->frameAdrs)
-
-/*
- * Console device
- */
-
-#include <linux/types.h>
-#include <stdio_dev.h>
-#include <video_font.h>
-
-#if defined(CONFIG_CMD_DATE)
-#include <rtc.h>
-#endif
-
-#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
-#include <watchdog.h>
-#include <bmp_layout.h>
-#include <splash.h>
-#endif
-
-#if !defined(CONFIG_VIDEO_SW_CURSOR)
-/* no Cursor defined */
-#define CURSOR_ON
-#define CURSOR_OFF
-#define CURSOR_SET
-#endif
-
-#if defined(CONFIG_VIDEO_SW_CURSOR)
-void console_cursor(int state);
-
-#define CURSOR_ON console_cursor(1)
-#define CURSOR_OFF console_cursor(0)
-#define CURSOR_SET video_set_cursor()
-#endif /* CONFIG_VIDEO_SW_CURSOR */
-
-#define VIDEO_COLS VIDEO_VISIBLE_COLS
-#define VIDEO_ROWS VIDEO_VISIBLE_ROWS
-#ifndef VIDEO_LINE_LEN
-#define VIDEO_LINE_LEN (VIDEO_COLS * VIDEO_PIXEL_SIZE)
-#endif
-#define VIDEO_SIZE (VIDEO_ROWS * VIDEO_LINE_LEN)
-#define VIDEO_BURST_LEN (VIDEO_COLS/8)
-
-#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
-
-#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
-#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
-#define CONSOLE_ROW_FIRST (video_console_address)
-#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
-#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
-#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
-
-/* By default we scroll by a single line */
-#ifndef CONFIG_CONSOLE_SCROLL_LINES
-#define CONFIG_CONSOLE_SCROLL_LINES 1
-#endif
-
-/* Macros */
-#ifdef VIDEO_FB_LITTLE_ENDIAN
-#define SWAP16(x) ((((x) & 0x00ff) << 8) | \
- ((x) >> 8) \
- )
-#define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
- (((x) & 0x0000ff00) << 8) | \
- (((x) & 0x00ff0000) >> 8) | \
- (((x) & 0xff000000) >> 24) \
- )
-#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
- (((x) & 0x0000ff00) >> 8) | \
- (((x) & 0x00ff0000) << 8) | \
- (((x) & 0xff000000) >> 8) \
- )
-#else
-#define SWAP16(x) (x)
-#define SWAP32(x) (x)
-#if defined(VIDEO_FB_16BPP_WORD_SWAP)
-#define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
-#else
-#define SHORTSWAP32(x) (x)
-#endif
-#endif
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* Locals */
-static GraphicDevice *pGD; /* Pointer to Graphic array */
-
-static void *video_fb_address; /* frame buffer address */
-static void *video_console_address; /* console buffer start address */
-
-static int video_logo_height; /* not supported anymore */
-
-static int __maybe_unused cursor_state;
-static int __maybe_unused old_col;
-static int __maybe_unused old_row;
-
-static int console_col; /* cursor col */
-static int console_row; /* cursor row */
-
-static u32 eorx, fgx, bgx; /* color pats */
-
-static int cfb_do_flush_cache;
-
-#ifdef CONFIG_CFB_CONSOLE_ANSI
-static char ansi_buf[10];
-static int ansi_buf_size;
-static int ansi_colors_need_revert;
-static int ansi_cursor_hidden;
-#endif
-
-static const int video_font_draw_table8[] = {
- 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
- 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
- 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
- 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
-};
-
-static const int video_font_draw_table15[] = {
- 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
-};
-
-static const int video_font_draw_table16[] = {
- 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
-};
-
-static const int video_font_draw_table24[16][3] = {
- {0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00ffffff},
- {0x00000000, 0x0000ffff, 0xff000000},
- {0x00000000, 0x0000ffff, 0xffffffff},
- {0x000000ff, 0xffff0000, 0x00000000},
- {0x000000ff, 0xffff0000, 0x00ffffff},
- {0x000000ff, 0xffffffff, 0xff000000},
- {0x000000ff, 0xffffffff, 0xffffffff},
- {0xffffff00, 0x00000000, 0x00000000},
- {0xffffff00, 0x00000000, 0x00ffffff},
- {0xffffff00, 0x0000ffff, 0xff000000},
- {0xffffff00, 0x0000ffff, 0xffffffff},
- {0xffffffff, 0xffff0000, 0x00000000},
- {0xffffffff, 0xffff0000, 0x00ffffff},
- {0xffffffff, 0xffffffff, 0xff000000},
- {0xffffffff, 0xffffffff, 0xffffffff}
-};
-
-static const int video_font_draw_table32[16][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
- {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
- {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
- {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
- {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
- {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
- {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
- {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
- {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
- {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
- {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
- {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
- {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
- {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
- {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
-};
-
-/*
- * Implement a weak default function for boards that optionally
- * need to skip the cfb initialization.
- */
-__weak int board_cfb_skip(void)
-{
- /* As default, don't skip cfb init */
- return 0;
-}
-
-static void video_drawchars(int xx, int yy, unsigned char *s, int count)
-{
- u8 *cdat, *dest, *dest0;
- int rows, offset, c;
-
- offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
- dest0 = video_fb_address + offset;
-
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_INDEX:
- case GDF__8BIT_332RGB:
- while (count--) {
- c = *s;
- cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
- for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
- rows--; dest += VIDEO_LINE_LEN) {
- u8 bits = *cdat++;
-
- ((u32 *) dest)[0] =
- (video_font_draw_table8[bits >> 4] &
- eorx) ^ bgx;
-
- if (VIDEO_FONT_WIDTH == 4)
- continue;
-
- ((u32 *) dest)[1] =
- (video_font_draw_table8[bits & 15] &
- eorx) ^ bgx;
- }
- dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
- s++;
- }
- break;
-
- case GDF_15BIT_555RGB:
- while (count--) {
- c = *s;
- cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
- for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
- rows--; dest += VIDEO_LINE_LEN) {
- u8 bits = *cdat++;
-
- ((u32 *) dest)[0] =
- SHORTSWAP32((video_font_draw_table15
- [bits >> 6] & eorx) ^
- bgx);
- ((u32 *) dest)[1] =
- SHORTSWAP32((video_font_draw_table15
- [bits >> 4 & 3] & eorx) ^
- bgx);
-
- if (VIDEO_FONT_WIDTH == 4)
- continue;
-
- ((u32 *) dest)[2] =
- SHORTSWAP32((video_font_draw_table15
- [bits >> 2 & 3] & eorx) ^
- bgx);
- ((u32 *) dest)[3] =
- SHORTSWAP32((video_font_draw_table15
- [bits & 3] & eorx) ^
- bgx);
- }
- dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
- s++;
- }
- break;
-
- case GDF_16BIT_565RGB:
- while (count--) {
- c = *s;
- cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
- for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
- rows--; dest += VIDEO_LINE_LEN) {
- u8 bits = *cdat++;
-
- ((u32 *) dest)[0] =
- SHORTSWAP32((video_font_draw_table16
- [bits >> 6] & eorx) ^
- bgx);
- ((u32 *) dest)[1] =
- SHORTSWAP32((video_font_draw_table16
- [bits >> 4 & 3] & eorx) ^
- bgx);
-
- if (VIDEO_FONT_WIDTH == 4)
- continue;
-
- ((u32 *) dest)[2] =
- SHORTSWAP32((video_font_draw_table16
- [bits >> 2 & 3] & eorx) ^
- bgx);
- ((u32 *) dest)[3] =
- SHORTSWAP32((video_font_draw_table16
- [bits & 3] & eorx) ^
- bgx);
- }
- dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
- s++;
- }
- break;
-
- case GDF_32BIT_X888RGB:
- while (count--) {
- c = *s;
- cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
- for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
- rows--; dest += VIDEO_LINE_LEN) {
- u8 bits = *cdat++;
-
- ((u32 *) dest)[0] =
- SWAP32((video_font_draw_table32
- [bits >> 4][0] & eorx) ^ bgx);
- ((u32 *) dest)[1] =
- SWAP32((video_font_draw_table32
- [bits >> 4][1] & eorx) ^ bgx);
- ((u32 *) dest)[2] =
- SWAP32((video_font_draw_table32
- [bits >> 4][2] & eorx) ^ bgx);
- ((u32 *) dest)[3] =
- SWAP32((video_font_draw_table32
- [bits >> 4][3] & eorx) ^ bgx);
-
-
- if (VIDEO_FONT_WIDTH == 4)
- continue;
-
- ((u32 *) dest)[4] =
- SWAP32((video_font_draw_table32
- [bits & 15][0] & eorx) ^ bgx);
- ((u32 *) dest)[5] =
- SWAP32((video_font_draw_table32
- [bits & 15][1] & eorx) ^ bgx);
- ((u32 *) dest)[6] =
- SWAP32((video_font_draw_table32
- [bits & 15][2] & eorx) ^ bgx);
- ((u32 *) dest)[7] =
- SWAP32((video_font_draw_table32
- [bits & 15][3] & eorx) ^ bgx);
- }
- dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
- s++;
- }
- break;
-
- case GDF_24BIT_888RGB:
- while (count--) {
- c = *s;
- cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
- for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
- rows--; dest += VIDEO_LINE_LEN) {
- u8 bits = *cdat++;
-
- ((u32 *) dest)[0] =
- (video_font_draw_table24[bits >> 4][0]
- & eorx) ^ bgx;
- ((u32 *) dest)[1] =
- (video_font_draw_table24[bits >> 4][1]
- & eorx) ^ bgx;
- ((u32 *) dest)[2] =
- (video_font_draw_table24[bits >> 4][2]
- & eorx) ^ bgx;
-
- if (VIDEO_FONT_WIDTH == 4)
- continue;
-
- ((u32 *) dest)[3] =
- (video_font_draw_table24[bits & 15][0]
- & eorx) ^ bgx;
- ((u32 *) dest)[4] =
- (video_font_draw_table24[bits & 15][1]
- & eorx) ^ bgx;
- ((u32 *) dest)[5] =
- (video_font_draw_table24[bits & 15][2]
- & eorx) ^ bgx;
- }
- dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
- s++;
- }
- break;
- }
-}
-
-static inline void video_drawstring(int xx, int yy, unsigned char *s)
-{
- video_drawchars(xx, yy, s, strlen((char *) s));
-}
-
-static void video_putchar(int xx, int yy, unsigned char c)
-{
- video_drawchars(xx, yy + video_logo_height, &c, 1);
-}
-
-#if defined(CONFIG_VIDEO_SW_CURSOR)
-static void video_set_cursor(void)
-{
- if (cursor_state)
- console_cursor(0);
- console_cursor(1);
-}
-
-static void video_invertchar(int xx, int yy)
-{
- int firstx = xx * VIDEO_PIXEL_SIZE;
- int lastx = (xx + VIDEO_FONT_WIDTH) * VIDEO_PIXEL_SIZE;
- int firsty = yy * VIDEO_LINE_LEN;
- int lasty = (yy + VIDEO_FONT_HEIGHT) * VIDEO_LINE_LEN;
- int x, y;
- for (y = firsty; y < lasty; y += VIDEO_LINE_LEN) {
- for (x = firstx; x < lastx; x++) {
- u8 *dest = (u8 *)(video_fb_address) + x + y;
- *dest = ~*dest;
- }
- }
-}
-
-void console_cursor(int state)
-{
- if (cursor_state != state) {
- if (cursor_state) {
- /* turn off the cursor */
- video_invertchar(old_col * VIDEO_FONT_WIDTH,
- old_row * VIDEO_FONT_HEIGHT +
- video_logo_height);
- } else {
- /* turn off the cursor and record where it is */
- video_invertchar(console_col * VIDEO_FONT_WIDTH,
- console_row * VIDEO_FONT_HEIGHT +
- video_logo_height);
- old_col = console_col;
- old_row = console_row;
- }
- cursor_state = state;
- }
- if (cfb_do_flush_cache)
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
-}
-#endif
-
-#ifndef VIDEO_HW_RECTFILL
-static void memsetl(int *p, int c, int v)
-{
- while (c--)
- *(p++) = v;
-}
-#endif
-
-#ifndef VIDEO_HW_BITBLT
-static void memcpyl(int *d, int *s, int c)
-{
- while (c--)
- *(d++) = *(s++);
-}
-#endif
-
-static void console_clear_line(int line, int begin, int end)
-{
-#ifdef VIDEO_HW_RECTFILL
- video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
- VIDEO_FONT_WIDTH * begin, /* dest pos x */
- video_logo_height +
- VIDEO_FONT_HEIGHT * line, /* dest pos y */
- VIDEO_FONT_WIDTH * (end - begin + 1), /* fr. width */
- VIDEO_FONT_HEIGHT, /* frame height */
- bgx /* fill color */
- );
-#else
- if (begin == 0 && (end + 1) == CONSOLE_COLS) {
- memsetl(CONSOLE_ROW_FIRST +
- CONSOLE_ROW_SIZE * line, /* offset of row */
- CONSOLE_ROW_SIZE >> 2, /* length of row */
- bgx /* fill color */
- );
- } else {
- void *offset;
- int i, size;
-
- offset = CONSOLE_ROW_FIRST +
- CONSOLE_ROW_SIZE * line + /* offset of row */
- VIDEO_FONT_WIDTH *
- VIDEO_PIXEL_SIZE * begin; /* offset of col */
- size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
- size >>= 2; /* length to end for memsetl() */
- /* fill at col offset of i'th line using bgx as fill color */
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
- }
-#endif
-}
-
-static void console_scrollup(void)
-{
- const int rows = CONFIG_CONSOLE_SCROLL_LINES;
- int i;
-
- /* copy up rows ignoring the first one */
-
-#ifdef VIDEO_HW_BITBLT
- video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
- 0, /* source pos x */
- video_logo_height +
- VIDEO_FONT_HEIGHT * rows, /* source pos y */
- 0, /* dest pos x */
- video_logo_height, /* dest pos y */
- VIDEO_VISIBLE_COLS, /* frame width */
- VIDEO_VISIBLE_ROWS
- - video_logo_height
- - VIDEO_FONT_HEIGHT * rows /* frame height */
- );
-#else
- memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_FIRST + rows * CONSOLE_ROW_SIZE,
- (CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows) >> 2);
-#endif
- /* clear the last one */
- for (i = 1; i <= rows; i++)
- console_clear_line(CONSOLE_ROWS - i, 0, CONSOLE_COLS - 1);
-
- /* Decrement row number */
- console_row -= rows;
-}
-
-static void console_back(void)
-{
- console_col--;
-
- if (console_col < 0) {
- console_col = CONSOLE_COLS - 1;
- console_row--;
- if (console_row < 0)
- console_row = 0;
- }
-}
-
-#ifdef CONFIG_CFB_CONSOLE_ANSI
-
-static void console_clear(void)
-{
-#ifdef VIDEO_HW_RECTFILL
- video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
- 0, /* dest pos x */
- video_logo_height, /* dest pos y */
- VIDEO_VISIBLE_COLS, /* frame width */
- VIDEO_VISIBLE_ROWS, /* frame height */
- bgx /* fill color */
- );
-#else
- memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
-#endif
-}
-
-static void console_cursor_fix(void)
-{
- if (console_row < 0)
- console_row = 0;
- if (console_row >= CONSOLE_ROWS)
- console_row = CONSOLE_ROWS - 1;
- if (console_col < 0)
- console_col = 0;
- if (console_col >= CONSOLE_COLS)
- console_col = CONSOLE_COLS - 1;
-}
-
-static void console_cursor_up(int n)
-{
- console_row -= n;
- console_cursor_fix();
-}
-
-static void console_cursor_down(int n)
-{
- console_row += n;
- console_cursor_fix();
-}
-
-static void console_cursor_left(int n)
-{
- console_col -= n;
- console_cursor_fix();
-}
-
-static void console_cursor_right(int n)
-{
- console_col += n;
- console_cursor_fix();
-}
-
-static void console_cursor_set_position(int row, int col)
-{
- if (console_row != -1)
- console_row = row;
- if (console_col != -1)
- console_col = col;
- console_cursor_fix();
-}
-
-static void console_previousline(int n)
-{
- /* FIXME: also scroll terminal ? */
- console_row -= n;
- console_cursor_fix();
-}
-
-static void console_swap_colors(void)
-{
- eorx = fgx;
- fgx = bgx;
- bgx = eorx;
- eorx = fgx ^ bgx;
-}
-
-static inline int console_cursor_is_visible(void)
-{
- return !ansi_cursor_hidden;
-}
-#else
-static inline int console_cursor_is_visible(void)
-{
- return 1;
-}
-#endif
-
-static void console_newline(int n)
-{
- console_row += n;
- console_col = 0;
-
- /* Check if we need to scroll the terminal */
- if (console_row >= CONSOLE_ROWS) {
- /* Scroll everything up */
- console_scrollup();
- }
-}
-
-static void console_cr(void)
-{
- console_col = 0;
-}
-
-static void parse_putc(const char c)
-{
- static int nl = 1;
-
- if (console_cursor_is_visible())
- CURSOR_OFF;
-
- switch (c) {
- case 13: /* back to first column */
- console_cr();
- break;
-
- case '\n': /* next line */
- if (console_col || nl)
- console_newline(1);
- nl = 1;
- break;
-
- case 9: /* tab 8 */
- console_col |= 0x0008;
- console_col &= ~0x0007;
-
- if (console_col >= CONSOLE_COLS)
- console_newline(1);
- break;
-
- case 8: /* backspace */
- console_back();
- break;
-
- case 7: /* bell */
- break; /* ignored */
-
- default: /* draw the char */
- video_putchar(console_col * VIDEO_FONT_WIDTH,
- console_row * VIDEO_FONT_HEIGHT, c);
- console_col++;
-
- /* check for newline */
- if (console_col >= CONSOLE_COLS) {
- console_newline(1);
- nl = 0;
- }
- }
-
- if (console_cursor_is_visible())
- CURSOR_SET;
-}
-
-static void cfb_video_putc(struct stdio_dev *dev, const char c)
-{
-#ifdef CONFIG_CFB_CONSOLE_ANSI
- int i;
-
- if (c == 27) {
- for (i = 0; i < ansi_buf_size; ++i)
- parse_putc(ansi_buf[i]);
- ansi_buf[0] = 27;
- ansi_buf_size = 1;
- return;
- }
-
- if (ansi_buf_size > 0) {
- /*
- * 0 - ESC
- * 1 - [
- * 2 - num1
- * 3 - ..
- * 4 - ;
- * 5 - num2
- * 6 - ..
- * - cchar
- */
- int next = 0;
-
- int flush = 0;
- int fail = 0;
-
- int num1 = 0;
- int num2 = 0;
- int cchar = 0;
-
- ansi_buf[ansi_buf_size++] = c;
-
- if (ansi_buf_size >= sizeof(ansi_buf))
- fail = 1;
-
- for (i = 0; i < ansi_buf_size; ++i) {
- if (fail)
- break;
-
- switch (next) {
- case 0:
- if (ansi_buf[i] == 27)
- next = 1;
- else
- fail = 1;
- break;
-
- case 1:
- if (ansi_buf[i] == '[')
- next = 2;
- else
- fail = 1;
- break;
-
- case 2:
- if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
- num1 = ansi_buf[i]-'0';
- next = 3;
- } else if (ansi_buf[i] != '?') {
- --i;
- num1 = 1;
- next = 4;
- }
- break;
-
- case 3:
- if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
- num1 *= 10;
- num1 += ansi_buf[i]-'0';
- } else {
- --i;
- next = 4;
- }
- break;
-
- case 4:
- if (ansi_buf[i] != ';') {
- --i;
- next = 7;
- } else
- next = 5;
- break;
-
- case 5:
- if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
- num2 = ansi_buf[i]-'0';
- next = 6;
- } else
- fail = 1;
- break;
-
- case 6:
- if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
- num2 *= 10;
- num2 += ansi_buf[i]-'0';
- } else {
- --i;
- next = 7;
- }
- break;
-
- case 7:
- if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
- || ansi_buf[i] == 'J'
- || ansi_buf[i] == 'K'
- || ansi_buf[i] == 'h'
- || ansi_buf[i] == 'l'
- || ansi_buf[i] == 'm') {
- cchar = ansi_buf[i];
- flush = 1;
- } else
- fail = 1;
- break;
- }
- }
-
- if (fail) {
- for (i = 0; i < ansi_buf_size; ++i)
- parse_putc(ansi_buf[i]);
- ansi_buf_size = 0;
- return;
- }
-
- if (flush) {
- if (!ansi_cursor_hidden)
- CURSOR_OFF;
- ansi_buf_size = 0;
- switch (cchar) {
- case 'A':
- /* move cursor num1 rows up */
- console_cursor_up(num1);
- break;
- case 'B':
- /* move cursor num1 rows down */
- console_cursor_down(num1);
- break;
- case 'C':
- /* move cursor num1 columns forward */
- console_cursor_right(num1);
- break;
- case 'D':
- /* move cursor num1 columns back */
- console_cursor_left(num1);
- break;
- case 'E':
- /* move cursor num1 rows up at begin of row */
- console_previousline(num1);
- break;
- case 'F':
- /* move cursor num1 rows down at begin of row */
- console_newline(num1);
- break;
- case 'G':
- /* move cursor to column num1 */
- console_cursor_set_position(-1, num1-1);
- break;
- case 'H':
- /* move cursor to row num1, column num2 */
- console_cursor_set_position(num1-1, num2-1);
- break;
- case 'J':
- /* clear console and move cursor to 0, 0 */
- console_clear();
- console_cursor_set_position(0, 0);
- break;
- case 'K':
- /* clear line */
- if (num1 == 0)
- console_clear_line(console_row,
- console_col,
- CONSOLE_COLS-1);
- else if (num1 == 1)
- console_clear_line(console_row,
- 0, console_col);
- else
- console_clear_line(console_row,
- 0, CONSOLE_COLS-1);
- break;
- case 'h':
- ansi_cursor_hidden = 0;
- break;
- case 'l':
- ansi_cursor_hidden = 1;
- break;
- case 'm':
- if (num1 == 0) { /* reset swapped colors */
- if (ansi_colors_need_revert) {
- console_swap_colors();
- ansi_colors_need_revert = 0;
- }
- } else if (num1 == 7) { /* once swap colors */
- if (!ansi_colors_need_revert) {
- console_swap_colors();
- ansi_colors_need_revert = 1;
- }
- }
- break;
- }
- if (!ansi_cursor_hidden)
- CURSOR_SET;
- }
- } else {
- parse_putc(c);
- }
-#else
- parse_putc(c);
-#endif
- if (cfb_do_flush_cache)
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
-}
-
-static void cfb_video_puts(struct stdio_dev *dev, const char *s)
-{
- int flush = cfb_do_flush_cache;
- int count = strlen(s);
-
- /* temporarily disable cache flush */
- cfb_do_flush_cache = 0;
-
- while (count--)
- cfb_video_putc(dev, *s++);
-
- if (flush) {
- cfb_do_flush_cache = flush;
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
- }
-}
-
-/*
- * Do not enforce drivers (or board code) to provide empty
- * video_set_lut() if they do not support 8 bpp format.
- * Implement weak default function instead.
- */
-__weak void video_set_lut(unsigned int index, unsigned char r,
- unsigned char g, unsigned char b)
-{
-}
-
-#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
-
-#define FILL_8BIT_332RGB(r,g,b) { \
- *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
- fb ++; \
-}
-
-#define FILL_15BIT_555RGB(r,g,b) { \
- *(unsigned short *)fb = \
- SWAP16((unsigned short)(((r>>3)<<10) | \
- ((g>>3)<<5) | \
- (b>>3))); \
- fb += 2; \
-}
-
-#define FILL_16BIT_565RGB(r,g,b) { \
- *(unsigned short *)fb = \
- SWAP16((unsigned short)((((r)>>3)<<11)| \
- (((g)>>2)<<5) | \
- ((b)>>3))); \
- fb += 2; \
-}
-
-#define FILL_32BIT_X888RGB(r,g,b) { \
- *(u32 *)fb = \
- SWAP32((unsigned int)(((r<<16) | \
- (g<<8) | \
- b))); \
- fb += 4; \
-}
-
-#ifdef VIDEO_FB_LITTLE_ENDIAN
-#define FILL_24BIT_888RGB(r,g,b) { \
- fb[0] = b; \
- fb[1] = g; \
- fb[2] = r; \
- fb += 3; \
-}
-#else
-#define FILL_24BIT_888RGB(r,g,b) { \
- fb[0] = r; \
- fb[1] = g; \
- fb[2] = b; \
- fb += 3; \
-}
-#endif
-
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
-static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
-{
- ushort *dst = (ushort *) fb;
- ushort color = (ushort) (((r >> 3) << 10) |
- ((g >> 3) << 5) |
- (b >> 3));
- if (x & 1)
- *(--dst) = color;
- else
- *(++dst) = color;
-}
-#endif
-
-/*
- * RLE8 bitmap support
- */
-
-#ifdef CONFIG_VIDEO_BMP_RLE8
-/* Pre-calculated color table entry */
-struct palette {
- union {
- unsigned short w; /* word */
- unsigned int dw; /* double word */
- } ce; /* color entry */
-};
-
-/*
- * Helper to draw encoded/unencoded run.
- */
-static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
- int cnt, int enc)
-{
- ulong addr = (ulong) *fb;
- int *off;
- int enc_off = 1;
- int i;
-
- /*
- * Setup offset of the color index in the bitmap.
- * Color index of encoded run is at offset 1.
- */
- off = enc ? &enc_off : &i;
-
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_INDEX:
- for (i = 0; i < cnt; i++)
- *(unsigned char *) addr++ = bm[*off];
- break;
- case GDF_15BIT_555RGB:
- case GDF_16BIT_565RGB:
- /* differences handled while pre-calculating palette */
- for (i = 0; i < cnt; i++) {
- *(unsigned short *) addr = p[bm[*off]].ce.w;
- addr += 2;
- }
- break;
- case GDF_32BIT_X888RGB:
- for (i = 0; i < cnt; i++) {
- *(u32 *) addr = p[bm[*off]].ce.dw;
- addr += 4;
- }
- break;
- }
- *fb = (uchar *) addr; /* return modified address */
-}
-
-static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
- int width, int height)
-{
- unsigned char *bm;
- unsigned char *fbp;
- unsigned int cnt, runlen;
- int decode = 1;
- int x, y, bpp, i, ncolors;
- struct palette p[256];
- struct bmp_color_table_entry cte;
- int green_shift, red_off;
- int limit = (VIDEO_LINE_LEN / VIDEO_PIXEL_SIZE) * VIDEO_ROWS;
- int pixels = 0;
-
- x = 0;
- y = __le32_to_cpu(img->header.height) - 1;
- ncolors = __le32_to_cpu(img->header.colors_used);
- bpp = VIDEO_PIXEL_SIZE;
- fbp = (unsigned char *) ((unsigned int) video_fb_address +
- (y + yoff) * VIDEO_LINE_LEN +
- xoff * bpp);
-
- bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
-
- /* pre-calculate and setup palette */
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_INDEX:
- for (i = 0; i < ncolors; i++) {
- cte = img->color_table[i];
- video_set_lut(i, cte.red, cte.green, cte.blue);
- }
- break;
- case GDF_15BIT_555RGB:
- case GDF_16BIT_565RGB:
- if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
- green_shift = 3;
- red_off = 10;
- } else {
- green_shift = 2;
- red_off = 11;
- }
- for (i = 0; i < ncolors; i++) {
- cte = img->color_table[i];
- p[i].ce.w = SWAP16((unsigned short)
- (((cte.red >> 3) << red_off) |
- ((cte.green >> green_shift) << 5) |
- cte.blue >> 3));
- }
- break;
- case GDF_32BIT_X888RGB:
- for (i = 0; i < ncolors; i++) {
- cte = img->color_table[i];
- p[i].ce.dw = SWAP32((cte.red << 16) |
- (cte.green << 8) |
- cte.blue);
- }
- break;
- default:
- printf("RLE Bitmap unsupported in video mode 0x%x\n",
- VIDEO_DATA_FORMAT);
- return -1;
- }
-
- while (decode) {
- switch (bm[0]) {
- case 0:
- switch (bm[1]) {
- case 0:
- /* scan line end marker */
- bm += 2;
- x = 0;
- y--;
- fbp = (unsigned char *)
- ((unsigned int) video_fb_address +
- (y + yoff) * VIDEO_LINE_LEN +
- xoff * bpp);
- continue;
- case 1:
- /* end of bitmap data marker */
- decode = 0;
- break;
- case 2:
- /* run offset marker */
- x += bm[2];
- y -= bm[3];
- fbp = (unsigned char *)
- ((unsigned int) video_fb_address +
- (y + yoff) * VIDEO_LINE_LEN +
- xoff * bpp);
- bm += 4;
- break;
- default:
- /* unencoded run */
- cnt = bm[1];
- runlen = cnt;
- pixels += cnt;
- if (pixels > limit)
- goto error;
-
- bm += 2;
- if (y < height) {
- if (x >= width) {
- x += runlen;
- goto next_run;
- }
- if (x + runlen > width)
- cnt = width - x;
- draw_bitmap(&fbp, bm, p, cnt, 0);
- x += runlen;
- }
-next_run:
- bm += runlen;
- if (runlen & 1)
- bm++; /* 0 padding if length is odd */
- }
- break;
- default:
- /* encoded run */
- cnt = bm[0];
- runlen = cnt;
- pixels += cnt;
- if (pixels > limit)
- goto error;
-
- if (y < height) { /* only draw into visible area */
- if (x >= width) {
- x += runlen;
- bm += 2;
- continue;
- }
- if (x + runlen > width)
- cnt = width - x;
- draw_bitmap(&fbp, bm, p, cnt, 1);
- x += runlen;
- }
- bm += 2;
- break;
- }
- }
-
- if (cfb_do_flush_cache)
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
-
- return 0;
-error:
- printf("Error: Too much encoded pixel data, validate your bitmap\n");
- return -1;
-}
-#endif
-
-/*
- * Display the BMP file located at address bmp_image.
- */
-int video_display_bitmap(ulong bmp_image, int x, int y)
-{
- ushort xcount, ycount;
- uchar *fb;
- struct bmp_image *bmp = (struct bmp_image *)bmp_image;
- uchar *bmap;
- ushort padded_line;
- unsigned long width, height, bpp;
- unsigned colors;
- unsigned long compression;
- struct bmp_color_table_entry cte;
-
-#ifdef CONFIG_VIDEO_BMP_GZIP
- unsigned char *dst = NULL;
- ulong len;
-#endif
-
- WATCHDOG_RESET();
-
- if (!((bmp->header.signature[0] == 'B') &&
- (bmp->header.signature[1] == 'M'))) {
-
-#ifdef CONFIG_VIDEO_BMP_GZIP
- /*
- * Could be a gzipped bmp image, try to decrompress...
- */
- len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
- dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
- if (dst == NULL) {
- printf("Error: malloc in gunzip failed!\n");
- return 1;
- }
- /*
- * NB: we need to force offset of +2
- * See doc/README.displaying-bmps
- */
- if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2,
- (uchar *) bmp_image,
- &len) != 0) {
- printf("Error: no valid bmp or bmp.gz image at %lx\n",
- bmp_image);
- free(dst);
- return 1;
- }
- if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
- printf("Image could be truncated "
- "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
- }
-
- /*
- * Set addr to decompressed image
- */
- bmp = (struct bmp_image *)(dst+2);
-
- if (!((bmp->header.signature[0] == 'B') &&
- (bmp->header.signature[1] == 'M'))) {
- printf("Error: no valid bmp.gz image at %lx\n",
- bmp_image);
- free(dst);
- return 1;
- }
-#else
- printf("Error: no valid bmp image at %lx\n", bmp_image);
- return 1;
-#endif /* CONFIG_VIDEO_BMP_GZIP */
- }
-
- width = le32_to_cpu(bmp->header.width);
- height = le32_to_cpu(bmp->header.height);
- bpp = le16_to_cpu(bmp->header.bit_count);
- colors = le32_to_cpu(bmp->header.colors_used);
- compression = le32_to_cpu(bmp->header.compression);
-
- debug("Display-bmp: %ld x %ld with %d colors\n",
- width, height, colors);
-
- if (compression != BMP_BI_RGB
-#ifdef CONFIG_VIDEO_BMP_RLE8
- && compression != BMP_BI_RLE8
-#endif
- ) {
- printf("Error: compression type %ld not supported\n",
- compression);
-#ifdef CONFIG_VIDEO_BMP_GZIP
- if (dst)
- free(dst);
-#endif
- return 1;
- }
-
- padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
-
-#ifdef CONFIG_SPLASH_SCREEN_ALIGN
- if (x == BMP_ALIGN_CENTER)
- x = max(0, (int)(VIDEO_VISIBLE_COLS - width) / 2);
- else if (x < 0)
- x = max(0, (int)(VIDEO_VISIBLE_COLS - width + x + 1));
-
- if (y == BMP_ALIGN_CENTER)
- y = max(0, (int)(VIDEO_VISIBLE_ROWS - height) / 2);
- else if (y < 0)
- y = max(0, (int)(VIDEO_VISIBLE_ROWS - height + y + 1));
-#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
-
- /*
- * Just ignore elements which are completely beyond screen
- * dimensions.
- */
- if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
- return 0;
-
- if ((x + width) > VIDEO_VISIBLE_COLS)
- width = VIDEO_VISIBLE_COLS - x;
- if ((y + height) > VIDEO_VISIBLE_ROWS)
- height = VIDEO_VISIBLE_ROWS - y;
-
- bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
- fb = (uchar *) (video_fb_address +
- ((y + height - 1) * VIDEO_LINE_LEN) +
- x * VIDEO_PIXEL_SIZE);
-
-#ifdef CONFIG_VIDEO_BMP_RLE8
- if (compression == BMP_BI_RLE8) {
- return display_rle8_bitmap(bmp, x, y, width, height);
- }
-#endif
-
- /* We handle only 4, 8, or 24 bpp bitmaps */
- switch (le16_to_cpu(bmp->header.bit_count)) {
- case 4:
- padded_line -= width / 2;
- ycount = height;
-
- switch (VIDEO_DATA_FORMAT) {
- case GDF_32BIT_X888RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- /*
- * Don't assume that 'width' is an
- * even number
- */
- for (xcount = 0; xcount < width; xcount++) {
- uchar idx;
-
- if (xcount & 1) {
- idx = *bmap & 0xF;
- bmap++;
- } else
- idx = *bmap >> 4;
- cte = bmp->color_table[idx];
- FILL_32BIT_X888RGB(cte.red, cte.green,
- cte.blue);
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- default:
- puts("4bpp bitmap unsupported with current "
- "video mode\n");
- break;
- }
- break;
-
- case 8:
- padded_line -= width;
- if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
- /* Copy colormap */
- for (xcount = 0; xcount < colors; ++xcount) {
- cte = bmp->color_table[xcount];
- video_set_lut(xcount, cte.red, cte.green,
- cte.blue);
- }
- }
- ycount = height;
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_INDEX:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- *fb++ = *bmap++;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF__8BIT_332RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- cte = bmp->color_table[*bmap++];
- FILL_8BIT_332RGB(cte.red, cte.green,
- cte.blue);
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_15BIT_555RGB:
- while (ycount--) {
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
- int xpos = x;
-#endif
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- cte = bmp->color_table[*bmap++];
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
- fill_555rgb_pswap(fb, xpos++, cte.red,
- cte.green,
- cte.blue);
- fb += 2;
-#else
- FILL_15BIT_555RGB(cte.red, cte.green,
- cte.blue);
-#endif
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_16BIT_565RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- cte = bmp->color_table[*bmap++];
- FILL_16BIT_565RGB(cte.red, cte.green,
- cte.blue);
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_32BIT_X888RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- cte = bmp->color_table[*bmap++];
- FILL_32BIT_X888RGB(cte.red, cte.green,
- cte.blue);
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_24BIT_888RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- cte = bmp->color_table[*bmap++];
- FILL_24BIT_888RGB(cte.red, cte.green,
- cte.blue);
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- }
- break;
- case 24:
- padded_line -= 3 * width;
- ycount = height;
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_332RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- FILL_8BIT_332RGB(bmap[2], bmap[1],
- bmap[0]);
- bmap += 3;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_15BIT_555RGB:
- while (ycount--) {
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
- int xpos = x;
-#endif
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
-#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
- fill_555rgb_pswap(fb, xpos++, bmap[2],
- bmap[1], bmap[0]);
- fb += 2;
-#else
- FILL_15BIT_555RGB(bmap[2], bmap[1],
- bmap[0]);
-#endif
- bmap += 3;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_16BIT_565RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- FILL_16BIT_565RGB(bmap[2], bmap[1],
- bmap[0]);
- bmap += 3;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_32BIT_X888RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- FILL_32BIT_X888RGB(bmap[2], bmap[1],
- bmap[0]);
- bmap += 3;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- case GDF_24BIT_888RGB:
- while (ycount--) {
- WATCHDOG_RESET();
- xcount = width;
- while (xcount--) {
- FILL_24BIT_888RGB(bmap[2], bmap[1],
- bmap[0]);
- bmap += 3;
- }
- bmap += padded_line;
- fb -= VIDEO_LINE_LEN + width *
- VIDEO_PIXEL_SIZE;
- }
- break;
- default:
- printf("Error: 24 bits/pixel bitmap incompatible "
- "with current video mode\n");
- break;
- }
- break;
- default:
- printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
- le16_to_cpu(bmp->header.bit_count));
- break;
- }
-
-#ifdef CONFIG_VIDEO_BMP_GZIP
- if (dst) {
- free(dst);
- }
-#endif
-
- if (cfb_do_flush_cache)
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
- return (0);
-}
-#endif
-
-static int cfb_fb_is_in_dram(void)
-{
- struct bd_info *bd = gd->bd;
- ulong start, end;
- int i;
-
- for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
- start = bd->bi_dram[i].start;
- end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
- if ((ulong)video_fb_address >= start &&
- (ulong)video_fb_address < end)
- return 1;
- }
-
- return 0;
-}
-
-void video_clear(void)
-{
- if (!video_fb_address)
- return;
-#ifdef VIDEO_HW_RECTFILL
- video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
- 0, /* dest pos x */
- 0, /* dest pos y */
- VIDEO_VISIBLE_COLS, /* frame width */
- VIDEO_VISIBLE_ROWS, /* frame height */
- bgx /* fill color */
- );
-#else
- memsetl(video_fb_address,
- (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);
-#endif
-}
-
-static int cfg_video_init(void)
-{
- unsigned char color8;
-
- pGD = video_hw_init();
- if (pGD == NULL)
- return -1;
-
- video_fb_address = (void *) VIDEO_FB_ADRS;
-
- cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
-
- /* Init drawing pats */
- switch (VIDEO_DATA_FORMAT) {
- case GDF__8BIT_INDEX:
- video_set_lut(0x01, CONFIG_SYS_CONSOLE_FG_COL,
- CONFIG_SYS_CONSOLE_FG_COL,
- CONFIG_SYS_CONSOLE_FG_COL);
- video_set_lut(0x00, CONFIG_SYS_CONSOLE_BG_COL,
- CONFIG_SYS_CONSOLE_BG_COL,
- CONFIG_SYS_CONSOLE_BG_COL);
- fgx = 0x01010101;
- bgx = 0x00000000;
- break;
- case GDF__8BIT_332RGB:
- color8 = ((CONFIG_SYS_CONSOLE_FG_COL & 0xe0) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) & 0x1c) |
- CONFIG_SYS_CONSOLE_FG_COL >> 6);
- fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
- color8;
- color8 = ((CONFIG_SYS_CONSOLE_BG_COL & 0xe0) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) & 0x1c) |
- CONFIG_SYS_CONSOLE_BG_COL >> 6);
- bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
- color8;
- break;
- case GDF_15BIT_555RGB:
- fgx = (((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 26) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 21) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 16) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 10) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 5) |
- (CONFIG_SYS_CONSOLE_FG_COL >> 3));
- bgx = (((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 26) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 21) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 16) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 10) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 5) |
- (CONFIG_SYS_CONSOLE_BG_COL >> 3));
- break;
- case GDF_16BIT_565RGB:
- fgx = (((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 27) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 2) << 21) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 16) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 3) << 11) |
- ((CONFIG_SYS_CONSOLE_FG_COL >> 2) << 5) |
- (CONFIG_SYS_CONSOLE_FG_COL >> 3));
- bgx = (((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 27) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 2) << 21) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 16) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 3) << 11) |
- ((CONFIG_SYS_CONSOLE_BG_COL >> 2) << 5) |
- (CONFIG_SYS_CONSOLE_BG_COL >> 3));
- break;
- case GDF_32BIT_X888RGB:
- fgx = (CONFIG_SYS_CONSOLE_FG_COL << 16) |
- (CONFIG_SYS_CONSOLE_FG_COL << 8) |
- CONFIG_SYS_CONSOLE_FG_COL;
- bgx = (CONFIG_SYS_CONSOLE_BG_COL << 16) |
- (CONFIG_SYS_CONSOLE_BG_COL << 8) |
- CONFIG_SYS_CONSOLE_BG_COL;
- break;
- case GDF_24BIT_888RGB:
- fgx = (CONFIG_SYS_CONSOLE_FG_COL << 24) |
- (CONFIG_SYS_CONSOLE_FG_COL << 16) |
- (CONFIG_SYS_CONSOLE_FG_COL << 8) |
- CONFIG_SYS_CONSOLE_FG_COL;
- bgx = (CONFIG_SYS_CONSOLE_BG_COL << 24) |
- (CONFIG_SYS_CONSOLE_BG_COL << 16) |
- (CONFIG_SYS_CONSOLE_BG_COL << 8) |
- CONFIG_SYS_CONSOLE_BG_COL;
- break;
- }
- eorx = fgx ^ bgx;
-
- if (!CONFIG_IS_ENABLED(NO_FB_CLEAR))
- video_clear();
-
-#ifdef CONFIG_VIDEO_LOGO
- /* Plot the logo and get start point of console */
- debug("Video: Drawing the logo ...\n");
- video_console_address = video_logo();
-#else
- video_console_address = video_fb_address;
-#endif
-
- /* Initialize the console */
- console_col = 0;
- console_row = 0;
-
- if (cfb_do_flush_cache)
- flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
-
- return 0;
-}
-
-/*
- * Implement a weak default function for boards that optionally
- * need to skip the video initialization.
- */
-__weak int board_video_skip(void)
-{
- /* As default, don't skip test */
- return 0;
-}
-
-int drv_video_init(void)
-{
- struct stdio_dev console_dev;
- bool have_keyboard;
- bool __maybe_unused keyboard_ok = false;
-
- /* Check if video initialization should be skipped */
- if (board_video_skip())
- return 0;
-
- /* Init video chip - returns with framebuffer cleared */
- if (cfg_video_init() == -1)
- return 0;
-
- if (board_cfb_skip())
- return 0;
-
-#if defined(CONFIG_VGA_AS_SINGLE_DEVICE)
- have_keyboard = false;
-#elif defined(CONFIG_OF_CONTROL)
- have_keyboard = !ofnode_conf_read_bool("u-boot,no-keyboard");
-#else
- have_keyboard = true;
-#endif
- if (have_keyboard) {
- debug("KBD: Keyboard init ...\n");
-#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
- keyboard_ok = !(VIDEO_KBD_INIT_FCT == -1);
-#endif
- }
-
- /* Init vga device */
- memset(&console_dev, 0, sizeof(console_dev));
- strcpy(console_dev.name, "vga");
- console_dev.flags = DEV_FLAGS_OUTPUT;
- console_dev.putc = cfb_video_putc; /* 'putc' function */
- console_dev.puts = cfb_video_puts; /* 'puts' function */
-
-#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
- if (have_keyboard && keyboard_ok) {
- /* Also init console device */
- console_dev.flags |= DEV_FLAGS_INPUT;
- console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
- console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
- }
-#endif
-
- if (stdio_register(&console_dev) != 0)
- return 0;
-
- /* Return success */
- return 1;
-}
-
-void video_position_cursor(unsigned col, unsigned row)
-{
- console_col = min(col, CONSOLE_COLS - 1);
- console_row = min(row, CONSOLE_ROWS - 1);
-}
-
-int video_get_pixel_width(void)
-{
- return VIDEO_VISIBLE_COLS;
-}
-
-int video_get_pixel_height(void)
-{
- return VIDEO_VISIBLE_ROWS;
-}
-
-int video_get_screen_rows(void)
-{
- return CONSOLE_ROWS;
-}
-
-int video_get_screen_columns(void)
-{
- return CONSOLE_COLS;
-}
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
deleted file mode 100644
index 462c318..0000000
--- a/drivers/video/da8xx-fb.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Porting to u-boot:
- *
- * (C) Copyright 2011
- * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
- *
- * Copyright (C) 2008-2009 MontaVista Software Inc.
- * Copyright (C) 2008-2009 Texas Instruments Inc
- *
- * Based on the LCD driver for TI Avalanche processors written by
- * Ajay Singh and Shalom Hai.
- */
-
-#include <common.h>
-#include <log.h>
-#include <malloc.h>
-#include <memalign.h>
-#include <video_fb.h>
-#include <asm/global_data.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/fb.h>
-
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-
-#include "videomodes.h"
-#include "da8xx-fb.h"
-
-#if !defined(DA8XX_LCD_CNTL_BASE)
-#define DA8XX_LCD_CNTL_BASE DAVINCI_LCD_CNTL_BASE
-#endif
-
-#define DRIVER_NAME "da8xx_lcdc"
-
-#define LCD_VERSION_1 1
-#define LCD_VERSION_2 2
-
-/* LCD Status Register */
-#define LCD_END_OF_FRAME1 (1 << 9)
-#define LCD_END_OF_FRAME0 (1 << 8)
-#define LCD_PL_LOAD_DONE (1 << 6)
-#define LCD_FIFO_UNDERFLOW (1 << 5)
-#define LCD_SYNC_LOST (1 << 2)
-
-/* LCD DMA Control Register */
-#define LCD_DMA_BURST_SIZE(x) ((x) << 4)
-#define LCD_DMA_BURST_1 0x0
-#define LCD_DMA_BURST_2 0x1
-#define LCD_DMA_BURST_4 0x2
-#define LCD_DMA_BURST_8 0x3
-#define LCD_DMA_BURST_16 0x4
-#define LCD_V1_END_OF_FRAME_INT_ENA (1 << 2)
-#define LCD_V2_END_OF_FRAME0_INT_ENA (1 << 8)
-#define LCD_V2_END_OF_FRAME1_INT_ENA (1 << 9)
-#define LCD_DUAL_FRAME_BUFFER_ENABLE (1 << 0)
-
-#define LCD_V2_TFT_24BPP_MODE (1 << 25)
-#define LCD_V2_TFT_24BPP_UNPACK (1 << 26)
-
-/* LCD Control Register */
-#define LCD_CLK_DIVISOR(x) ((x) << 8)
-#define LCD_RASTER_MODE 0x01
-
-/* LCD Raster Control Register */
-#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20)
-#define PALETTE_AND_DATA 0x00
-#define PALETTE_ONLY 0x01
-#define DATA_ONLY 0x02
-
-#define LCD_MONO_8BIT_MODE (1 << 9)
-#define LCD_RASTER_ORDER (1 << 8)
-#define LCD_TFT_MODE (1 << 7)
-#define LCD_V1_UNDERFLOW_INT_ENA (1 << 6)
-#define LCD_V2_UNDERFLOW_INT_ENA (1 << 5)
-#define LCD_V1_PL_INT_ENA (1 << 4)
-#define LCD_V2_PL_INT_ENA (1 << 6)
-#define LCD_MONOCHROME_MODE (1 << 1)
-#define LCD_RASTER_ENABLE (1 << 0)
-#define LCD_TFT_ALT_ENABLE (1 << 23)
-#define LCD_STN_565_ENABLE (1 << 24)
-#define LCD_V2_DMA_CLK_EN (1 << 2)
-#define LCD_V2_LIDD_CLK_EN (1 << 1)
-#define LCD_V2_CORE_CLK_EN (1 << 0)
-#define LCD_V2_LPP_B10 26
-#define LCD_V2_TFT_24BPP_MODE (1 << 25)
-#define LCD_V2_TFT_24BPP_UNPACK (1 << 26)
-
-/* LCD Raster Timing 2 Register */
-#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
-#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8)
-#define LCD_SYNC_CTRL (1 << 25)
-#define LCD_SYNC_EDGE (1 << 24)
-#define LCD_INVERT_PIXEL_CLOCK (1 << 22)
-#define LCD_INVERT_LINE_CLOCK (1 << 21)
-#define LCD_INVERT_FRAME_CLOCK (1 << 20)
-
-/* Clock registers available only on Version 2 */
-#define LCD_CLK_MAIN_RESET (1 << 3)
-/* LCD Block */
-struct da8xx_lcd_regs {
- u32 revid;
- u32 ctrl;
- u32 stat;
- u32 lidd_ctrl;
- u32 lidd_cs0_conf;
- u32 lidd_cs0_addr;
- u32 lidd_cs0_data;
- u32 lidd_cs1_conf;
- u32 lidd_cs1_addr;
- u32 lidd_cs1_data;
- u32 raster_ctrl;
- u32 raster_timing_0;
- u32 raster_timing_1;
- u32 raster_timing_2;
- u32 raster_subpanel;
- u32 reserved;
- u32 dma_ctrl;
- u32 dma_frm_buf_base_addr_0;
- u32 dma_frm_buf_ceiling_addr_0;
- u32 dma_frm_buf_base_addr_1;
- u32 dma_frm_buf_ceiling_addr_1;
- u32 resv1;
- u32 raw_stat;
- u32 masked_stat;
- u32 int_ena_set;
- u32 int_ena_clr;
- u32 end_of_int_ind;
- /* Clock registers available only on Version 2 */
- u32 clk_ena;
- u32 clk_reset;
-};
-
-#define LCD_NUM_BUFFERS 1
-
-#define WSI_TIMEOUT 50
-#define PALETTE_SIZE 256
-#define LEFT_MARGIN 64
-#define RIGHT_MARGIN 64
-#define UPPER_MARGIN 32
-#define LOWER_MARGIN 32
-#define WAIT_FOR_FRAME_DONE true
-#define NO_WAIT_FOR_FRAME_DONE false
-
-#define calc_fbsize() (panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP)
-
-static struct da8xx_lcd_regs *da8xx_fb_reg_base;
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* graphics setup */
-static GraphicDevice gpanel;
-static const struct da8xx_panel *lcd_panel;
-static struct fb_info *da8xx_fb_info;
-static int bits_x_pixel;
-static unsigned int lcd_revision;
-const struct lcd_ctrl_config *da8xx_lcd_cfg;
-
-static inline unsigned int lcdc_read(u32 *addr)
-{
- return (unsigned int)readl(addr);
-}
-
-static inline void lcdc_write(unsigned int val, u32 *addr)
-{
- writel(val, addr);
-}
-
-struct da8xx_fb_par {
- u32 p_palette_base;
- unsigned char *v_palette_base;
- dma_addr_t vram_phys;
- unsigned long vram_size;
- void *vram_virt;
- unsigned int dma_start;
- unsigned int dma_end;
- struct clk *lcdc_clk;
- int irq;
- unsigned short pseudo_palette[16];
- unsigned int palette_sz;
- unsigned int pxl_clk;
- int blank;
- int vsync_flag;
- int vsync_timeout;
-};
-
-
-/* Variable Screen Information */
-static struct fb_var_screeninfo da8xx_fb_var = {
- .xoffset = 0,
- .yoffset = 0,
- .transp = {0, 0, 0},
- .nonstd = 0,
- .activate = 0,
- .height = -1,
- .width = -1,
- .pixclock = 46666, /* 46us - AUO display */
- .accel_flags = 0,
- .left_margin = LEFT_MARGIN,
- .right_margin = RIGHT_MARGIN,
- .upper_margin = UPPER_MARGIN,
- .lower_margin = LOWER_MARGIN,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_fix_screeninfo da8xx_fb_fix = {
- .id = "DA8xx FB Drv",
- .type = FB_TYPE_PACKED_PIXELS,
- .type_aux = 0,
- .visual = FB_VISUAL_PSEUDOCOLOR,
- .xpanstep = 0,
- .ypanstep = 1,
- .ywrapstep = 0,
- .accel = FB_ACCEL_NONE
-};
-
-/* Enable the Raster Engine of the LCD Controller */
-static inline void lcd_enable_raster(void)
-{
- u32 reg;
-
- /* Put LCDC in reset for several cycles */
- if (lcd_revision == LCD_VERSION_2)
- lcdc_write(LCD_CLK_MAIN_RESET,
- &da8xx_fb_reg_base->clk_reset);
-
- udelay(1000);
- /* Bring LCDC out of reset */
- if (lcd_revision == LCD_VERSION_2)
- lcdc_write(0,
- &da8xx_fb_reg_base->clk_reset);
-
- udelay(1000);
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);
- if (!(reg & LCD_RASTER_ENABLE))
- lcdc_write(reg | LCD_RASTER_ENABLE,
- &da8xx_fb_reg_base->raster_ctrl);
-}
-
-/* Disable the Raster Engine of the LCD Controller */
-static inline void lcd_disable_raster(bool wait_for_frame_done)
-{
- u32 reg;
- u32 loop_cnt = 0;
- u32 stat;
- u32 i = 0;
-
- if (wait_for_frame_done)
- loop_cnt = 5000;
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);
- if (reg & LCD_RASTER_ENABLE)
- lcdc_write(reg & ~LCD_RASTER_ENABLE,
- &da8xx_fb_reg_base->raster_ctrl);
-
- /* Wait for the current frame to complete */
- do {
- if (lcd_revision == LCD_VERSION_1)
- stat = lcdc_read(&da8xx_fb_reg_base->stat);
- else
- stat = lcdc_read(&da8xx_fb_reg_base->raw_stat);
-
- mdelay(1);
- } while (!(stat & 0x01) && (i++ < loop_cnt));
-
- if (lcd_revision == LCD_VERSION_1)
- lcdc_write(stat, &da8xx_fb_reg_base->stat);
- else
- lcdc_write(stat, &da8xx_fb_reg_base->raw_stat);
-
- if ((loop_cnt != 0) && (i >= loop_cnt)) {
- printf("LCD Controller timed out\n");
- return;
- }
-}
-
-static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
-{
- u32 start;
- u32 end;
- u32 reg_ras;
- u32 reg_dma;
- u32 reg_int;
-
- /* init reg to clear PLM (loading mode) fields */
- reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);
- reg_ras &= ~(3 << 20);
-
- reg_dma = lcdc_read(&da8xx_fb_reg_base->dma_ctrl);
-
- if (load_mode == LOAD_DATA) {
- start = par->dma_start;
- end = par->dma_end;
-
- reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
- if (lcd_revision == LCD_VERSION_1) {
- reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
- } else {
- reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) |
- LCD_V2_END_OF_FRAME0_INT_ENA |
- LCD_V2_END_OF_FRAME1_INT_ENA |
- LCD_V2_UNDERFLOW_INT_ENA | LCD_SYNC_LOST;
- lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set);
- }
-
-#if (LCD_NUM_BUFFERS == 2)
- reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
- lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1);
- lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1);
-#else
- reg_dma &= ~LCD_DUAL_FRAME_BUFFER_ENABLE;
- lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1);
- lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1);
-#endif
-
- } else if (load_mode == LOAD_PALETTE) {
- start = par->p_palette_base;
- end = start + par->palette_sz - 1;
-
- reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
- if (lcd_revision == LCD_VERSION_1) {
- reg_ras |= LCD_V1_PL_INT_ENA;
- } else {
- reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) |
- LCD_V2_PL_INT_ENA;
- lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set);
- }
-
- lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- }
-
- lcdc_write(reg_dma, &da8xx_fb_reg_base->dma_ctrl);
- lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl);
-
- /*
- * The Raster enable bit must be set after all other control fields are
- * set.
- */
- lcd_enable_raster();
-}
-
-/* Configure the Burst Size of DMA */
-static int lcd_cfg_dma(int burst_size)
-{
- u32 reg;
-
- reg = lcdc_read(&da8xx_fb_reg_base->dma_ctrl) & 0x00000001;
- switch (burst_size) {
- case 1:
- reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
- break;
- case 2:
- reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
- break;
- case 4:
- reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
- break;
- case 8:
- reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
- break;
- case 16:
- reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
- break;
- default:
- return -EINVAL;
- }
- lcdc_write(reg, &da8xx_fb_reg_base->dma_ctrl);
-
- return 0;
-}
-
-static void lcd_cfg_ac_bias(int period, int transitions_per_int)
-{
- u32 reg;
-
- /* Set the AC Bias Period and Number of Transitions per Interrupt */
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2) & 0xFFF00000;
- reg |= LCD_AC_BIAS_FREQUENCY(period) |
- LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2);
-}
-
-static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
- int front_porch)
-{
- u32 reg;
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0) & 0xf;
- reg |= ((back_porch & 0xff) << 24)
- | ((front_porch & 0xff) << 16)
- | ((pulse_width & 0x3f) << 10);
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0);
-}
-
-static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
- int front_porch)
-{
- u32 reg;
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1) & 0x3ff;
- reg |= ((back_porch & 0xff) << 24)
- | ((front_porch & 0xff) << 16)
- | ((pulse_width & 0x3f) << 10);
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1);
-}
-
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
-{
- u32 reg;
- u32 reg_int;
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(LCD_TFT_MODE |
- LCD_MONO_8BIT_MODE |
- LCD_MONOCHROME_MODE);
-
- switch (cfg->p_disp_panel->panel_shade) {
- case MONOCHROME:
- reg |= LCD_MONOCHROME_MODE;
- if (cfg->mono_8bit_mode)
- reg |= LCD_MONO_8BIT_MODE;
- break;
- case COLOR_ACTIVE:
- reg |= LCD_TFT_MODE;
- if (cfg->tft_alt_mode)
- reg |= LCD_TFT_ALT_ENABLE;
- break;
-
- case COLOR_PASSIVE:
- if (cfg->stn_565_mode)
- reg |= LCD_STN_565_ENABLE;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* enable additional interrupts here */
- if (lcd_revision == LCD_VERSION_1) {
- reg |= LCD_V1_UNDERFLOW_INT_ENA;
- } else {
- reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) |
- LCD_V2_UNDERFLOW_INT_ENA;
- lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set);
- }
-
- lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl);
-
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2);
-
- if (cfg->sync_ctrl)
- reg |= LCD_SYNC_CTRL;
- else
- reg &= ~LCD_SYNC_CTRL;
-
- if (cfg->sync_edge)
- reg |= LCD_SYNC_EDGE;
- else
- reg &= ~LCD_SYNC_EDGE;
-
- if (cfg->invert_line_clock)
- reg |= LCD_INVERT_LINE_CLOCK;
- else
- reg &= ~LCD_INVERT_LINE_CLOCK;
-
- if (cfg->invert_frm_clock)
- reg |= LCD_INVERT_FRAME_CLOCK;
- else
- reg &= ~LCD_INVERT_FRAME_CLOCK;
-
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2);
-
- return 0;
-}
-
-static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
- u32 bpp, u32 raster_order)
-{
- u32 reg;
-
- /* Set the Panel Width */
- /* Pixels per line = (PPL + 1)*16 */
- if (lcd_revision == LCD_VERSION_1) {
- /*
- * 0x3F in bits 4..9 gives max horizontal resolution = 1024
- * pixels
- */
- width &= 0x3f0;
- } else {
- /*
- * 0x7F in bits 4..10 gives max horizontal resolution = 2048
- * pixels.
- */
- width &= 0x7f0;
- }
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0);
- reg &= 0xfffffc00;
- if (lcd_revision == LCD_VERSION_1) {
- reg |= ((width >> 4) - 1) << 4;
- } else {
- width = (width >> 4) - 1;
- reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
- }
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0);
-
- /* Set the Panel Height */
- /* Set bits 9:0 of Lines Per Pixel */
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1);
- reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1);
-
- /* Set bit 10 of Lines Per Pixel */
- if (lcd_revision == LCD_VERSION_2) {
- reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2);
- reg |= ((height - 1) & 0x400) << 16;
- lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2);
- }
-
- /* Set the Raster Order of the Frame Buffer */
- reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(1 << 8);
- if (raster_order)
- reg |= LCD_RASTER_ORDER;
-
- if (bpp == 24)
- reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE);
- else if (bpp == 32)
- reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE
- | LCD_V2_TFT_24BPP_UNPACK);
-
- lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl);
-
- switch (bpp) {
- case 1:
- case 2:
- case 4:
- case 16:
- case 24:
- case 32:
- par->palette_sz = 16 * 2;
- break;
-
- case 8:
- par->palette_sz = 256 * 2;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct da8xx_fb_par *par = info->par;
- unsigned short *palette = (unsigned short *) par->v_palette_base;
- u_short pal;
- int update_hw = 0;
-
- if (regno > 255)
- return 1;
-
- if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
- return 1;
-
- if (info->var.bits_per_pixel == 8) {
- red >>= 4;
- green >>= 8;
- blue >>= 12;
-
- pal = (red & 0x0f00);
- pal |= (green & 0x00f0);
- pal |= (blue & 0x000f);
-
- if (palette[regno] != pal) {
- update_hw = 1;
- palette[regno] = pal;
- }
- } else if ((info->var.bits_per_pixel == 16) && regno < 16) {
- red >>= (16 - info->var.red.length);
- red <<= info->var.red.offset;
-
- green >>= (16 - info->var.green.length);
- green <<= info->var.green.offset;
-
- blue >>= (16 - info->var.blue.length);
- blue <<= info->var.blue.offset;
-
- par->pseudo_palette[regno] = red | green | blue;
-
- if (palette[0] != 0x4000) {
- update_hw = 1;
- palette[0] = 0x4000;
- }
- } else if (((info->var.bits_per_pixel == 32) && regno < 32) ||
- ((info->var.bits_per_pixel == 24) && regno < 24)) {
- red >>= (24 - info->var.red.length);
- red <<= info->var.red.offset;
-
- green >>= (24 - info->var.green.length);
- green <<= info->var.green.offset;
-
- blue >>= (24 - info->var.blue.length);
- blue <<= info->var.blue.offset;
-
- par->pseudo_palette[regno] = red | green | blue;
-
- if (palette[0] != 0x4000) {
- update_hw = 1;
- palette[0] = 0x4000;
- }
- }
-
- /* Update the palette in the h/w as needed. */
- if (update_hw)
- lcd_blit(LOAD_PALETTE, par);
-
- return 0;
-}
-
-static void lcd_reset(struct da8xx_fb_par *par)
-{
- /* Disable the Raster if previously Enabled */
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
-
- /* DMA has to be disabled */
- lcdc_write(0, &da8xx_fb_reg_base->dma_ctrl);
- lcdc_write(0, &da8xx_fb_reg_base->raster_ctrl);
-
- if (lcd_revision == LCD_VERSION_2) {
- lcdc_write(0, &da8xx_fb_reg_base->int_ena_set);
- /* Write 1 to reset */
- lcdc_write(LCD_CLK_MAIN_RESET, &da8xx_fb_reg_base->clk_reset);
- lcdc_write(0, &da8xx_fb_reg_base->clk_reset);
- }
-}
-
-static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
-{
- unsigned int lcd_clk, div;
-
- /* Get clock from sysclk2 */
- lcd_clk = clk_get(2);
-
- div = lcd_clk / par->pxl_clk;
- debug("LCD Clock: %d Divider: %d PixClk: %d\n",
- lcd_clk, div, par->pxl_clk);
-
- /* Configure the LCD clock divisor. */
- lcdc_write(LCD_CLK_DIVISOR(div) |
- (LCD_RASTER_MODE & 0x1), &da8xx_fb_reg_base->ctrl);
-
- if (lcd_revision == LCD_VERSION_2)
- lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
- LCD_V2_CORE_CLK_EN,
- &da8xx_fb_reg_base->clk_ena);
-}
-
-static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
- const struct da8xx_panel *panel)
-{
- u32 bpp;
- int ret = 0;
-
- lcd_reset(par);
-
- /* Calculate the divider */
- lcd_calc_clk_divider(par);
-
- if (panel->invert_pxl_clk)
- lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) |
- LCD_INVERT_PIXEL_CLOCK),
- &da8xx_fb_reg_base->raster_timing_2);
- else
- lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) &
- ~LCD_INVERT_PIXEL_CLOCK),
- &da8xx_fb_reg_base->raster_timing_2);
-
- /* Configure the DMA burst size. */
- ret = lcd_cfg_dma(cfg->dma_burst_sz);
- if (ret < 0)
- return ret;
-
- /* Configure the AC bias properties. */
- lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-
- /* Configure the vertical and horizontal sync properties. */
- lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
- lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
-
- /* Configure for display */
- ret = lcd_cfg_display(cfg);
- if (ret < 0)
- return ret;
-
- if ((QVGA != cfg->p_disp_panel->panel_type) &&
- (WVGA != cfg->p_disp_panel->panel_type))
- return -EINVAL;
-
- if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
- cfg->bpp >= cfg->p_disp_panel->min_bpp)
- bpp = cfg->bpp;
- else
- bpp = cfg->p_disp_panel->max_bpp;
- if (bpp == 12)
- bpp = 16;
- ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
- (unsigned int)panel->height, bpp,
- cfg->raster_order);
- if (ret < 0)
- return ret;
-
- /* Configure FDD */
- lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & 0xfff00fff) |
- (cfg->fdd << 12), &da8xx_fb_reg_base->raster_ctrl);
-
- return 0;
-}
-
-static void lcdc_dma_start(void)
-{
- struct da8xx_fb_par *par = da8xx_fb_info->par;
- lcdc_write(par->dma_start,
- &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(par->dma_end,
- &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- lcdc_write(0,
- &da8xx_fb_reg_base->dma_frm_buf_base_addr_1);
- lcdc_write(0,
- &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1);
-}
-
-static u32 lcdc_irq_handler_rev01(void)
-{
- struct da8xx_fb_par *par = da8xx_fb_info->par;
- u32 stat = lcdc_read(&da8xx_fb_reg_base->stat);
- u32 reg_ras;
-
- if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
- debug("LCD_SYNC_LOST\n");
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
- lcdc_write(stat, &da8xx_fb_reg_base->stat);
- lcd_enable_raster();
- return LCD_SYNC_LOST;
- } else if (stat & LCD_PL_LOAD_DONE) {
- debug("LCD_PL_LOAD_DONE\n");
- /*
- * Must disable raster before changing state of any control bit.
- * And also must be disabled before clearing the PL loading
- * interrupt via the following write to the status register. If
- * this is done after then one gets multiple PL done interrupts.
- */
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
-
- lcdc_write(stat, &da8xx_fb_reg_base->stat);
-
- /* Disable PL completion interrupt */
- reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl);
- reg_ras &= ~LCD_V1_PL_INT_ENA;
- lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl);
-
- /* Setup and start data loading mode */
- lcd_blit(LOAD_DATA, par);
- return LCD_PL_LOAD_DONE;
- } else {
- lcdc_write(stat, &da8xx_fb_reg_base->stat);
-
- if (stat & LCD_END_OF_FRAME0)
- debug("LCD_END_OF_FRAME0\n");
-
- lcdc_write(par->dma_start,
- &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(par->dma_end,
- &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- par->vsync_flag = 1;
- return LCD_END_OF_FRAME0;
- }
- return stat;
-}
-
-static u32 lcdc_irq_handler_rev02(void)
-{
- struct da8xx_fb_par *par = da8xx_fb_info->par;
- u32 stat = lcdc_read(&da8xx_fb_reg_base->masked_stat);
- u32 reg_int;
-
- if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
- debug("LCD_SYNC_LOST\n");
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
- lcdc_write(stat, &da8xx_fb_reg_base->masked_stat);
- lcd_enable_raster();
- lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind);
- return LCD_SYNC_LOST;
- } else if (stat & LCD_PL_LOAD_DONE) {
- debug("LCD_PL_LOAD_DONE\n");
- /*
- * Must disable raster before changing state of any control bit.
- * And also must be disabled before clearing the PL loading
- * interrupt via the following write to the status register. If
- * this is done after then one gets multiple PL done interrupts.
- */
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
-
- lcdc_write(stat, &da8xx_fb_reg_base->masked_stat);
-
- /* Disable PL completion interrupt */
- reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_clr) |
- (LCD_V2_PL_INT_ENA);
- lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_clr);
-
- /* Setup and start data loading mode */
- lcd_blit(LOAD_DATA, par);
- lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind);
- return LCD_PL_LOAD_DONE;
- } else {
- lcdc_write(stat, &da8xx_fb_reg_base->masked_stat);
-
- if (stat & LCD_END_OF_FRAME0)
- debug("LCD_END_OF_FRAME0\n");
-
- lcdc_write(par->dma_start,
- &da8xx_fb_reg_base->dma_frm_buf_base_addr_0);
- lcdc_write(par->dma_end,
- &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0);
- par->vsync_flag = 1;
- lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind);
- return LCD_END_OF_FRAME0;
- }
- lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind);
- return stat;
-}
-
-static u32 lcdc_irq_handler(void)
-{
- if (lcd_revision == LCD_VERSION_1)
- return lcdc_irq_handler_rev01();
- else
- return lcdc_irq_handler_rev02();
-}
-
-static u32 wait_for_event(u32 event)
-{
- u32 timeout = 50000;
- u32 ret;
-
- do {
- ret = lcdc_irq_handler();
- udelay(1000);
- --timeout;
- } while (!(ret & event) && timeout);
-
- if (!(ret & event)) {
- printf("%s: event %d not hit\n", __func__, event);
- return -1;
- }
-
- return 0;
-
-}
-
-void *video_hw_init(void)
-{
- struct da8xx_fb_par *par;
- u32 size;
- u32 rev;
- char *p;
-
- if (!lcd_panel) {
- printf("Display not initialized\n");
- return NULL;
- }
- gpanel.winSizeX = lcd_panel->width;
- gpanel.winSizeY = lcd_panel->height;
- gpanel.plnSizeX = lcd_panel->width;
- gpanel.plnSizeY = lcd_panel->height;
-
- switch (bits_x_pixel) {
- case 32:
- gpanel.gdfBytesPP = 4;
- gpanel.gdfIndex = GDF_32BIT_X888RGB;
- break;
- case 24:
- gpanel.gdfBytesPP = 4;
- gpanel.gdfIndex = GDF_32BIT_X888RGB;
- break;
- case 16:
- gpanel.gdfBytesPP = 2;
- gpanel.gdfIndex = GDF_16BIT_565RGB;
- break;
- default:
- gpanel.gdfBytesPP = 1;
- gpanel.gdfIndex = GDF__8BIT_INDEX;
- break;
- }
-
- da8xx_fb_reg_base = (struct da8xx_lcd_regs *)DA8XX_LCD_CNTL_BASE;
-
- /* Determine LCD IP Version */
- rev = lcdc_read(&da8xx_fb_reg_base->revid);
- switch (rev) {
- case 0x4C100102:
- lcd_revision = LCD_VERSION_1;
- break;
- case 0x4F200800:
- case 0x4F201000:
- lcd_revision = LCD_VERSION_2;
- break;
- default:
- printf("Unknown PID Reg value 0x%x, defaulting to LCD revision 1\n",
- rev);
- lcd_revision = LCD_VERSION_1;
- break;
- }
-
- debug("rev: 0x%x Resolution: %dx%d %d\n", rev,
- gpanel.winSizeX,
- gpanel.winSizeY,
- da8xx_lcd_cfg->bpp);
-
- size = sizeof(struct fb_info) + sizeof(struct da8xx_fb_par);
- da8xx_fb_info = malloc_cache_aligned(size);
- debug("da8xx_fb_info at %x\n", (unsigned int)da8xx_fb_info);
-
- if (!da8xx_fb_info) {
- printf("Memory allocation failed for fb_info\n");
- return NULL;
- }
- memset(da8xx_fb_info, 0, size);
- p = (char *)da8xx_fb_info;
- da8xx_fb_info->par = p + sizeof(struct fb_info);
- debug("da8xx_par at %x\n", (unsigned int)da8xx_fb_info->par);
-
- par = da8xx_fb_info->par;
- par->pxl_clk = lcd_panel->pxl_clk;
-
- if (lcd_init(par, da8xx_lcd_cfg, lcd_panel) < 0) {
- printf("lcd_init failed\n");
- goto err_release_fb;
- }
-
- /* allocate frame buffer */
- par->vram_size = lcd_panel->width * lcd_panel->height *
- da8xx_lcd_cfg->bpp;
- par->vram_size = par->vram_size * LCD_NUM_BUFFERS / 8;
-
- par->vram_virt = malloc_cache_aligned(par->vram_size);
-
- par->vram_phys = (dma_addr_t) par->vram_virt;
- debug("Requesting 0x%x bytes for framebuffer at 0x%x\n",
- (unsigned int)par->vram_size,
- (unsigned int)par->vram_virt);
- if (!par->vram_virt) {
- printf("GLCD: malloc for frame buffer failed\n");
- goto err_release_fb;
- }
- gd->fb_base = (int)par->vram_virt;
-
- gpanel.frameAdrs = (unsigned int)par->vram_virt;
- da8xx_fb_info->screen_base = (char *) par->vram_virt;
- da8xx_fb_fix.smem_start = gpanel.frameAdrs;
- da8xx_fb_fix.smem_len = par->vram_size;
- da8xx_fb_fix.line_length = (lcd_panel->width * da8xx_lcd_cfg->bpp) / 8;
-
- par->dma_start = par->vram_phys;
- par->dma_end = par->dma_start + lcd_panel->height *
- da8xx_fb_fix.line_length - 1;
-
- /* allocate palette buffer */
- par->v_palette_base = malloc_cache_aligned(PALETTE_SIZE);
- if (!par->v_palette_base) {
- printf("GLCD: malloc for palette buffer failed\n");
- goto err_release_fb_mem;
- }
- memset(par->v_palette_base, 0, PALETTE_SIZE);
- par->p_palette_base = (unsigned int)par->v_palette_base;
-
- /* Initialize par */
- da8xx_fb_info->var.bits_per_pixel = da8xx_lcd_cfg->bpp;
-
- da8xx_fb_var.xres = lcd_panel->width;
- da8xx_fb_var.xres_virtual = lcd_panel->width;
-
- da8xx_fb_var.yres = lcd_panel->height;
- da8xx_fb_var.yres_virtual = lcd_panel->height * LCD_NUM_BUFFERS;
-
- da8xx_fb_var.grayscale =
- da8xx_lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
- da8xx_fb_var.bits_per_pixel = da8xx_lcd_cfg->bpp;
-
- da8xx_fb_var.hsync_len = lcd_panel->hsw;
- da8xx_fb_var.vsync_len = lcd_panel->vsw;
-
- /* Initialize fbinfo */
- da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
- da8xx_fb_info->fix = da8xx_fb_fix;
- da8xx_fb_info->var = da8xx_fb_var;
- da8xx_fb_info->pseudo_palette = par->pseudo_palette;
- da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-
- /* Clear interrupt */
- memset((void *)par->vram_virt, 0, par->vram_size);
- lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE);
- if (lcd_revision == LCD_VERSION_1)
- lcdc_write(0xFFFF, &da8xx_fb_reg_base->stat);
- else
- lcdc_write(0xFFFF, &da8xx_fb_reg_base->masked_stat);
- debug("Palette at 0x%x size %d\n", par->p_palette_base,
- par->palette_sz);
- lcdc_dma_start();
-
- /* Load a default palette */
- fb_setcolreg(0, 0, 0, 0, 0xffff, da8xx_fb_info);
-
- /* Check that the palette is loaded */
- wait_for_event(LCD_PL_LOAD_DONE);
-
- /* Wait until DMA is working */
- wait_for_event(LCD_END_OF_FRAME0);
-
- return (void *)&gpanel;
-
-err_release_fb_mem:
- free(par->vram_virt);
-
-err_release_fb:
- free(da8xx_fb_info);
-
- return NULL;
-}
-
-void da8xx_video_init(const struct da8xx_panel *panel,
- const struct lcd_ctrl_config *lcd_cfg, int bits_pixel)
-{
- lcd_panel = panel;
- da8xx_lcd_cfg = lcd_cfg;
- bits_x_pixel = bits_pixel;
-}
diff --git a/drivers/video/da8xx-fb.h b/drivers/video/da8xx-fb.h
deleted file mode 100644
index 9b30d98..0000000
--- a/drivers/video/da8xx-fb.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Porting to u-boot:
- *
- * (C) Copyright 2011
- * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
- *
- * Copyright (C) 2008-2009 MontaVista Software Inc.
- * Copyright (C) 2008-2009 Texas Instruments Inc
- *
- * Based on the LCD driver for TI Avalanche processors written by
- * Ajay Singh and Shalom Hai.
- */
-
-#ifndef DA8XX_FB_H
-#define DA8XX_FB_H
-
-enum panel_type {
- QVGA = 0,
- WVGA
-};
-
-enum panel_shade {
- MONOCHROME = 0,
- COLOR_ACTIVE,
- COLOR_PASSIVE,
-};
-
-enum raster_load_mode {
- LOAD_DATA = 1,
- LOAD_PALETTE,
-};
-
-struct display_panel {
- enum panel_type panel_type; /* QVGA */
- int max_bpp;
- int min_bpp;
- enum panel_shade panel_shade;
-};
-
-struct da8xx_panel {
- const char name[25]; /* Full name <vendor>_<model> */
- unsigned short width;
- unsigned short height;
- int hfp; /* Horizontal front porch */
- int hbp; /* Horizontal back porch */
- int hsw; /* Horizontal Sync Pulse Width */
- int vfp; /* Vertical front porch */
- int vbp; /* Vertical back porch */
- int vsw; /* Vertical Sync Pulse Width */
- unsigned int pxl_clk; /* Pixel clock */
- unsigned char invert_pxl_clk; /* Invert Pixel clock */
-};
-
-struct da8xx_lcdc_platform_data {
- const char manu_name[10];
- void *controller_data;
- const char type[25];
- void (*panel_power_ctrl)(int);
-};
-
-struct lcd_ctrl_config {
- const struct display_panel *p_disp_panel;
-
- /* AC Bias Pin Frequency */
- int ac_bias;
-
- /* AC Bias Pin Transitions per Interrupt */
- int ac_bias_intrpt;
-
- /* DMA burst size */
- int dma_burst_sz;
-
- /* Bits per pixel */
- int bpp;
-
- /* FIFO DMA Request Delay */
- int fdd;
-
- /* TFT Alternative Signal Mapping (Only for active) */
- unsigned char tft_alt_mode;
-
- /* 12 Bit Per Pixel (5-6-5) Mode (Only for passive) */
- unsigned char stn_565_mode;
-
- /* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
- unsigned char mono_8bit_mode;
-
- /* Invert line clock */
- unsigned char invert_line_clock;
-
- /* Invert frame clock */
- unsigned char invert_frm_clock;
-
- /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
- unsigned char sync_edge;
-
- /* Horizontal and Vertical Sync: Control: 0=ignore */
- unsigned char sync_ctrl;
-
- /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
- unsigned char raster_order;
-};
-
-struct lcd_sync_arg {
- int back_porch;
- int front_porch;
- int pulse_width;
-};
-
-void da8xx_video_init(const struct da8xx_panel *panel,
- const struct lcd_ctrl_config *lcd_cfg,
- int bits_pixel);
-
-#endif /* ifndef DA8XX_FB_H */
diff --git a/drivers/video/formike.c b/drivers/video/formike.c
deleted file mode 100644
index 5cbe50d..0000000
--- a/drivers/video/formike.c
+++ /dev/null
@@ -1,513 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * LCD: Formike, TFT 4.3", 480x800, RGB24, KWH043ST20-F01, DriverIC NT35510-16
- * LCD initialization via SPI
- * Based on:
- *
- */
-#include <common.h>
-#include <errno.h>
-#include <log.h>
-#include <spi.h>
-#include <linux/delay.h>
-
-#define TAG_READ 0x80
-#define TAG_WRITE 0x00
-
-#define TAG_DATA 0x40
-#define TAG_COMMAND 0x00
-
-#define TAG_ADDR_H 0x20
-#define TAG_ADDR_L 0x00
-
-static int spi_write_tag_val(struct spi_slave *spi, unsigned char tag,
- unsigned char val)
-{
- unsigned long flags = SPI_XFER_BEGIN;
- u8 buf[2];
- int ret;
-
- buf[0] = tag;
- ret = spi_xfer(spi, 8, buf, NULL, flags);
- buf[0] = val;
- flags = SPI_XFER_END;
- ret = spi_xfer(spi, 8, buf, NULL, flags);
-
-#ifdef KWH043ST20_F01_SPI_DEBUG
- printf("spi_write_tag_val: tag=%02X, val=%02X ret: %d\n",
- tag, val, ret);
-#endif /* KWH043ST20_F01_SPI_DEBUG */
- if (ret)
- debug("%s: Failed to send: %d\n", __func__, ret);
-
- return ret;
-}
-
-static void spi_write_dat(struct spi_slave *spi, unsigned int val)
-{
- spi_write_tag_val(spi, TAG_WRITE|TAG_DATA, val);
-}
-
-static void spi_write_com(struct spi_slave *spi, unsigned int addr)
-{
- spi_write_tag_val(spi, TAG_WRITE|TAG_COMMAND|TAG_ADDR_H,
- (addr & 0xff00) >> 8);
- spi_write_tag_val(spi, TAG_WRITE|TAG_COMMAND|TAG_ADDR_L,
- (addr & 0x00ff) >> 0);
-}
-
-int kwh043st20_f01_spi_startup(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int spi_mode)
-{
- struct spi_slave *spi;
- int ret;
-
- spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
- if (!spi) {
- debug("%s: Failed to set up slave\n", __func__);
- return -1;
- }
-
- ret = spi_claim_bus(spi);
- if (ret) {
- debug("%s: Failed to claim SPI bus: %d\n", __func__, ret);
- goto err_claim_bus;
- }
-
-
- /* LV2 Page 1 enable */
- spi_write_com(spi, 0xF000); spi_write_dat(spi, 0x55);
- spi_write_com(spi, 0xF001); spi_write_dat(spi, 0xAA);
- spi_write_com(spi, 0xF002); spi_write_dat(spi, 0x52);
- spi_write_com(spi, 0xF003); spi_write_dat(spi, 0x08);
- spi_write_com(spi, 0xF004); spi_write_dat(spi, 0x01);
-
- /* AVDD Set AVDD 5.2V */
- spi_write_com(spi, 0xB000); spi_write_dat(spi, 0x0D);
- spi_write_com(spi, 0xB001); spi_write_dat(spi, 0x0D);
- spi_write_com(spi, 0xB002); spi_write_dat(spi, 0x0D);
-
- /* AVDD ratio */
- spi_write_com(spi, 0xB600); spi_write_dat(spi, 0x34);
- spi_write_com(spi, 0xB601); spi_write_dat(spi, 0x34);
- spi_write_com(spi, 0xB602); spi_write_dat(spi, 0x34);
-
- /* AVEE -5.2V */
- spi_write_com(spi, 0xB100); spi_write_dat(spi, 0x0D);
- spi_write_com(spi, 0xB101); spi_write_dat(spi, 0x0D);
- spi_write_com(spi, 0xB102); spi_write_dat(spi, 0x0D);
-
- /* AVEE ratio */
- spi_write_com(spi, 0xB700); spi_write_dat(spi, 0x35);
- spi_write_com(spi, 0xB701); spi_write_dat(spi, 0x35);
- spi_write_com(spi, 0xB702); spi_write_dat(spi, 0x35);
-
- /* VCL -2.5V */
- spi_write_com(spi, 0xB200); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xB201); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xB202); spi_write_dat(spi, 0x00);
-
- /* VCL ratio */
- spi_write_com(spi, 0xB800); spi_write_dat(spi, 0x24);
- spi_write_com(spi, 0xB801); spi_write_dat(spi, 0x24);
- spi_write_com(spi, 0xB802); spi_write_dat(spi, 0x24);
-
- /* VGH 15V */
- spi_write_com(spi, 0xBF00); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xB300); spi_write_dat(spi, 0x08);
- spi_write_com(spi, 0xB301); spi_write_dat(spi, 0x08);
- spi_write_com(spi, 0xB302); spi_write_dat(spi, 0x08);
-
- /* VGH ratio */
- spi_write_com(spi, 0xB900); spi_write_dat(spi, 0x34);
- spi_write_com(spi, 0xB901); spi_write_dat(spi, 0x34);
- spi_write_com(spi, 0xB902); spi_write_dat(spi, 0x34);
-
- /* VGLX ratio */
- spi_write_com(spi, 0xBA00); spi_write_dat(spi, 0x24);
- spi_write_com(spi, 0xBA01); spi_write_dat(spi, 0x24);
- spi_write_com(spi, 0xBA02); spi_write_dat(spi, 0x24);
-
- /* VGMP/VGSP 4.7V/0V */
- spi_write_com(spi, 0xBC00); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xBC01); spi_write_dat(spi, 0x88);
- spi_write_com(spi, 0xBC02); spi_write_dat(spi, 0x00);
-
- /* VGMN/VGSN -4.7V/0V */
- spi_write_com(spi, 0xBD00); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xBD01); spi_write_dat(spi, 0x88);
- spi_write_com(spi, 0xBD02); spi_write_dat(spi, 0x00);
-
- /* VCOM 1.525V */
- spi_write_com(spi, 0xBE00); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xBE01); spi_write_dat(spi, 0x7A);
-
- /* Gamma Setting */
- spi_write_com(spi, 0xD100); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD101); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD102); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD103); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD104); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD105); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD106); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD107); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD108); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD109); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD10A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD10B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD10C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD10D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD10E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD10F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD110); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD111); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD112); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD113); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD114); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD115); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD116); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD117); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD118); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD119); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD11A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD11B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD11C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD11D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD11E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD11F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD120); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD121); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD122); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD123); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD124); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD125); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD126); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD127); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD128); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD129); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD12A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD12B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD12C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD12D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD12E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD12F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD130); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD131); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD132); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD133); spi_write_dat(spi, 0xFF);
-
- spi_write_com(spi, 0xD200); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD201); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD202); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD203); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD204); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD205); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD206); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD207); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD208); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD209); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD20A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD20B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD20C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD20D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD20E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD20F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD210); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD211); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD212); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD213); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD214); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD215); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD216); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD217); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD218); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD219); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD21A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD21B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD21C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD21D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD21E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD21F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD220); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD221); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD222); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD223); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD224); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD225); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD226); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD227); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD228); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD229); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD22A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD22B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD22C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD22D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD22E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD22F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD230); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD231); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD232); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD233); spi_write_dat(spi, 0xFF);
-
- spi_write_com(spi, 0xD300); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD301); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD302); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD303); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD304); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD305); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD306); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD307); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD308); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD309); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD30A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD30B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD30C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD30D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD30E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD30F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD310); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD311); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD312); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD313); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD314); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD315); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD316); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD317); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD318); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD319); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD31A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD31B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD31C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD31D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD31E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD31F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD320); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD321); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD322); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD323); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD324); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD325); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD326); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD327); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD328); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD329); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD32A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD32B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD32C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD32D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD32E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD32F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD330); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD331); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD332); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD333); spi_write_dat(spi, 0xFF);
-
- spi_write_com(spi, 0xD400); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD401); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD402); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD403); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD404); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD405); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD406); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD407); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD408); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD409); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD40A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD40B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD40C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD40D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD40E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD40F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD410); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD411); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD412); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD413); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD414); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD415); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD416); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD417); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD418); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD419); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD41A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD41B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD41C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD41D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD41E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD41F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD420); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD421); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD422); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD423); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD424); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD425); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD426); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD427); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD428); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD429); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD42A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD42B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD42C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD42D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD42E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD42F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD430); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD431); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD432); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD433); spi_write_dat(spi, 0xFF);
-
- spi_write_com(spi, 0xD500); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD501); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD502); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD503); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD504); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD505); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD506); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD507); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD508); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD509); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD50A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD50B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD50C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD50D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD50E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD50F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD510); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD511); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD512); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD513); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD514); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD515); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD516); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD517); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD518); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD519); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD51A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD51B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD51C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD51D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD51E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD51F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD520); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD521); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD522); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD523); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD524); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD525); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD526); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD527); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD528); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD529); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD52A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD52B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD52C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD52D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD52E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD52F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD530); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD531); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD532); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD533); spi_write_dat(spi, 0xFF);
-
- spi_write_com(spi, 0xD600); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD601); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xD602); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD603); spi_write_dat(spi, 0x15);
- spi_write_com(spi, 0xD604); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD605); spi_write_dat(spi, 0x30);
- spi_write_com(spi, 0xD606); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD607); spi_write_dat(spi, 0x47);
- spi_write_com(spi, 0xD608); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD609); spi_write_dat(spi, 0x5B);
- spi_write_com(spi, 0xD60A); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD60B); spi_write_dat(spi, 0x7D);
- spi_write_com(spi, 0xD60C); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD60D); spi_write_dat(spi, 0x9D);
- spi_write_com(spi, 0xD60E); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD60F); spi_write_dat(spi, 0xCC);
- spi_write_com(spi, 0xD610); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xD611); spi_write_dat(spi, 0xF3);
- spi_write_com(spi, 0xD612); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD613); spi_write_dat(spi, 0x32);
- spi_write_com(spi, 0xD614); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD615); spi_write_dat(spi, 0x63);
- spi_write_com(spi, 0xD616); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD617); spi_write_dat(spi, 0xB1);
- spi_write_com(spi, 0xD618); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD619); spi_write_dat(spi, 0xF0);
- spi_write_com(spi, 0xD61A); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xD61B); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD61C); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD61D); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD61E); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD61F); spi_write_dat(spi, 0x67);
- spi_write_com(spi, 0xD620); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD621); spi_write_dat(spi, 0x90);
- spi_write_com(spi, 0xD622); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD623); spi_write_dat(spi, 0xCB);
- spi_write_com(spi, 0xD624); spi_write_dat(spi, 0x02);
- spi_write_com(spi, 0xD625); spi_write_dat(spi, 0xF2);
- spi_write_com(spi, 0xD626); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD627); spi_write_dat(spi, 0x2A);
- spi_write_com(spi, 0xD628); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD629); spi_write_dat(spi, 0x51);
- spi_write_com(spi, 0xD62A); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD62B); spi_write_dat(spi, 0x80);
- spi_write_com(spi, 0xD62C); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD62D); spi_write_dat(spi, 0x9F);
- spi_write_com(spi, 0xD62E); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD62F); spi_write_dat(spi, 0xBE);
- spi_write_com(spi, 0xD630); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD631); spi_write_dat(spi, 0xF9);
- spi_write_com(spi, 0xD632); spi_write_dat(spi, 0x03);
- spi_write_com(spi, 0xD633); spi_write_dat(spi, 0xFF);
-
- /* LV2 Page 0 enable */
- spi_write_com(spi, 0xF000); spi_write_dat(spi, 0x55);
- spi_write_com(spi, 0xF001); spi_write_dat(spi, 0xAA);
- spi_write_com(spi, 0xF002); spi_write_dat(spi, 0x52);
- spi_write_com(spi, 0xF003); spi_write_dat(spi, 0x08);
- spi_write_com(spi, 0xF004); spi_write_dat(spi, 0x00);
-
- /* Display control */
- spi_write_com(spi, 0xB100); spi_write_dat(spi, 0xFC);
- spi_write_com(spi, 0xB101); spi_write_dat(spi, 0x00);
-
- /* Source hold time */
- spi_write_com(spi, 0xB600); spi_write_dat(spi, 0x05);
-
- /* Gate EQ control */
- spi_write_com(spi, 0xB700); spi_write_dat(spi, 0x70);
- spi_write_com(spi, 0xB701); spi_write_dat(spi, 0x70);
-
- /* Source EQ control (Mode 2) */
- spi_write_com(spi, 0xB800); spi_write_dat(spi, 0x01);
- spi_write_com(spi, 0xB801); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xB802); spi_write_dat(spi, 0x05);
- spi_write_com(spi, 0xB803); spi_write_dat(spi, 0x05);
-
- /* Inversion mode (Column) */
- spi_write_com(spi, 0xBC00); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xBC01); spi_write_dat(spi, 0x00);
- spi_write_com(spi, 0xBC02); spi_write_dat(spi, 0x00);
-
- /* Timing control 8phase dual side/4H/4delay/RST_EN */
- spi_write_com(spi, 0xC900); spi_write_dat(spi, 0xD0);
- spi_write_com(spi, 0xC901); spi_write_dat(spi, 0x82);
- spi_write_com(spi, 0xC902); spi_write_dat(spi, 0x50);
- spi_write_com(spi, 0xC903); spi_write_dat(spi, 0x50);
- spi_write_com(spi, 0xC904); spi_write_dat(spi, 0x50);
-
- spi_write_com(spi, 0x3A00); spi_write_dat(spi, 0x55);
- mdelay(120);
- spi_write_com(spi, 0x1100);
- mdelay(120);
- spi_write_com(spi, 0x2900);
- mdelay(120);
- /* spi_write_com(spi, 0x2100); spi_write_dat(spi, 0x00); */
- spi_write_com(spi, 0x2C00);
-
- return 0;
-err_claim_bus:
- spi_free_slave(spi);
- return -1;
-}
diff --git a/drivers/video/fsl_dcu_fb.c b/drivers/video/fsl_dcu_fb.c
deleted file mode 100644
index dc5b24c..0000000
--- a/drivers/video/fsl_dcu_fb.c
+++ /dev/null
@@ -1,549 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2014 Freescale Semiconductor, Inc.
- * Copyright 2019 Toradex AG
- *
- * FSL DCU Framebuffer driver
- */
-
-#include <init.h>
-#include <asm/cache.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <common.h>
-#include <dm.h>
-#include <fdt_support.h>
-#include <fsl_dcu_fb.h>
-#include <linux/fb.h>
-#include <malloc.h>
-#include <video.h>
-#include <video_fb.h>
-#include "videomodes.h"
-
-/* Convert the X,Y resolution pair into a single number */
-#define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
-
-#ifdef CONFIG_SYS_FSL_DCU_LE
-#define dcu_read32 in_le32
-#define dcu_write32 out_le32
-#elif defined(CONFIG_SYS_FSL_DCU_BE)
-#define dcu_read32 in_be32
-#define dcu_write32 out_be32
-#endif
-
-#define DCU_MODE_BLEND_ITER(x) ((x) << 20)
-#define DCU_MODE_RASTER_EN (1 << 14)
-#define DCU_MODE_NORMAL 1
-#define DCU_MODE_COLORBAR 3
-#define DCU_BGND_R(x) ((x) << 16)
-#define DCU_BGND_G(x) ((x) << 8)
-#define DCU_BGND_B(x) (x)
-#define DCU_DISP_SIZE_DELTA_Y(x) ((x) << 16)
-#define DCU_DISP_SIZE_DELTA_X(x) (x)
-#define DCU_HSYN_PARA_BP(x) ((x) << 22)
-#define DCU_HSYN_PARA_PW(x) ((x) << 11)
-#define DCU_HSYN_PARA_FP(x) (x)
-#define DCU_VSYN_PARA_BP(x) ((x) << 22)
-#define DCU_VSYN_PARA_PW(x) ((x) << 11)
-#define DCU_VSYN_PARA_FP(x) (x)
-#define DCU_SYN_POL_INV_PXCK_FALL (1 << 6)
-#define DCU_SYN_POL_NEG_REMAIN (0 << 5)
-#define DCU_SYN_POL_INV_VS_LOW (1 << 1)
-#define DCU_SYN_POL_INV_HS_LOW (1)
-#define DCU_THRESHOLD_LS_BF_VS(x) ((x) << 16)
-#define DCU_THRESHOLD_OUT_BUF_HIGH(x) ((x) << 8)
-#define DCU_THRESHOLD_OUT_BUF_LOW(x) (x)
-#define DCU_UPDATE_MODE_MODE (1 << 31)
-#define DCU_UPDATE_MODE_READREG (1 << 30)
-
-#define DCU_CTRLDESCLN_1_HEIGHT(x) ((x) << 16)
-#define DCU_CTRLDESCLN_1_WIDTH(x) (x)
-#define DCU_CTRLDESCLN_2_POSY(x) ((x) << 16)
-#define DCU_CTRLDESCLN_2_POSX(x) (x)
-#define DCU_CTRLDESCLN_4_EN (1 << 31)
-#define DCU_CTRLDESCLN_4_TILE_EN (1 << 30)
-#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT (1 << 29)
-#define DCU_CTRLDESCLN_4_SAFETY_EN (1 << 28)
-#define DCU_CTRLDESCLN_4_TRANS(x) ((x) << 20)
-#define DCU_CTRLDESCLN_4_BPP(x) ((x) << 16)
-#define DCU_CTRLDESCLN_4_RLE_EN (1 << 15)
-#define DCU_CTRLDESCLN_4_LUOFFS(x) ((x) << 4)
-#define DCU_CTRLDESCLN_4_BB_ON (1 << 2)
-#define DCU_CTRLDESCLN_4_AB(x) (x)
-#define DCU_CTRLDESCLN_5_CKMAX_R(x) ((x) << 16)
-#define DCU_CTRLDESCLN_5_CKMAX_G(x) ((x) << 8)
-#define DCU_CTRLDESCLN_5_CKMAX_B(x) (x)
-#define DCU_CTRLDESCLN_6_CKMIN_R(x) ((x) << 16)
-#define DCU_CTRLDESCLN_6_CKMIN_G(x) ((x) << 8)
-#define DCU_CTRLDESCLN_6_CKMIN_B(x) (x)
-#define DCU_CTRLDESCLN_7_TILE_VER(x) ((x) << 16)
-#define DCU_CTRLDESCLN_7_TILE_HOR(x) (x)
-#define DCU_CTRLDESCLN_8_FG_FCOLOR(x) (x)
-#define DCU_CTRLDESCLN_9_BG_BCOLOR(x) (x)
-
-#define BPP_16_RGB565 4
-#define BPP_24_RGB888 5
-#define BPP_32_ARGB8888 6
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * This setting is used for the TWR_LCD_RGB card
- */
-static struct fb_videomode fsl_dcu_mode_480_272 = {
- .name = "480x272-60",
- .refresh = 60,
- .xres = 480,
- .yres = 272,
- .pixclock = 91996,
- .left_margin = 2,
- .right_margin = 2,
- .upper_margin = 1,
- .lower_margin = 1,
- .hsync_len = 41,
- .vsync_len = 2,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-/*
- * This setting is used for Siliconimage SiI9022A HDMI
- */
-static struct fb_videomode fsl_dcu_cea_mode_640_480 = {
- .name = "640x480-60",
- .refresh = 60,
- .xres = 640,
- .yres = 480,
- .pixclock = 39722,
- .left_margin = 48,
- .right_margin = 16,
- .upper_margin = 33,
- .lower_margin = 10,
- .hsync_len = 96,
- .vsync_len = 2,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_videomode fsl_dcu_mode_640_480 = {
- .name = "640x480-60",
- .refresh = 60,
- .xres = 640,
- .yres = 480,
- .pixclock = 25175,
- .left_margin = 40,
- .right_margin = 24,
- .upper_margin = 32,
- .lower_margin = 11,
- .hsync_len = 96,
- .vsync_len = 2,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_videomode fsl_dcu_mode_800_480 = {
- .name = "800x480-60",
- .refresh = 60,
- .xres = 800,
- .yres = 480,
- .pixclock = 33260,
- .left_margin = 216,
- .right_margin = 40,
- .upper_margin = 35,
- .lower_margin = 10,
- .hsync_len = 128,
- .vsync_len = 2,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_videomode fsl_dcu_mode_1024_600 = {
- .name = "1024x600-60",
- .refresh = 60,
- .xres = 1024,
- .yres = 600,
- .pixclock = 48000,
- .left_margin = 104,
- .right_margin = 43,
- .upper_margin = 24,
- .lower_margin = 20,
- .hsync_len = 5,
- .vsync_len = 5,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-/*
- * DCU register map
- */
-struct dcu_reg {
- u32 desc_cursor[4];
- u32 mode;
- u32 bgnd;
- u32 disp_size;
- u32 hsyn_para;
- u32 vsyn_para;
- u32 synpol;
- u32 threshold;
- u32 int_status;
- u32 int_mask;
- u32 colbar[8];
- u32 div_ratio;
- u32 sign_calc[2];
- u32 crc_val;
- u8 res_064[0x6c-0x64];
- u32 parr_err_status1;
- u8 res_070[0x7c-0x70];
- u32 parr_err_status3;
- u32 mparr_err_status1;
- u8 res_084[0x90-0x84];
- u32 mparr_err_status3;
- u32 threshold_inp_buf[2];
- u8 res_09c[0xa0-0x9c];
- u32 luma_comp;
- u32 chroma_red;
- u32 chroma_green;
- u32 chroma_blue;
- u32 crc_pos;
- u32 lyr_intpol_en;
- u32 lyr_luma_comp;
- u32 lyr_chrm_red;
- u32 lyr_chrm_grn;
- u32 lyr_chrm_blue;
- u8 res_0c4[0xcc-0xc8];
- u32 update_mode;
- u32 underrun;
- u8 res_0d4[0x100-0xd4];
- u32 gpr;
- u32 slr_l[2];
- u32 slr_disp_size;
- u32 slr_hvsync_para;
- u32 slr_pol;
- u32 slr_l_transp[2];
- u8 res_120[0x200-0x120];
- u32 ctrldescl[DCU_LAYER_MAX_NUM][16];
-};
-
-static void reset_total_layers(void)
-{
- struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
- int i;
-
- for (i = 0; i < DCU_LAYER_MAX_NUM; i++) {
- dcu_write32(&regs->ctrldescl[i][0], 0);
- dcu_write32(&regs->ctrldescl[i][1], 0);
- dcu_write32(&regs->ctrldescl[i][2], 0);
- dcu_write32(&regs->ctrldescl[i][3], 0);
- dcu_write32(&regs->ctrldescl[i][4], 0);
- dcu_write32(&regs->ctrldescl[i][5], 0);
- dcu_write32(&regs->ctrldescl[i][6], 0);
- dcu_write32(&regs->ctrldescl[i][7], 0);
- dcu_write32(&regs->ctrldescl[i][8], 0);
- dcu_write32(&regs->ctrldescl[i][9], 0);
- dcu_write32(&regs->ctrldescl[i][10], 0);
- }
-}
-
-static int layer_ctrldesc_init(struct fb_info fbinfo,
- int index, u32 pixel_format)
-{
- struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
- unsigned int bpp = BPP_24_RGB888;
-
- dcu_write32(&regs->ctrldescl[index][0],
- DCU_CTRLDESCLN_1_HEIGHT(fbinfo.var.yres) |
- DCU_CTRLDESCLN_1_WIDTH(fbinfo.var.xres));
-
- dcu_write32(&regs->ctrldescl[index][1],
- DCU_CTRLDESCLN_2_POSY(0) |
- DCU_CTRLDESCLN_2_POSX(0));
-
- dcu_write32(&regs->ctrldescl[index][2],
- (unsigned int)fbinfo.screen_base);
-
- switch (pixel_format) {
- case 16:
- bpp = BPP_16_RGB565;
- break;
- case 24:
- bpp = BPP_24_RGB888;
- break;
- case 32:
- bpp = BPP_32_ARGB8888;
- break;
- default:
- printf("unsupported color depth: %u\n", pixel_format);
- }
-
- dcu_write32(&regs->ctrldescl[index][3],
- DCU_CTRLDESCLN_4_EN |
- DCU_CTRLDESCLN_4_TRANS(0xff) |
- DCU_CTRLDESCLN_4_BPP(bpp) |
- DCU_CTRLDESCLN_4_AB(0));
-
- dcu_write32(&regs->ctrldescl[index][4],
- DCU_CTRLDESCLN_5_CKMAX_R(0xff) |
- DCU_CTRLDESCLN_5_CKMAX_G(0xff) |
- DCU_CTRLDESCLN_5_CKMAX_B(0xff));
- dcu_write32(&regs->ctrldescl[index][5],
- DCU_CTRLDESCLN_6_CKMIN_R(0) |
- DCU_CTRLDESCLN_6_CKMIN_G(0) |
- DCU_CTRLDESCLN_6_CKMIN_B(0));
-
- dcu_write32(&regs->ctrldescl[index][6],
- DCU_CTRLDESCLN_7_TILE_VER(0) |
- DCU_CTRLDESCLN_7_TILE_HOR(0));
-
- dcu_write32(&regs->ctrldescl[index][7], DCU_CTRLDESCLN_8_FG_FCOLOR(0));
- dcu_write32(&regs->ctrldescl[index][8], DCU_CTRLDESCLN_9_BG_BCOLOR(0));
-
- return 0;
-}
-
-int fsl_dcu_init(struct fb_info *fbinfo, unsigned int xres,
- unsigned int yres, unsigned int pixel_format)
-{
- struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
- unsigned int div, mode;
-/*
- * When DM_VIDEO is enabled reservation of framebuffer is done
- * in advance during bind() call.
- */
-#if !CONFIG_IS_ENABLED(DM_VIDEO)
- fbinfo->screen_size = fbinfo->var.xres * fbinfo->var.yres *
- (fbinfo->var.bits_per_pixel / 8);
-
- if (fbinfo->screen_size > CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB) {
- fbinfo->screen_size = 0;
- return -ENOMEM;
- }
- /* Reserve framebuffer at the end of memory */
- gd->fb_base = gd->bd->bi_dram[0].start +
- gd->bd->bi_dram[0].size - fbinfo->screen_size;
- fbinfo->screen_base = (char *)gd->fb_base;
-
- memset(fbinfo->screen_base, 0, fbinfo->screen_size);
-#endif
-
- reset_total_layers();
-
- dcu_write32(&regs->disp_size,
- DCU_DISP_SIZE_DELTA_Y(fbinfo->var.yres) |
- DCU_DISP_SIZE_DELTA_X(fbinfo->var.xres / 16));
-
- dcu_write32(&regs->hsyn_para,
- DCU_HSYN_PARA_BP(fbinfo->var.left_margin) |
- DCU_HSYN_PARA_PW(fbinfo->var.hsync_len) |
- DCU_HSYN_PARA_FP(fbinfo->var.right_margin));
-
- dcu_write32(&regs->vsyn_para,
- DCU_VSYN_PARA_BP(fbinfo->var.upper_margin) |
- DCU_VSYN_PARA_PW(fbinfo->var.vsync_len) |
- DCU_VSYN_PARA_FP(fbinfo->var.lower_margin));
-
- dcu_write32(&regs->synpol,
- DCU_SYN_POL_INV_PXCK_FALL |
- DCU_SYN_POL_NEG_REMAIN |
- DCU_SYN_POL_INV_VS_LOW |
- DCU_SYN_POL_INV_HS_LOW);
-
- dcu_write32(&regs->bgnd,
- DCU_BGND_R(0) | DCU_BGND_G(0) | DCU_BGND_B(0));
-
- dcu_write32(&regs->mode,
- DCU_MODE_BLEND_ITER(2) |
- DCU_MODE_RASTER_EN);
-
- dcu_write32(&regs->threshold,
- DCU_THRESHOLD_LS_BF_VS(0x3) |
- DCU_THRESHOLD_OUT_BUF_HIGH(0x78) |
- DCU_THRESHOLD_OUT_BUF_LOW(0));
-
- mode = dcu_read32(&regs->mode);
- dcu_write32(&regs->mode, mode | DCU_MODE_NORMAL);
-
- layer_ctrldesc_init(*fbinfo, 0, pixel_format);
-
- div = dcu_set_pixel_clock(fbinfo->var.pixclock);
- dcu_write32(&regs->div_ratio, (div - 1));
-
- dcu_write32(&regs->update_mode, DCU_UPDATE_MODE_READREG);
-
- return 0;
-}
-
-ulong board_get_usable_ram_top(ulong total_size)
-{
- return gd->ram_top - CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB;
-}
-
-int fsl_probe_common(struct fb_info *fbinfo, unsigned int *win_x,
- unsigned int *win_y)
-{
- const char *options;
- unsigned int depth = 0, freq = 0;
-
- struct fb_videomode *fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
-
- if (!video_get_video_mode(win_x, win_y, &depth, &freq,
- &options))
- return -EINVAL;
-
- /* Find the monitor port, which is a required option */
- if (!options)
- return -EINVAL;
-
- if (strncmp(options, "monitor=", 8) != 0)
- return -EINVAL;
-
- switch (RESOLUTION(*win_x, *win_y)) {
- case RESOLUTION(480, 272):
- fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
- break;
- case RESOLUTION(640, 480):
- if (!strncmp(options, "monitor=hdmi", 12))
- fsl_dcu_mode_db = &fsl_dcu_cea_mode_640_480;
- else
- fsl_dcu_mode_db = &fsl_dcu_mode_640_480;
- break;
- case RESOLUTION(800, 480):
- fsl_dcu_mode_db = &fsl_dcu_mode_800_480;
- break;
- case RESOLUTION(1024, 600):
- fsl_dcu_mode_db = &fsl_dcu_mode_1024_600;
- break;
- default:
- printf("unsupported resolution %ux%u\n",
- *win_x, *win_y);
- }
-
- fbinfo->var.xres = fsl_dcu_mode_db->xres;
- fbinfo->var.yres = fsl_dcu_mode_db->yres;
- fbinfo->var.bits_per_pixel = 32;
- fbinfo->var.pixclock = fsl_dcu_mode_db->pixclock;
- fbinfo->var.left_margin = fsl_dcu_mode_db->left_margin;
- fbinfo->var.right_margin = fsl_dcu_mode_db->right_margin;
- fbinfo->var.upper_margin = fsl_dcu_mode_db->upper_margin;
- fbinfo->var.lower_margin = fsl_dcu_mode_db->lower_margin;
- fbinfo->var.hsync_len = fsl_dcu_mode_db->hsync_len;
- fbinfo->var.vsync_len = fsl_dcu_mode_db->vsync_len;
- fbinfo->var.sync = fsl_dcu_mode_db->sync;
- fbinfo->var.vmode = fsl_dcu_mode_db->vmode;
- fbinfo->fix.line_length = fbinfo->var.xres *
- fbinfo->var.bits_per_pixel / 8;
-
- return platform_dcu_init(fbinfo, *win_x, *win_y,
- options + 8, fsl_dcu_mode_db);
-}
-
-#ifndef CONFIG_DM_VIDEO
-static struct fb_info info;
-
-#if defined(CONFIG_OF_BOARD_SETUP)
-int fsl_dcu_fixedfb_setup(void *blob)
-{
- u64 start, size;
- int ret;
-
- start = gd->bd->bi_dram[0].start;
- size = gd->bd->bi_dram[0].size - info.screen_size;
-
- /*
- * Align size on section size (1 MiB).
- */
- size &= 0xfff00000;
- ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
- if (ret) {
- eprintf("Cannot setup fb: Error reserving memory\n");
- return ret;
- }
-
- return 0;
-}
-#endif
-
-void *video_hw_init(void)
-{
- static GraphicDevice ctfb;
-
- if (fsl_probe_common(&info, &ctfb.winSizeX, &ctfb.winSizeY) < 0)
- return NULL;
-
- ctfb.frameAdrs = (unsigned int)info.screen_base;
- ctfb.plnSizeX = ctfb.winSizeX;
- ctfb.plnSizeY = ctfb.winSizeY;
-
- ctfb.gdfBytesPP = 4;
- ctfb.gdfIndex = GDF_32BIT_X888RGB;
-
- ctfb.memSize = info.screen_size;
-
- return &ctfb;
-}
-
-#else /* ifndef CONFIG_DM_VIDEO */
-
-static int fsl_dcu_video_probe(struct udevice *dev)
-{
- struct video_uc_plat *plat = dev_get_uclass_plat(dev);
- struct video_priv *uc_priv = dev_get_uclass_priv(dev);
- struct fb_info fbinfo = { 0 };
- unsigned int win_x;
- unsigned int win_y;
- u32 fb_start, fb_end;
- int ret = 0;
-
- fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
- fb_end = plat->base + plat->size;
- fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
-
- fbinfo.screen_base = (char *)fb_start;
- fbinfo.screen_size = plat->size;
-
- ret = fsl_probe_common(&fbinfo, &win_x, &win_y);
- if (ret < 0)
- return ret;
-
- uc_priv->bpix = VIDEO_BPP32;
- uc_priv->xsize = win_x;
- uc_priv->ysize = win_y;
-
- /* Enable dcache for the frame buffer */
- mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
- DCACHE_WRITEBACK);
- video_set_flush_dcache(dev, true);
- return ret;
-}
-
-static int fsl_dcu_video_bind(struct udevice *dev)
-{
- struct video_uc_plat *plat = dev_get_uclass_plat(dev);
- unsigned int win_x;
- unsigned int win_y;
- unsigned int depth = 0, freq = 0;
- const char *options;
- int ret = 0;
-
- ret = video_get_video_mode(&win_x, &win_y, &depth, &freq, &options);
- if (ret < 0)
- return ret;
-
- plat->size = win_x * win_y * 32;
-
- return 0;
-}
-
-static const struct udevice_id fsl_dcu_video_ids[] = {
- { .compatible = "fsl,vf610-dcu" },
- { /* sentinel */ }
-};
-
-U_BOOT_DRIVER(fsl_dcu_video) = {
- .name = "fsl_dcu_video",
- .id = UCLASS_VIDEO,
- .of_match = fsl_dcu_video_ids,
- .bind = fsl_dcu_video_bind,
- .probe = fsl_dcu_video_probe,
- .flags = DM_FLAG_PRE_RELOC,
-};
-#endif /* ifndef CONFIG_DM_VIDEO */
diff --git a/drivers/video/fsl_diu_fb.c b/drivers/video/fsl_diu_fb.c
deleted file mode 100644
index 2c21e29..0000000
--- a/drivers/video/fsl_diu_fb.c
+++ /dev/null
@@ -1,416 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
- * Authors: York Sun <yorksun@freescale.com>
- * Timur Tabi <timur@freescale.com>
- *
- * FSL DIU Framebuffer driver
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <asm/io.h>
-
-#include "videomodes.h"
-#include <video_fb.h>
-#include <fsl_diu_fb.h>
-#include <linux/list.h>
-#include <linux/fb.h>
-
-/* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
-static struct fb_videomode fsl_diu_mode_800_480 = {
- .name = "800x480-60",
- .refresh = 60,
- .xres = 800,
- .yres = 480,
- .pixclock = 31250,
- .left_margin = 86,
- .right_margin = 42,
- .upper_margin = 33,
- .lower_margin = 10,
- .hsync_len = 128,
- .vsync_len = 2,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-/* For the SHARP LQ084S3LG01, used on the P1022DS board */
-static struct fb_videomode fsl_diu_mode_800_600 = {
- .name = "800x600-60",
- .refresh = 60,
- .xres = 800,
- .yres = 600,
- .pixclock = 25000,
- .left_margin = 88,
- .right_margin = 40,
- .upper_margin = 23,
- .lower_margin = 1,
- .hsync_len = 128,
- .vsync_len = 4,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-/*
- * These parameters give default parameters
- * for video output 1024x768,
- * FIXME - change timing to proper amounts
- * hsync 31.5kHz, vsync 60Hz
- */
-static struct fb_videomode fsl_diu_mode_1024_768 = {
- .name = "1024x768-60",
- .refresh = 60,
- .xres = 1024,
- .yres = 768,
- .pixclock = 15385,
- .left_margin = 160,
- .right_margin = 24,
- .upper_margin = 29,
- .lower_margin = 3,
- .hsync_len = 136,
- .vsync_len = 6,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_videomode fsl_diu_mode_1280_1024 = {
- .name = "1280x1024-60",
- .refresh = 60,
- .xres = 1280,
- .yres = 1024,
- .pixclock = 9375,
- .left_margin = 38,
- .right_margin = 128,
- .upper_margin = 2,
- .lower_margin = 7,
- .hsync_len = 216,
- .vsync_len = 37,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_videomode fsl_diu_mode_1280_720 = {
- .name = "1280x720-60",
- .refresh = 60,
- .xres = 1280,
- .yres = 720,
- .pixclock = 13426,
- .left_margin = 192,
- .right_margin = 64,
- .upper_margin = 22,
- .lower_margin = 1,
- .hsync_len = 136,
- .vsync_len = 3,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_videomode fsl_diu_mode_1920_1080 = {
- .name = "1920x1080-60",
- .refresh = 60,
- .xres = 1920,
- .yres = 1080,
- .pixclock = 5787,
- .left_margin = 328,
- .right_margin = 120,
- .upper_margin = 34,
- .lower_margin = 1,
- .hsync_len = 208,
- .vsync_len = 3,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-/*
- * These are the fields of area descriptor(in DDR memory) for every plane
- */
-struct diu_ad {
- /* Word 0(32-bit) in DDR memory */
- __le32 pix_fmt; /* hard coding pixel format */
- /* Word 1(32-bit) in DDR memory */
- __le32 addr;
- /* Word 2(32-bit) in DDR memory */
- __le32 src_size_g_alpha;
- /* Word 3(32-bit) in DDR memory */
- __le32 aoi_size;
- /* Word 4(32-bit) in DDR memory */
- __le32 offset_xyi;
- /* Word 5(32-bit) in DDR memory */
- __le32 offset_xyd;
- /* Word 6(32-bit) in DDR memory */
- __le32 ckmax_r:8;
- __le32 ckmax_g:8;
- __le32 ckmax_b:8;
- __le32 res9:8;
- /* Word 7(32-bit) in DDR memory */
- __le32 ckmin_r:8;
- __le32 ckmin_g:8;
- __le32 ckmin_b:8;
- __le32 res10:8;
- /* Word 8(32-bit) in DDR memory */
- __le32 next_ad;
- /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
- __le32 res[3];
-} __attribute__ ((packed));
-
-/*
- * DIU register map
- */
-struct diu {
- __be32 desc[3];
- __be32 gamma;
- __be32 pallete;
- __be32 cursor;
- __be32 curs_pos;
- __be32 diu_mode;
- __be32 bgnd;
- __be32 bgnd_wb;
- __be32 disp_size;
- __be32 wb_size;
- __be32 wb_mem_addr;
- __be32 hsyn_para;
- __be32 vsyn_para;
- __be32 syn_pol;
- __be32 thresholds;
- __be32 int_status;
- __be32 int_mask;
- __be32 colorbar[8];
- __be32 filling;
- __be32 plut;
-} __attribute__ ((packed));
-
-struct diu_addr {
- void *vaddr; /* Virtual address */
- u32 paddr; /* 32-bit physical address */
- unsigned int offset; /* Alignment offset */
-};
-
-static struct fb_info info;
-
-/*
- * Align to 64-bit(8-byte), 32-byte, etc.
- */
-static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
-{
- u32 offset, ssize;
- u32 mask;
-
- ssize = size + bytes_align;
- buf->vaddr = malloc(ssize);
- if (!buf->vaddr)
- return -1;
-
- memset(buf->vaddr, 0, ssize);
- mask = bytes_align - 1;
- offset = (u32)buf->vaddr & mask;
- if (offset) {
- buf->offset = bytes_align - offset;
- buf->vaddr += offset;
- } else
- buf->offset = 0;
-
- buf->paddr = virt_to_phys(buf->vaddr);
- return 0;
-}
-
-/*
- * Allocate a framebuffer and an Area Descriptor that points to it. Both
- * are created in the same memory block. The Area Descriptor is updated to
- * point to the framebuffer memory. Memory is aligned as needed.
- */
-static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
- unsigned int depth, char **fb)
-{
- unsigned long size = xres * yres * depth;
- struct diu_addr addr;
- struct diu_ad *ad;
- size_t ad_size = roundup(sizeof(struct diu_ad), 32);
-
- /*
- * Allocate a memory block that holds the Area Descriptor and the
- * frame buffer right behind it. To keep the code simple, everything
- * is aligned on a 32-byte address.
- */
- if (allocate_buf(&addr, ad_size + size, 32) < 0)
- return NULL;
-
- ad = addr.vaddr;
- ad->addr = cpu_to_le32(addr.paddr + ad_size);
- ad->aoi_size = cpu_to_le32((yres << 16) | xres);
- ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
- ad->offset_xyi = 0;
- ad->offset_xyd = 0;
-
- if (fb)
- *fb = addr.vaddr + ad_size;
-
- return ad;
-}
-
-int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
-{
- struct fb_videomode *fsl_diu_mode_db;
- struct diu_ad *ad;
- struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
- u8 *gamma_table_base;
- unsigned int i, j;
- struct diu_addr gamma;
- struct diu_addr cursor;
-
-/* Convert the X,Y resolution pair into a single number */
-#define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
-
- switch (RESOLUTION(xres, yres)) {
- case RESOLUTION(800, 480):
- fsl_diu_mode_db = &fsl_diu_mode_800_480;
- break;
- case RESOLUTION(800, 600):
- fsl_diu_mode_db = &fsl_diu_mode_800_600;
- break;
- case RESOLUTION(1024, 768):
- fsl_diu_mode_db = &fsl_diu_mode_1024_768;
- break;
- case RESOLUTION(1280, 1024):
- fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
- break;
- case RESOLUTION(1280, 720):
- fsl_diu_mode_db = &fsl_diu_mode_1280_720;
- break;
- case RESOLUTION(1920, 1080):
- fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
- break;
- default:
- printf("DIU: Unsupported resolution %ux%u\n", xres, yres);
- return -1;
- }
-
- /* read mode info */
- info.var.xres = fsl_diu_mode_db->xres;
- info.var.yres = fsl_diu_mode_db->yres;
- info.var.bits_per_pixel = 32;
- info.var.pixclock = fsl_diu_mode_db->pixclock;
- info.var.left_margin = fsl_diu_mode_db->left_margin;
- info.var.right_margin = fsl_diu_mode_db->right_margin;
- info.var.upper_margin = fsl_diu_mode_db->upper_margin;
- info.var.lower_margin = fsl_diu_mode_db->lower_margin;
- info.var.hsync_len = fsl_diu_mode_db->hsync_len;
- info.var.vsync_len = fsl_diu_mode_db->vsync_len;
- info.var.sync = fsl_diu_mode_db->sync;
- info.var.vmode = fsl_diu_mode_db->vmode;
- info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
-
- /* Memory allocation for framebuffer */
- info.screen_size =
- info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
- ad = allocate_fb(info.var.xres, info.var.yres,
- info.var.bits_per_pixel / 8, &info.screen_base);
- if (!ad) {
- printf("DIU: Out of memory\n");
- return -1;
- }
-
- ad->pix_fmt = pixel_format;
-
- /* Disable chroma keying function */
- ad->ckmax_r = 0;
- ad->ckmax_g = 0;
- ad->ckmax_b = 0;
-
- ad->ckmin_r = 255;
- ad->ckmin_g = 255;
- ad->ckmin_b = 255;
-
- /* Initialize the gamma table */
- if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
- printf("DIU: Out of memory\n");
- return -1;
- }
- gamma_table_base = gamma.vaddr;
- for (i = 0; i <= 2; i++)
- for (j = 0; j < 256; j++)
- *gamma_table_base++ = j;
-
- if (gamma_fix == 1) { /* fix the gamma */
- gamma_table_base = gamma.vaddr;
- for (i = 0; i < 256 * 3; i++) {
- gamma_table_base[i] = (gamma_table_base[i] << 2)
- | ((gamma_table_base[i] >> 6) & 0x03);
- }
- }
-
- /* Initialize the cursor */
- if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
- printf("DIU: Can't alloc cursor data\n");
- return -1;
- }
-
- /* Program DIU registers */
- out_be32(&hw->diu_mode, 0); /* Temporarily disable the DIU */
-
- out_be32(&hw->gamma, gamma.paddr);
- out_be32(&hw->cursor, cursor.paddr);
- out_be32(&hw->bgnd, 0x007F7F7F);
- out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
- out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
- info.var.hsync_len << 11 |
- info.var.right_margin);
-
- out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
- info.var.vsync_len << 11 |
- info.var.lower_margin);
-
- /* Pixel Clock configuration */
- diu_set_pixel_clock(info.var.pixclock);
-
- /* Set the frame buffers */
- out_be32(&hw->desc[0], virt_to_phys(ad));
- out_be32(&hw->desc[1], 0);
- out_be32(&hw->desc[2], 0);
-
- /* Enable the DIU, set display to all three planes */
- out_be32(&hw->diu_mode, 1);
-
- return 0;
-}
-
-void *video_hw_init(void)
-{
- static GraphicDevice ctfb;
- const char *options;
- unsigned int depth = 0, freq = 0;
-
- if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
- &options))
- return NULL;
-
- /* Find the monitor port, which is a required option */
- if (!options)
- return NULL;
- if (strncmp(options, "monitor=", 8) != 0)
- return NULL;
-
- if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
- return NULL;
-
- /* fill in Graphic device struct */
- sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
- ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
-
- ctfb.frameAdrs = (unsigned int)info.screen_base;
- ctfb.plnSizeX = ctfb.winSizeX;
- ctfb.plnSizeY = ctfb.winSizeY;
-
- ctfb.gdfBytesPP = 4;
- ctfb.gdfIndex = GDF_32BIT_X888RGB;
-
- ctfb.isaBase = 0;
- ctfb.pciBase = 0;
- ctfb.memSize = info.screen_size;
-
- /* Cursor Start Address */
- ctfb.dprBase = 0;
- ctfb.vprBase = 0;
- ctfb.cprBase = 0;
-
- return &ctfb;
-}
diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 98228f2..49bbeef 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -22,7 +22,6 @@
#include <asm/io.h>
#include <asm/mach-imx/video.h>
#include <malloc.h>
-#include <video_fb.h>
#include "../videomodes.h"
#include "ipu.h"
#include "mxcfb.h"
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 5f85c0c..1043394 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -15,7 +15,6 @@
#include <linux/errno.h>
#include <malloc.h>
#include <video.h>
-#include <video_fb.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
@@ -253,94 +252,6 @@ static int mxs_remove_common(u32 fb)
return 0;
}
-#ifndef CONFIG_DM_VIDEO
-
-static GraphicDevice panel;
-
-void lcdif_power_down(void)
-{
- mxs_remove_common(panel.frameAdrs);
-}
-
-void *video_hw_init(void)
-{
- int bpp = -1;
- int ret = 0;
- char *penv;
- void *fb = NULL;
- struct ctfb_res_modes mode;
- struct display_timing timings;
-
- puts("Video: ");
-
- /* Suck display configuration from "videomode" variable */
- penv = env_get("videomode");
- if (!penv) {
- puts("MXSFB: 'videomode' variable not set!\n");
- return NULL;
- }
-
- bpp = video_get_params(&mode, penv);
-
- /* fill in Graphic device struct */
- sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp);
-
- panel.winSizeX = mode.xres;
- panel.winSizeY = mode.yres;
- panel.plnSizeX = mode.xres;
- panel.plnSizeY = mode.yres;
-
- switch (bpp) {
- case 24:
- case 18:
- panel.gdfBytesPP = 4;
- panel.gdfIndex = GDF_32BIT_X888RGB;
- break;
- case 16:
- panel.gdfBytesPP = 2;
- panel.gdfIndex = GDF_16BIT_565RGB;
- break;
- case 8:
- panel.gdfBytesPP = 1;
- panel.gdfIndex = GDF__8BIT_INDEX;
- break;
- default:
- printf("MXSFB: Invalid BPP specified! (bpp = %i)\n", bpp);
- return NULL;
- }
-
- panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP;
-
- /* Allocate framebuffer */
- fb = memalign(ARCH_DMA_MINALIGN,
- roundup(panel.memSize, ARCH_DMA_MINALIGN));
- if (!fb) {
- printf("MXSFB: Error allocating framebuffer!\n");
- return NULL;
- }
-
- /* Wipe framebuffer */
- memset(fb, 0, panel.memSize);
-
- panel.frameAdrs = (u32)fb;
-
- printf("%s\n", panel.modeIdent);
-
- video_ctfb_mode_to_display_timing(&mode, &timings);
-
- ret = mxs_probe_common(NULL, &timings, bpp, (u32)fb);
- if (ret)
- goto dealloc_fb;
-
- return (void *)&panel;
-
-dealloc_fb:
- free(fb);
-
- return NULL;
-}
-#else /* ifndef CONFIG_DM_VIDEO */
-
static int mxs_of_get_timings(struct udevice *dev,
struct display_timing *timings,
u32 *bpp)
@@ -490,4 +401,3 @@ U_BOOT_DRIVER(mxs_video) = {
.remove = mxs_video_remove,
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
};
-#endif /* ifndef CONFIG_DM_VIDEO */
diff --git a/drivers/video/nexell_display.c b/drivers/video/nexell_display.c
index c7621ef..090fd6e 100644
--- a/drivers/video/nexell_display.c
+++ b/drivers/video/nexell_display.c
@@ -16,7 +16,6 @@
#include <linux/compat.h>
#include <linux/err.h>
#include <video.h> /* For struct video_uc_plat */
-#include <video_fb.h>
#include <lcd.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -537,7 +536,6 @@ static int nx_display_probe(struct udevice *dev)
struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct nx_display_plat *plat = dev_get_plat(dev);
- static GraphicDevice *graphic_device;
char addr[64];
debug("%s()\n", __func__);
@@ -564,7 +562,6 @@ static int nx_display_probe(struct udevice *dev)
}
struct nx_display_dev *dp;
- unsigned int pp_index = 0;
dp = nx_display_setup();
if (!dp) {
@@ -575,7 +572,6 @@ static int nx_display_probe(struct udevice *dev)
switch (dp->depth) {
case 2:
- pp_index = GDF_16BIT_565RGB;
uc_priv->bpix = VIDEO_BPP16;
break;
case 3:
@@ -583,7 +579,6 @@ static int nx_display_probe(struct udevice *dev)
* type video_log2_bpp
*/
case 4:
- pp_index = GDF_32BIT_X888RGB;
uc_priv->bpix = VIDEO_BPP32;
break;
default:
@@ -596,19 +591,9 @@ static int nx_display_probe(struct udevice *dev)
uc_priv->ysize = dp->fb_plane->height;
uc_priv->rot = 0;
- graphic_device = &dp->graphic_device;
- graphic_device->frameAdrs = dp->fb_addr;
- graphic_device->gdfIndex = pp_index;
- graphic_device->gdfBytesPP = dp->depth;
- graphic_device->winSizeX = dp->fb_plane->width;
- graphic_device->winSizeY = dp->fb_plane->height;
- graphic_device->plnSizeX =
- graphic_device->winSizeX * graphic_device->gdfBytesPP;
-
/*
* set environment variable "fb_addr" (frame buffer address), required
- * for splash image. Because drv_video_init() in common/stdio.c is only
- * called when CONFIG_VIDEO is set (and not if CONFIG_DM_VIDEO is set).
+ * for splash image, which is not set if CONFIG_DM_VIDEO is enabled).
*/
sprintf(addr, "0x%x", dp->fb_addr);
debug("%s(): env_set(\"fb_addr\", %s) ...\n", __func__, addr);
diff --git a/drivers/video/omap3_dss.c b/drivers/video/omap3_dss.c
index 6efba12..432b16b 100644
--- a/drivers/video/omap3_dss.c
+++ b/drivers/video/omap3_dss.c
@@ -28,7 +28,6 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/dss.h>
-#include <video_fb.h>
/* Configure VENC for a given Mode (NTSC / PAL) */
void omap3_dss_venc_config(const struct venc_regs *venc_cfg,
@@ -137,31 +136,3 @@ void omap3_dss_enable(void)
l |= LCD_ENABLE | GO_LCD | DIG_ENABLE | GO_DIG | GP_OUT0 | GP_OUT1;
writel(l, &dispc->control);
}
-
-#ifdef CONFIG_CFB_CONSOLE
-int __board_video_init(void)
-{
- return -1;
-}
-
-int board_video_init(void)
- __attribute__((weak, alias("__board_video_init")));
-
-void *video_hw_init(void)
-{
- static GraphicDevice dssfb;
- GraphicDevice *pGD = &dssfb;
- struct dispc_regs *dispc = (struct dispc_regs *) OMAP3_DISPC_BASE;
-
- if (board_video_init() || !readl(&dispc->gfx_ba0))
- return NULL;
-
- pGD->winSizeX = (readl(&dispc->size_lcd) & 0x7FF) + 1;
- pGD->winSizeY = ((readl(&dispc->size_lcd) >> 16) & 0x7FF) + 1;
- pGD->gdfBytesPP = 4;
- pGD->gdfIndex = GDF_32BIT_X888RGB;
- pGD->frameAdrs = readl(&dispc->gfx_ba0);
-
- return pGD;
-}
-#endif
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 5a21f7a..2ee6212 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -30,7 +30,6 @@
#include <i2c.h>
#include <malloc.h>
#include <video.h>
-#include <video_fb.h>
#include <dm/uclass-internal.h>
#include "../videomodes.h"
#include "../anx9804.h"
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index f9c2c40..01e8af5 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -209,7 +209,7 @@ int video_sync(struct udevice *vid, bool force)
struct video_priv *priv = dev_get_uclass_priv(vid);
static ulong last_sync;
- if (force || get_timer(last_sync) > 10) {
+ if (force || get_timer(last_sync) > 100) {
sandbox_sdl_sync(priv->fb);
last_sync = get_timer(0);
}
diff --git a/drivers/video/zynqmp_dpsub.c b/drivers/video/zynqmp_dpsub.c
new file mode 100644
index 0000000..4ead663
--- /dev/null
+++ b/drivers/video/zynqmp_dpsub.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Xilinx Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <video.h>
+#include <dm/device_compat.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+
+/**
+ * struct zynqmp_dpsub_priv - Private structure
+ * @dev: Device uclass for video_ops
+ */
+struct zynqmp_dpsub_priv {
+ struct udevice *dev;
+};
+
+static int zynqmp_dpsub_probe(struct udevice *dev)
+{
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct zynqmp_dpsub_priv *priv = dev_get_priv(dev);
+
+ uc_priv->bpix = VIDEO_BPP16;
+ uc_priv->xsize = WIDTH;
+ uc_priv->ysize = HEIGHT;
+ uc_priv->rot = 0;
+
+ priv->dev = dev;
+
+ /* Only placeholder for power domain driver */
+ return 0;
+}
+
+static int zynqmp_dpsub_bind(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ plat->size = WIDTH * HEIGHT * 16;
+
+ return 0;
+}
+
+static const struct video_ops zynqmp_dpsub_ops = {
+};
+
+static const struct udevice_id zynqmp_dpsub_ids[] = {
+ { .compatible = "xlnx,zynqmp-dpsub-1.7" },
+ { }
+};
+
+U_BOOT_DRIVER(zynqmp_dpsub_video) = {
+ .name = "zynqmp_dpsub_video",
+ .id = UCLASS_VIDEO,
+ .of_match = zynqmp_dpsub_ids,
+ .ops = &zynqmp_dpsub_ops,
+ .plat_auto = sizeof(struct video_uc_plat),
+ .bind = zynqmp_dpsub_bind,
+ .probe = zynqmp_dpsub_probe,
+ .priv_auto = sizeof(struct zynqmp_dpsub_priv),
+};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f90f0ca..5b614cf 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -129,7 +129,8 @@ config WDT_AT91
config WDT_BCM6345
bool "BCM6345 watchdog timer support"
depends on WDT && (ARCH_BMIPS || ARCH_BCM68360 || \
- ARCH_BCM6858 || ARCH_BCM63158)
+ ARCH_BCM6858 || ARCH_BCM63158 || \
+ ARCH_BCM6753)
help
Select this to enable watchdog timer for BCM6345 SoCs.
The watchdog timer is stopped when initialized.