summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/imx/Makefile2
-rw-r--r--drivers/clk/imx/clk-gate-93.c146
-rw-r--r--drivers/clk/imx/clk-imx93.c4
-rw-r--r--drivers/clk/imx/clk.h3
-rw-r--r--drivers/crypto/fsl/fsl_hash.c1
-rw-r--r--drivers/ddr/imx/imx9/Kconfig8
-rw-r--r--drivers/ddr/imx/imx9/ddr_init.c35
-rw-r--r--drivers/fastboot/fb_fsl/fb_fsl_command.c19
-rw-r--r--drivers/fastboot/fb_fsl/fb_fsl_partitions.c12
-rw-r--r--drivers/misc/sentinel/s400_api.c78
-rw-r--r--drivers/mtd/spi/spi-nor-ids.c4
-rw-r--r--drivers/net/fec_mxc.c3
-rw-r--r--drivers/thermal/Kconfig6
-rw-r--r--drivers/thermal/imx_tmu.c98
-rw-r--r--drivers/usb/cdns3/gadget.c2
-rw-r--r--drivers/video/nxp/imx/Kconfig7
-rw-r--r--drivers/video/nxp/imx/Makefile1
-rw-r--r--drivers/video/nxp/imx/dw_dsi_imx.c4
-rw-r--r--drivers/video/nxp/imx/imx8_lvds.c14
-rw-r--r--drivers/video/nxp/imx/imx93-parallel-disp-fmt.c166
-rw-r--r--drivers/video/nxp/imx/imx_lcdifv3.c19
-rw-r--r--drivers/video/nxp/imx/sec_dsim_imx.c17
-rw-r--r--drivers/video/simple_panel.c27
23 files changed, 645 insertions, 31 deletions
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 2e44b249cb..4eebc34092 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -20,4 +20,4 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o
obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o
-obj-$(CONFIG_$(SPL_TPL_)CLK_IMX93) += clk-imx93.o clk-fracn-gppll.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_IMX93) += clk-imx93.o clk-fracn-gppll.o clk-gate-93.o
diff --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c
new file mode 100644
index 0000000000..7b43f18e6e
--- /dev/null
+++ b/drivers/clk/imx/clk-gate-93.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ *
+ * Author: Alice Guo <alice.guo@nxp.com>
+ */
+
+#include <asm/io.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <linux/bug.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+#define LPCG_DIRECT 0x0
+#define LPCG_LPM_CUR 0x1c
+#define LPM_SETTING_OFF 0x0
+#define LPM_SETTING_ON 0x4
+#define LPCG_AUTHEN 0x30
+#define WHITE_LIST_DM0 16
+#define DOMAIN_ID_A55 3
+#define TZ_NS BIT(9)
+#define CPULPM_MOD BIT(2)
+
+struct imx93_clk_gate {
+ struct clk clk;
+ void __iomem *reg_base;
+ u8 lpcg_on_offset;
+ u8 lpcg_on_ctrl;
+ u8 lpcg_on_mask;
+ ulong flags;
+};
+
+#define to_imx93_clk_gate(_clk) container_of(_clk, struct imx93_clk_gate, clk)
+
+static bool imx93_clk_gate_check_authen(void __iomem *reg_base)
+{
+ u32 authen;
+
+ authen = readl(reg_base + LPCG_AUTHEN);
+ if (!(authen & TZ_NS) || !(authen & BIT(WHITE_LIST_DM0 + DOMAIN_ID_A55)))
+ return false;
+
+ return true;
+}
+
+static void imx93_clk_gate_ctrl_hw(struct clk *clk, bool enable)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
+ u32 v;
+
+ v = readl(gate->reg_base + LPCG_AUTHEN);
+ if (v & CPULPM_MOD) {
+ v = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
+ writel(v, gate->reg_base + LPCG_LPM_CUR);
+ } else {
+ v = readl(gate->reg_base + LPCG_DIRECT);
+ v &= ~(gate->lpcg_on_mask << gate->lpcg_on_offset);
+ if (enable)
+ v |= (gate->lpcg_on_ctrl & gate->lpcg_on_mask) << gate->lpcg_on_offset;
+ writel(v, gate->reg_base + LPCG_DIRECT);
+ }
+}
+
+static int imx93_clk_gate_enable(struct clk *clk)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
+
+ if (!imx93_clk_gate_check_authen(gate->reg_base))
+ return -EINVAL;
+
+ imx93_clk_gate_ctrl_hw(clk, true);
+
+ return 0;
+}
+
+static int imx93_clk_gate_disable(struct clk *clk)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
+
+ if (!imx93_clk_gate_check_authen(gate->reg_base))
+ return -EINVAL;
+
+ imx93_clk_gate_ctrl_hw(clk, false);
+
+ return 0;
+}
+
+static ulong imx93_clk_gate_set_rate(struct clk *clk, ulong rate)
+{
+ struct clk *parent = clk_get_parent(clk);
+
+ if (parent)
+ return clk_set_rate(parent, rate);
+
+ return -ENODEV;
+}
+
+static const struct clk_ops imx93_clk_gate_ops = {
+ .set_rate = imx93_clk_gate_set_rate,
+ .enable = imx93_clk_gate_enable,
+ .disable = imx93_clk_gate_disable,
+ .get_rate = clk_generic_get_rate,
+};
+
+static struct clk *register_clk_gate(const char *name, const char *parent_name,
+ void __iomem *reg_base, u8 lpcg_on_offset,
+ u8 lpcg_on_ctrl, u8 lpcg_on_mask, ulong flags)
+{
+ struct imx93_clk_gate *gate;
+ int ret;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->reg_base = reg_base;
+ gate->lpcg_on_offset = lpcg_on_offset;
+ gate->lpcg_on_ctrl = lpcg_on_ctrl;
+ gate->lpcg_on_mask = lpcg_on_mask;
+ gate->flags = flags;
+
+ ret = clk_register(&gate->clk, "imx93_clk_gate", name, parent_name);
+ if (ret) {
+ kfree(gate);
+ return ERR_PTR(ret);
+ }
+
+ return &gate->clk;
+}
+
+struct clk *clk_register_imx93_clk_gate(const char *name, const char *parent_name,
+ void __iomem *reg_base, u8 lpcg_on_offset,
+ ulong flags)
+{
+ return register_clk_gate(name, parent_name, reg_base, lpcg_on_offset, 1,
+ 1, flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
+}
+
+U_BOOT_DRIVER(imx93_clk_gate) = {
+ .name = "imx93_clk_gate",
+ .id = UCLASS_CLK,
+ .ops = &imx93_clk_gate_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 87ba829841..f0d7f49a1f 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -407,8 +407,8 @@ static int imx93_clk_probe(struct udevice *dev)
for (int i = 0; i < ARRAY_SIZE(clk_ccgrs); i++) {
ccgr = &clk_ccgrs[i];
- clk = imx_clk_gate4_flags(ccgr->name, ccgr->parent_names,
- ccm_base + ccgr->off, 0, ccgr->flags);
+ clk = clk_register_imx93_clk_gate(ccgr->name, ccgr->parent_names,
+ ccm_base + ccgr->off, 0, ccgr->flags);
clk_dm(ccgr->clk_id, clk);
}
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index dd4df82125..e690756150 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -52,6 +52,9 @@ struct imx93_pll_fracn_gp {
struct clk *clk_register_imx93_pll(const char *name, const char *parent_name,
void __iomem *reg);
+struct clk *clk_register_imx93_clk_gate(const char *name, const char *parent_name,
+ void __iomem *reg_base, u8 lpcg_on_offset,
+ ulong flags);
struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
void __iomem *base,
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index 09d744464b..226e4be51d 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -186,7 +186,6 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len,
uint32_t *desc;
unsigned int size;
- debug("\ncaam hash\n");
desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
if (!desc) {
debug("Not enough memory for descriptor allocation\n");
diff --git a/drivers/ddr/imx/imx9/Kconfig b/drivers/ddr/imx/imx9/Kconfig
index 123ad173cf..0c2ee89c31 100644
--- a/drivers/ddr/imx/imx9/Kconfig
+++ b/drivers/ddr/imx/imx9/Kconfig
@@ -17,11 +17,17 @@ config IMX9_DRAM_PM_COUNTER
help
Enable DDR controller performance monitor counter for reference events.
+config IMX9_DRAM_INLINE_ECC
+ bool "Enable DDR INLINE ECC feature"
+ default n
+ help
+ Select to enable DDR INLINE ECC feature
+
config SAVED_DRAM_TIMING_BASE
hex "Define the base address for saved dram timing"
help
after DRAM is trained, need to save the dram related timming
info into memory for low power use.
- default 0x204DC000
+ default 0x2051C000
endmenu
diff --git a/drivers/ddr/imx/imx9/ddr_init.c b/drivers/ddr/imx/imx9/ddr_init.c
index 7cf1142f9a..17b4b259ac 100644
--- a/drivers/ddr/imx/imx9/ddr_init.c
+++ b/drivers/ddr/imx/imx9/ddr_init.c
@@ -197,6 +197,37 @@ void update_umctl2_rank_space_setting(unsigned int pstat_num)
writel(tmp_t, REG_DDR_TIMING_CFG_4);
}
+void update_inline_ecc_setting(void)
+{
+ u32 val, sa, ea;
+
+ val = readl(REG_DDR_CS0_BNDS);
+ if (val != 0) {
+ sa = (val >> 16) & 0xff;
+ ea = val & 0xff;
+
+ /* 1/8 size is used for inline ecc */
+ ea = ea - ((ea + 1 - sa) >> 3);
+ writel((sa << 16) | ea, REG_DDR_CS0_BNDS);
+ }
+
+ val = readl(REG_DDR_CS1_BNDS);
+ if (val != 0) {
+ sa = (val >> 16) & 0xff;
+ ea = val & 0xff;
+
+ /* 1/8 size is used for inline ecc */
+ ea = ea - ((ea + 1 - sa) >> 3);
+ writel((sa << 16) | ea, REG_DDR_CS1_BNDS);
+ }
+
+ /* Enable Inline ECC */
+ setbits_le32(REG_DDR_ERR_EN, BIT(31) | BIT(30));
+
+ /* Enable data initialization */
+ setbits_le32(REG_DDR_SDRAM_CFG2, BIT(4));
+}
+
int ddr_init(struct dram_timing_info *dram_timing)
{
unsigned int initial_drate;
@@ -233,6 +264,10 @@ int ddr_init(struct dram_timing_info *dram_timing)
update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1);
+#ifdef CONFIG_IMX9_DRAM_INLINE_ECC
+ update_inline_ecc_setting();
+#endif
+
#ifdef CONFIG_IMX9_DRAM_PM_COUNTER
writel(0x200000, REG_DDR_DEBUG_19);
#endif
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_command.c b/drivers/fastboot/fb_fsl/fb_fsl_command.c
index 11224728a8..61b1a9d580 100644
--- a/drivers/fastboot/fb_fsl/fb_fsl_command.c
+++ b/drivers/fastboot/fb_fsl/fb_fsl_command.c
@@ -472,6 +472,16 @@ static bool endswith(char* s, char* subs) {
return true;
}
+static bool erase_uboot_env(void) {
+ FbLockState status;
+ status = fastboot_get_lock_stat();
+ if (status == FASTBOOT_LOCK) {
+ printf("can not erase env when device is in locked state\n");
+ return false;
+ } else
+ return env_erase() ? false : true;
+}
+
static void flashing(char *cmd, char *response)
{
FbLockState status;
@@ -726,7 +736,14 @@ static void flashing(char *cmd, char *response)
}
#endif /* !CONFIG_AVB_ATX */
#endif /* CONFIG_IMX_TRUSTY_OS */
- else if (endswith(cmd, "unlock_critical")) {
+ else if (endswith(cmd, ERASE_UBOOT_ENV)) {
+ if(erase_uboot_env())
+ strcpy(response, "OKAY");
+ else {
+ printf("ERROR erase uboot environment variable failed!");
+ strcpy(response, "FAILerase uboot environment variable failed!");
+ }
+ } else if (endswith(cmd, "unlock_critical")) {
strcpy(response, "OKAY");
} else if (endswith(cmd, "unlock")) {
printf("flashing unlock.\n");
diff --git a/drivers/fastboot/fb_fsl/fb_fsl_partitions.c b/drivers/fastboot/fb_fsl/fb_fsl_partitions.c
index 237ae875ab..a43c70db93 100644
--- a/drivers/fastboot/fb_fsl/fb_fsl_partitions.c
+++ b/drivers/fastboot/fb_fsl/fb_fsl_partitions.c
@@ -118,16 +118,16 @@ static int _fastboot_parts_add_ptable_entry(int ptable_index,
!strcmp((const char *)info.name, FASTBOOT_PARTITION_OEM_A) ||
!strcmp((const char *)info.name, FASTBOOT_PARTITION_VENDOR_A) ||
!strcmp((const char *)info.name, FASTBOOT_PARTITION_OEM_B) ||
- !strcmp((const char *)info.name, FASTBOOT_PARTITION_VENDOR_B) ||
- !strcmp((const char *)info.name, FASTBOOT_PARTITION_DATA) ||
+ !strcmp((const char *)info.name, FASTBOOT_PARTITION_VENDOR_B))
#else
if (!strcmp((const char *)info.name, FASTBOOT_PARTITION_SYSTEM) ||
- !strcmp((const char *)info.name, FASTBOOT_PARTITION_DATA) ||
!strcmp((const char *)info.name, FASTBOOT_PARTITION_DEVICE) ||
- !strcmp((const char *)info.name, FASTBOOT_PARTITION_CACHE) ||
+ !strcmp((const char *)info.name, FASTBOOT_PARTITION_CACHE))
#endif
- !strcmp((const char *)info.name, FASTBOOT_PARTITION_METADATA))
- strcpy(ptable[ptable_index].fstype, "ext4");
+ strcpy(ptable[ptable_index].fstype, "erofs");
+ else if (!strcmp((const char *)info.name, FASTBOOT_PARTITION_DATA) ||
+ !strcmp((const char *)info.name, FASTBOOT_PARTITION_METADATA))
+ strcpy(ptable[ptable_index].fstype, "f2fs");
else
strcpy(ptable[ptable_index].fstype, "raw");
return 0;
diff --git a/drivers/misc/sentinel/s400_api.c b/drivers/misc/sentinel/s400_api.c
index 271d12191d..baab9b2c9b 100644
--- a/drivers/misc/sentinel/s400_api.c
+++ b/drivers/misc/sentinel/s400_api.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright 2020 NXP
+ * Copyright 2020, 2022 NXP
*
*/
@@ -14,6 +14,18 @@
DECLARE_GLOBAL_DATA_PTR;
+static uint32_t compute_crc(const struct sentinel_msg *msg)
+{
+ u32 crc = 0;
+ size_t i = 0;
+ u32 *data = (u32 *)msg;
+
+ for (i = 0; i < (msg->size - 1); i++)
+ crc ^= data[i];
+
+ return crc;
+}
+
int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response)
{
struct udevice *dev = gd->arch.s400_dev;
@@ -516,3 +528,67 @@ int ahab_start_rng(void)
return ret;
}
+
+int ahab_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr,
+ u32 max_output_size)
+{
+ struct udevice *dev = gd->arch.s400_dev;
+ int size = sizeof(struct sentinel_msg);
+ struct sentinel_msg msg;
+ int ret;
+
+ if (!dev) {
+ printf("s400 dev is not initialized\n");
+ return -ENODEV;
+ }
+
+ msg.version = AHAB_VERSION;
+ msg.tag = AHAB_CMD_TAG;
+ msg.size = 8;
+ msg.command = ELE_GENERATE_DEK_BLOB;
+ msg.data[0] = key_id;
+ msg.data[1] = 0x0;
+ msg.data[2] = src_paddr;
+ msg.data[3] = 0x0;
+ msg.data[4] = dst_paddr;
+ msg.data[5] = max_output_size;
+ msg.data[6] = compute_crc(&msg);
+
+ ret = misc_call(dev, false, &msg, size, &msg, size);
+ if (ret)
+ printf("Error: %s: ret 0x%x, response 0x%x\n",
+ __func__, ret, msg.data[0]);
+
+ return ret;
+}
+
+int ahab_write_secure_fuse(ulong signed_msg_blk, u32 *response)
+{
+ struct udevice *dev = gd->arch.s400_dev;
+ int size = sizeof(struct sentinel_msg);
+ struct sentinel_msg msg;
+ int ret;
+
+ if (!dev) {
+ printf("s400 dev is not initialized\n");
+ return -ENODEV;
+ }
+
+ msg.version = AHAB_VERSION;
+ msg.tag = AHAB_CMD_TAG;
+ msg.size = 3;
+ msg.command = ELE_WRITE_SECURE_FUSE_REQ;
+
+ msg.data[0] = upper_32_bits(signed_msg_blk);
+ msg.data[1] = lower_32_bits(signed_msg_blk);
+
+ ret = misc_call(dev, false, &msg, size, &msg, size);
+ if (ret)
+ printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n",
+ __func__, ret, msg.data[0], msg.data[1]);
+
+ if (response)
+ *response = msg.data[0];
+
+ return ret;
+}
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 7524337746..86a1c4c81b 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -136,6 +136,10 @@ const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
+ {
+ INFO("gd25lx256e", 0xc86819, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_HAS_LOCK | SPI_NOR_4B_OPCODES)
+ },
#endif
#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
/* ISSI */
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 84fbc43a37..b67569b7cd 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -884,6 +884,9 @@ static int fec_recv(struct eth_device *dev)
ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
#endif
+ if (!(readl(&fec->eth->ecntrl) & FEC_ECNTRL_ETHER_EN))
+ return 0;
+
/* Check if any critical events have happened */
ievent = readl(&fec->eth->ievent);
writel(ievent, &fec->eth->ievent);
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 8666d67483..6274640c41 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -27,10 +27,10 @@ config IMX_SCU_THERMAL
trip is crossed
config IMX_TMU
- bool "Thermal Management Unit driver for NXP i.MX8M"
- depends on ARCH_IMX8M
+ bool "Thermal Management Unit driver for NXP i.MX8M and iMX93"
+ depends on ARCH_IMX8M || IMX93
help
- Support for Temperature sensors on NXP i.MX8M.
+ Support for Temperature sensors on NXP i.MX8M and iMX93.
It supports one critical trip point and one passive trip point.
The boot is hold to the cool device to throttle CPUs when the
passive trip is crossed
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c
index ca45abbb8e..893e674455 100644
--- a/drivers/thermal/imx_tmu.c
+++ b/drivers/thermal/imx_tmu.c
@@ -24,6 +24,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define SITES_MAX 16
#define FLAGS_VER2 0x1
#define FLAGS_VER3 0x2
+#define FLAGS_VER4 0x4
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
@@ -75,6 +76,46 @@ struct imx_tmu_regs {
u32 ttr3cr; /* Temperature Range 3 Control Register */
};
+struct imx_tmu_regs_v4 {
+ u32 tmr; /* Mode Register */
+ u32 tsr; /* Status Register */
+ u32 tmsr; /* Monitor Site Register */
+ u32 tmtmir; /* Temperature measurement interval Register */
+ u8 res0[0x10];
+ u32 tier; /* Interrupt Enable Register */
+ u32 tidr; /* Interrupt Detect Register */
+ u8 res1[0x8];
+ u32 tiiscr; /* Interrupt Immediate Site Capture Register */
+ u32 tiascr; /* Interrupt Average Site Capture Register */
+ u32 ticscr; /* Interrupt Critical Site Capture Register */
+ u8 res2[0x4];
+ u32 tmhtcr; /* Monitor High Temperature Capture Register */
+ u32 tmltcr; /* MonitorLow Temperature Capture Register */
+ u32 tmrtrcr; /* Monitor Rising Temperature Rate Capture Register */
+ u32 tmftrcr; /* Monitor Falling Temperature Rate Capture Register */
+ u32 tmhtitr; /* Monitor High Temperature Immediate Threshold */
+ u32 tmhtatr; /* Monitor High Temperature Average Threshold */
+ u32 tmhtactr; /* Monitor High Temperature Average Crit Threshold */
+ u8 res3[0x4];
+ u32 tmltitr; /* Monitor Low Temperature Immediate Threshold */
+ u32 tmltatr; /* Monitor Low Temperature Average Threshold */
+ u32 tmltactr; /* Monitor Low Temperature Average Crit Threshold */
+ u8 res4[0x4];
+ u32 tmrtrctr; /* Monitor Rising Temperature Rate Critical Threshold Register */
+ u32 tmftrctr; /* Monitor Falling Temperature Rate Critical Threshold Register */
+ u8 res5[0x8];
+ u32 ttcfgr; /* Temperature Configuration Register */
+ u32 tscfgr; /* Sensor Configuration Register */
+ u8 res6[0x78];
+ u32 tritsr0; /* Immediate Temperature Site Register */
+ u32 tratsr0; /* Average Temperature Site Register */
+ u8 res7[0xdf8];
+ u32 tcmcfg; /* Central Module Configuration */
+ u8 res8[0xc];
+ u32 ttrcr[16]; /* Temperature Range Control Register */
+};
+
+
struct imx_tmu_regs_v2 {
u32 ter; /* TMU enable Register */
u32 tsr; /* Status Register */
@@ -114,6 +155,7 @@ union tmu_regs {
struct imx_tmu_regs regs_v1;
struct imx_tmu_regs_v2 regs_v2;
struct imx_tmu_regs_v3 regs_v3;
+ struct imx_tmu_regs_v4 regs_v4;
};
struct imx_tmu_plat {
@@ -147,6 +189,9 @@ static int read_temperature(struct udevice *dev, int *temp)
* only reflects the RAW uncalibrated data
*/
valid = ((val & 0xff) < 10 || (val & 0xff) > 125) ? 0 : 1;
+ } else if (drv_data & FLAGS_VER4) {
+ val = readl(&pdata->regs->regs_v4.tritsr0);
+ valid = val & 0x80000000;
} else {
val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr);
valid = val & 0x80000000;
@@ -164,6 +209,13 @@ static int read_temperature(struct udevice *dev, int *temp)
return -EINVAL;
*temp *= 1000;
+ } else if (drv_data & FLAGS_VER4) {
+ *temp = (val & 0x1ff) * 1000;
+ if (val & 0x200)
+ *temp += 500;
+
+ /* Convert Kelvin to Celsius */
+ *temp -= 273000;
} else {
*temp = (val & 0xff) * 1000;
}
@@ -215,6 +267,26 @@ static int imx_tmu_calibration(struct udevice *dev)
if (drv_data & (FLAGS_VER2 | FLAGS_VER3))
return 0;
+ if (drv_data & FLAGS_VER4) {
+ int index;
+ calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
+ if (!calibration || len % 8 || len > 128) {
+ printf("TMU: invalid calibration data.\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < len; i += 8, calibration += 2) {
+ index = i / 8;
+ writel(index, &pdata->regs->regs_v4.ttcfgr);
+ val = fdt32_to_cpu(*calibration);
+ writel(val, &pdata->regs->regs_v4.tscfgr);
+ val = fdt32_to_cpu(*(calibration + 1));
+ writel((1 << 31) | val, &pdata->regs->regs_v4.ttrcr[index]);
+ }
+
+ return 0;
+ }
+
ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
if (ret) {
printf("TMU: missing calibration range, ret = %d.\n", ret);
@@ -267,6 +339,15 @@ static void imx_tmu_init(struct udevice *dev)
/* Disable interrupt, using polling instead */
writel(0x0, &pdata->regs->regs_v2.tier);
+ } else if (drv_data & FLAGS_VER4) {
+ /* Disable monitoring */
+ writel(TMR_DISABLE, &pdata->regs->regs_v4.tmr);
+
+ /* Disable interrupt, using polling instead */
+ writel(TIER_DISABLE, &pdata->regs->regs_v4.tier);
+
+ /* Set update_interval */
+ writel(TMTMIR_DEFAULT, &pdata->regs->regs_v4.tmtmir);
} else {
/* Disable monitoring */
writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
@@ -319,6 +400,22 @@ static int imx_tmu_enable_msite(struct udevice *dev)
/* Enable monitor */
reg |= TER_EN;
writel(reg, &pdata->regs->regs_v2.ter);
+ } else if (drv_data & FLAGS_VER4) {
+ reg = readl(&pdata->regs->regs_v4.tcmcfg);
+ reg |= (1 << 30) | (1 << 28);
+ reg &= ~0xF000; /* set SAR clk = IPG clk /16 */
+ writel(reg, &pdata->regs->regs_v4.tcmcfg);
+
+ /* Set ALPF*/
+ reg = readl(&pdata->regs->regs_v4.tmr);
+ reg |= TMR_ALPF;
+ writel(reg, &pdata->regs->regs_v4.tmr);
+
+ writel(1, &pdata->regs->regs_v4.tmsr);
+
+ /* Enable ME */
+ reg |= TMR_ME;
+ writel(reg, &pdata->regs->regs_v4.tmr);
} else {
/* Clear the ME before setting MSITE and ALPF*/
reg = readl(&pdata->regs->regs_v1.tmr);
@@ -460,6 +557,7 @@ static const struct udevice_id imx_tmu_ids[] = {
{ .compatible = "fsl,imx8mq-tmu", },
{ .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
{ .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, },
+ { .compatible = "fsl,imx93-tmu", .data = FLAGS_VER4, },
{ }
};
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
index 5bd80cf986..730454c66e 100644
--- a/drivers/usb/cdns3/gadget.c
+++ b/drivers/usb/cdns3/gadget.c
@@ -55,7 +55,7 @@ static struct usb_request *next_request(struct list_head *list)
static void select_ep(struct usb_ss_dev *usb_ss, u32 ep)
{
if (!usb_ss || !usb_ss->regs) {
- dev_err(&usb_ss->dev, "Failed to select endpoint!\n");
+ printf("Failed to select endpoint!\n");
return;
}
diff --git a/drivers/video/nxp/imx/Kconfig b/drivers/video/nxp/imx/Kconfig
index 49455fac49..1824b969fb 100644
--- a/drivers/video/nxp/imx/Kconfig
+++ b/drivers/video/nxp/imx/Kconfig
@@ -123,3 +123,10 @@ config VIDEO_IMX_DCNANO
help
Support for i.MX8ULP DCNANO LCD controller.
+config VIDEO_IMX93_PARALLEL_DISPLAY_FORMAT
+ bool "Support for i.MX93 parallel display format"
+ select VIDEO_BRIDGE
+ select VIDEO_LINK
+ help
+ Choose this to enable the internal parallel display format
+ configuration found on i.MX93 processors.
diff --git a/drivers/video/nxp/imx/Makefile b/drivers/video/nxp/imx/Makefile
index 1d2035c63a..019789fe0c 100644
--- a/drivers/video/nxp/imx/Makefile
+++ b/drivers/video/nxp/imx/Makefile
@@ -15,4 +15,5 @@ obj-$(CONFIG_VIDEO_NW_MIPI_DSI) += mipi_dsi_northwest.o
obj-$(CONFIG_VIDEO_IMX_NW_DSI) += nw_dsi_imx.o
obj-$(CONFIG_VIDEO_IMX_DW_DSI) += dw_dsi_imx.o
obj-$(CONFIG_VIDEO_IMX_DCNANO) += dcnano.o
+obj-$(CONFIG_VIDEO_IMX93_PARALLEL_DISPLAY_FORMAT) += imx93-parallel-disp-fmt.o
obj-y += hdmi/
diff --git a/drivers/video/nxp/imx/dw_dsi_imx.c b/drivers/video/nxp/imx/dw_dsi_imx.c
index cf65ec02e5..6bdd382621 100644
--- a/drivers/video/nxp/imx/dw_dsi_imx.c
+++ b/drivers/video/nxp/imx/dw_dsi_imx.c
@@ -349,6 +349,10 @@ static int dw_dsi_imx_check_timing(struct udevice *dev, struct display_timing *t
return -ENOTCONN;
}
+ /* DSI force the Polarities as high */
+ priv->adj.flags &= ~(DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW);
+ priv->adj.flags |= DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH;
+
*timing = priv->adj;
return 0;
diff --git a/drivers/video/nxp/imx/imx8_lvds.c b/drivers/video/nxp/imx/imx8_lvds.c
index d9162dbbc2..87b0108838 100644
--- a/drivers/video/nxp/imx/imx8_lvds.c
+++ b/drivers/video/nxp/imx/imx8_lvds.c
@@ -80,6 +80,20 @@ static int imx8_ldb_soc_setup(struct udevice *dev, sc_pm_clock_rate_t pixel_cloc
return -EIO;
}
+ err = sc_pm_set_clock_parent(-1, lvds_rsrc, SC_PM_CLK_PER, SC_PM_PARENT_BYPS);
+ if (err) {
+ printf("LVDS set SC_PM_CLK_PER parent failed! (error = %d)\n",
+ err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_parent(-1, lvds_rsrc, SC_PM_CLK_PHY, SC_PM_PARENT_BYPS);
+ if (err) {
+ printf("LVDS set SC_PM_CLK_PHY parent failed! (error = %d)\n",
+ err);
+ return -EIO;
+ }
+
err = sc_pm_set_clock_rate(-1, lvds_rsrc, SC_PM_CLK_PER, &pixel_clock);
if (err) {
printf("LVDS set rate SC_PM_CLK_BYPASS failed! (error = %d)\n", err);
diff --git a/drivers/video/nxp/imx/imx93-parallel-disp-fmt.c b/drivers/video/nxp/imx/imx93-parallel-disp-fmt.c
new file mode 100644
index 0000000000..72af93873f
--- /dev/null
+++ b/drivers/video/nxp/imx/imx93-parallel-disp-fmt.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <panel.h>
+#include <reset.h>
+#include <video.h>
+#include <video_bridge.h>
+#include <video_link.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <dm/device-internal.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <media_bus_format.h>
+
+#define DISPLAY_MUX_CTRL 0x60
+#define PARALLEL_DISP_FORMAT 0x700
+
+enum imx93_pdf_format {
+ RGB888_TO_RGB888 = 0x0,
+ RGB888_TO_RGB666 = 0x1 << 8,
+ RGB565_TO_RGB565 = 0x2 << 8,
+};
+
+struct imx93_pdf_priv {
+ struct udevice *panel;
+ struct display_timing adj;
+ enum imx93_pdf_format format;
+ void *__iomem addr;
+};
+
+static int imx93_pdf_attach(struct udevice *dev)
+{
+ struct imx93_pdf_priv *priv = dev_get_priv(dev);
+ struct display_timing timings;
+ int ret;
+
+ priv->panel = video_link_get_next_device(dev);
+ if (!priv->panel ||
+ device_get_uclass_id(priv->panel) != UCLASS_PANEL) {
+ dev_err(dev, "get panel device error\n");
+ return -ENODEV;
+ }
+
+ ret = video_link_get_display_timings(&timings);
+ if (ret) {
+ dev_err(dev, "decode display timing error %d\n", ret);
+ return ret;
+ }
+
+ priv->adj = timings;
+
+ writel(priv->format, priv->addr + DISPLAY_MUX_CTRL);
+
+ return 0;
+}
+
+static int imx93_pdf_check_timing(struct udevice *dev, struct display_timing *timing)
+{
+ struct imx93_pdf_priv *priv = dev_get_priv(dev);
+
+ /* Ensure the bridge device attached to panel */
+ if (!priv->panel) {
+ dev_err(dev, "%s No panel device attached\n", __func__);
+ return -ENOTCONN;
+ }
+
+ *timing = priv->adj;
+
+ return 0;
+}
+
+static int imx93_pdf_probe(struct udevice *dev)
+{
+ struct imx93_pdf_priv *priv = dev_get_priv(dev);
+ const char *fmt;
+ u32 bus_format;
+ int ret;
+
+ priv->addr = (void __iomem *)dev_read_addr(dev_get_parent(dev));
+ if ((fdt_addr_t)priv->addr == FDT_ADDR_T_NONE) {
+ dev_err(dev, "not able to get addr\n");
+ return -EINVAL;
+ }
+
+ ret = ofnode_read_string_index(dev_ofnode(dev), "fsl,interface-pix-fmt", 0, &fmt);
+ if (!ret) {
+ if (!strcmp(fmt, "rgb565"))
+ bus_format = MEDIA_BUS_FMT_RGB565_1X16;
+ else if (!strcmp(fmt, "rgb666"))
+ bus_format = MEDIA_BUS_FMT_RGB666_1X18;
+ else if (!strcmp(fmt, "rgb888"))
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+ }
+
+ switch (bus_format) {
+ case MEDIA_BUS_FMT_RGB565_1X16:
+ priv->format = RGB565_TO_RGB565;
+ break;
+ case MEDIA_BUS_FMT_RGB666_1X18:
+ priv->format = RGB888_TO_RGB666;
+ break;
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ priv->format = RGB888_TO_RGB888;
+ break;
+ default:
+ dev_dbg(dev, "invalid bus format 0x%x\n", bus_format);
+ return -EINVAL;
+ }
+
+
+ return 0;
+}
+
+static int imx93_pdf_remove(struct udevice *dev)
+{
+ struct imx93_pdf_priv *priv = dev_get_priv(dev);
+
+ if (priv->panel)
+ device_remove(priv->panel, DM_REMOVE_NORMAL);
+
+ return 0;
+}
+
+static int imx93_pdf_set_backlight(struct udevice *dev, int percent)
+{
+ struct imx93_pdf_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = panel_enable_backlight(priv->panel);
+ if (ret) {
+ dev_err(dev, "panel %s enable backlight error %d\n", priv->panel->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+struct video_bridge_ops imx93_pdf_ops = {
+ .attach = imx93_pdf_attach,
+ .check_timing = imx93_pdf_check_timing,
+ .set_backlight = imx93_pdf_set_backlight,
+};
+
+static const struct udevice_id imx93_pdf_ids[] = {
+ { .compatible = "fsl,imx93-parallel-display-format" },
+ { }
+};
+
+U_BOOT_DRIVER(imx93_pdf_driver) = {
+ .name = "imx93_pdf_driver",
+ .id = UCLASS_VIDEO_BRIDGE,
+ .of_match = imx93_pdf_ids,
+ .bind = dm_scan_fdt_dev,
+ .remove = imx93_pdf_remove,
+ .probe = imx93_pdf_probe,
+ .ops = &imx93_pdf_ops,
+ .priv_auto = sizeof(struct imx93_pdf_priv),
+};
diff --git a/drivers/video/nxp/imx/imx_lcdifv3.c b/drivers/video/nxp/imx/imx_lcdifv3.c
index 8313e09848..66e6ad6a86 100644
--- a/drivers/video/nxp/imx/imx_lcdifv3.c
+++ b/drivers/video/nxp/imx/imx_lcdifv3.c
@@ -99,8 +99,15 @@ static void lcdifv3_set_mode(struct lcdifv3_priv *priv,
writel(ctrldescl0_1, (ulong)(priv->reg_base + LCDIFV3_CTRLDESCL0_1));
/* Polarities */
- writel(CTRL_INV_HS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
- writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
+ else
+ writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_SET));
+
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+ writel(CTRL_INV_HS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
+ else
+ writel(CTRL_INV_HS, (ulong)(priv->reg_base + LCDIFV3_CTRL_SET));
/* SEC MIPI DSI specific */
writel(CTRL_INV_PXCK, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
@@ -316,7 +323,6 @@ static void lcdifv3_of_parse_thres(struct udevice *dev)
}
}
-
static int lcdifv3_video_probe(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
@@ -377,6 +383,13 @@ static int lcdifv3_video_probe(struct udevice *dev)
mode.hsync_len = timings.hsync_len.typ;
mode.vsync_len = timings.vsync_len.typ;
mode.pixclock = HZ2PS(timings.pixelclock.typ);
+ mode.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
+
+ if (timings.flags & DISPLAY_FLAGS_HSYNC_LOW )
+ mode.sync &= ~FB_SYNC_HOR_HIGH_ACT;
+
+ if (timings.flags & DISPLAY_FLAGS_VSYNC_LOW )
+ mode.sync &= ~FB_SYNC_VERT_HIGH_ACT;
lcdifv3_init(dev, &mode, GDF_32BIT_X888RGB);
diff --git a/drivers/video/nxp/imx/sec_dsim_imx.c b/drivers/video/nxp/imx/sec_dsim_imx.c
index 2e6aa467f7..9c6e7d2bca 100644
--- a/drivers/video/nxp/imx/sec_dsim_imx.c
+++ b/drivers/video/nxp/imx/sec_dsim_imx.c
@@ -32,6 +32,7 @@ struct imx_sec_dsim_priv {
struct reset_ctl_bulk soft_resetn;
struct reset_ctl_bulk clk_enable;
struct reset_ctl_bulk mipi_reset;
+ struct display_timing adj;
};
#if IS_ENABLED(CONFIG_DM_RESET)
@@ -120,6 +121,8 @@ static int imx_sec_dsim_attach(struct udevice *dev)
return ret;
}
+ priv->adj = timings;
+
ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
if (ret) {
dev_err(dev, "No video dsi host detected %d\n", ret);
@@ -209,9 +212,23 @@ static int imx_sec_dsim_remove(struct udevice *dev)
return 0;
}
+static int imx_sec_dsim_check_timing(struct udevice *dev, struct display_timing *timing)
+{
+ struct imx_sec_dsim_priv *priv = dev_get_priv(dev);
+
+ /* DSI force the Polarities as high */
+ priv->adj.flags &= ~(DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW);
+ priv->adj.flags |= DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH;
+
+ *timing = priv->adj;
+
+ return 0;
+}
+
struct video_bridge_ops imx_sec_dsim_ops = {
.attach = imx_sec_dsim_attach,
.set_backlight = imx_sec_dsim_set_backlight,
+ .check_timing = imx_sec_dsim_check_timing,
};
static const struct udevice_id imx_sec_dsim_ids[] = {
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
index c8f7022ea6..f9281d5e83 100644
--- a/drivers/video/simple_panel.c
+++ b/drivers/video/simple_panel.c
@@ -23,12 +23,14 @@ static int simple_panel_enable_backlight(struct udevice *dev)
struct simple_panel_priv *priv = dev_get_priv(dev);
int ret;
- debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name);
dm_gpio_set_value(&priv->enable, 1);
- ret = backlight_enable(priv->backlight);
- debug("%s: done, ret = %d\n", __func__, ret);
- if (ret)
- return ret;
+ if (priv->backlight) {
+ debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name);
+ ret = backlight_enable(priv->backlight);
+ debug("%s: done, ret = %d\n", __func__, ret);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -40,10 +42,12 @@ static int simple_panel_set_backlight(struct udevice *dev, int percent)
debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name);
dm_gpio_set_value(&priv->enable, 1);
- ret = backlight_set_brightness(priv->backlight, percent);
- debug("%s: done, ret = %d\n", __func__, ret);
- if (ret)
- return ret;
+ if (priv->backlight) {
+ ret = backlight_set_brightness(priv->backlight, percent);
+ debug("%s: done, ret = %d\n", __func__, ret);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -66,9 +70,10 @@ static int simple_panel_of_to_plat(struct udevice *dev)
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
"backlight", &priv->backlight);
if (ret) {
- debug("%s: Cannot get backlight: ret=%d\n", __func__, ret);
- return log_ret(ret);
+ printf("%s: Cannot get backlight: ret=%d\n", __func__, ret);
+ priv->backlight = NULL;
}
+
ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
GPIOD_IS_OUT);
if (ret) {