From 927adc27abf8db8454a162102b00c0b272a28762 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 19 Jan 2022 12:03:23 +0100 Subject: zynqmp: Use the same style for macro definitions Use the same coding style for all macros. #defineNAMEVALUE Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/3960de81a04acbaaa01936f743d3d6b3876fe4b7.1642590201.git.michal.simek@xilinx.com --- include/zynqmp_firmware.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 0b068d7da29..cfd92d3fe56 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -342,20 +342,20 @@ enum pm_ioctl_id { IOCTL_AIE_ISR_CLEAR = 24, }; -#define PM_SIP_SVC 0xc2000000 +#define PM_SIP_SVC 0xc2000000 -#define ZYNQMP_PM_VERSION_MAJOR 1 -#define ZYNQMP_PM_VERSION_MINOR 0 -#define ZYNQMP_PM_VERSION_MAJOR_SHIFT 16 -#define ZYNQMP_PM_VERSION_MINOR_MASK 0xFFFF +#define ZYNQMP_PM_VERSION_MAJOR 1 +#define ZYNQMP_PM_VERSION_MINOR 0 +#define ZYNQMP_PM_VERSION_MAJOR_SHIFT 16 +#define ZYNQMP_PM_VERSION_MINOR_MASK 0xFFFF #define ZYNQMP_PM_VERSION \ ((ZYNQMP_PM_VERSION_MAJOR << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | \ ZYNQMP_PM_VERSION_MINOR) -#define ZYNQMP_PM_VERSION_INVALID ~0 +#define ZYNQMP_PM_VERSION_INVALID ~0 -#define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0) +#define PMUFW_V1_0 ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0) /* * Return payload size -- cgit v1.3.1 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 --- MAINTAINERS | 1 + drivers/firmware/firmware-zynqmp.c | 20 +++++++ drivers/power/domain/Kconfig | 9 +++ drivers/power/domain/Makefile | 1 + drivers/power/domain/zynqmp-power-domain.c | 89 ++++++++++++++++++++++++++++++ include/zynqmp_firmware.h | 31 +++++++++++ 6 files changed, 151 insertions(+) create mode 100644 drivers/power/domain/zynqmp-power-domain.c (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index dcdd99e368d..8bcdea2e34f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -634,6 +634,7 @@ F: drivers/mtd/nand/raw/zynq_nand.c F: drivers/net/phy/xilinx_phy.c F: drivers/net/zynq_gem.c F: drivers/phy/phy-zynqmp.c +F: drivers/power/domain/zynqmp-power-domain.c F: drivers/serial/serial_zynq.c F: drivers/reset/reset-zynqmp.c F: drivers/rtc/zynqmp_rtc.c 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, }; diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 9aea5fcdf08..93d2599d83c 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -88,4 +88,13 @@ config TI_POWER_DOMAIN help Generic power domain implementation for TI K3 devices. +config ZYNQMP_POWER_DOMAIN + bool "Enable the Xilinx ZynqMP Power domain driver" + depends on POWER_DOMAIN && ZYNQMP_FIRMWARE + help + Generic power domain implementation for Xilinx ZynqMP devices. + The driver should be enabled when system starts in very minimal + configuration and it is extended at run time. Then enabling + the driver will ensure that PMUFW enable access to requested IP. + endmenu diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 530ae35671a..7c8af67dbd6 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o obj-$(CONFIG_TI_POWER_DOMAIN) += ti-power-domain.o +obj-$(CONFIG_ZYNQMP_POWER_DOMAIN) += zynqmp-power-domain.o diff --git a/drivers/power/domain/zynqmp-power-domain.c b/drivers/power/domain/zynqmp-power-domain.c new file mode 100644 index 00000000000..5383d098969 --- /dev/null +++ b/drivers/power/domain/zynqmp-power-domain.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021, Xilinx. Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 */ +}; + +static int zynqmp_pm_request_node(const u32 node, const u32 capabilities, + const u32 qos, const enum zynqmp_pm_request_ack ack) +{ + return xilinx_pm_request(PM_REQUEST_NODE, node, capabilities, + qos, ack, NULL); +} + +static int zynqmp_power_domain_request(struct power_domain *power_domain) +{ + /* Record power domain id */ + xpm_configobject[NODE_ID_LOCATION] = power_domain->id; + + zynqmp_pmufw_load_config_object(xpm_configobject, sizeof(xpm_configobject)); + + return 0; +} + +static int zynqmp_power_domain_free(struct power_domain *power_domain) +{ + /* nop now */ + return 0; +} + +static int zynqmp_power_domain_on(struct power_domain *power_domain) +{ + return zynqmp_pm_request_node(power_domain->id, + ZYNQMP_PM_CAPABILITY_ACCESS, + ZYNQMP_PM_MAX_QOS, + ZYNQMP_PM_REQUEST_ACK_BLOCKING); +} + +static int zynqmp_power_domain_off(struct power_domain *power_domain) +{ + /* nop now */ + return 0; +} + +struct power_domain_ops zynqmp_power_domain_ops = { + .request = zynqmp_power_domain_request, + .rfree = zynqmp_power_domain_free, + .on = zynqmp_power_domain_on, + .off = zynqmp_power_domain_off, +}; + +static int zynqmp_power_domain_probe(struct udevice *dev) +{ + return 0; +} + +U_BOOT_DRIVER(zynqmp_power_domain) = { + .name = "zynqmp_power_domain", + .id = UCLASS_POWER_DOMAIN, + .probe = zynqmp_power_domain_probe, + .ops = &zynqmp_power_domain_ops, +}; diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index cfd92d3fe56..19c004e9199 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -371,4 +371,35 @@ 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); +/* Type of Config Object */ +#define PM_CONFIG_OBJECT_TYPE_BASE 0x1U +#define PM_CONFIG_OBJECT_TYPE_OVERLAY 0x2U + +/* Section Id */ +#define PM_CONFIG_SLAVE_SECTION_ID 0x102U +#define PM_CONFIG_SET_CONFIG_SECTION_ID 0x107U + +/* Flag Option */ +#define PM_SLAVE_FLAG_IS_SHAREABLE 0x1U +#define PM_MASTER_USING_SLAVE_MASK 0x2U + +/* IPI Mask for Master */ +#define PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK 0x00000001 +#define PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK 0x00000100 +#define PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK 0x00000200 + +enum zynqmp_pm_request_ack { + ZYNQMP_PM_REQUEST_ACK_NO = 1, + ZYNQMP_PM_REQUEST_ACK_BLOCKING = 2, + ZYNQMP_PM_REQUEST_ACK_NON_BLOCKING = 3, +}; + +/* Node capabilities */ +#define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U +#define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U +#define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U +#define ZYNQMP_PM_CAPABILITY_UNUSABLE 0x8U + +#define ZYNQMP_PM_MAX_QOS 100U + #endif /* _ZYNQMP_FIRMWARE_H_ */ -- cgit v1.3.1 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 'include') 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.3.1 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 'include') 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.3.1 From 1669b3d1a0b56178ec8123c48fbf6dabe46b23a4 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Sun, 13 Feb 2022 10:09:20 +0200 Subject: microblaze: exception: migrate MICROBLAZE_V5 to Kconfig Also, rename it to XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP, since it only covers delay slot exception support. Signed-off-by: Ovidiu Panait Link: https://lore.kernel.org/r/20220213080925.1548411-2-ovidiu.panait@windriver.com Signed-off-by: Michal Simek --- arch/microblaze/cpu/exception.c | 2 +- board/xilinx/microblaze-generic/Kconfig | 9 +++++++++ include/configs/microblaze-generic.h | 3 --- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index f60f1fc6936..5601dde5b47 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -40,7 +40,7 @@ void _hw_exception_handler (void) case 0x7: puts("Priviledged or stack protection violation exception\n"); break; -#ifdef MICROBLAZE_V5 +#if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP) case 0x1000: puts("Exception in delay slot\n"); break; diff --git a/board/xilinx/microblaze-generic/Kconfig b/board/xilinx/microblaze-generic/Kconfig index e31257d3351..117b476f3f4 100644 --- a/board/xilinx/microblaze-generic/Kconfig +++ b/board/xilinx/microblaze-generic/Kconfig @@ -47,6 +47,15 @@ config XILINX_MICROBLAZE0_USR_EXCEP the exception vector table. The user exception vector is located at C_BASE_VECTORS + 0x8 address. +config XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP + bool "MicroBlaze delay slot exception support" + default y + help + Enable this option if the MicroBlaze processor supports exceptions + caused by delay slot instructions (processor version >= v5.00). When + enabled, the hw exception handler will print a message indicating + whether the exception was triggered by a delay slot instruction. + config XILINX_MICROBLAZE0_VECTOR_BASE_ADDR hex "Location of MicroBlaze vectors" default 0x0 diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index ca749ed18ac..fd5a9cf8b8e 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -11,9 +11,6 @@ /* Microblaze is microblaze_0 */ #define XILINX_FSL_NUMBER 3 -/* MicroBlaze CPU */ -#define MICROBLAZE_V5 1 - #define CONFIG_SYS_BOOTM_LEN (64 * 1024 * 1024) /* uart */ -- cgit v1.3.1