diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/misc/fs_loader.c | 2 | ||||
-rw-r--r-- | drivers/misc/imx8/scu_api.c | 31 | ||||
-rw-r--r-- | drivers/misc/mpfs_syscontroller.c | 200 | ||||
-rw-r--r-- | drivers/misc/npcm_host_intf.c | 33 |
5 files changed, 265 insertions, 2 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 29b84430ff5..e3a207866ea 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -440,6 +440,7 @@ config STM32MP_FUSE config K3_FUSE bool "Enable TI K3 fuse wrapper providing the fuse API" depends on MISC && CMD_FUSE && CMD_FUSE_WRITEBUFF + depends on ARCH_K3 help If you say Y here, you will get support for the fuse API (OTP) for TI K3 architecture. diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 66803f4b997..2928cf75f89 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -148,7 +148,7 @@ static int _request_firmware_prepare(struct udevice *dev, */ static int fw_get_filesystem_firmware(struct udevice *dev) { - loff_t actread; + loff_t actread = 0; char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume; int ret; diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c index 8985ab6584d..d9cc7acb970 100644 --- a/drivers/misc/imx8/scu_api.c +++ b/drivers/misc/imx8/scu_api.c @@ -1286,3 +1286,34 @@ int sc_seco_secvio_dgo_config(sc_ipc_t ipc, u8 id, u8 access, u32 *data) return ret; } + +int sc_seco_commit(sc_ipc_t ipc, u32 *info) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + /* Fill in header */ + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 2U; + RPC_SVC(&msg) = (u8)SC_RPC_SVC_SECO; + RPC_FUNC(&msg) = (u8)SECO_FUNC_COMMIT; + + /* Fill in send message */ + RPC_U32(&msg, 0U) = *info; + + /* Call RPC */ + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + return ret; + + /* Copy out result */ + ret = (int)RPC_R8(&msg); + + /* Copy out receive message */ + if (!ret) + *info = RPC_U32(&msg, 0U); + + return ret; +} diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c index 41e80815ab5..f608d5518b0 100644 --- a/drivers/misc/mpfs_syscontroller.c +++ b/drivers/misc/mpfs_syscontroller.c @@ -22,7 +22,27 @@ #include <misc.h> #include <mpfs-mailbox.h> +#define SYS_SPI_CMD 0x50 +#define SYS_SPI_MAILBOX_DATA_LEN 17 +#define SYS_SPI_MAILBOX_SRC_OFFSET 8 +#define SYS_SPI_MAILBOX_LENGTH_OFFSET 12 +#define SYS_SPI_MAILBOX_FREQ_OFFSET 16 +#define SYS_SPI_MAILBOX_FREQ 3 +#define SPI_FLASH_ADDR 0x400 + /* Descriptor table */ +#define START_OFFSET 4 +#define END_OFFSET 8 +#define SIZE_OFFSET 12 +#define DESC_NEXT 12 +#define DESC_RESERVED_SIZE 0 +#define DESC_SIZE 16 + +#define DESIGN_MAGIC_0 0x4d /* 'M' */ +#define DESIGN_MAGIC_1 0x43 /* 'C'*/ +#define DESIGN_MAGIC_2 0x48 /* 'H'*/ +#define DESIGN_MAGIC_3 0x50 /* 'P'*/ + #define CMD_OPCODE 0x0u #define CMD_DATA_SIZE 0U #define CMD_DATA NULL @@ -109,6 +129,186 @@ int mpfs_syscontroller_read_sernum(struct mpfs_sys_serv *sys_serv_priv, u8 *devi } EXPORT_SYMBOL(mpfs_syscontroller_read_sernum); +static u16 mpfs_syscontroller_service_spi_copy(struct mpfs_sys_serv *sys_serv_priv, u64 dst_addr, u32 src_addr, u32 length) +{ + int ret; + u32 mailbox_format[SYS_SPI_MAILBOX_DATA_LEN]; + + *(u64 *)mailbox_format = dst_addr; + mailbox_format[SYS_SPI_MAILBOX_SRC_OFFSET/4] = src_addr; + mailbox_format[SYS_SPI_MAILBOX_LENGTH_OFFSET/4] = length; + mailbox_format[SYS_SPI_MAILBOX_FREQ_OFFSET/4] = SYS_SPI_MAILBOX_FREQ; + + struct mpfs_mss_response response = { + .resp_status = 0U, + .resp_msg = mailbox_format, + .resp_size = RESP_BYTES}; + struct mpfs_mss_msg msg = { + .cmd_opcode = SYS_SPI_CMD, + .cmd_data_size = SYS_SPI_MAILBOX_DATA_LEN, + .response = &response, + .cmd_data = (u8 *)mailbox_format, + .mbox_offset = MBOX_OFFSET, + .resp_offset = RESP_OFFSET}; + + ret = mpfs_syscontroller_run_service(sys_serv_priv->sys_controller, &msg); + if (ret) { + dev_err(sys_serv_priv->sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret, msg.response->resp_status); + } + + return ret; +} + +static u16 mpfs_syscontroller_get_dtbo_desc_header(struct mpfs_sys_serv *sys_serv_priv, u8 *desc_data, u32 desc_addr) +{ + u32 length, no_of_descs; + int ret = -ENOENT; + + /* Get first four bytes to calculate length */ + ret = mpfs_syscontroller_service_spi_copy(sys_serv_priv, (u64)desc_data, desc_addr, BYTES_4); + if (!ret) { + no_of_descs = *((u32 *)desc_data); + if (no_of_descs) { + length = DESC_SIZE + ((no_of_descs - 1) * DESC_SIZE); + ret = mpfs_syscontroller_service_spi_copy(sys_serv_priv, (u64)desc_data, desc_addr, + length); + } + } + + return ret; +} + +static u8 *mpfs_syscontroller_get_dtbo(struct mpfs_sys_serv *sys_serv_priv, u32 start_addr, u32 size) +{ + int ret; + u8 *dtbo; + + /* Intentionally never freed, even on success so that u-boot "userspace" can access it. */ + dtbo = (u8 *)malloc(size); + + ret = mpfs_syscontroller_service_spi_copy(sys_serv_priv, (u64)dtbo, start_addr, size); + if (ret) { + free(dtbo); + dtbo = NULL; + } + + return dtbo; +} + +static void mpfs_syscontroller_parse_desc_header(struct mpfs_sys_serv *sys_serv_priv, u8 *desc_header, u8 *no_of_dtbo, u32 *dtbos_size) +{ + u32 dtbo_desc_start_addr; + u32 dtbo_desc_size; + u32 no_of_descs; + u16 i; + u8 dtbo_name[16]; + u8 dtbo_addr[20]; + u8 *desc; + u8 *dtbo; + + no_of_descs = *((u32 *)desc_header); + + for (i = 0; i < no_of_descs; i++) { + desc = &desc_header[START_OFFSET + (DESC_NEXT * i)]; + /* + * The dtbo info structure contains addresses that are relative + * to the start of structure, so the offset of the structure in + * flash must be added to get the actual start address. + */ + dtbo_desc_start_addr = *((u32 *)desc) + SPI_FLASH_ADDR; + + desc = &desc_header[SIZE_OFFSET + (DESC_NEXT * i)]; + dtbo_desc_size = *((u32 *)desc); + + dtbo = mpfs_syscontroller_get_dtbo(sys_serv_priv, dtbo_desc_start_addr, dtbo_desc_size); + if (dtbo) { + sprintf(dtbo_name, "dtbo_image%d", *no_of_dtbo); + sprintf(dtbo_addr, "0x%llx", (u64)dtbo); + env_set(dtbo_name, dtbo_addr); + ++*no_of_dtbo; + *dtbos_size += dtbo_desc_size; + } + } +} + +void mpfs_syscontroller_process_dtbo(struct mpfs_sys_serv *sys_serv_priv) +{ + u32 desc_length; + u32 dtbo_desc_addr; + u32 dtbo_addr[5]; + u16 i, hart, no_of_harts; + u8 design_info_desc[256]; + u8 dtbo_desc_data[256]; + u8 no_of_dtbos[8]; + u8 dtbo_size[8]; + u8 *desc; + u8 no_of_dtbo = 0; + u32 dtbos_size = 0; + int ret; + + /* Read first 10 bytes to verify the descriptor is found or not */ + ret = mpfs_syscontroller_service_spi_copy(sys_serv_priv, (u64)design_info_desc, SPI_FLASH_ADDR, 10); + if (ret) { + sprintf(no_of_dtbos, "%d", no_of_dtbo); + env_set("no_of_overlays", no_of_dtbos); + sprintf(dtbo_size, "%d", dtbos_size); + env_set("dtbo_size", dtbo_size); + return; + } + + if (design_info_desc[0] != DESIGN_MAGIC_0 || + design_info_desc[1] != DESIGN_MAGIC_1 || + design_info_desc[2] != DESIGN_MAGIC_2 || + design_info_desc[3] != DESIGN_MAGIC_3) { + dev_dbg(sys_serv_priv->dev, "magic not found in desc structure.\n"); + sprintf(no_of_dtbos, "%d", no_of_dtbo); + env_set("no_of_overlays", no_of_dtbos); + sprintf(dtbo_size, "%d", dtbos_size); + env_set("dtbo_size", dtbo_size); + return; + } + desc_length = *((u32 *)&design_info_desc[4]); + /* Read Design descriptor */ + ret = mpfs_syscontroller_service_spi_copy(sys_serv_priv, (u64)design_info_desc, + SPI_FLASH_ADDR, desc_length); + if (ret) + return; + + no_of_harts = *((u16 *)&design_info_desc[10]); + + for (hart = 0; hart < no_of_harts; hart++) { + /* Start address of DTBO descriptor */ + desc = &design_info_desc[(0x4 * hart) + 0xc]; + + dtbo_desc_addr = *((u32 *)desc); + dtbo_addr[hart] = dtbo_desc_addr; + + if (!dtbo_addr[hart]) + continue; + + for (i = 0; i < hart; i++) { + if (dtbo_addr[hart] == dtbo_addr[i]) + continue; + } + + if (hart && hart == i) + continue; + + dtbo_desc_addr += SPI_FLASH_ADDR; + ret = mpfs_syscontroller_get_dtbo_desc_header(sys_serv_priv, dtbo_desc_data, + dtbo_desc_addr); + if (ret) + continue; + else + mpfs_syscontroller_parse_desc_header(sys_serv_priv, dtbo_desc_data, &no_of_dtbo, &dtbos_size); + } + sprintf(no_of_dtbos, "%d", no_of_dtbo); + env_set("no_of_overlays", no_of_dtbos); + sprintf(dtbo_size, "%d", dtbos_size); + env_set("dtbo_size", dtbo_size); +} +EXPORT_SYMBOL(mpfs_syscontroller_process_dtbo); + static int mpfs_syscontroller_probe(struct udevice *dev) { struct mpfs_syscontroller_priv *sys_controller = dev_get_priv(dev); diff --git a/drivers/misc/npcm_host_intf.c b/drivers/misc/npcm_host_intf.c index 58bab888c3c..e3b0663625b 100644 --- a/drivers/misc/npcm_host_intf.c +++ b/drivers/misc/npcm_host_intf.c @@ -22,6 +22,8 @@ /* ESPI Register offsets */ #define ESPICFG 0x4 #define ESPIHINDP 0x80 +#define ESPI_TEN 0xF0 +#define ESPI_ENG 0xF1 /* MFSEL bit fileds */ #define MFSEL1_LPCSEL BIT(26) @@ -40,10 +42,23 @@ #define AUTO_HS2 BIT(12) #define AUTO_HS3 BIT(16) +#define ESPI_TEN_ENABLE 0x55 +#define ESPI_TEN_DISABLE 0 + +/* KCS/BPC interrupt control */ +#define BPCFEN 0x46 +#define FRIE BIT(3) +#define HRIE BIT(4) +#define KCS1CTL 0x18 +#define KCS2CTL 0x2a +#define KCS3CTL 0x3c +#define IBFIE BIT(0) +#define OBEIE BIT(1) + static int npcm_host_intf_bind(struct udevice *dev) { struct regmap *syscon; - void __iomem *base; + void __iomem *base, *kcs_base; u32 ch_supp, val; u32 ioaddr; const char *type; @@ -83,6 +98,13 @@ static int npcm_host_intf_bind(struct udevice *dev) val &= ~(CHSUPP_MASK | IOMODE_MASK | MAXFREQ_MASK); val |= IOMODE_SDQ | MAXFREQ_33MHZ | FIELD_PREP(CHSUPP_MASK, ch_supp); writel(val, base + ESPICFG); + + if (device_is_compatible(dev, "nuvoton,npcm845-host-intf")) { + /* Workaround: avoid eSPI module getting into wrong state */ + writeb(ESPI_TEN_ENABLE, base + ESPI_TEN); + writeb(BIT(6), base + ESPI_ENG); + writeb(ESPI_TEN_DISABLE, base + ESPI_TEN); + } } else if (!strcmp(type, "lpc")) { /* Select LPC pin function */ regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, 0); @@ -92,6 +114,15 @@ static int npcm_host_intf_bind(struct udevice *dev) /* Release host wait */ setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); + kcs_base = dev_read_addr_index_ptr(dev, 1); + if (kcs_base) { + /* Disable KCS/BPC interrupts */ + clrbits_8(kcs_base + BPCFEN, FRIE | HRIE); + clrbits_8(kcs_base + KCS1CTL, IBFIE | OBEIE); + clrbits_8(kcs_base + KCS2CTL, IBFIE | OBEIE); + clrbits_8(kcs_base + KCS3CTL, IBFIE | OBEIE); + } + return 0; } |