1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright 2018 NXP 4 * 5 * Peng Fan <peng.fan@nxp.com> 6 */ 7 8 #include <common.h> 9 #include <asm/io.h> 10 #include <dm.h> 11 #include <asm/arch/sci/sci.h> 12 #include <misc.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 /* CLK and PM */ 17 int sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, 18 sc_pm_clock_rate_t *rate) 19 { 20 struct udevice *dev = gd->arch.scu_dev; 21 int size = sizeof(struct sc_rpc_msg_s); 22 struct sc_rpc_msg_s msg; 23 int ret; 24 25 RPC_VER(&msg) = SC_RPC_VERSION; 26 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM; 27 RPC_FUNC(&msg) = (u8)PM_FUNC_SET_CLOCK_RATE; 28 RPC_U32(&msg, 0U) = *(u32 *)rate; 29 RPC_U16(&msg, 4U) = (u16)resource; 30 RPC_U8(&msg, 6U) = (u8)clk; 31 RPC_SIZE(&msg) = 3U; 32 33 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 34 if (ret) 35 printf("%s: rate:%u resource:%u: clk:%u res:%d\n", 36 __func__, *rate, resource, clk, RPC_R8(&msg)); 37 38 *rate = RPC_U32(&msg, 0U); 39 40 return ret; 41 } 42 43 int sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, 44 sc_pm_clock_rate_t *rate) 45 { 46 struct udevice *dev = gd->arch.scu_dev; 47 int size = sizeof(struct sc_rpc_msg_s); 48 struct sc_rpc_msg_s msg; 49 int ret; 50 51 RPC_VER(&msg) = SC_RPC_VERSION; 52 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM; 53 RPC_FUNC(&msg) = (u8)PM_FUNC_GET_CLOCK_RATE; 54 RPC_U16(&msg, 0U) = (u16)resource; 55 RPC_U8(&msg, 2U) = (u8)clk; 56 RPC_SIZE(&msg) = 2U; 57 58 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 59 if (ret) { 60 printf("%s: resource:%d clk:%d: res:%d\n", 61 __func__, resource, clk, RPC_R8(&msg)); 62 return ret; 63 } 64 65 if (rate) 66 *rate = RPC_U32(&msg, 0U); 67 68 return 0; 69 } 70 71 int sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, 72 sc_bool_t enable, sc_bool_t autog) 73 { 74 struct udevice *dev = gd->arch.scu_dev; 75 int size = sizeof(struct sc_rpc_msg_s); 76 struct sc_rpc_msg_s msg; 77 int ret; 78 79 RPC_VER(&msg) = SC_RPC_VERSION; 80 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM; 81 RPC_FUNC(&msg) = (u8)PM_FUNC_CLOCK_ENABLE; 82 RPC_U16(&msg, 0U) = (u16)resource; 83 RPC_U8(&msg, 2U) = (u8)clk; 84 RPC_U8(&msg, 3U) = (u8)enable; 85 RPC_U8(&msg, 4U) = (u8)autog; 86 RPC_SIZE(&msg) = 3U; 87 88 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 89 if (ret) 90 printf("%s: resource:%d clk:%d: enable:%d autog: %d, res:%d\n", 91 __func__, resource, clk, enable, autog, RPC_R8(&msg)); 92 93 return ret; 94 } 95 96 int sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, 97 sc_pm_power_mode_t mode) 98 { 99 struct udevice *dev = gd->arch.scu_dev; 100 int size = sizeof(struct sc_rpc_msg_s); 101 struct sc_rpc_msg_s msg; 102 int ret; 103 104 if (!dev) 105 hang(); 106 107 RPC_VER(&msg) = SC_RPC_VERSION; 108 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PM; 109 RPC_FUNC(&msg) = (u8)PM_FUNC_SET_RESOURCE_POWER_MODE; 110 RPC_U16(&msg, 0U) = (u16)resource; 111 RPC_U8(&msg, 2U) = (u8)mode; 112 RPC_SIZE(&msg) = 2U; 113 114 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 115 if (ret) 116 printf("%s: resource:%d mode:%d: res:%d\n", 117 __func__, resource, mode, RPC_R8(&msg)); 118 119 return ret; 120 } 121 122 /* PAD */ 123 int sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, u32 val) 124 { 125 struct udevice *dev = gd->arch.scu_dev; 126 int size = sizeof(struct sc_rpc_msg_s); 127 struct sc_rpc_msg_s msg; 128 int ret; 129 130 if (!dev) 131 hang(); 132 133 RPC_VER(&msg) = SC_RPC_VERSION; 134 RPC_SVC(&msg) = (u8)SC_RPC_SVC_PAD; 135 RPC_FUNC(&msg) = (u8)PAD_FUNC_SET; 136 RPC_U32(&msg, 0U) = (u32)val; 137 RPC_U16(&msg, 4U) = (u16)pad; 138 RPC_SIZE(&msg) = 3U; 139 140 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 141 if (ret) 142 printf("%s: val:%d pad:%d: res:%d\n", 143 __func__, val, pad, RPC_R8(&msg)); 144 145 return ret; 146 } 147 148 /* MISC */ 149 int sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, sc_ctrl_t ctrl, 150 u32 *val) 151 { 152 struct udevice *dev = gd->arch.scu_dev; 153 int size = sizeof(struct sc_rpc_msg_s); 154 struct sc_rpc_msg_s msg; 155 int ret; 156 157 if (!dev) 158 hang(); 159 160 RPC_VER(&msg) = SC_RPC_VERSION; 161 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC; 162 RPC_FUNC(&msg) = (u8)MISC_FUNC_GET_CONTROL; 163 RPC_U32(&msg, 0U) = (u32)ctrl; 164 RPC_U16(&msg, 4U) = (u16)resource; 165 RPC_SIZE(&msg) = 3U; 166 167 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 168 if (ret) 169 printf("%s: ctrl:%d resource:%d: res:%d\n", 170 __func__, ctrl, resource, RPC_R8(&msg)); 171 172 if (!val) 173 *val = RPC_U32(&msg, 0U); 174 175 return ret; 176 } 177 178 void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *boot_dev) 179 { 180 struct udevice *dev = gd->arch.scu_dev; 181 int size = sizeof(struct sc_rpc_msg_s); 182 struct sc_rpc_msg_s msg; 183 int ret; 184 185 if (!dev) 186 hang(); 187 188 RPC_VER(&msg) = SC_RPC_VERSION; 189 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC; 190 RPC_FUNC(&msg) = (u8)MISC_FUNC_GET_BOOT_DEV; 191 RPC_SIZE(&msg) = 1U; 192 193 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 194 if (ret) 195 printf("%s: res:%d\n", __func__, RPC_R8(&msg)); 196 197 if (!boot_dev) 198 *boot_dev = RPC_U16(&msg, 0U); 199 } 200 201 void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status) 202 { 203 struct udevice *dev = gd->arch.scu_dev; 204 int size = sizeof(struct sc_rpc_msg_s); 205 struct sc_rpc_msg_s msg; 206 int ret; 207 208 if (!dev) 209 hang(); 210 211 RPC_VER(&msg) = SC_RPC_VERSION; 212 RPC_SVC(&msg) = (u8)SC_RPC_SVC_MISC; 213 RPC_FUNC(&msg) = (u8)MISC_FUNC_BOOT_STATUS; 214 RPC_U8(&msg, 0U) = (u8)status; 215 RPC_SIZE(&msg) = 2U; 216 217 ret = misc_call(dev, SC_TRUE, &msg, size, &msg, size); 218 if (ret) 219 printf("%s: status:%d res:%d\n", 220 __func__, status, RPC_R8(&msg)); 221 } 222 223 void sc_misc_build_info(sc_ipc_t ipc, u32 *build, u32 *commit) 224 { 225 struct udevice *dev = gd->arch.scu_dev; 226 int size = sizeof(struct sc_rpc_msg_s); 227 struct sc_rpc_msg_s msg; 228 int ret; 229 230 if (!dev) 231 hang(); 232 233 RPC_VER(&msg) = SC_RPC_VERSION; 234 RPC_SVC(&msg) = SC_RPC_SVC_MISC; 235 RPC_FUNC(&msg) = MISC_FUNC_BUILD_INFO; 236 RPC_SIZE(&msg) = 1; 237 238 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 239 if (ret < 0) { 240 printf("%s: err: %d\n", __func__, ret); 241 return; 242 } 243 244 if (build) 245 *build = RPC_U32(&msg, 0); 246 if (commit) 247 *commit = RPC_U32(&msg, 4); 248 } 249 250 int sc_misc_otp_fuse_read(sc_ipc_t ipc, u32 word, u32 *val) 251 { 252 struct udevice *dev = gd->arch.scu_dev; 253 int size = sizeof(struct sc_rpc_msg_s); 254 struct sc_rpc_msg_s msg; 255 int ret; 256 257 if (!dev) 258 hang(); 259 260 RPC_VER(&msg) = SC_RPC_VERSION; 261 RPC_SVC(&msg) = SC_RPC_SVC_MISC; 262 RPC_FUNC(&msg) = MISC_FUNC_OTP_FUSE_READ; 263 RPC_U32(&msg, 0) = word; 264 RPC_SIZE(&msg) = 2; 265 266 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 267 if (ret < 0) 268 return ret; 269 270 if (val) 271 *val = RPC_U32(&msg, 0U); 272 273 return 0; 274 } 275 276 /* RM */ 277 sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr) 278 { 279 struct udevice *dev = gd->arch.scu_dev; 280 int size = sizeof(struct sc_rpc_msg_s); 281 struct sc_rpc_msg_s msg; 282 int ret; 283 sc_err_t result; 284 285 if (!dev) 286 hang(); 287 288 RPC_VER(&msg) = SC_RPC_VERSION; 289 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM; 290 RPC_FUNC(&msg) = (u8)RM_FUNC_IS_MEMREG_OWNED; 291 RPC_U8(&msg, 0U) = (u8)mr; 292 RPC_SIZE(&msg) = 2U; 293 294 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 295 result = RPC_R8(&msg); 296 297 if (result != 0 && result != 1) { 298 printf("%s: mr:%d res:%d\n", __func__, mr, RPC_R8(&msg)); 299 if (ret) 300 printf("%s: mr:%d res:%d\n", __func__, mr, 301 RPC_R8(&msg)); 302 } 303 304 return (sc_bool_t)result; 305 } 306 307 int sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, sc_faddr_t *addr_start, 308 sc_faddr_t *addr_end) 309 { 310 struct udevice *dev = gd->arch.scu_dev; 311 int size = sizeof(struct sc_rpc_msg_s); 312 struct sc_rpc_msg_s msg; 313 int ret; 314 315 if (!dev) 316 hang(); 317 318 RPC_VER(&msg) = SC_RPC_VERSION; 319 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM; 320 RPC_FUNC(&msg) = (u8)RM_FUNC_GET_MEMREG_INFO; 321 RPC_U8(&msg, 0U) = (u8)mr; 322 RPC_SIZE(&msg) = 2U; 323 324 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 325 if (ret) 326 printf("%s: mr:%d res:%d\n", __func__, mr, RPC_R8(&msg)); 327 328 if (addr_start) 329 *addr_start = ((u64)RPC_U32(&msg, 0U) << 32U) | 330 RPC_U32(&msg, 4U); 331 332 if (addr_end) 333 *addr_end = ((u64)RPC_U32(&msg, 8U) << 32U) | 334 RPC_U32(&msg, 12U); 335 336 return ret; 337 } 338 339 sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource) 340 { 341 struct udevice *dev = gd->arch.scu_dev; 342 int size = sizeof(struct sc_rpc_msg_s); 343 struct sc_rpc_msg_s msg; 344 int ret; 345 u8 result; 346 347 if (!dev) 348 hang(); 349 350 RPC_VER(&msg) = SC_RPC_VERSION; 351 RPC_SVC(&msg) = (u8)SC_RPC_SVC_RM; 352 RPC_FUNC(&msg) = (u8)RM_FUNC_IS_RESOURCE_OWNED; 353 RPC_U16(&msg, 0U) = (u16)resource; 354 RPC_SIZE(&msg) = 2U; 355 356 ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); 357 result = RPC_R8(&msg); 358 if (result != 0 && result != 1) { 359 printf("%s: resource:%d res:%d\n", 360 __func__, resource, RPC_R8(&msg)); 361 if (ret) 362 printf("%s: res:%d res:%d\n", __func__, resource, 363 RPC_R8(&msg)); 364 } 365 366 return !!result; 367 } 368