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