From e0283cbdfd49a437ef3cfdd662b196d2f70b5ea0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 7 Feb 2022 10:27:37 +0100 Subject: power: zynqmp: Add power domain driver for ZynqMP Driver should be enabled by CONFIG_POWER_DOMAIN=y and CONFIG_ZYNQMP_POWER_DOMAIN=y. Power domain driver doesn't have own DT node but it uses zynqmp firmware DT node that's why there is a need to bind driver when firmware node is found. Driver itself is simple. It is sending pmufw config object overlay for enabling access to device which is done in ...domain_request(). In ...domain_on() capabilities are passed and node is requested. This should be bare minimum of required to get power domain driver working. Signed-off-by: Michal Simek Reviewed-by: Jaehoon Chung Link: https://lore.kernel.org/r/f4b9433b91c0b18c375b061c7a4e29d428f70547.1644226055.git.michal.simek@xilinx.com --- drivers/firmware/firmware-zynqmp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 839203ec82a..8d78888eff7 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -226,8 +227,27 @@ static const struct udevice_id zynqmp_firmware_ids[] = { { } }; +static int zynqmp_firmware_bind(struct udevice *dev) +{ + int ret; + struct udevice *child; + + if (IS_ENABLED(CONFIG_ZYNQMP_POWER_DOMAIN)) { + ret = device_bind_driver_to_node(dev, "zynqmp_power_domain", + "zynqmp_power_domain", + dev_ofnode(dev), &child); + if (ret) { + printf("zynqmp power domain driver is not bound: %d\n", ret); + return ret; + } + } + + return dm_scan_fdt_dev(dev); +} + U_BOOT_DRIVER(zynqmp_firmware) = { .id = UCLASS_FIRMWARE, .name = "zynqmp_firmware", .of_match = zynqmp_firmware_ids, + .bind = zynqmp_firmware_bind, }; -- cgit v1.2.3 From c750c6dbb29535efa01464d46afc6ccf999cf7c5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 14 Jan 2022 13:25:35 +0100 Subject: xilinx: firmware: Introduce zynqmp_pmufw_node() for loading PMU fragments Introduce zynqmp_pmufw_node() for loading PMU configuration fragment for enabling IPs. Firmware driver has small overlay where NODE id is added and config fragment is sent to PMUFW. There is a need to build PMUFW with fragment support. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/636e8150bd4e2b1f988d59795772c685ceeec083.1642163135.git.michal.simek@xilinx.com --- drivers/firmware/firmware-zynqmp.c | 32 ++++++++++++++++++++++++++++++++ include/zynqmp_firmware.h | 1 + 2 files changed, 33 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 8d78888eff7..05628da9b03 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -28,6 +28,38 @@ struct zynqmp_power { struct mbox_chan rx_chan; } zynqmp_power; +#define NODE_ID_LOCATION 5 + +static unsigned int xpm_configobject[] = { + /**********************************************************************/ + /* HEADER */ + 2, /* Number of remaining words in the header */ + 1, /* Number of sections included in config object */ + PM_CONFIG_OBJECT_TYPE_OVERLAY, /* Type of Config object as overlay */ + /**********************************************************************/ + /* SLAVE SECTION */ + + PM_CONFIG_SLAVE_SECTION_ID, /* Section ID */ + 1, /* Number of slaves */ + + 0, /* Node ID which will be changed below */ + PM_SLAVE_FLAG_IS_SHAREABLE, + PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK | + PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK | + PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK, /* IPI Mask */ +}; + +int zynqmp_pmufw_node(u32 id) +{ + /* Record power domain id */ + xpm_configobject[NODE_ID_LOCATION] = id; + + zynqmp_pmufw_load_config_object(xpm_configobject, + sizeof(xpm_configobject)); + + return 0; +} + static int ipi_req(const u32 *req, size_t req_len, u32 *res, size_t res_maxlen) { struct zynqmp_ipi_msg msg; diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 19c004e9199..76c161806a0 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -367,6 +367,7 @@ enum pm_ioctl_id { #define PAYLOAD_ARG_CNT 5U unsigned int zynqmp_firmware_version(void); +int zynqmp_pmufw_node(u32 id); void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 *ret_payload); -- cgit v1.2.3 From fac46bc446e0ca2e5bd8fa4d28f243ee4a1d8995 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 14 Jan 2022 13:25:38 +0100 Subject: arm64: zynqmp: Add command for disabling loading other overlays Add command "zynqmp pmufw node close" to disable permission to load additional pmufw config overlays. This command will make sure that any other sw will ask for changing permission. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/cfa5cc7909eb8deb23eb0f11c26954cbaddeb861.1642163135.git.michal.simek@xilinx.com --- board/xilinx/zynqmp/cmds.c | 16 ++++++++++++++++ drivers/firmware/firmware-zynqmp.c | 19 +++++++++++++++++++ include/zynqmp_firmware.h | 1 + 3 files changed, 36 insertions(+) (limited to 'drivers/firmware') diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c index 5a277c712f6..2ab9596248c 100644 --- a/board/xilinx/zynqmp/cmds.c +++ b/board/xilinx/zynqmp/cmds.c @@ -209,6 +209,19 @@ static int do_zynqmp_pmufw(struct cmd_tbl *cmdtp, int flag, int argc, if (argc != cmdtp->maxargs) return CMD_RET_USAGE; + if (!strncmp(argv[2], "node", 4)) { + u32 id; + + if (!strncmp(argv[3], "close", 5)) + return zynqmp_pmufw_config_close(); + + id = dectoul(argv[3], NULL); + + printf("Enable permission for node ID %d\n", id); + + return zynqmp_pmufw_node(id); + } + addr = hextoul(argv[2], NULL); size = hextoul(argv[3], NULL); @@ -416,6 +429,9 @@ static char zynqmp_help_text[] = " lock(0)/split(1)\n" #endif "zynqmp pmufw address size - load PMU FW configuration object\n" + "zynqmp pmufw node - load PMU FW configuration object\n" + "zynqmp pmufw node close - disable config object loading\n" + " node: keyword, id: NODE_ID in decimal format\n" "zynqmp rsa srcaddr srclen mod exp rsaop -\n" " Performs RSA encryption and RSA decryption on blob of data\n" " at srcaddr and puts it back in srcaddr using modulus and\n" diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 05628da9b03..8d8492d99f7 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -49,6 +49,25 @@ static unsigned int xpm_configobject[] = { PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK, /* IPI Mask */ }; +static unsigned int xpm_configobject_close[] = { + /**********************************************************************/ + /* HEADER */ + 2, /* Number of remaining words in the header */ + 1, /* Number of sections included in config object */ + PM_CONFIG_OBJECT_TYPE_OVERLAY, /* Type of Config object as overlay */ + /**********************************************************************/ + /* SET CONFIG SECTION */ + PM_CONFIG_SET_CONFIG_SECTION_ID, + 0U, /* Loading permission to Overlay config object */ +}; + +int zynqmp_pmufw_config_close(void) +{ + zynqmp_pmufw_load_config_object(xpm_configobject_close, + sizeof(xpm_configobject_close)); + return 0; +} + int zynqmp_pmufw_node(u32 id) { /* Record power domain id */ diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 76c161806a0..50bf4ef3953 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -368,6 +368,7 @@ enum pm_ioctl_id { unsigned int zynqmp_firmware_version(void); int zynqmp_pmufw_node(u32 id); +int zynqmp_pmufw_config_close(void); void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 *ret_payload); -- cgit v1.2.3