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

clk: zynqmp: use structs for clk query responses

The driver retrieves the clock tree by querying the ATF for the clock
names, the clock topology, the parents and other attributes. The driver
needs to unmarshal the responses.

The definition of the fields in the firmware responses to the queries is
inconsistent. Some are specified as a mask, some as a shift, and by the
length of the previous field.

Define C structs for the entire firmware responses to avoid passing
pointers to arrays of an implicit size and make the format of the
responses to the queries obvious.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Reviewed-by: Jolly Shah <jolly.shah@xilinx.com>
[sboyd@kernel.org: Drop 0 initializers because sparse complains]
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Michael Tretter and committed by
Stephen Boyd
5852b136 c06e6440

+99 -77
-6
drivers/clk/zynqmp/clk-zynqmp.h
··· 10 10 11 11 #include <linux/firmware/xlnx-zynqmp.h> 12 12 13 - /* Clock APIs payload parameters */ 14 - #define CLK_GET_NAME_RESP_LEN 16 15 - #define CLK_GET_TOPOLOGY_RESP_WORDS 3 16 - #define CLK_GET_PARENTS_RESP_WORDS 3 17 - #define CLK_GET_ATTR_RESP_WORDS 1 18 - 19 13 enum topology_type { 20 14 TYPE_INVALID, 21 15 TYPE_MUX,
+99 -71
drivers/clk/zynqmp/clkc.c
··· 21 21 #define MAX_NODES 6 22 22 #define MAX_NAME_LEN 50 23 23 24 - #define CLK_TYPE_SHIFT 2 25 - 26 - #define PM_API_PAYLOAD_LEN 3 27 - 28 - #define NA_PARENT 0xFFFFFFFF 29 - #define DUMMY_PARENT 0xFFFFFFFE 30 - 31 - #define CLK_TYPE_FIELD_LEN 4 32 - #define CLK_TOPOLOGY_NODE_OFFSET 16 33 - #define NODES_PER_RESP 3 34 - 35 - #define CLK_TYPE_FIELD_MASK 0xF 36 - #define CLK_FLAG_FIELD_MASK GENMASK(21, 8) 37 - #define CLK_TYPE_FLAG_FIELD_MASK GENMASK(31, 24) 38 - 39 - #define CLK_PARENTS_ID_LEN 16 40 - #define CLK_PARENTS_ID_MASK 0xFFFF 41 - 42 24 /* Flags for parents */ 43 25 #define PARENT_CLK_SELF 0 44 26 #define PARENT_CLK_NODE1 1 ··· 34 52 #define END_OF_PARENTS 1 35 53 #define RESERVED_CLK_NAME "" 36 54 37 - #define CLK_VALID_MASK 0x1 38 - #define NODE_CLASS_SHIFT 26U 39 - #define NODE_SUBCLASS_SHIFT 20U 40 - #define NODE_TYPE_SHIFT 14U 41 - #define NODE_INDEX_SHIFT 0U 55 + #define CLK_GET_NAME_RESP_LEN 16 56 + #define CLK_GET_TOPOLOGY_RESP_WORDS 3 57 + #define CLK_GET_PARENTS_RESP_WORDS 3 58 + #define CLK_GET_ATTR_RESP_WORDS 1 42 59 43 60 enum clk_type { 44 61 CLK_TYPE_OUTPUT, ··· 76 95 struct clock_parent parent[MAX_PARENT]; 77 96 u32 num_parents; 78 97 u32 clk_id; 98 + }; 99 + 100 + struct name_resp { 101 + char name[CLK_GET_NAME_RESP_LEN]; 102 + }; 103 + 104 + struct topology_resp { 105 + #define CLK_TOPOLOGY_TYPE GENMASK(3, 0) 106 + #define CLK_TOPOLOGY_FLAGS GENMASK(23, 8) 107 + #define CLK_TOPOLOGY_TYPE_FLAGS GENMASK(31, 24) 108 + u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS]; 109 + }; 110 + 111 + struct parents_resp { 112 + #define NA_PARENT 0xFFFFFFFF 113 + #define DUMMY_PARENT 0xFFFFFFFE 114 + #define CLK_PARENTS_ID GENMASK(15, 0) 115 + #define CLK_PARENTS_FLAGS GENMASK(31, 16) 116 + u32 parents[CLK_GET_PARENTS_RESP_WORDS]; 117 + }; 118 + 119 + struct attr_resp { 120 + #define CLK_ATTR_VALID BIT(0) 121 + #define CLK_ATTR_TYPE BIT(2) 122 + #define CLK_ATTR_NODE_INDEX GENMASK(13, 0) 123 + #define CLK_ATTR_NODE_TYPE GENMASK(19, 14) 124 + #define CLK_ATTR_NODE_SUBCLASS GENMASK(25, 20) 125 + #define CLK_ATTR_NODE_CLASS GENMASK(31, 26) 126 + u32 attr[CLK_GET_ATTR_RESP_WORDS]; 79 127 }; 80 128 81 129 static const char clk_type_postfix[][10] = { ··· 215 205 /** 216 206 * zynqmp_pm_clock_get_name() - Get the name of clock for given id 217 207 * @clock_id: ID of the clock to be queried 218 - * @name: Name of given clock 208 + * @response: Name of the clock with the given id 219 209 * 220 210 * This function is used to get name of clock specified by given 221 211 * clock ID. 222 212 * 223 - * Return: Returns 0, in case of error name would be 0 213 + * Return: Returns 0 224 214 */ 225 - static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) 215 + static int zynqmp_pm_clock_get_name(u32 clock_id, 216 + struct name_resp *response) 226 217 { 227 218 struct zynqmp_pm_query_data qdata = {0}; 228 219 u32 ret_payload[PAYLOAD_ARG_CNT]; ··· 232 221 qdata.arg1 = clock_id; 233 222 234 223 eemi_ops->query_data(qdata, ret_payload); 235 - memcpy(name, ret_payload, CLK_GET_NAME_RESP_LEN); 224 + memcpy(response, ret_payload, sizeof(*response)); 236 225 237 226 return 0; 238 227 } ··· 241 230 * zynqmp_pm_clock_get_topology() - Get the topology of clock for given id 242 231 * @clock_id: ID of the clock to be queried 243 232 * @index: Node index of clock topology 244 - * @topology: Buffer to store nodes in topology and flags 233 + * @response: Buffer used for the topology response 245 234 * 246 235 * This function is used to get topology information for the clock 247 236 * specified by given clock ID. ··· 254 243 * 255 244 * Return: 0 on success else error+reason 256 245 */ 257 - static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology) 246 + static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, 247 + struct topology_resp *response) 258 248 { 259 249 struct zynqmp_pm_query_data qdata = {0}; 260 250 u32 ret_payload[PAYLOAD_ARG_CNT]; ··· 266 254 qdata.arg2 = index; 267 255 268 256 ret = eemi_ops->query_data(qdata, ret_payload); 269 - memcpy(topology, &ret_payload[1], CLK_GET_TOPOLOGY_RESP_WORDS * 4); 257 + memcpy(response, &ret_payload[1], sizeof(*response)); 270 258 271 259 return ret; 272 260 } ··· 315 303 * zynqmp_pm_clock_get_parents() - Get the first 3 parents of clock for given id 316 304 * @clock_id: Clock ID 317 305 * @index: Parent index 318 - * @parents: 3 parents of the given clock 306 + * @response: Parents of the given clock 319 307 * 320 308 * This function is used to get 3 parents for the clock specified by 321 309 * given clock ID. ··· 328 316 * 329 317 * Return: 0 on success else error+reason 330 318 */ 331 - static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents) 319 + static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, 320 + struct parents_resp *response) 332 321 { 333 322 struct zynqmp_pm_query_data qdata = {0}; 334 323 u32 ret_payload[PAYLOAD_ARG_CNT]; ··· 340 327 qdata.arg2 = index; 341 328 342 329 ret = eemi_ops->query_data(qdata, ret_payload); 343 - memcpy(parents, &ret_payload[1], CLK_GET_PARENTS_RESP_WORDS * 4); 330 + memcpy(response, &ret_payload[1], sizeof(*response)); 344 331 345 332 return ret; 346 333 } ··· 348 335 /** 349 336 * zynqmp_pm_clock_get_attributes() - Get the attributes of clock for given id 350 337 * @clock_id: Clock ID 351 - * @attr: Clock attributes 338 + * @response: Clock attributes response 352 339 * 353 340 * This function is used to get clock's attributes(e.g. valid, clock type, etc). 354 341 * 355 342 * Return: 0 on success else error+reason 356 343 */ 357 - static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr) 344 + static int zynqmp_pm_clock_get_attributes(u32 clock_id, 345 + struct attr_resp *response) 358 346 { 359 347 struct zynqmp_pm_query_data qdata = {0}; 360 348 u32 ret_payload[PAYLOAD_ARG_CNT]; ··· 365 351 qdata.arg1 = clock_id; 366 352 367 353 ret = eemi_ops->query_data(qdata, ret_payload); 368 - memcpy(attr, &ret_payload[1], CLK_GET_ATTR_RESP_WORDS * 4); 354 + memcpy(response, &ret_payload[1], sizeof(*response)); 369 355 370 356 return ret; 371 357 } ··· 374 360 * __zynqmp_clock_get_topology() - Get topology data of clock from firmware 375 361 * response data 376 362 * @topology: Clock topology 377 - * @data: Clock topology data received from firmware 363 + * @response: Clock topology data received from firmware 378 364 * @nnodes: Number of nodes 379 365 * 380 366 * Return: 0 on success else error+reason 381 367 */ 382 368 static int __zynqmp_clock_get_topology(struct clock_topology *topology, 383 - u32 *data, u32 *nnodes) 369 + struct topology_resp *response, 370 + u32 *nnodes) 384 371 { 385 372 int i; 373 + u32 type; 386 374 387 - for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { 388 - if (!(data[i] & CLK_TYPE_FIELD_MASK)) 375 + for (i = 0; i < ARRAY_SIZE(response->topology); i++) { 376 + type = FIELD_GET(CLK_TOPOLOGY_TYPE, response->topology[i]); 377 + if (type == TYPE_INVALID) 389 378 return END_OF_TOPOLOGY_NODE; 390 - topology[*nnodes].type = data[i] & CLK_TYPE_FIELD_MASK; 391 - topology[*nnodes].flag = FIELD_GET(CLK_FLAG_FIELD_MASK, 392 - data[i]); 379 + topology[*nnodes].type = type; 380 + topology[*nnodes].flag = FIELD_GET(CLK_TOPOLOGY_FLAGS, 381 + response->topology[i]); 393 382 topology[*nnodes].type_flag = 394 - FIELD_GET(CLK_TYPE_FLAG_FIELD_MASK, data[i]); 383 + FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS, 384 + response->topology[i]); 395 385 (*nnodes)++; 396 386 } 397 387 ··· 416 398 u32 *num_nodes) 417 399 { 418 400 int j, ret; 419 - u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; 401 + struct topology_resp response = { }; 420 402 421 403 *num_nodes = 0; 422 - for (j = 0; j <= MAX_NODES; j += 3) { 404 + for (j = 0; j <= MAX_NODES; j += ARRAY_SIZE(response.topology)) { 423 405 ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j, 424 - pm_resp); 406 + &response); 425 407 if (ret) 426 408 return ret; 427 - ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes); 409 + ret = __zynqmp_clock_get_topology(topology, &response, 410 + num_nodes); 428 411 if (ret == END_OF_TOPOLOGY_NODE) 429 412 return 0; 430 413 } ··· 437 418 * __zynqmp_clock_get_parents() - Get parents info of clock from firmware 438 419 * response data 439 420 * @parents: Clock parents 440 - * @data: Clock parents data received from firmware 421 + * @response: Clock parents data received from firmware 441 422 * @nparent: Number of parent 442 423 * 443 424 * Return: 0 on success else error+reason 444 425 */ 445 - static int __zynqmp_clock_get_parents(struct clock_parent *parents, u32 *data, 426 + static int __zynqmp_clock_get_parents(struct clock_parent *parents, 427 + struct parents_resp *response, 446 428 u32 *nparent) 447 429 { 448 430 int i; 449 431 struct clock_parent *parent; 450 432 451 - for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { 452 - if (data[i] == NA_PARENT) 433 + for (i = 0; i < ARRAY_SIZE(response->parents); i++) { 434 + if (response->parents[i] == NA_PARENT) 453 435 return END_OF_PARENTS; 454 436 455 437 parent = &parents[i]; 456 - parent->id = data[i] & CLK_PARENTS_ID_MASK; 457 - if (data[i] == DUMMY_PARENT) { 438 + parent->id = FIELD_GET(CLK_PARENTS_ID, response->parents[i]); 439 + if (response->parents[i] == DUMMY_PARENT) { 458 440 strcpy(parent->name, "dummy_name"); 459 441 parent->flag = 0; 460 442 } else { 461 - parent->flag = data[i] >> CLK_PARENTS_ID_LEN; 443 + parent->flag = FIELD_GET(CLK_PARENTS_FLAGS, 444 + response->parents[i]); 462 445 if (zynqmp_get_clock_name(parent->id, parent->name)) 463 446 continue; 464 447 } ··· 482 461 u32 *num_parents) 483 462 { 484 463 int j = 0, ret; 485 - u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; 464 + struct parents_resp response = { }; 486 465 487 466 *num_parents = 0; 488 467 do { 489 468 /* Get parents from firmware */ 490 469 ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j, 491 - pm_resp); 470 + &response); 492 471 if (ret) 493 472 return ret; 494 473 495 - ret = __zynqmp_clock_get_parents(&parents[j], pm_resp, 474 + ret = __zynqmp_clock_get_parents(&parents[j], &response, 496 475 num_parents); 497 476 if (ret == END_OF_PARENTS) 498 477 return 0; 499 - j += PM_API_PAYLOAD_LEN; 478 + j += ARRAY_SIZE(response.parents); 500 479 } while (*num_parents <= MAX_PARENT); 501 480 502 481 return 0; ··· 652 631 static void zynqmp_get_clock_info(void) 653 632 { 654 633 int i, ret; 655 - u32 attr, type = 0, nodetype, subclass, class; 634 + u32 type = 0; 635 + u32 nodetype, subclass, class; 636 + struct attr_resp attr; 637 + struct name_resp name; 656 638 657 639 for (i = 0; i < clock_max_idx; i++) { 658 640 ret = zynqmp_pm_clock_get_attributes(i, &attr); 659 641 if (ret) 660 642 continue; 661 643 662 - clock[i].valid = attr & CLK_VALID_MASK; 663 - clock[i].type = ((attr >> CLK_TYPE_SHIFT) & 0x1) ? 664 - CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; 665 - nodetype = (attr >> NODE_TYPE_SHIFT) & 0x3F; 666 - subclass = (attr >> NODE_SUBCLASS_SHIFT) & 0x3F; 667 - class = (attr >> NODE_CLASS_SHIFT) & 0x3F; 644 + clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]); 645 + clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ? 646 + CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; 668 647 669 - clock[i].clk_id = (class << NODE_CLASS_SHIFT) | 670 - (subclass << NODE_SUBCLASS_SHIFT) | 671 - (nodetype << NODE_TYPE_SHIFT) | 672 - (i << NODE_INDEX_SHIFT); 648 + nodetype = FIELD_GET(CLK_ATTR_NODE_TYPE, attr.attr[0]); 649 + subclass = FIELD_GET(CLK_ATTR_NODE_SUBCLASS, attr.attr[0]); 650 + class = FIELD_GET(CLK_ATTR_NODE_CLASS, attr.attr[0]); 673 651 674 - zynqmp_pm_clock_get_name(clock[i].clk_id, clock[i].clk_name); 652 + clock[i].clk_id = FIELD_PREP(CLK_ATTR_NODE_CLASS, class) | 653 + FIELD_PREP(CLK_ATTR_NODE_SUBCLASS, subclass) | 654 + FIELD_PREP(CLK_ATTR_NODE_TYPE, nodetype) | 655 + FIELD_PREP(CLK_ATTR_NODE_INDEX, i); 656 + 657 + zynqmp_pm_clock_get_name(clock[i].clk_id, &name); 658 + if (!strcmp(name.name, RESERVED_CLK_NAME)) 659 + continue; 660 + strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN); 675 661 } 676 662 677 663 /* Get topology of all clock */