diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index f8a9945c1da..fb583580ebe 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -427,6 +427,104 @@ U_BOOT_DRIVER(zynqmp_power) = { }; #endif +static const char *const pinctrl_functions[] = { + "can0", + "can1", + "ethernet0", + "ethernet1", + "ethernet2", + "ethernet3", + "gemtsu0", + "gpio0", + "i2c0", + "i2c1", + "mdio0", + "mdio1", + "mdio2", + "mdio3", + "qspi0", + "qspi_fbclk", + "qspi_ss", + "spi0", + "spi1", + "spi0_ss", + "spi1_ss", + "sdio0", + "sdio0_pc", + "sdio0_cd", + "sdio0_wp", + "sdio1", + "sdio1_pc", + "sdio1_cd", + "sdio1_wp", + "nand0", + "nand0_ce", + "nand0_rb", + "nand0_dqs", + "ttc0_clk", + "ttc0_wav", + "ttc1_clk", + "ttc1_wav", + "ttc2_clk", + "ttc2_wav", + "ttc3_clk", + "ttc3_wav", + "uart0", + "uart1", + "usb0", + "usb1", + "swdt0_clk", + "swdt0_rst", + "swdt1_clk", + "swdt1_rst", + "pmu0", + "pcie0", + "csu0", + "dpaux0", + "pjtag0", + "trace0", + "trace0_clk", + "testscan0", +}; + +/* + * PM_QUERY_DATA is implemented by ATF and not the PMU firmware, so we have to + * emulate it in SPL. Just implement functions/pins since the groups take up a + * lot of rodata and are mostly superfluous. + */ +static int zynqmp_pm_query_data(enum pm_query_id qid, u32 arg1, u32 arg2, + u32 *ret_payload) +{ + switch (qid) { + case PM_QID_PINCTRL_GET_NUM_PINS: + ret_payload[1] = 78; /* NUM_PINS */ + ret_payload[0] = 0; + return 0; + case PM_QID_PINCTRL_GET_NUM_FUNCTIONS: + ret_payload[1] = ARRAY_SIZE(pinctrl_functions); + ret_payload[0] = 0; + return 0; + case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS: + ret_payload[1] = 0; + ret_payload[0] = 0; + return 0; + case PM_QID_PINCTRL_GET_FUNCTION_NAME: + assert(arg1 < ARRAY_SIZE(pinctrl_functions)); + memset(ret_payload, 0, MAX_FUNC_NAME_LEN); + strcpy((char *)ret_payload, pinctrl_functions[arg1]); + return 0; + case PM_QID_PINCTRL_GET_FUNCTION_GROUPS: + case PM_QID_PINCTRL_GET_PIN_GROUPS: + memset(ret_payload + 1, 0xff, + sizeof(s16) * NUM_GROUPS_PER_RESP); + ret_payload[0] = 0; + return 0; + default: + ret_payload[0] = 1; + return 1; + } +} + smc_call_handler_t __data smc_call_handler; static int smc_call_legacy(u32 api_id, u32 arg0, u32 arg1, u32 arg2, @@ -493,6 +591,9 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, __func__, current_el(), api_id, arg0, arg1, arg2, arg3, arg4, arg5); if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { + if (CONFIG_IS_ENABLED(PINCTRL_ZYNQMP) && + api_id == PM_QUERY_DATA) + return zynqmp_pm_query_data(arg0, arg1, arg2, ret_payload); #if defined(CONFIG_ZYNQMP_IPI) /* * Use fixed payload and arg size as the EL2 call. The firmware diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ea90713ec6c..73dd5ff4a79 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -386,6 +386,14 @@ config PINCTRL_ZYNQMP Generic Pinctrl framework and is compatible with the Linux driver, i.e. it uses the same device tree configuration. +config SPL_PINCTRL_ZYNQMP + bool "Xilinx ZynqMP pin control driver in SPL" + depends on SPL_DM && SPL_PINCTRL_GENERIC && ARCH_ZYNQMP + default PINCTRL_ZYNQMP + help + Support pin multiplexing control in SPL on Xilinx ZynqMP. Only "pins" + can be muxed; "groups" are not supported. + endif source "drivers/pinctrl/broadcom/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 33ff7b95ef2..4fb6cef3113 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -36,5 +36,5 @@ obj-$(CONFIG_$(PHASE_)PINCTRL_SX150X) += pinctrl-sx150x.o obj-$(CONFIG_$(PHASE_)PINCTRL_STMFX) += pinctrl-stmfx.o obj-$(CONFIG_PINCTRL_TH1520) += pinctrl-th1520.o obj-y += broadcom/ -obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o +obj-$(CONFIG_$(PHASE_)PINCTRL_ZYNQMP) += pinctrl-zynqmp.o obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/ diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c index 7c11ac4c8b8..0b936684f8a 100644 --- a/drivers/pinctrl/pinctrl-zynqmp.c +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -19,15 +19,11 @@ #include #include -#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 -#define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 -#define NUM_GROUPS_PER_RESP 6 -#define NA_GROUP -1 -#define RESERVED_GROUP -2 +#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN (sizeof(s16) * NUM_GROUPS_PER_RESP) +#define PINCTRL_GET_PIN_GROUPS_RESP_LEN (sizeof(s16) * NUM_GROUPS_PER_RESP) #define MAX_GROUP_PIN 50 #define MAX_PIN_GROUPS 50 #define MAX_GROUP_NAME_LEN 32 -#define MAX_FUNC_NAME_LEN 16 #define DRIVE_STRENGTH_2MA 2 #define DRIVE_STRENGTH_4MA 4 diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 05df49f292a..f5e72625e53 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -185,6 +185,11 @@ enum pm_query_id { PM_QID_CLOCK_GET_MAX_DIVISOR = 13, }; +#define NUM_GROUPS_PER_RESP 6 +#define NA_GROUP -1 +#define RESERVED_GROUP -2 +#define MAX_FUNC_NAME_LEN 16 + enum pm_pinctrl_config_param { PM_PINCTRL_CONFIG_SLEW_RATE = 0, PM_PINCTRL_CONFIG_BIAS_STATUS = 1,