Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: xilinx: Add clock APIs

Add clock APIs to control clocks through firmware
interface.

Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
Signed-off-by: Jolly Shah <jollys@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>

authored by

Rajan Vaja and committed by
Michal Simek
f9627312 59ecdd77

+214 -2
+184 -2
drivers/firmware/xilinx/zynqmp.c
··· 250 250 */ 251 251 static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) 252 252 { 253 - return zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 254 - qdata.arg2, qdata.arg3, out); 253 + int ret; 254 + 255 + ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 256 + qdata.arg2, qdata.arg3, out); 257 + 258 + /* 259 + * For clock name query, all bytes in SMC response are clock name 260 + * characters and return code is always success. For invalid clocks, 261 + * clock name bytes would be zeros. 262 + */ 263 + return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; 264 + } 265 + 266 + /** 267 + * zynqmp_pm_clock_enable() - Enable the clock for given id 268 + * @clock_id: ID of the clock to be enabled 269 + * 270 + * This function is used by master to enable the clock 271 + * including peripherals and PLL clocks. 272 + * 273 + * Return: Returns status, either success or error+reason 274 + */ 275 + static int zynqmp_pm_clock_enable(u32 clock_id) 276 + { 277 + return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); 278 + } 279 + 280 + /** 281 + * zynqmp_pm_clock_disable() - Disable the clock for given id 282 + * @clock_id: ID of the clock to be disable 283 + * 284 + * This function is used by master to disable the clock 285 + * including peripherals and PLL clocks. 286 + * 287 + * Return: Returns status, either success or error+reason 288 + */ 289 + static int zynqmp_pm_clock_disable(u32 clock_id) 290 + { 291 + return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); 292 + } 293 + 294 + /** 295 + * zynqmp_pm_clock_getstate() - Get the clock state for given id 296 + * @clock_id: ID of the clock to be queried 297 + * @state: 1/0 (Enabled/Disabled) 298 + * 299 + * This function is used by master to get the state of clock 300 + * including peripherals and PLL clocks. 301 + * 302 + * Return: Returns status, either success or error+reason 303 + */ 304 + static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) 305 + { 306 + u32 ret_payload[PAYLOAD_ARG_CNT]; 307 + int ret; 308 + 309 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0, 310 + 0, 0, ret_payload); 311 + *state = ret_payload[1]; 312 + 313 + return ret; 314 + } 315 + 316 + /** 317 + * zynqmp_pm_clock_setdivider() - Set the clock divider for given id 318 + * @clock_id: ID of the clock 319 + * @divider: divider value 320 + * 321 + * This function is used by master to set divider for any clock 322 + * to achieve desired rate. 323 + * 324 + * Return: Returns status, either success or error+reason 325 + */ 326 + static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) 327 + { 328 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 329 + 0, 0, NULL); 330 + } 331 + 332 + /** 333 + * zynqmp_pm_clock_getdivider() - Get the clock divider for given id 334 + * @clock_id: ID of the clock 335 + * @divider: divider value 336 + * 337 + * This function is used by master to get divider values 338 + * for any clock. 339 + * 340 + * Return: Returns status, either success or error+reason 341 + */ 342 + static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) 343 + { 344 + u32 ret_payload[PAYLOAD_ARG_CNT]; 345 + int ret; 346 + 347 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0, 348 + 0, 0, ret_payload); 349 + *divider = ret_payload[1]; 350 + 351 + return ret; 352 + } 353 + 354 + /** 355 + * zynqmp_pm_clock_setrate() - Set the clock rate for given id 356 + * @clock_id: ID of the clock 357 + * @rate: rate value in hz 358 + * 359 + * This function is used by master to set rate for any clock. 360 + * 361 + * Return: Returns status, either success or error+reason 362 + */ 363 + static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) 364 + { 365 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id, 366 + lower_32_bits(rate), 367 + upper_32_bits(rate), 368 + 0, NULL); 369 + } 370 + 371 + /** 372 + * zynqmp_pm_clock_getrate() - Get the clock rate for given id 373 + * @clock_id: ID of the clock 374 + * @rate: rate value in hz 375 + * 376 + * This function is used by master to get rate 377 + * for any clock. 378 + * 379 + * Return: Returns status, either success or error+reason 380 + */ 381 + static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) 382 + { 383 + u32 ret_payload[PAYLOAD_ARG_CNT]; 384 + int ret; 385 + 386 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0, 387 + 0, 0, ret_payload); 388 + *rate = ((u64)ret_payload[2] << 32) | ret_payload[1]; 389 + 390 + return ret; 391 + } 392 + 393 + /** 394 + * zynqmp_pm_clock_setparent() - Set the clock parent for given id 395 + * @clock_id: ID of the clock 396 + * @parent_id: parent id 397 + * 398 + * This function is used by master to set parent for any clock. 399 + * 400 + * Return: Returns status, either success or error+reason 401 + */ 402 + static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) 403 + { 404 + return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id, 405 + parent_id, 0, 0, NULL); 406 + } 407 + 408 + /** 409 + * zynqmp_pm_clock_getparent() - Get the clock parent for given id 410 + * @clock_id: ID of the clock 411 + * @parent_id: parent id 412 + * 413 + * This function is used by master to get parent index 414 + * for any clock. 415 + * 416 + * Return: Returns status, either success or error+reason 417 + */ 418 + static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) 419 + { 420 + u32 ret_payload[PAYLOAD_ARG_CNT]; 421 + int ret; 422 + 423 + ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0, 424 + 0, 0, ret_payload); 425 + *parent_id = ret_payload[1]; 426 + 427 + return ret; 255 428 } 256 429 257 430 static const struct zynqmp_eemi_ops eemi_ops = { 258 431 .get_api_version = zynqmp_pm_get_api_version, 259 432 .query_data = zynqmp_pm_query_data, 433 + .clock_enable = zynqmp_pm_clock_enable, 434 + .clock_disable = zynqmp_pm_clock_disable, 435 + .clock_getstate = zynqmp_pm_clock_getstate, 436 + .clock_setdivider = zynqmp_pm_clock_setdivider, 437 + .clock_getdivider = zynqmp_pm_clock_getdivider, 438 + .clock_setrate = zynqmp_pm_clock_setrate, 439 + .clock_getrate = zynqmp_pm_clock_getrate, 440 + .clock_setparent = zynqmp_pm_clock_setparent, 441 + .clock_getparent = zynqmp_pm_clock_getparent, 260 442 }; 261 443 262 444 /**
+30
include/linux/firmware/xlnx-zynqmp.h
··· 35 35 enum pm_api_id { 36 36 PM_GET_API_VERSION = 1, 37 37 PM_QUERY_DATA = 35, 38 + PM_CLOCK_ENABLE, 39 + PM_CLOCK_DISABLE, 40 + PM_CLOCK_GETSTATE, 41 + PM_CLOCK_SETDIVIDER, 42 + PM_CLOCK_GETDIVIDER, 43 + PM_CLOCK_SETRATE, 44 + PM_CLOCK_GETRATE, 45 + PM_CLOCK_SETPARENT, 46 + PM_CLOCK_GETPARENT, 38 47 }; 39 48 40 49 /* PMU-FW return status codes */ ··· 57 48 XST_PM_ABORT_SUSPEND, 58 49 }; 59 50 51 + enum pm_ioctl_id { 52 + IOCTL_SET_PLL_FRAC_MODE = 8, 53 + IOCTL_GET_PLL_FRAC_MODE, 54 + IOCTL_SET_PLL_FRAC_DATA, 55 + IOCTL_GET_PLL_FRAC_DATA, 56 + }; 57 + 60 58 enum pm_query_id { 61 59 PM_QID_INVALID, 60 + PM_QID_CLOCK_GET_NAME, 61 + PM_QID_CLOCK_GET_TOPOLOGY, 62 + PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, 63 + PM_QID_CLOCK_GET_PARENTS, 64 + PM_QID_CLOCK_GET_ATTRIBUTES, 62 65 }; 63 66 64 67 /** ··· 90 69 struct zynqmp_eemi_ops { 91 70 int (*get_api_version)(u32 *version); 92 71 int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out); 72 + int (*clock_enable)(u32 clock_id); 73 + int (*clock_disable)(u32 clock_id); 74 + int (*clock_getstate)(u32 clock_id, u32 *state); 75 + int (*clock_setdivider)(u32 clock_id, u32 divider); 76 + int (*clock_getdivider)(u32 clock_id, u32 *divider); 77 + int (*clock_setrate)(u32 clock_id, u64 rate); 78 + int (*clock_getrate)(u32 clock_id, u64 *rate); 79 + int (*clock_setparent)(u32 clock_id, u32 parent_id); 80 + int (*clock_getparent)(u32 clock_id, u32 *parent_id); 93 81 }; 94 82 95 83 #if IS_REACHABLE(CONFIG_ARCH_ZYNQMP)