From e908a9fe7a1fa7ff39d96dd29140e73e655746ad Mon Sep 17 00:00:00 2001 From: Ye Li Date: Wed, 30 Jan 2019 22:09:23 -0800 Subject: [PATCH] MLK-20886-5 imx8qm/qxp: Implement VService function and buffer pagetable Override the board_imx_vservice_find_mu for finding MU device for virtual devices. The matching logic is if the M4_0 partition ownes the resource of the device, we select MU8 for this Vservice channel. Otherwise, if the M4_1 partition ownes the resource, we select MU9. We reuse the kernel RPMSG Vring buffer for VService buffer, because it is shared between OS partition and M4 partition. The pagetable is needed for this region, since it is not in memregs of OS partition. board_imx_vservice_get_buffer is also overriden is this patch to divide VService buffer for MU8 and MU9. Signed-off-by: Ye Li (cherry picked from commit 4358b4cdfc4752822066d480dd1c10086c211be7) (cherry picked from commit 8c407ea63ad7c7cf59eb6d8b96766cd163026d82) (cherry picked from commit 10decd628e25e4ac07651b35f7e11b2efc331edd) --- arch/arm/mach-imx/imx8/cpu.c | 105 ++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c index e600d0c8f6..19e9c4804f 100644 --- a/arch/arm/mach-imx/imx8/cpu.c +++ b/arch/arm/mach-imx/imx8/cpu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018 NXP + * Copyright 2017-2019 NXP */ #include @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -679,6 +681,16 @@ void enable_caches(void) PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; i = 1; + +#ifdef CONFIG_IMX_VSERVICE_SHARED_BUFFER + imx8_mem_map[i].virt = CONFIG_IMX_VSERVICE_SHARED_BUFFER; + imx8_mem_map[i].phys = CONFIG_IMX_VSERVICE_SHARED_BUFFER; + imx8_mem_map[i].size = CONFIG_IMX_VSERVICE_SHARED_BUFFER_SIZE; + imx8_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; + i++; +#endif + for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) { err = get_owned_memreg(mr, &start, &end); if (!err) { @@ -862,3 +874,94 @@ void disconnect_from_pc(void) return; } } + +#ifdef CONFIG_IMX_VSERVICE +struct udevice * board_imx_vservice_find_mu(struct udevice *dev) +{ + int ret; + const char *m4_mu_name[2] = { + "mu@5d230000", + "mu@5d240000" + }; + struct udevice *m4_mu[2]; + sc_rm_pt_t m4_parts[2]; + int err; + struct ofnode_phandle_args args; + sc_rsrc_t resource_id; + sc_rm_pt_t resource_part; + + /* Get the resource id from its power-domain */ + ret = dev_read_phandle_with_args(dev, "power-domains", + "#power-domain-cells", 0, 0, &args); + if (ret) { + printf("Can't find the power-domains property for udev %s\n", dev->name); + return NULL; + } + + /* Get the owner partition for resource*/ + resource_id = (sc_rsrc_t)ofnode_read_u32_default(args.node, "reg", SC_R_NONE); + if (resource_id == SC_R_NONE) { + printf("Can't find the resource id for udev %s\n", dev->name); + return NULL; + } + + err = sc_rm_get_resource_owner(-1, resource_id, &resource_part); + if (err != SC_ERR_NONE) { + printf("%s get resource [%d] owner error: %d\n", __func__, resource_id, err); + return NULL; + } + + debug("udev %s, resource id %d, resource part %d\n", dev->name, resource_id, resource_part); + + /* MU8 for communication between M4_0 and u-boot, MU9 for M4_1 and u-boot */ + err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]); + if (err != SC_ERR_NONE) { + printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_0_PID0, err); + return NULL; + } + + ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[0], &m4_mu[0]); + if (!ret) { + /* If the i2c is in m4_0 partition, return the mu8 */ + if (resource_part == m4_parts[0]) + return m4_mu[0]; + } + + if (is_imx8qm()) { + err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]); + if (err != SC_ERR_NONE) { + printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_1_PID0, err); + return NULL; + } + + ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[1], &m4_mu[1]); + if (!ret) { + /* If the i2c is in m4_1 partition, return the mu9 */ + if (resource_part == m4_parts[1]) + return m4_mu[1]; + } + } + + return NULL; +} + +void * board_imx_vservice_get_buffer(struct imx_vservice_channel *node, u32 size) +{ + const char *m4_mu_name[2] = { + "mu@5d230000", + "mu@5d240000" + }; + + /* Each MU ownes 1M buffer */ + if (size <= 0x100000) { + if (!strcmp(node->mu_dev->name, m4_mu_name[0])) + return (void * )CONFIG_IMX_VSERVICE_SHARED_BUFFER; + else if (!strcmp(node->mu_dev->name, m4_mu_name[1])) + return (void * )(CONFIG_IMX_VSERVICE_SHARED_BUFFER + 0x100000); + else + return NULL; + } + + return NULL; +} +#endif -- 2.17.1