1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* 8 * ZynqMP system level PM-API functions for ioctl. 9 */ 10 11 #include <arch_helpers.h> 12 #include <delay_timer.h> 13 #include <mmio.h> 14 #include <platform.h> 15 #include "pm_api_ioctl.h" 16 #include "pm_api_sys.h" 17 #include "pm_client.h" 18 #include "pm_common.h" 19 #include "pm_ipi.h" 20 #include "../zynqmp_def.h" 21 22 /** 23 * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode 24 * @mode Buffer to store value of oper mode(Split/Lock-step) 25 * 26 * This function provides current configured RPU operational mode. 27 * 28 * @return Returns status, either success or error+reason 29 */ 30 static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode) 31 { 32 unsigned int val; 33 34 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 35 val &= ZYNQMP_SLSPLIT_MASK; 36 if (val) 37 *mode = PM_RPU_MODE_SPLIT; 38 else 39 *mode = PM_RPU_MODE_LOCKSTEP; 40 41 return PM_RET_SUCCESS; 42 } 43 44 /** 45 * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode 46 * @mode Value to set for oper mode(Split/Lock-step) 47 * 48 * This function configures RPU operational mode(Split/Lock-step). 49 * It also sets TCM combined mode in RPU lock-step and TCM non-combined 50 * mode for RPU split mode. In case of Lock step mode, RPU1's output is 51 * clamped. 52 * 53 * @return Returns status, either success or error+reason 54 */ 55 static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode) 56 { 57 unsigned int val; 58 59 if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET) 60 return PM_RET_ERROR_ACCESS; 61 62 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 63 64 if (mode == PM_RPU_MODE_SPLIT) { 65 val |= ZYNQMP_SLSPLIT_MASK; 66 val &= ~ZYNQMP_TCM_COMB_MASK; 67 val &= ~ZYNQMP_SLCLAMP_MASK; 68 } else if (mode == PM_RPU_MODE_LOCKSTEP) { 69 val &= ~ZYNQMP_SLSPLIT_MASK; 70 val |= ZYNQMP_TCM_COMB_MASK; 71 val |= ZYNQMP_SLCLAMP_MASK; 72 } else { 73 return PM_RET_ERROR_ARGS; 74 } 75 76 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); 77 78 return PM_RET_SUCCESS; 79 } 80 81 /** 82 * pm_ioctl_config_boot_addr() - Configure RPU boot address 83 * @nid Node ID of RPU 84 * @value Value to set for boot address (TCM/OCM) 85 * 86 * This function configures RPU boot address(memory). 87 * 88 * @return Returns status, either success or error+reason 89 */ 90 static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid, 91 unsigned int value) 92 { 93 unsigned int rpu_cfg_addr, val; 94 95 if (nid == NODE_RPU_0) 96 rpu_cfg_addr = ZYNQMP_RPU0_CFG; 97 else if (nid == NODE_RPU_1) 98 rpu_cfg_addr = ZYNQMP_RPU1_CFG; 99 else 100 return PM_RET_ERROR_ARGS; 101 102 val = mmio_read_32(rpu_cfg_addr); 103 104 if (value == PM_RPU_BOOTMEM_LOVEC) 105 val &= ~ZYNQMP_VINITHI_MASK; 106 else if (value == PM_RPU_BOOTMEM_HIVEC) 107 val |= ZYNQMP_VINITHI_MASK; 108 else 109 return PM_RET_ERROR_ARGS; 110 111 mmio_write_32(rpu_cfg_addr, val); 112 113 return PM_RET_SUCCESS; 114 } 115 116 /** 117 * pm_ioctl_config_tcm_comb() - Configure TCM combined mode 118 * @value Value to set (Split/Combined) 119 * 120 * This function configures TCM to be in split mode or combined 121 * mode. 122 * 123 * @return Returns status, either success or error+reason 124 */ 125 static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value) 126 { 127 unsigned int val; 128 129 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); 130 131 if (value == PM_RPU_TCM_SPLIT) 132 val &= ~ZYNQMP_TCM_COMB_MASK; 133 else if (value == PM_RPU_TCM_COMB) 134 val |= ZYNQMP_TCM_COMB_MASK; 135 else 136 return PM_RET_ERROR_ARGS; 137 138 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); 139 140 return PM_RET_SUCCESS; 141 } 142 143 /** 144 * pm_api_ioctl() - PM IOCTL API for device control and configs 145 * @node_id Node ID of the device 146 * @ioctl_id ID of the requested IOCTL 147 * @arg1 Argument 1 to requested IOCTL call 148 * @arg2 Argument 2 to requested IOCTL call 149 * @value Returned output value 150 * 151 * This function calls IOCTL to firmware for device control and configuration. 152 * 153 * @return Returns status, either success or error+reason 154 */ 155 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, 156 unsigned int ioctl_id, 157 unsigned int arg1, 158 unsigned int arg2, 159 unsigned int *value) 160 { 161 int ret; 162 163 switch (ioctl_id) { 164 case IOCTL_GET_RPU_OPER_MODE: 165 ret = pm_ioctl_get_rpu_oper_mode(value); 166 break; 167 case IOCTL_SET_RPU_OPER_MODE: 168 ret = pm_ioctl_set_rpu_oper_mode(arg1); 169 break; 170 case IOCTL_RPU_BOOT_ADDR_CONFIG: 171 ret = pm_ioctl_config_boot_addr(nid, arg1); 172 break; 173 case IOCTL_TCM_COMB_CONFIG: 174 ret = pm_ioctl_config_tcm_comb(arg1); 175 break; 176 default: 177 ret = PM_RET_ERROR_NOTSUPPORTED; 178 } 179 180 return ret; 181 } 182