aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-07-19 08:29:24 -0400
committerTom Rini <trini@konsulko.com>2021-07-19 08:29:24 -0400
commit83befb446664af32ce18f0e42e99a353e6622e58 (patch)
tree563a58575010c89767e6e8d21bf82443e5f44e52 /drivers
parentabf0061eabf43f43a3889871e259c9633e7a42e3 (diff)
parent652982309d316b14aae5805d09239f89eb89f038 (diff)
downloadu-boot-83befb446664af32ce18f0e42e99a353e6622e58.zip
u-boot-83befb446664af32ce18f0e42e99a353e6622e58.tar.gz
u-boot-83befb446664af32ce18f0e42e99a353e6622e58.tar.bz2
Merge tag 'ti-v2021.10-rc1' of https://source.denx.de/u-boot/custodians/u-boot-ti
- Enabled distro boot for all TI platforms. - Cleanup for AM335x Guardian Board - PRUSS rproc on AM65 platform. - Add PMIC support for J7200 - Misc fixes for Nokia RX-51 # Conflicts: # arch/arm/mach-omap2/am33xx/Kconfig
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bootcount/Kconfig34
-rw-r--r--drivers/bootcount/Makefile1
-rw-r--r--drivers/bootcount/bootcount_nvmem.c57
-rw-r--r--drivers/power/pmic/tps65941.c1
-rw-r--r--drivers/remoteproc/Kconfig11
-rw-r--r--drivers/remoteproc/Makefile1
-rw-r--r--drivers/remoteproc/pru_rproc.c461
-rw-r--r--drivers/soc/ti/Kconfig11
-rw-r--r--drivers/soc/ti/Makefile1
-rw-r--r--drivers/soc/ti/pruss.c217
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/hx8238d.c4
12 files changed, 795 insertions, 6 deletions
diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index b5ccea0..0de2b7b 100644
--- a/drivers/bootcount/Kconfig
+++ b/drivers/bootcount/Kconfig
@@ -42,6 +42,25 @@ config BOOTCOUNT_AM33XX
This requires the RTC clocks, etc, to be enabled prior to use and
not all boards with this IP block on it will have the RTC in use.
+config BOOTCOUNT_AM33XX_NVMEM
+ bool "Boot counter in AM33XX RTC IP block with upgrade_available flag"
+ depends on AM33XX
+ select SPL_AM33XX_ENABLE_RTC32K_OSC if AM33XX
+ help
+ Add support for maintaining bootcount,upgrade_available,
+ version and BOOTMAGIC in a AM33xx RTC IP block
+ scratch register2.
+
+ A bootcount driver for the RTC IP block found on many TI platforms.
+ This requires the RTC clocks, etc, to be enabled prior to use and
+ not all boards with this IP block on it will have the RTC in use.
+
+ If there is upgrade in software then "upgrade_available" is 1,
+ "bootcount" is incremented otherwise "upgrade_available" and
+ "bootcount" is always 0. So the Userspace Application must set
+ the "upgrade_available" and "bootcount" variable to 0, if a boot
+ was successfully.
+
config BOOTCOUNT_ENV
bool "Boot counter in environment"
help
@@ -177,16 +196,25 @@ config SYS_BOOTCOUNT_EXT_NAME
config SYS_BOOTCOUNT_ADDR
hex "RAM address used for reading and writing the boot counter"
- default 0x44E3E000 if BOOTCOUNT_AM33XX
+ default 0x44E3E000 if BOOTCOUNT_AM33XX || BOOTCOUNT_AM33XX_NVMEM
default 0xE0115FF8 if ARCH_LS1043A || ARCH_LS1021A
depends on BOOTCOUNT_AM33XX || BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
- BOOTCOUNT_I2C
+ BOOTCOUNT_I2C || BOOTCOUNT_AM33XX_NVMEM
help
Set the address used for reading and writing the boot counter.
config SYS_BOOTCOUNT_MAGIC
hex "Magic value for the boot counter"
- default 0xB001C041
+ default 0xB001C041 if BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
+ BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
+ BOOTCOUNT_RAM || BOOTCOUNT_I2C || \
+ BOOTCOUNT_AT91 || DM_BOOTCOUNT
+ default 0xB0 if BOOTCOUNT_AM33XX_NVMEM
+ depends on BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
+ BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
+ BOOTCOUNT_RAM || BOOTCOUNT_I2C || \
+ BOOTCOUNT_AT91 || DM_BOOTCOUNT || \
+ BOOTCOUNT_AM33XX_NVMEM
help
Set the magic value used for the boot counter.
diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile
index 51d860b..12658ff 100644
--- a/drivers/bootcount/Makefile
+++ b/drivers/bootcount/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_BOOTCOUNT_RAM) += bootcount_ram.o
obj-$(CONFIG_BOOTCOUNT_ENV) += bootcount_env.o
obj-$(CONFIG_BOOTCOUNT_I2C) += bootcount_i2c.o
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_RTC) += rtc.o
diff --git a/drivers/bootcount/bootcount_nvmem.c b/drivers/bootcount/bootcount_nvmem.c
new file mode 100644
index 0000000..5f266d5
--- /dev/null
+++ b/drivers/bootcount/bootcount_nvmem.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ * (C) Copyright 2018 Robert Bosch Power Tools GmbH.
+ *
+ * A bootcount driver for the RTC IP block found on many TI platforms.
+ * This requires the RTC clocks, etc, to be enabled prior to use and
+ * not all boards with this IP block on it will have the RTC in use.
+ */
+
+#include <bootcount.h>
+#include <asm/davinci_rtc.h>
+
+#define BC_VERSION 2
+
+void bootcount_store(ulong bootcount)
+{
+ u8 upgrade_available = 0;
+ ulong val = 0;
+ struct davinci_rtc *reg =
+ (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
+
+ val = raw_bootcount_load(&reg->scratch2);
+ upgrade_available = (val >> 8) & 0x000000ff;
+
+ /* Only update bootcount during upgrade process */
+ if (!upgrade_available)
+ bootcount = 0;
+
+ val = (bootcount & 0x000000ff) |
+ (upgrade_available << 8) |
+ (BC_VERSION << 16) |
+ (CONFIG_SYS_BOOTCOUNT_MAGIC << 24);
+
+ /*
+ * write RTC kick registers to enable write
+ * for RTC Scratch registers. Scratch register 2 is
+ * used for bootcount value.
+ */
+ writel(RTC_KICK0R_WE, &reg->kick0r);
+ writel(RTC_KICK1R_WE, &reg->kick1r);
+ raw_bootcount_store(&reg->scratch2, val);
+}
+
+ulong bootcount_load(void)
+{
+ unsigned long val = 0;
+ struct davinci_rtc *reg =
+ (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
+
+ val = raw_bootcount_load(&reg->scratch2);
+ if ((val >> 24) != CONFIG_SYS_BOOTCOUNT_MAGIC)
+ return 0;
+ else
+ return val & 0x000000ff;
+}
diff --git a/drivers/power/pmic/tps65941.c b/drivers/power/pmic/tps65941.c
index 3dfc191..114ef4d 100644
--- a/drivers/power/pmic/tps65941.c
+++ b/drivers/power/pmic/tps65941.c
@@ -72,6 +72,7 @@ static struct dm_pmic_ops tps65941_ops = {
static const struct udevice_id tps65941_ids[] = {
{ .compatible = "ti,tps659411", .data = TPS659411 },
{ .compatible = "ti,tps659413", .data = TPS659413 },
+ { .compatible = "ti,lp876441", .data = LP876441 },
{ }
};
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 7c2e480..24e5364 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -81,4 +81,15 @@ config REMOTEPROC_TI_POWER
help
Say 'y' here to add support for TI power processors such as those
found on certain TI keystone and OMAP generation SoCs.
+
+config REMOTEPROC_TI_PRU
+ bool "Support for TI's K3 based PRU remoteproc driver"
+ select REMOTEPROC
+ depends on DM
+ depends on TI_PRUSS
+ depends on ARCH_K3
+ depends on OF_CONTROL
+ help
+ Say 'y' here to add support for TI' K3 remoteproc driver.
+
endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 69ae7bd..f0e8345 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
+obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
new file mode 100644
index 0000000..924070a
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.c
@@ -0,0 +1,461 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PRU-RTU remoteproc driver for various SoCs
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Keerthy <j-keerthy@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <elf.h>
+#include <dm/of_access.h>
+#include <remoteproc.h>
+#include <errno.h>
+#include <clk.h>
+#include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <power-domain.h>
+#include <linux/pruss_driver.h>
+#include <dm/device_compat.h>
+
+/* PRU_ICSS_PRU_CTRL registers */
+#define PRU_CTRL_CTRL 0x0000
+#define PRU_CTRL_STS 0x0004
+#define PRU_CTRL_WAKEUP_EN 0x0008
+#define PRU_CTRL_CYCLE 0x000C
+#define PRU_CTRL_STALL 0x0010
+#define PRU_CTRL_CTBIR0 0x0020
+#define PRU_CTRL_CTBIR1 0x0024
+#define PRU_CTRL_CTPPR0 0x0028
+#define PRU_CTRL_CTPPR1 0x002C
+
+/* CTRL register bit-fields */
+#define CTRL_CTRL_SOFT_RST_N BIT(0)
+#define CTRL_CTRL_EN BIT(1)
+#define CTRL_CTRL_SLEEPING BIT(2)
+#define CTRL_CTRL_CTR_EN BIT(3)
+#define CTRL_CTRL_SINGLE_STEP BIT(8)
+#define CTRL_CTRL_RUNSTATE BIT(15)
+
+#define RPROC_FLAGS_SHIFT 16
+#define RPROC_FLAGS_NONE 0
+#define RPROC_FLAGS_ELF_PHDR BIT(0 + RPROC_FLAGS_SHIFT)
+#define RPROC_FLAGS_ELF_SHDR BIT(1 + RPROC_FLAGS_SHIFT)
+
+/**
+ * enum pru_mem - PRU core memory range identifiers
+ */
+enum pru_mem {
+ PRU_MEM_IRAM = 0,
+ PRU_MEM_CTRL,
+ PRU_MEM_DEBUG,
+ PRU_MEM_MAX,
+};
+
+struct pru_privdata {
+ phys_addr_t pru_iram;
+ phys_addr_t pru_ctrl;
+ phys_addr_t pru_debug;
+ fdt_size_t pru_iramsz;
+ fdt_size_t pru_ctrlsz;
+ fdt_size_t pru_debugsz;
+ const char *fw_name;
+ u32 iram_da;
+ u32 pdram_da;
+ u32 sdram_da;
+ u32 shrdram_da;
+ u32 bootaddr;
+ int id;
+ struct pruss *prusspriv;
+};
+
+static inline u32 pru_control_read_reg(struct pru_privdata *pru, unsigned int reg)
+{
+ return readl(pru->pru_ctrl + reg);
+}
+
+static inline
+void pru_control_write_reg(struct pru_privdata *pru, unsigned int reg, u32 val)
+{
+ writel(val, pru->pru_ctrl + reg);
+}
+
+static inline
+void pru_control_set_reg(struct pru_privdata *pru, unsigned int reg,
+ u32 mask, u32 set)
+{
+ u32 val;
+
+ val = pru_control_read_reg(pru, reg);
+ val &= ~mask;
+ val |= (set & mask);
+ pru_control_write_reg(pru, reg, val);
+}
+
+/**
+ * pru_rproc_set_ctable() - set the constant table index for the PRU
+ * @rproc: the rproc instance of the PRU
+ * @c: constant table index to set
+ * @addr: physical address to set it to
+ */
+static int pru_rproc_set_ctable(struct pru_privdata *pru, enum pru_ctable_idx c, u32 addr)
+{
+ unsigned int reg;
+ u32 mask, set;
+ u16 idx;
+ u16 idx_mask;
+
+ /* pointer is 16 bit and index is 8-bit so mask out the rest */
+ idx_mask = (c >= PRU_C28) ? 0xFFFF : 0xFF;
+
+ /* ctable uses bit 8 and upwards only */
+ idx = (addr >> 8) & idx_mask;
+
+ /* configurable ctable (i.e. C24) starts at PRU_CTRL_CTBIR0 */
+ reg = PRU_CTRL_CTBIR0 + 4 * (c >> 1);
+ mask = idx_mask << (16 * (c & 1));
+ set = idx << (16 * (c & 1));
+
+ pru_control_set_reg(pru, reg, mask, set);
+
+ return 0;
+}
+
+/**
+ * pru_start() - start the pru processor
+ * @dev: corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int pru_start(struct udevice *dev)
+{
+ struct pru_privdata *priv;
+ int val = 0;
+
+ priv = dev_get_priv(dev);
+
+ pru_rproc_set_ctable(priv, PRU_C28, 0x100 << 8);
+
+ val = CTRL_CTRL_EN | ((priv->bootaddr >> 2) << 16);
+ writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
+
+ return 0;
+}
+
+/**
+ * pru_stop() - Stop pru processor
+ * @dev: corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int pru_stop(struct udevice *dev)
+{
+ struct pru_privdata *priv;
+ int val = 0;
+
+ priv = dev_get_priv(dev);
+
+ val = readl(priv->pru_ctrl + PRU_CTRL_CTRL);
+ val &= ~CTRL_CTRL_EN;
+ writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
+
+ return 0;
+}
+
+/**
+ * pru_init() - Initialize the remote processor
+ * @dev: rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int pru_init(struct udevice *dev)
+{
+ return 0;
+}
+
+/*
+ * Convert PRU device address (data spaces only) to kernel virtual address
+ *
+ * Each PRU has access to all data memories within the PRUSS, accessible at
+ * different ranges. So, look through both its primary and secondary Data
+ * RAMs as well as any shared Data RAM to convert a PRU device address to
+ * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
+ * RAM1 is primary Data RAM for PRU1.
+ */
+static void *pru_d_da_to_pa(struct pru_privdata *priv, u32 da, int len)
+{
+ u32 offset;
+ void *pa = NULL;
+ phys_addr_t dram0, dram1, shrdram2;
+ u32 dram0sz, dram1sz, shrdram2sz;
+
+ if (len <= 0)
+ return NULL;
+
+ dram0 = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM0].pa;
+ dram1 = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].pa;
+ shrdram2 = priv->prusspriv->mem_regions[PRUSS_MEM_SHRD_RAM2].pa;
+ dram0sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM0].size;
+ dram1sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].size;
+ shrdram2sz = priv->prusspriv->mem_regions[PRUSS_MEM_SHRD_RAM2].size;
+
+ /* PRU1 has its local RAM addresses reversed */
+ if (priv->id == 1) {
+ dram1 = dram0;
+ dram1sz = dram0sz;
+
+ dram0 = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].pa;
+ dram0sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].size;
+ }
+
+ if (da >= priv->pdram_da && da + len <= priv->pdram_da + dram0sz) {
+ offset = da - priv->pdram_da;
+ pa = (__force void *)(dram0 + offset);
+ } else if (da >= priv->sdram_da &&
+ da + len <= priv->sdram_da + dram1sz) {
+ offset = da - priv->sdram_da;
+ pa = (__force void *)(dram1 + offset);
+ } else if (da >= priv->shrdram_da &&
+ da + len <= priv->shrdram_da + shrdram2sz) {
+ offset = da - priv->shrdram_da;
+ pa = (__force void *)(shrdram2 + offset);
+ }
+
+ return pa;
+}
+
+/*
+ * Convert PRU device address (instruction space) to kernel virtual address
+ *
+ * A PRU does not have an unified address space. Each PRU has its very own
+ * private Instruction RAM, and its device address is identical to that of
+ * its primary Data RAM device address.
+ */
+static void *pru_i_da_to_pa(struct pru_privdata *priv, u32 da, int len)
+{
+ u32 offset;
+ void *pa = NULL;
+
+ if (len <= 0)
+ return NULL;
+
+ if (da >= priv->iram_da &&
+ da + len <= priv->iram_da + priv->pru_iramsz) {
+ offset = da - priv->iram_da;
+ pa = (__force void *)(priv->pru_iram + offset);
+ }
+
+ return pa;
+}
+
+/* PRU-specific address translator */
+static void *pru_da_to_pa(struct pru_privdata *priv, u64 da, int len, u32 flags)
+{
+ void *pa;
+ u32 exec_flag;
+
+ exec_flag = ((flags & RPROC_FLAGS_ELF_SHDR) ? flags & SHF_EXECINSTR :
+ ((flags & RPROC_FLAGS_ELF_PHDR) ? flags & PF_X : 0));
+
+ if (exec_flag)
+ pa = pru_i_da_to_pa(priv, da, len);
+ else
+ pa = pru_d_da_to_pa(priv, da, len);
+
+ return pa;
+}
+
+/*
+ * Custom memory copy implementation for ICSSG PRU/RTU Cores
+ *
+ * The ICSSG PRU/RTU cores have a memory copying issue with IRAM memories, that
+ * is not seen on previous generation SoCs. The data is reflected properly in
+ * the IRAM memories only for integer (4-byte) copies. Any unaligned copies
+ * result in all the other pre-existing bytes zeroed out within that 4-byte
+ * boundary, thereby resulting in wrong text/code in the IRAMs. Also, the
+ * IRAM memory port interface does not allow any 8-byte copies (as commonly
+ * used by ARM64 memcpy implementation) and throws an exception. The DRAM
+ * memory ports do not show this behavior. Use this custom copying function
+ * to properly load the PRU/RTU firmware images on all memories for simplicity.
+ *
+ * TODO: Improve the function to deal with additional corner cases like
+ * unaligned copy sizes or sub-integer trailing bytes when the need arises.
+ */
+static int pru_rproc_memcpy(void *dest, void *src, size_t count)
+{
+ const int *s = src;
+ int *d = dest;
+ int size = count / 4;
+ int *tmp_src = NULL;
+
+ /* limited to 4-byte aligned addresses and copy sizes */
+ if ((long)dest % 4 || count % 4)
+ return -EINVAL;
+
+ /* src offsets in ELF firmware image can be non-aligned */
+ if ((long)src % 4) {
+ tmp_src = malloc(count);
+ if (!tmp_src)
+ return -ENOMEM;
+
+ memcpy(tmp_src, src, count);
+ s = tmp_src;
+ }
+
+ while (size--)
+ *d++ = *s++;
+
+ kfree(tmp_src);
+
+ return 0;
+}
+
+/**
+ * pru_load() - Load pru firmware
+ * @dev: corresponding k3 remote processor device
+ * @addr: Address on the RAM from which firmware is to be loaded
+ * @size: Size of the pru firmware in bytes
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int pru_load(struct udevice *dev, ulong addr, ulong size)
+{
+ struct pru_privdata *priv;
+ Elf32_Ehdr *ehdr;
+ Elf32_Phdr *phdr;
+ int i, ret = 0;
+
+ priv = dev_get_priv(dev);
+
+ ehdr = (Elf32_Ehdr *)addr;
+ phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
+
+ /* go through the available ELF segments */
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+ u32 da = phdr->p_paddr;
+ u32 memsz = phdr->p_memsz;
+ u32 filesz = phdr->p_filesz;
+ u32 offset = phdr->p_offset;
+ void *ptr;
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
+ phdr->p_type, da, memsz, filesz);
+
+ if (filesz > memsz) {
+ dev_dbg(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+ filesz, memsz);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (offset + filesz > size) {
+ dev_dbg(dev, "truncated fw: need 0x%x avail 0x%zx\n",
+ offset + filesz, size);
+ ret = -EINVAL;
+ break;
+ }
+
+ /* grab the kernel address for this device address */
+ ptr = pru_da_to_pa(priv, da, memsz,
+ RPROC_FLAGS_ELF_PHDR | phdr->p_flags);
+ if (!ptr) {
+ dev_dbg(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+ ret = -EINVAL;
+ break;
+ }
+
+ /* skip the memzero logic performed by remoteproc ELF loader */
+ if (!phdr->p_filesz)
+ continue;
+
+ ret = pru_rproc_memcpy(ptr,
+ (void *)addr + phdr->p_offset, filesz);
+ if (ret) {
+ dev_dbg(dev, "PRU custom memory copy failed for da 0x%x memsz 0x%x\n",
+ da, memsz);
+ break;
+ }
+ }
+
+ priv->bootaddr = ehdr->e_entry;
+
+ return ret;
+}
+
+static const struct dm_rproc_ops pru_ops = {
+ .init = pru_init,
+ .start = pru_start,
+ .stop = pru_stop,
+ .load = pru_load,
+};
+
+static void pru_set_id(struct pru_privdata *priv, struct udevice *dev)
+{
+ u32 mask2 = 0x38000;
+
+ if (device_is_compatible(dev, "ti,am654-rtu"))
+ mask2 = 0x6000;
+
+ if (device_is_compatible(dev, "ti,am654-tx-pru"))
+ mask2 = 0xc000;
+
+ if ((priv->pru_iram & mask2) == mask2)
+ priv->id = 1;
+ else
+ priv->id = 0;
+}
+
+/**
+ * pru_probe() - Basic probe
+ * @dev: corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int pru_probe(struct udevice *dev)
+{
+ struct pru_privdata *priv;
+ ofnode node;
+
+ node = dev_ofnode(dev);
+
+ priv = dev_get_priv(dev);
+ priv->prusspriv = dev_get_priv(dev->parent);
+
+ priv->pru_iram = devfdt_get_addr_size_index(dev, PRU_MEM_IRAM,
+ &priv->pru_iramsz);
+ priv->pru_ctrl = devfdt_get_addr_size_index(dev, PRU_MEM_CTRL,
+ &priv->pru_ctrlsz);
+ priv->pru_debug = devfdt_get_addr_size_index(dev, PRU_MEM_DEBUG,
+ &priv->pru_debugsz);
+
+ priv->iram_da = 0;
+ priv->pdram_da = 0;
+ priv->sdram_da = 0x2000;
+ priv->shrdram_da = 0x10000;
+
+ pru_set_id(priv, dev);
+
+ return 0;
+}
+
+static const struct udevice_id pru_ids[] = {
+ { .compatible = "ti,am654-pru"},
+ { .compatible = "ti,am654-rtu"},
+ { .compatible = "ti,am654-tx-pru" },
+ {}
+};
+
+U_BOOT_DRIVER(pru) = {
+ .name = "pru",
+ .of_match = pru_ids,
+ .id = UCLASS_REMOTEPROC,
+ .ops = &pru_ops,
+ .probe = pru_probe,
+ .priv_auto = sizeof(struct pru_privdata),
+};
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index e4f8834..0ee21f9 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -23,4 +23,15 @@ config TI_KEYSTONE_SERDES
SerDes driver for Keystone SoC used for ethernet support on TI
K2 platforms.
+config TI_PRUSS
+ bool "Support for TI's K3 based Pruss driver"
+ depends on DM
+ depends on ARCH_K3
+ depends on OF_CONTROL
+ depends on SYSCON
+ help
+ Support for TI PRU-ICSSG subsystem.
+ Currently supported on AM65xx SoCs Say Y here to support the
+ Programmable Realtime Unit (PRU).
+
endif # SOC_TI
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index 4ec04ee..34f80aa 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_TI_K3_NAVSS_RINGACC) += k3-navss-ringacc.o
obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o
+obj-$(CONFIG_TI_PRUSS) += pruss.o
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
new file mode 100644
index 0000000..4613909
--- /dev/null
+++ b/drivers/soc/ti/pruss.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PRU-ICSS platform driver for various TI SoCs
+ *
+ * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <errno.h>
+#include <clk.h>
+#include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <power-domain.h>
+#include <linux/pruss_driver.h>
+#include <dm/device_compat.h>
+
+#define PRUSS_CFG_IEPCLK 0x30
+#define ICSSG_CFG_CORE_SYNC 0x3c
+
+#define ICSSG_TASK_MGR_OFFSET 0x2a000
+
+/* PRUSS_IEPCLK register bits */
+#define PRUSS_IEPCLK_IEP_OCP_CLK_EN BIT(0)
+
+/* ICSSG CORE_SYNC register bits */
+#define ICSSG_CORE_VBUSP_SYNC_EN BIT(0)
+
+/*
+ * pruss_request_tm_region() - Request pruss for task manager region
+ * @dev: corresponding k3 device
+ * @loc: the task manager physical address
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+int pruss_request_tm_region(struct udevice *dev, phys_addr_t *loc)
+{
+ struct pruss *priv;
+
+ priv = dev_get_priv(dev);
+ if (!priv || !priv->mem_regions[PRUSS_MEM_DRAM0].pa)
+ return -EINVAL;
+
+ *loc = priv->mem_regions[PRUSS_MEM_DRAM0].pa + ICSSG_TASK_MGR_OFFSET;
+
+ return 0;
+}
+
+/**
+ * pruss_request_mem_region() - request a memory resource
+ * @dev: the pruss device
+ * @mem_id: the memory resource id
+ * @region: pointer to memory region structure to be filled in
+ *
+ * This function allows a client driver to request a memory resource,
+ * and if successful, will let the client driver own the particular
+ * memory region until released using the pruss_release_mem_region()
+ * API.
+ *
+ * Returns the memory region if requested resource is available, an
+ * error otherwise
+ */
+int pruss_request_mem_region(struct udevice *dev, enum pruss_mem mem_id,
+ struct pruss_mem_region *region)
+{
+ struct pruss *pruss;
+
+ pruss = dev_get_priv(dev);
+ if (!pruss || !region)
+ return -EINVAL;
+
+ if (mem_id >= PRUSS_MEM_MAX)
+ return -EINVAL;
+
+ if (pruss->mem_in_use[mem_id])
+ return -EBUSY;
+
+ *region = pruss->mem_regions[mem_id];
+ pruss->mem_in_use[mem_id] = region;
+
+ return 0;
+}
+
+/**
+ * pruss_release_mem_region() - release a memory resource
+ * @dev: the pruss device
+ * @region: the memory region to release
+ *
+ * This function is the complimentary function to
+ * pruss_request_mem_region(), and allows the client drivers to
+ * release back a memory resource.
+ *
+ * Returns 0 on success, an error code otherwise
+ */
+int pruss_release_mem_region(struct udevice *dev,
+ struct pruss_mem_region *region)
+{
+ struct pruss *pruss;
+ int id;
+
+ pruss = dev_get_priv(dev);
+ if (!pruss || !region)
+ return -EINVAL;
+
+ /* find out the memory region being released */
+ for (id = 0; id < PRUSS_MEM_MAX; id++) {
+ if (pruss->mem_in_use[id] == region)
+ break;
+ }
+
+ if (id == PRUSS_MEM_MAX)
+ return -EINVAL;
+
+ pruss->mem_in_use[id] = NULL;
+
+ return 0;
+}
+
+/**
+ * pruss_cfg_update() - configure a PRUSS CFG sub-module register
+ * @dev: the pruss device
+ * @reg: register offset within the CFG sub-module
+ * @mask: bit mask to use for programming the @val
+ * @val: value to write
+ *
+ * Programs a given register within the PRUSS CFG sub-module
+ *
+ * Returns 0 on success, or an error code otherwise
+ */
+int pruss_cfg_update(struct udevice *dev, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ struct pruss *pruss;
+
+ pruss = dev_get_priv(dev);
+ if (IS_ERR_OR_NULL(pruss))
+ return -EINVAL;
+
+ return regmap_update_bits(pruss->cfg, reg, mask, val);
+}
+
+/**
+ * pruss_probe() - Basic probe
+ * @dev: corresponding k3 device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int pruss_probe(struct udevice *dev)
+{
+ const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
+ ofnode sub_node, node, memories;
+ struct udevice *syscon;
+ struct pruss *priv;
+ int ret, idx, i;
+
+ priv = dev_get_priv(dev);
+ node = dev_ofnode(dev);
+ priv->dev = dev;
+ memories = ofnode_find_subnode(node, "memories");
+
+ for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+ idx = ofnode_stringlist_search(memories, "reg-names", mem_names[i]);
+ priv->mem_regions[i].pa = ofnode_get_addr_size_index(memories, idx,
+ (u64 *)&priv->mem_regions[i].size);
+ }
+
+ sub_node = ofnode_find_subnode(node, "cfg");
+ ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, sub_node,
+ &syscon);
+
+ priv->cfg = syscon_get_regmap(syscon);
+ if (IS_ERR(priv->cfg)) {
+ dev_err(dev, "unable to get cfg regmap (%ld)\n",
+ PTR_ERR(priv->cfg));
+ return -ENODEV;
+ }
+
+ /*
+ * ToDo: To be modelled as clocks.
+ * The CORE block uses two multiplexers to allow software to
+ * select one of three source clocks (ICSSGn_CORE_CLK, ICSSGn_ICLK or
+ * ICSSGn_IEP_CLK) for the final clock source of the CORE block.
+ * The user needs to configure ICSSG_CORE_SYNC_REG[0] CORE_VBUSP_SYNC_EN
+ * bit & ICSSG_IEPCLK_REG[0] IEP_OCP_CLK_EN bit in order to select the
+ * clock source to the CORE block.
+ */
+ ret = regmap_update_bits(priv->cfg, ICSSG_CFG_CORE_SYNC,
+ ICSSG_CORE_VBUSP_SYNC_EN,
+ ICSSG_CORE_VBUSP_SYNC_EN);
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(priv->cfg, PRUSS_CFG_IEPCLK,
+ PRUSS_IEPCLK_IEP_OCP_CLK_EN,
+ PRUSS_IEPCLK_IEP_OCP_CLK_EN);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "pruss successfully probed %s\n", dev->name);
+
+ return 0;
+}
+
+static const struct udevice_id pruss_ids[] = {
+ { .compatible = "ti,am654-icssg"},
+ {}
+};
+
+U_BOOT_DRIVER(pruss) = {
+ .name = "pruss",
+ .of_match = pruss_ids,
+ .id = UCLASS_MISC,
+ .probe = pruss_probe,
+ .priv_auto = sizeof(struct pruss),
+};
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 933f06e..1c534a6 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o
obj-$(CONFIG_DM_VIDEO) += video_bmp.o
obj-$(CONFIG_PANEL) += panel-uclass.o
-obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o
+obj-$(CONFIG_DM_PANEL_HX8238D) += hx8238d.o
obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o
endif
diff --git a/drivers/video/hx8238d.c b/drivers/video/hx8238d.c
index f7e7753..6ee97cb 100644
--- a/drivers/video/hx8238d.c
+++ b/drivers/video/hx8238d.c
@@ -191,7 +191,7 @@ U_BOOT_DRIVER(hx8238d) = {
.name = "hx8238d",
.id = UCLASS_PANEL,
.of_match = hx8238d_ids,
- .ofdata_to_platdata = hx8238d_ofdata_to_platdata,
+ .of_to_plat = hx8238d_ofdata_to_platdata,
.probe = hx8238d_probe,
- .priv_auto_alloc_size = sizeof(struct hx8238d_priv),
+ .priv_auto = sizeof(struct hx8238d_priv),
};