diff options
Diffstat (limited to 'drivers/remoteproc/ti_k3_r5f_rproc.c')
-rw-r--r-- | drivers/remoteproc/ti_k3_r5f_rproc.c | 99 |
1 files changed, 89 insertions, 10 deletions
diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c index 1a7f1f8a00..8e21a38be7 100644 --- a/drivers/remoteproc/ti_k3_r5f_rproc.c +++ b/drivers/remoteproc/ti_k3_r5f_rproc.c @@ -2,8 +2,9 @@ /* * Texas Instruments' K3 R5 Remoteproc driver * - * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018-2020 Texas Instruments Incorporated - https://www.ti.com/ * Lokesh Vutla <lokeshvutla@ti.com> + * Suman Anna <s-anna@ti.com> */ #include <common.h> @@ -37,6 +38,8 @@ #define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 #define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 #define PROC_BOOT_CFG_FLAG_GEN_IGN_BOOTVECTOR 0x10000000 +/* Available from J7200 SoCs onwards */ +#define PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS 0x00004000 /* R5 TI-SCI Processor Control Flags */ #define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 @@ -55,6 +58,16 @@ enum cluster_mode { }; /** + * struct k3_r5f_ip_data - internal data structure used for IP variations + * @tcm_is_double: flag to denote the larger unified TCMs in certain modes + * @tcm_ecc_autoinit: flag to denote the auto-initialization of TCMs for ECC + */ +struct k3_r5f_ip_data { + bool tcm_is_double; + bool tcm_ecc_autoinit; +}; + +/** * struct k3_r5_mem - internal memory structure * @cpu_addr: MPU virtual address of the memory region * @bus_addr: Bus address used to access the memory region @@ -74,6 +87,7 @@ struct k3_r5f_mem { * @cluster: pointer to the parent cluster. * @reset: reset control handle * @tsp: TI-SCI processor control handle + * @ipdata: cached pointer to R5F IP specific feature data * @mem: Array of available internal memories * @num_mem: Number of available memories * @atcm_enable: flag to control ATCM enablement @@ -86,6 +100,7 @@ struct k3_r5f_core { struct k3_r5f_cluster *cluster; struct reset_ctl reset; struct ti_sci_proc tsp; + struct k3_r5f_ip_data *ipdata; struct k3_r5f_mem *mem; int num_mems; u32 atcm_enable; @@ -257,6 +272,18 @@ static int k3_r5f_core_sanity_check(struct k3_r5f_core *core) return 0; } +/* Zero out TCMs so that ECC can be effective on all TCM addresses */ +void k3_r5f_init_tcm_memories(struct k3_r5f_core *core, bool auto_inited) +{ + if (core->ipdata->tcm_ecc_autoinit && auto_inited) + return; + + if (core->atcm_enable) + memset(core->mem[0].cpu_addr, 0x00, core->mem[0].size); + if (core->btcm_enable) + memset(core->mem[1].cpu_addr, 0x00, core->mem[1].size); +} + /** * k3_r5f_load() - Load up the Remote processor image * @dev: rproc device pointer @@ -268,7 +295,9 @@ static int k3_r5f_core_sanity_check(struct k3_r5f_core *core) static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size) { struct k3_r5f_core *core = dev_get_priv(dev); - u32 boot_vector; + u64 boot_vector; + u32 ctrl, sts, cfg = 0; + bool mem_auto_init; int ret; dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); @@ -281,6 +310,12 @@ static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size) if (ret) return ret; + ret = ti_sci_proc_get_status(&core->tsp, &boot_vector, &cfg, &ctrl, + &sts); + if (ret) + return ret; + mem_auto_init = !(cfg & PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS); + ret = k3_r5f_prepare(dev); if (ret) { dev_err(dev, "R5f prepare failed for core %d\n", @@ -288,11 +323,7 @@ static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size) goto proc_release; } - /* Zero out TCMs so that ECC can be effective on all TCM addresses */ - if (core->atcm_enable) - memset(core->mem[0].cpu_addr, 0x00, core->mem[0].size); - if (core->btcm_enable) - memset(core->mem[1].cpu_addr, 0x00, core->mem[1].size); + k3_r5f_init_tcm_memories(core, mem_auto_init); ret = rproc_elf_load_image(dev, addr, size); if (ret < 0) { @@ -302,7 +333,7 @@ static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size) boot_vector = rproc_elf_get_boot_addr(dev, addr); - dev_dbg(dev, "%s: Boot vector = 0x%x\n", __func__, boot_vector); + dev_dbg(dev, "%s: Boot vector = 0x%llx\n", __func__, boot_vector); ret = ti_sci_proc_set_config(&core->tsp, boot_vector, 0, 0); @@ -657,6 +688,8 @@ static int k3_r5f_of_to_priv(struct k3_r5f_core *core) return ret; } + core->ipdata = (struct k3_r5f_ip_data *)dev_get_driver_data(core->dev); + return 0; } @@ -702,6 +735,38 @@ static int k3_r5f_core_of_get_memories(struct k3_r5f_core *core) return 0; } +/* + * Each R5F core within a typical R5FSS instance has a total of 64 KB of TCMs, + * split equally into two 32 KB banks between ATCM and BTCM. The TCMs from both + * cores are usable in Split-mode, but only the Core0 TCMs can be used in + * LockStep-mode. The newer revisions of the R5FSS IP maximizes these TCMs by + * leveraging the Core1 TCMs as well in certain modes where they would have + * otherwise been unusable (Eg: LockStep-mode on J7200 SoCs). This is done by + * making a Core1 TCM visible immediately after the corresponding Core0 TCM. + * The SoC memory map uses the larger 64 KB sizes for the Core0 TCMs, and the + * dts representation reflects this increased size on supported SoCs. The Core0 + * TCM sizes therefore have to be adjusted to only half the original size in + * Split mode. + */ +static void k3_r5f_core_adjust_tcm_sizes(struct k3_r5f_core *core) +{ + struct k3_r5f_cluster *cluster = core->cluster; + + if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + return; + + if (!core->ipdata->tcm_is_double) + return; + + if (core == cluster->cores[0]) { + core->mem[0].size /= 2; + core->mem[1].size /= 2; + + dev_dbg(core->dev, "adjusted TCM sizes, ATCM = 0x%zx BTCM = 0x%zx\n", + core->mem[0].size, core->mem[1].size); + } +} + /** * k3_r5f_probe() - Basic probe * @dev: corresponding k3 remote processor device @@ -755,6 +820,8 @@ static int k3_r5f_probe(struct udevice *dev) return ret; } + k3_r5f_core_adjust_tcm_sizes(core); + dev_dbg(dev, "Remoteproc successfully probed\n"); return 0; @@ -771,9 +838,20 @@ static int k3_r5f_remove(struct udevice *dev) return 0; } +static const struct k3_r5f_ip_data k3_data = { + .tcm_is_double = false, + .tcm_ecc_autoinit = false, +}; + +static const struct k3_r5f_ip_data j7200_data = { + .tcm_is_double = true, + .tcm_ecc_autoinit = true, +}; + static const struct udevice_id k3_r5f_rproc_ids[] = { - { .compatible = "ti,am654-r5f"}, - { .compatible = "ti,j721e-r5f"}, + { .compatible = "ti,am654-r5f", .data = (ulong)&k3_data, }, + { .compatible = "ti,j721e-r5f", .data = (ulong)&k3_data, }, + { .compatible = "ti,j7200-r5f", .data = (ulong)&j7200_data, }, {} }; @@ -810,6 +888,7 @@ static int k3_r5f_cluster_probe(struct udevice *dev) static const struct udevice_id k3_r5fss_ids[] = { { .compatible = "ti,am654-r5fss"}, { .compatible = "ti,j721e-r5fss"}, + { .compatible = "ti,j7200-r5fss"}, {} }; |