From 7c0b17e34b28decfab4f7de361fbbfd8b18b3e33 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:03:25 +0530 Subject: [PATCH 01/11] zynqmp: pm_service: Add support for resetting ULPI transceiver To make ULPI transceiver work, a HIGH - LOW - HIGH pulse needs to be given to resetb pin of ULPI chip. In ZYNQMP, this resetb pin is being driven by BOOT MODE PIN 1. The BOOT MODE PIN's are controlled by BOOT_PIN_CTRL register present in CRL_APB address region. Since CRL_APB can be resticted to secure access, this pin should be controlled by ATF. This patch adds the support for the same. Signed-off-by: Anurag Kumar Vulisha Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 37 ++++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 2 ++ plat/xilinx/zynqmp/zynqmp_def.h | 9 +++++ 3 files changed, 48 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index cdbb515b0..17918338d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -471,6 +471,40 @@ static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index, return pm_mmio_read(PGGS_BASEADDR + (index << 2), value); } +/** + * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset + * + * This function peerforms the ULPI reset sequence for resetting + * the ULPI transceiver. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_ulpi_reset(void) +{ + enum pm_ret_status ret; + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_HIGH); + if (ret != PM_RET_SUCCESS) + return ret; + + /* Drive ULPI assert for atleast 1ms */ + mdelay(1); + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_LOW); + if (ret != PM_RET_SUCCESS) + return ret; + + /* Drive ULPI de-assert for atleast 1ms */ + mdelay(1); + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_HIGH); + + return ret; +} + /** * pm_api_ioctl() - PM IOCTL API for device control and configs * @node_id Node ID of the device @@ -540,6 +574,9 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, case IOCTL_READ_PGGS: ret = pm_ioctl_read_pggs(arg1, value); break; + case IOCTL_ULPI_RESET: + ret = pm_ioctl_ulpi_reset(); + break; default: ret = PM_RET_ERROR_NOTSUPPORTED; break; diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index 081259f64..bf17117f0 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -32,6 +32,8 @@ enum { IOCTL_READ_GGS, IOCTL_WRITE_PGGS, IOCTL_READ_PGGS, + /* IOCTL for ULPI reset */ + IOCTL_ULPI_RESET, }; //RPU operation mode diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 22256ebfa..dd26c6c2c 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -48,6 +48,7 @@ #define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200) #define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) #define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C) +#define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + U(0x250)) #define CRL_APB_CLK_BASE U(0xFF5E0020) #define CRL_APB_RPU_AMBA_RESET (U(1) << 2) @@ -56,7 +57,15 @@ #define CRL_APB_RESET_CTRL_SOFT_RESET (U(1) << 4) #define CRL_APB_BOOT_MODE_MASK (U(0xf) << 0) +#define CRL_APB_BOOT_PIN_MASK (U(0xf0f) << 0) +#define CRL_APB_BOOT_DRIVE_PIN_1_SHIFT U(9) +#define CRL_APB_BOOT_ENABLE_PIN_1_SHIFT U(1) +#define CRL_APB_BOOT_ENABLE_PIN_1 (U(0x1) << CRL_APB_BOOT_ENABLE_PIN_1_SHIFT) +#define CRL_APB_BOOT_DRIVE_PIN_1 (U(0x1) << CRL_APB_BOOT_DRIVE_PIN_1_SHIFT) #define ZYNQMP_BOOTMODE_JTAG U(0) +#define ZYNQMP_ULPI_RESET_VAL_HIGH (CRL_APB_BOOT_ENABLE_PIN_1 | \ + CRL_APB_BOOT_DRIVE_PIN_1) +#define ZYNQMP_ULPI_RESET_VAL_LOW CRL_APB_BOOT_ENABLE_PIN_1 /* system counter registers and bitfields */ #define IOU_SCNTRS_BASE 0xFF260000 From 9a2850e5fa2e1a96a4510e0bd62f8b660da08a0d Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:12:51 +0530 Subject: [PATCH 02/11] zynqmp: pm: Add IOCTL to set boot health status Since the MMIO read/write APIs are removed from Linux user space, Linux cannot directly write to the Global General Storage Register 4 any more to set healthy boot status. Create an IOCTL to allow Linux to set boot health status. Signed-off-by: Rajan Vaja Signed-off-by: Siva Durga Prasad Paladugu Acked-by: Will Wong --- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 17 +++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 2 ++ plat/xilinx/zynqmp/zynqmp_def.h | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index 17918338d..6f60e47e6 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -505,6 +505,20 @@ static enum pm_ret_status pm_ioctl_ulpi_reset(void) return ret; } +/** + * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status + * + * This function sets healthy bit value to indicate boot health status + * to firmware. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value) +{ + return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG, + PM_BOOT_HEALTH_STATUS_MASK, value); +} + /** * pm_api_ioctl() - PM IOCTL API for device control and configs * @node_id Node ID of the device @@ -577,6 +591,9 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, case IOCTL_ULPI_RESET: ret = pm_ioctl_ulpi_reset(); break; + case IOCTL_SET_BOOT_HEALTH_STATUS: + ret = pm_ioctl_set_boot_health_status(arg1); + break; default: ret = PM_RET_ERROR_NOTSUPPORTED; break; diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index bf17117f0..29cd96ef2 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -34,6 +34,8 @@ enum { IOCTL_READ_PGGS, /* IOCTL for ULPI reset */ IOCTL_ULPI_RESET, + /* Set healthy bit value */ + IOCTL_SET_BOOT_HEALTH_STATUS, }; //RPU operation mode diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index dd26c6c2c..bfd61976f 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -335,4 +335,8 @@ #define PGGS_BASEADDR (0xFFD80050U) #define PGGS_NUM_REGS U(4) +/* Warm restart boot health status register and mask */ +#define PM_BOOT_HEALTH_STATUS_REG (GGS_BASEADDR + U(0x10)) +#define PM_BOOT_HEALTH_STATUS_MASK U(0x01) + #endif /* __ZYNQMP_DEF_H__ */ From 6ad42b989d3c8352f15bb9d14dd403cd15bb652e Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:27:12 +0530 Subject: [PATCH 03/11] zynqmp: pm_service: Add support for writing to AFI registers Add support for writing to AFI registers. So that after writing a bitstream the interface can be programmed. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 45 ++++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 1 + plat/xilinx/zynqmp/zynqmp_def.h | 4 ++ 3 files changed, 50 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index 6f60e47e6..32c73577a 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -452,6 +452,48 @@ static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index, 0xFFFFFFFFU, value); } +/** + * pm_ioctl_afi() - Ioctl function for writing afi values + * + * @index AFI register index + * @value Register value to be written + * + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_afi(unsigned int index, + unsigned int value) +{ + unsigned int mask; + unsigned int regarr[] = {0xFD360000, + 0xFD360014, + 0xFD370000, + 0xFD370014, + 0xFD380000, + 0xFD380014, + 0xFD390000, + 0xFD390014, + 0xFD3a0000, + 0xFD3a0014, + 0xFD3b0000, + 0xFD3b0014, + 0xFF9b0000, + 0xFF9b0014, + 0xFD615000, + 0xFF419000, + }; + + if (index >= ARRAY_SIZE(regarr)) + return PM_RET_ERROR_ARGS; + + if (index < AFIFM6_WRCTRL) + mask = FABRIC_WIDTH; + else + mask = 0xf00; + + return pm_mmio_write(regarr[index], mask, value); +} + /** * pm_ioctl_read_pggs() - Ioctl function for reading persistent * global general storage (pggs) @@ -594,6 +636,9 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, case IOCTL_SET_BOOT_HEALTH_STATUS: ret = pm_ioctl_set_boot_health_status(arg1); break; + case IOCTL_AFI: + ret = pm_ioctl_afi(arg1, arg2); + break; default: ret = PM_RET_ERROR_NOTSUPPORTED; break; diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index 29cd96ef2..d68c5e313 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -36,6 +36,7 @@ enum { IOCTL_ULPI_RESET, /* Set healthy bit value */ IOCTL_SET_BOOT_HEALTH_STATUS, + IOCTL_AFI, }; //RPU operation mode diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index bfd61976f..8bd75e425 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -339,4 +339,8 @@ #define PM_BOOT_HEALTH_STATUS_REG (GGS_BASEADDR + U(0x10)) #define PM_BOOT_HEALTH_STATUS_MASK U(0x01) +/*AFI registers */ +#define AFIFM6_WRCTRL U(13) +#define FABRIC_WIDTH U(3) + #endif /* __ZYNQMP_DEF_H__ */ From 96cd17f49d9a40ca3620b05d4e5cd09b8205f59a Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:33:19 +0530 Subject: [PATCH 04/11] zynqmp: pm: Correct WDT clock database WDT used by APU is FPD_WDT. FPD WDT clock is controlled by FPD_SLCR.WDT_CLK_SEL register. Correct the same in WDT clock database. As per FPD_SLCR.WDT_CLK_SEL register, there can be only two parents of WDT clock not three. Fix the same by correcting it's parents in clock database. Signed-off-by: Tejas Patel Signed-off-by: Siva Durga Prasad Paladugu Acked-by: Jolly Shah --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 3 +-- plat/xilinx/zynqmp/zynqmp_def.h | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index fefd9ea8f..3b3d088c7 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -2022,12 +2022,11 @@ static struct pm_clock clocks[] = { }, [CLK_WDT] = { .name = "wdt", - .control_reg = IOU_SLCR_WDT_CLK_SEL, + .control_reg = FPD_SLCR_WDT_CLK_SEL, .status_reg = 0, .parents = &((int32_t []) { CLK_TOPSW_LSBUS, EXT_CLK_SWDT0 | CLK_EXTERNAL_PARENT, - EXT_CLK_SWDT1 | CLK_EXTERNAL_PARENT, CLK_NA_PARENT }), .nodes = &wdt_nodes, diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 8bd75e425..50fe88aea 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -201,6 +201,7 @@ #define ACTLR_EL3_L2ACTLR_BIT (1 << 6) #define ACTLR_EL3_CPUACTLR_BIT (1 << 0) +#define FPD_SLCR_BASEADDR U(0xFD610000) #define IOU_SLCR_BASEADDR U(0xFF180000) #define ZYNQMP_RPU_GLBL_CNTL U(0xFF9A0000) @@ -325,7 +326,7 @@ #define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_CLK_BASE + 0x108) #define IOU_SLCR_GEM_CLK_CTRL (IOU_SLCR_BASEADDR + 0x308) #define IOU_SLCR_CAN_MIO_CTRL (IOU_SLCR_BASEADDR + 0x304) -#define IOU_SLCR_WDT_CLK_SEL (IOU_SLCR_BASEADDR + 0x300) +#define FPD_SLCR_WDT_CLK_SEL (FPD_SLCR_BASEADDR + 0x100) /* Global general storage register base address */ #define GGS_BASEADDR (0xFFD80030U) From 88a28a405fcb221a56e3f00694ca2251ba736aba Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:37:27 +0530 Subject: [PATCH 05/11] zynqmp: pm: Use critical flag instead of initenable CCF has already provision to enable clock during registration through CLK_IS_CRITICAL flag. Use CLK_IS_CRITICAL instead of init_enable attribute. Signed-off-by: Rajan Vaja Signed-off-by: Siva Durga Prasad Paladugu Acked-by: Jolly Shah --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 35 ++------------------ 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index 3b3d088c7..dab9edabd 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -25,7 +25,6 @@ #define CLK_TOPOLOGY_NODE_OFFSET U(16) #define CLK_TOPOLOGY_PAYLOAD_LEN U(12) #define CLK_PARENTS_PAYLOAD_LEN U(12) -#define CLK_INIT_ENABLE_SHIFT U(1) #define CLK_TYPE_SHIFT U(2) #define CLK_CLKFLAGS_SHIFT U(8) #define CLK_TYPEFLAGS_SHIFT U(24) @@ -337,7 +336,8 @@ static struct pm_clock_node acpu_nodes[] = { .width = PERIPH_GATE_WIDTH, .clkflags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED | - CLK_IS_BASIC, + CLK_IS_BASIC | + CLK_IS_CRITICAL, .typeflags = NA_TYPE_FLAGS, .mult = NA_MULT, .div = NA_DIV, @@ -496,7 +496,7 @@ static struct pm_clock_node ddr_nodes[] = { .type = TYPE_DIV1, .offset = 8, .width = 6, - .clkflags = CLK_IS_BASIC, + .clkflags = CLK_IS_BASIC | CLK_IS_CRITICAL, .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, .mult = NA_MULT, .div = NA_DIV, @@ -2242,12 +2242,6 @@ static struct pm_ext_clock ext_clocks[] = { /* Array of clock which are invalid for this variant */ static uint32_t pm_clk_invalid_list[] = {CLK_USB0, CLK_USB1, CLK_CSU_SPB}; -/* Array of clocks which needs to be enabled at init */ -static uint32_t pm_clk_init_enable_list[] = { - CLK_ACPU, - CLK_DDR_REF, -}; - /** * pm_clock_valid - Check if clock is valid or not * @clock_id Id of the clock to be queried @@ -2271,26 +2265,6 @@ static bool pm_clock_valid(unsigned int clock_id) return 1; } -/** - * pm_clock_init_enable - Check if clock needs to be enabled at init - * @clock_id Id of the clock to be queried - * - * This function is used to check if given clock needs to be enabled - * at boot up or not. Some clocks needs to be enabled at init. - * - * Return: Returns 1 if clock needs to be enabled at boot up else 0. - */ -static unsigned int pm_clock_init_enable(unsigned int clock_id) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(pm_clk_init_enable_list); i++) - if (pm_clk_init_enable_list[i] == clock_id) - return 1; - - return 0; -} - /** * pm_clock_type - Get clock's type * @clock_id Id of the clock to be queried @@ -2508,9 +2482,6 @@ enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, /* Clock valid bit */ *attr = pm_clock_valid(clock_id); - /* If clock needs to be enabled during init */ - *attr |= (pm_clock_init_enable(clock_id) << CLK_INIT_ENABLE_SHIFT); - /* Clock type (Output/External) */ *attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT); From 26a754f6ad41a4dc5e5b84233cb5eba1de59c4a3 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:41:34 +0530 Subject: [PATCH 06/11] zynqmp: Add new API for pl configuration readback This patch adds new API's for performing pl configuration readback. Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 30 +++++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 7 +++++ plat/xilinx/zynqmp/pm_service/pm_defs.h | 2 ++ plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 9 +++++++ 4 files changed, 48 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index fe1029f66..18c6cd734 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -1183,3 +1183,33 @@ enum pm_ret_status pm_secure_image(uint32_t address_low, key_hi, key_lo); return pm_ipi_send_sync(primary_proc, payload, value, 2); } + +/** + * pm_fpga_read - Perform the fpga configuration readback + * + * @reg_numframes: Configuration register offset (or) Number of frames to read + * @address_low: lower 32-bit Linear memory space address + * @address_high: higher 32-bit Linear memory space address + * @readback_type: Type of fpga readback operation + * 0 -- Configuration Register readback + * 1 -- Configuration Data readback + * @value: Value to read + * + * This function provides access to the xilfpga library to read + * the PL configuration. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, + uint32_t address_low, + uint32_t address_high, + uint32_t readback_type, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low, + address_high, readback_type); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index c304895ac..3726e8569 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -166,4 +166,11 @@ enum pm_ret_status pm_secure_image(uint32_t address_low, uint32_t key_lo, uint32_t key_hi, uint32_t *value); + +enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, + uint32_t address_low, + uint32_t address_high, + uint32_t readback_type, + uint32_t *value); + #endif /* _PM_API_SYS_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 9a8026f46..0775bf9e6 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -89,6 +89,8 @@ enum pm_api_id { PM_CLOCK_SETPARENT, PM_CLOCK_GETPARENT, PM_SECURE_IMAGE, + /* FPGA PL Readback */ + PM_FPGA_READ, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index dd9bbc8c7..92b7b3e83 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -546,6 +546,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, result[1]); } + case PM_FPGA_READ: + { + uint32_t value; + + ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3], + &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From 6a0f7c0077983f1f56b4214f05a22fb93beb9593 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 17:49:32 +0530 Subject: [PATCH 07/11] zynqmp: pm_service: Ignore enable/disable of PLL type clocks PLL type clock is enabled by FSBL on boot-up. PMUFW enable/disable them based on their user count. So, it should not be handled from ATF. Put PLL type clock into bypass and reset mode only while changing PLL rate (FBDIV). Signed-off-by: Tejas Patel Acked-by: Will Wong Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 25 +++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index dab9edabd..cecd5587a 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -2627,10 +2627,11 @@ enum pm_ret_status pm_api_clock_enable(unsigned int clock_id) if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) return PM_RET_ERROR_NOTSUPPORTED; - if (ISPLL(clock_id)) - ret = pm_api_pll_bypass_and_reset(clock_id, - CLK_PLL_RESET_PULSE); - else + /* + * PLL type clock should not enable explicitly. + * It is done by FSBL on boot-up and by PMUFW whenever required. + */ + if (!ISPLL(clock_id)) ret = pm_api_clk_enable_disable(clock_id, 1); return ret; @@ -2656,10 +2657,11 @@ enum pm_ret_status pm_api_clock_disable(unsigned int clock_id) if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) return PM_RET_ERROR_NOTSUPPORTED; - if (ISPLL(clock_id)) - ret = pm_api_pll_bypass_and_reset(clock_id, - CLK_PLL_RESET_ASSERT); - else + /* + * PLL type clock should not be disabled explicitly. + * It is done by PMUFW if required. + */ + if (!ISPLL(clock_id)) ret = pm_api_clk_enable_disable(clock_id, 0); return ret; @@ -2807,8 +2809,13 @@ static enum pm_ret_status pm_api_pll_set_divider(unsigned int clock_id, unsigned int divider) { unsigned int reg = clocks[clock_id].control_reg; + enum pm_ret_status ret; - return pm_mmio_write(reg, PLL_FBDIV_MASK, divider << PLL_FBDIV_SHIFT); + pm_api_pll_bypass_and_reset(clock_id, CLK_PLL_RESET_ASSERT); + ret = pm_mmio_write(reg, PLL_FBDIV_MASK, divider << PLL_FBDIV_SHIFT); + pm_api_pll_bypass_and_reset(clock_id, CLK_PLL_RESET_RELEASE); + + return ret; } /** From e02c90cafd1fc26b287a47319765de456f2d851d Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 9 Jul 2018 00:01:38 -0700 Subject: [PATCH 08/11] zynqmp: pm: Correct function header of clock APIs Correct function header of pm_api_clock_getparent() and pm_api_clock_setparent(). Signed-off-by: Rajan Vaja Acked-by: Will Wong --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index cecd5587a..b175b78b3 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -2965,7 +2965,7 @@ enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id, /** * pm_api_clock_setparent - Set the clock parent for given id * @clock_id Id of the clock - * @parent_id parent id + * @parent_idx parent index * * This function is used by master to set parent for any clock. * @@ -3016,7 +3016,7 @@ enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id, /** * pm_api_clock_getparent - Get the clock parent for given id * @clock_id Id of the clock - * @parent_id parent id + * @parent_idx parent index * * This function is used by master to get parent index * for any clock. From 976c26801553cbe2cddb981f26ba8834a05a0b90 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 18:02:25 +0530 Subject: [PATCH 09/11] zynqmp: Remove emulation platform support This patch removes support for emulation platforms EP108 and Veloce. Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/aarch64/zynqmp_common.c | 36 ++++------------------ plat/xilinx/zynqmp/zynqmp_def.h | 2 -- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index c3612706a..2f4228fea 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -44,19 +44,10 @@ unsigned int zynqmp_get_uart_clk(void) { unsigned int ver = zynqmp_get_silicon_ver(); - switch (ver) { - case ZYNQMP_CSU_VERSION_VELOCE: - return 48000; - case ZYNQMP_CSU_VERSION_EP108: - return 25000000; - case ZYNQMP_CSU_VERSION_QEMU: + if (ver == ZYNQMP_CSU_VERSION_QEMU) return 133000000; - default: - /* Do nothing in default case */ - break; - } - - return 100000000; + else + return 100000000; } #if LOG_LEVEL >= LOG_LEVEL_NOTICE @@ -298,12 +289,6 @@ static void zynqmp_print_platform_name(void) char *label = "Unknown"; switch (ver) { - case ZYNQMP_CSU_VERSION_VELOCE: - label = "VELOCE"; - break; - case ZYNQMP_CSU_VERSION_EP108: - label = "EP108"; - break; case ZYNQMP_CSU_VERSION_QEMU: label = "QEMU"; break; @@ -346,17 +331,8 @@ unsigned int plat_get_syscnt_freq2(void) { unsigned int ver = zynqmp_get_silicon_ver(); - switch (ver) { - case ZYNQMP_CSU_VERSION_VELOCE: - return 10000; - case ZYNQMP_CSU_VERSION_EP108: - return 4000000; - case ZYNQMP_CSU_VERSION_QEMU: + if (ver == ZYNQMP_CSU_VERSION_QEMU) return 50000000; - default: - /* Do nothing in default case */ - break; - } - - return mmio_read_32(IOU_SCNTRS_BASEFREQ); + else + return mmio_read_32(IOU_SCNTRS_BASEFREQ); } diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 50fe88aea..50a733176 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -157,8 +157,6 @@ #define ZYNQMP_SILICON_VER_MASK 0xF000 #define ZYNQMP_SILICON_VER_SHIFT 12 #define ZYNQMP_CSU_VERSION_SILICON 0 -#define ZYNQMP_CSU_VERSION_EP108 1 -#define ZYNQMP_CSU_VERSION_VELOCE 2 #define ZYNQMP_CSU_VERSION_QEMU 3 #define ZYNQMP_RTL_VER_MASK 0xFF0 From db4845349399f9fd5a2a9027e0376372f67c4d60 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 4 Sep 2018 18:05:50 +0530 Subject: [PATCH 10/11] zynqmp: Add ATF support for Data blob encryption and decryption This patch adds ATF support for AES data blob encrypt/decrypt. ATF establishes a path to send the address of the structure to the xilsecure, so that it will pick addresses of the data and performs the requested operation (encrypt/decrypt) and puts the result in load address. where structure contains - Data blob src address - load address - IV address - Key address - this will actual key addr in case of KUP else it will be zero. - Data-size - Aes-op type - KeySrc Signed-off-by: Kalyani Akula Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 24 +++++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 3 +++ plat/xilinx/zynqmp/pm_service/pm_defs.h | 1 + plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 8 +++++++ 4 files changed, 36 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 18c6cd734..e85b2cee3 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -601,6 +601,30 @@ enum pm_ret_status pm_secure_rsaaes(uint32_t address_low, return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } +/** + * pm_aes_engine() - Aes data blob encryption/decryption + * This function provides access to the xilsecure library to + * encrypt/decrypt data blobs. + * + * address_low: lower 32-bit address of the AesParams structure + * + * address_high: higher 32-bit address of the AesParams structure + * + * value: Returned output value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_aes_engine(uint32_t address_high, + uint32_t address_low, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + /** * pm_pinctrl_request() - Request Pin from firmware * @pin Pin number to request diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index 3726e8569..1c9255e6f 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -172,5 +172,8 @@ enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, uint32_t address_high, uint32_t readback_type, uint32_t *value); +enum pm_ret_status pm_aes_engine(uint32_t address_high, + uint32_t address_low, + uint32_t *value); #endif /* _PM_API_SYS_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 0775bf9e6..1fbf6eed9 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -91,6 +91,7 @@ enum pm_api_id { PM_SECURE_IMAGE, /* FPGA PL Readback */ PM_FPGA_READ, + PM_SECURE_AES, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 92b7b3e83..7790c979d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -555,6 +555,14 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_SECURE_AES: + { + uint32_t value; + + ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From e8fae4bc64c9bcd1af79ac1943aa51b4c908ca2e Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Mon, 13 Aug 2018 16:40:04 +0530 Subject: [PATCH 11/11] zynqmp: Define and enable ARM_XLAT_TABLES_LIB_V1 Enable ARM_XLAT_TABLES_LIB_V1 as ZynqMP is using v1 library of translation tables. With upstream patch d323af9e3d903d981b42f954844a95a6bfef91ab, the usage of MAP_REGION_FLAT is referring to definition in file include/lib/xlat_tables/xlat_tables_v2.h but while preparing xlat tables in lib/xlat_tables/xlat_tables_common.c it is referring to include/lib/xlat_tables/xlat_tables.h which is v1 xlat tables. Also, ZynqMP was using v1 so defined ARM_XLAT_TABLES_LIB_V1 to use v1 xlat tables everywhere. This fixes the issue of xlat tables failures as it takes v2 library mmap_region structure in some files and v1 in other files. Signed-off-by: Siva Durga Prasad Paladugu --- plat/xilinx/zynqmp/platform.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 3ac9db959..f806d4605 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -17,6 +17,10 @@ ENABLE_SVE_FOR_NS := 0 WORKAROUND_CVE_2017_5715 := 0 +ARM_XLAT_TABLES_LIB_V1 := 1 +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + ifdef ZYNQMP_ATF_MEM_BASE $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))