linux/drivers/clk/zynqmp/clkc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Zynq UltraScale+ MPSoC clock controller
   4 *
   5 *  Copyright (C) 2016-2019 Xilinx
   6 *
   7 * Based on drivers/clk/zynq/clkc.c
   8 */
   9
  10#include <linux/bitfield.h>
  11#include <linux/clk.h>
  12#include <linux/clk-provider.h>
  13#include <linux/module.h>
  14#include <linux/of_platform.h>
  15#include <linux/slab.h>
  16#include <linux/string.h>
  17
  18#include "clk-zynqmp.h"
  19
  20#define MAX_PARENT                      100
  21#define MAX_NODES                       6
  22#define MAX_NAME_LEN                    50
  23
  24/* Flags for parents */
  25#define PARENT_CLK_SELF                 0
  26#define PARENT_CLK_NODE1                1
  27#define PARENT_CLK_NODE2                2
  28#define PARENT_CLK_NODE3                3
  29#define PARENT_CLK_NODE4                4
  30#define PARENT_CLK_EXTERNAL             5
  31
  32#define END_OF_CLK_NAME                 "END_OF_CLK"
  33#define END_OF_TOPOLOGY_NODE            1
  34#define END_OF_PARENTS                  1
  35#define RESERVED_CLK_NAME               ""
  36
  37#define CLK_GET_NAME_RESP_LEN           16
  38#define CLK_GET_TOPOLOGY_RESP_WORDS     3
  39#define CLK_GET_PARENTS_RESP_WORDS      3
  40#define CLK_GET_ATTR_RESP_WORDS         1
  41
  42enum clk_type {
  43        CLK_TYPE_OUTPUT,
  44        CLK_TYPE_EXTERNAL,
  45};
  46
  47/**
  48 * struct clock_parent - Clock parent
  49 * @name:       Parent name
  50 * @id:         Parent clock ID
  51 * @flag:       Parent flags
  52 */
  53struct clock_parent {
  54        char name[MAX_NAME_LEN];
  55        int id;
  56        u32 flag;
  57};
  58
  59/**
  60 * struct zynqmp_clock - Clock
  61 * @clk_name:           Clock name
  62 * @valid:              Validity flag of clock
  63 * @type:               Clock type (Output/External)
  64 * @node:               Clock topology nodes
  65 * @num_nodes:          Number of nodes present in topology
  66 * @parent:             Parent of clock
  67 * @num_parents:        Number of parents of clock
  68 * @clk_id:             Clock id
  69 */
  70struct zynqmp_clock {
  71        char clk_name[MAX_NAME_LEN];
  72        u32 valid;
  73        enum clk_type type;
  74        struct clock_topology node[MAX_NODES];
  75        u32 num_nodes;
  76        struct clock_parent parent[MAX_PARENT];
  77        u32 num_parents;
  78        u32 clk_id;
  79};
  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_CUSTOM_TYPE_FLAGS  GENMASK(7, 4)
  88#define CLK_TOPOLOGY_FLAGS              GENMASK(23, 8)
  89#define CLK_TOPOLOGY_TYPE_FLAGS         GENMASK(31, 24)
  90        u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS];
  91};
  92
  93struct parents_resp {
  94#define NA_PARENT                       0xFFFFFFFF
  95#define DUMMY_PARENT                    0xFFFFFFFE
  96#define CLK_PARENTS_ID                  GENMASK(15, 0)
  97#define CLK_PARENTS_FLAGS               GENMASK(31, 16)
  98        u32 parents[CLK_GET_PARENTS_RESP_WORDS];
  99};
 100
 101struct attr_resp {
 102#define CLK_ATTR_VALID                  BIT(0)
 103#define CLK_ATTR_TYPE                   BIT(2)
 104#define CLK_ATTR_NODE_INDEX             GENMASK(13, 0)
 105#define CLK_ATTR_NODE_TYPE              GENMASK(19, 14)
 106#define CLK_ATTR_NODE_SUBCLASS          GENMASK(25, 20)
 107#define CLK_ATTR_NODE_CLASS             GENMASK(31, 26)
 108        u32 attr[CLK_GET_ATTR_RESP_WORDS];
 109};
 110
 111static const char clk_type_postfix[][10] = {
 112        [TYPE_INVALID] = "",
 113        [TYPE_MUX] = "_mux",
 114        [TYPE_GATE] = "",
 115        [TYPE_DIV1] = "_div1",
 116        [TYPE_DIV2] = "_div2",
 117        [TYPE_FIXEDFACTOR] = "_ff",
 118        [TYPE_PLL] = ""
 119};
 120
 121static struct clk_hw *(* const clk_topology[]) (const char *name, u32 clk_id,
 122                                        const char * const *parents,
 123                                        u8 num_parents,
 124                                        const struct clock_topology *nodes)
 125                                        = {
 126        [TYPE_INVALID] = NULL,
 127        [TYPE_MUX] = zynqmp_clk_register_mux,
 128        [TYPE_PLL] = zynqmp_clk_register_pll,
 129        [TYPE_FIXEDFACTOR] = zynqmp_clk_register_fixed_factor,
 130        [TYPE_DIV1] = zynqmp_clk_register_divider,
 131        [TYPE_DIV2] = zynqmp_clk_register_divider,
 132        [TYPE_GATE] = zynqmp_clk_register_gate
 133};
 134
 135static struct zynqmp_clock *clock;
 136static struct clk_hw_onecell_data *zynqmp_data;
 137static unsigned int clock_max_idx;
 138
 139/**
 140 * zynqmp_is_valid_clock() - Check whether clock is valid or not
 141 * @clk_id:     Clock index
 142 *
 143 * Return: 1 if clock is valid, 0 if clock is invalid else error code
 144 */
 145static inline int zynqmp_is_valid_clock(u32 clk_id)
 146{
 147        if (clk_id >= clock_max_idx)
 148                return -ENODEV;
 149
 150        return clock[clk_id].valid;
 151}
 152
 153/**
 154 * zynqmp_get_clock_name() - Get name of clock from Clock index
 155 * @clk_id:     Clock index
 156 * @clk_name:   Name of clock
 157 *
 158 * Return: 0 on success else error code
 159 */
 160static int zynqmp_get_clock_name(u32 clk_id, char *clk_name)
 161{
 162        int ret;
 163
 164        ret = zynqmp_is_valid_clock(clk_id);
 165        if (ret == 1) {
 166                strncpy(clk_name, clock[clk_id].clk_name, MAX_NAME_LEN);
 167                return 0;
 168        }
 169
 170        return ret == 0 ? -EINVAL : ret;
 171}
 172
 173/**
 174 * zynqmp_get_clock_type() - Get type of clock
 175 * @clk_id:     Clock index
 176 * @type:       Clock type: CLK_TYPE_OUTPUT or CLK_TYPE_EXTERNAL
 177 *
 178 * Return: 0 on success else error code
 179 */
 180static int zynqmp_get_clock_type(u32 clk_id, u32 *type)
 181{
 182        int ret;
 183
 184        ret = zynqmp_is_valid_clock(clk_id);
 185        if (ret == 1) {
 186                *type = clock[clk_id].type;
 187                return 0;
 188        }
 189
 190        return ret == 0 ? -EINVAL : ret;
 191}
 192
 193/**
 194 * zynqmp_pm_clock_get_num_clocks() - Get number of clocks in system
 195 * @nclocks:    Number of clocks in system/board.
 196 *
 197 * Call firmware API to get number of clocks.
 198 *
 199 * Return: 0 on success else error code.
 200 */
 201static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks)
 202{
 203        struct zynqmp_pm_query_data qdata = {0};
 204        u32 ret_payload[PAYLOAD_ARG_CNT];
 205        int ret;
 206
 207        qdata.qid = PM_QID_CLOCK_GET_NUM_CLOCKS;
 208
 209        ret = zynqmp_pm_query_data(qdata, ret_payload);
 210        *nclocks = ret_payload[1];
 211
 212        return ret;
 213}
 214
 215/**
 216 * zynqmp_pm_clock_get_name() - Get the name of clock for given id
 217 * @clock_id:   ID of the clock to be queried
 218 * @response:   Name of the clock with the given id
 219 *
 220 * This function is used to get name of clock specified by given
 221 * clock ID.
 222 *
 223 * Return: Returns 0
 224 */
 225static int zynqmp_pm_clock_get_name(u32 clock_id,
 226                                    struct name_resp *response)
 227{
 228        struct zynqmp_pm_query_data qdata = {0};
 229        u32 ret_payload[PAYLOAD_ARG_CNT];
 230
 231        qdata.qid = PM_QID_CLOCK_GET_NAME;
 232        qdata.arg1 = clock_id;
 233
 234        zynqmp_pm_query_data(qdata, ret_payload);
 235        memcpy(response, ret_payload, sizeof(*response));
 236
 237        return 0;
 238}
 239
 240/**
 241 * zynqmp_pm_clock_get_topology() - Get the topology of clock for given id
 242 * @clock_id:   ID of the clock to be queried
 243 * @index:      Node index of clock topology
 244 * @response:   Buffer used for the topology response
 245 *
 246 * This function is used to get topology information for the clock
 247 * specified by given clock ID.
 248 *
 249 * This API will return 3 node of topology with a single response. To get
 250 * other nodes, master should call same API in loop with new
 251 * index till error is returned. E.g First call should have
 252 * index 0 which will return nodes 0,1 and 2. Next call, index
 253 * should be 3 which will return nodes 3,4 and 5 and so on.
 254 *
 255 * Return: 0 on success else error+reason
 256 */
 257static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index,
 258                                        struct topology_resp *response)
 259{
 260        struct zynqmp_pm_query_data qdata = {0};
 261        u32 ret_payload[PAYLOAD_ARG_CNT];
 262        int ret;
 263
 264        qdata.qid = PM_QID_CLOCK_GET_TOPOLOGY;
 265        qdata.arg1 = clock_id;
 266        qdata.arg2 = index;
 267
 268        ret = zynqmp_pm_query_data(qdata, ret_payload);
 269        memcpy(response, &ret_payload[1], sizeof(*response));
 270
 271        return ret;
 272}
 273
 274/**
 275 * zynqmp_clk_register_fixed_factor() - Register fixed factor with the
 276 *                                      clock framework
 277 * @name:               Name of this clock
 278 * @clk_id:             Clock ID
 279 * @parents:            Name of this clock's parents
 280 * @num_parents:        Number of parents
 281 * @nodes:              Clock topology node
 282 *
 283 * Return: clock hardware to the registered clock
 284 */
 285struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
 286                                        const char * const *parents,
 287                                        u8 num_parents,
 288                                        const struct clock_topology *nodes)
 289{
 290        u32 mult, div;
 291        struct clk_hw *hw;
 292        struct zynqmp_pm_query_data qdata = {0};
 293        u32 ret_payload[PAYLOAD_ARG_CNT];
 294        int ret;
 295
 296        qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS;
 297        qdata.arg1 = clk_id;
 298
 299        ret = zynqmp_pm_query_data(qdata, ret_payload);
 300        if (ret)
 301                return ERR_PTR(ret);
 302
 303        mult = ret_payload[1];
 304        div = ret_payload[2];
 305
 306        hw = clk_hw_register_fixed_factor(NULL, name,
 307                                          parents[0],
 308                                          nodes->flag, mult,
 309                                          div);
 310
 311        return hw;
 312}
 313
 314/**
 315 * zynqmp_pm_clock_get_parents() - Get the first 3 parents of clock for given id
 316 * @clock_id:   Clock ID
 317 * @index:      Parent index
 318 * @response:   Parents of the given clock
 319 *
 320 * This function is used to get 3 parents for the clock specified by
 321 * given clock ID.
 322 *
 323 * This API will return 3 parents with a single response. To get
 324 * other parents, master should call same API in loop with new
 325 * parent index till error is returned. E.g First call should have
 326 * index 0 which will return parents 0,1 and 2. Next call, index
 327 * should be 3 which will return parent 3,4 and 5 and so on.
 328 *
 329 * Return: 0 on success else error+reason
 330 */
 331static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index,
 332                                       struct parents_resp *response)
 333{
 334        struct zynqmp_pm_query_data qdata = {0};
 335        u32 ret_payload[PAYLOAD_ARG_CNT];
 336        int ret;
 337
 338        qdata.qid = PM_QID_CLOCK_GET_PARENTS;
 339        qdata.arg1 = clock_id;
 340        qdata.arg2 = index;
 341
 342        ret = zynqmp_pm_query_data(qdata, ret_payload);
 343        memcpy(response, &ret_payload[1], sizeof(*response));
 344
 345        return ret;
 346}
 347
 348/**
 349 * zynqmp_pm_clock_get_attributes() - Get the attributes of clock for given id
 350 * @clock_id:   Clock ID
 351 * @response:   Clock attributes response
 352 *
 353 * This function is used to get clock's attributes(e.g. valid, clock type, etc).
 354 *
 355 * Return: 0 on success else error+reason
 356 */
 357static int zynqmp_pm_clock_get_attributes(u32 clock_id,
 358                                          struct attr_resp *response)
 359{
 360        struct zynqmp_pm_query_data qdata = {0};
 361        u32 ret_payload[PAYLOAD_ARG_CNT];
 362        int ret;
 363
 364        qdata.qid = PM_QID_CLOCK_GET_ATTRIBUTES;
 365        qdata.arg1 = clock_id;
 366
 367        ret = zynqmp_pm_query_data(qdata, ret_payload);
 368        memcpy(response, &ret_payload[1], sizeof(*response));
 369
 370        return ret;
 371}
 372
 373/**
 374 * __zynqmp_clock_get_topology() - Get topology data of clock from firmware
 375 *                                 response data
 376 * @topology:           Clock topology
 377 * @response:           Clock topology data received from firmware
 378 * @nnodes:             Number of nodes
 379 *
 380 * Return: 0 on success else error+reason
 381 */
 382static int __zynqmp_clock_get_topology(struct clock_topology *topology,
 383                                       struct topology_resp *response,
 384                                       u32 *nnodes)
 385{
 386        int i;
 387        u32 type;
 388
 389        for (i = 0; i < ARRAY_SIZE(response->topology); i++) {
 390                type = FIELD_GET(CLK_TOPOLOGY_TYPE, response->topology[i]);
 391                if (type == TYPE_INVALID)
 392                        return END_OF_TOPOLOGY_NODE;
 393                topology[*nnodes].type = type;
 394                topology[*nnodes].flag = FIELD_GET(CLK_TOPOLOGY_FLAGS,
 395                                                   response->topology[i]);
 396                topology[*nnodes].type_flag =
 397                                FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS,
 398                                          response->topology[i]);
 399                topology[*nnodes].custom_type_flag =
 400                        FIELD_GET(CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS,
 401                                  response->topology[i]);
 402                (*nnodes)++;
 403        }
 404
 405        return 0;
 406}
 407
 408/**
 409 * zynqmp_clock_get_topology() - Get topology of clock from firmware using
 410 *                               PM_API
 411 * @clk_id:             Clock index
 412 * @topology:           Clock topology
 413 * @num_nodes:          Number of nodes
 414 *
 415 * Return: 0 on success else error+reason
 416 */
 417static int zynqmp_clock_get_topology(u32 clk_id,
 418                                     struct clock_topology *topology,
 419                                     u32 *num_nodes)
 420{
 421        int j, ret;
 422        struct topology_resp response = { };
 423
 424        *num_nodes = 0;
 425        for (j = 0; j <= MAX_NODES; j += ARRAY_SIZE(response.topology)) {
 426                ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j,
 427                                                   &response);
 428                if (ret)
 429                        return ret;
 430                ret = __zynqmp_clock_get_topology(topology, &response,
 431                                                  num_nodes);
 432                if (ret == END_OF_TOPOLOGY_NODE)
 433                        return 0;
 434        }
 435
 436        return 0;
 437}
 438
 439/**
 440 * __zynqmp_clock_get_parents() - Get parents info of clock from firmware
 441 *                                 response data
 442 * @parents:            Clock parents
 443 * @response:           Clock parents data received from firmware
 444 * @nparent:            Number of parent
 445 *
 446 * Return: 0 on success else error+reason
 447 */
 448static int __zynqmp_clock_get_parents(struct clock_parent *parents,
 449                                      struct parents_resp *response,
 450                                      u32 *nparent)
 451{
 452        int i;
 453        struct clock_parent *parent;
 454
 455        for (i = 0; i < ARRAY_SIZE(response->parents); i++) {
 456                if (response->parents[i] == NA_PARENT)
 457                        return END_OF_PARENTS;
 458
 459                parent = &parents[i];
 460                parent->id = FIELD_GET(CLK_PARENTS_ID, response->parents[i]);
 461                if (response->parents[i] == DUMMY_PARENT) {
 462                        strcpy(parent->name, "dummy_name");
 463                        parent->flag = 0;
 464                } else {
 465                        parent->flag = FIELD_GET(CLK_PARENTS_FLAGS,
 466                                                 response->parents[i]);
 467                        if (zynqmp_get_clock_name(parent->id, parent->name))
 468                                continue;
 469                }
 470                *nparent += 1;
 471        }
 472
 473        return 0;
 474}
 475
 476/**
 477 * zynqmp_clock_get_parents() - Get parents info from firmware using PM_API
 478 * @clk_id:             Clock index
 479 * @parents:            Clock parents
 480 * @num_parents:        Total number of parents
 481 *
 482 * Return: 0 on success else error+reason
 483 */
 484static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents,
 485                                    u32 *num_parents)
 486{
 487        int j = 0, ret;
 488        struct parents_resp response = { };
 489
 490        *num_parents = 0;
 491        do {
 492                /* Get parents from firmware */
 493                ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j,
 494                                                  &response);
 495                if (ret)
 496                        return ret;
 497
 498                ret = __zynqmp_clock_get_parents(&parents[j], &response,
 499                                                 num_parents);
 500                if (ret == END_OF_PARENTS)
 501                        return 0;
 502                j += ARRAY_SIZE(response.parents);
 503        } while (*num_parents <= MAX_PARENT);
 504
 505        return 0;
 506}
 507
 508/**
 509 * zynqmp_get_parent_list() - Create list of parents name
 510 * @np:                 Device node
 511 * @clk_id:             Clock index
 512 * @parent_list:        List of parent's name
 513 * @num_parents:        Total number of parents
 514 *
 515 * Return: 0 on success else error+reason
 516 */
 517static int zynqmp_get_parent_list(struct device_node *np, u32 clk_id,
 518                                  const char **parent_list, u32 *num_parents)
 519{
 520        int i = 0, ret;
 521        u32 total_parents = clock[clk_id].num_parents;
 522        struct clock_topology *clk_nodes;
 523        struct clock_parent *parents;
 524
 525        clk_nodes = clock[clk_id].node;
 526        parents = clock[clk_id].parent;
 527
 528        for (i = 0; i < total_parents; i++) {
 529                if (!parents[i].flag) {
 530                        parent_list[i] = parents[i].name;
 531                } else if (parents[i].flag == PARENT_CLK_EXTERNAL) {
 532                        ret = of_property_match_string(np, "clock-names",
 533                                                       parents[i].name);
 534                        if (ret < 0)
 535                                strcpy(parents[i].name, "dummy_name");
 536                        parent_list[i] = parents[i].name;
 537                } else {
 538                        strcat(parents[i].name,
 539                               clk_type_postfix[clk_nodes[parents[i].flag - 1].
 540                               type]);
 541                        parent_list[i] = parents[i].name;
 542                }
 543        }
 544
 545        *num_parents = total_parents;
 546        return 0;
 547}
 548
 549/**
 550 * zynqmp_register_clk_topology() - Register clock topology
 551 * @clk_id:             Clock index
 552 * @clk_name:           Clock Name
 553 * @num_parents:        Total number of parents
 554 * @parent_names:       List of parents name
 555 *
 556 * Return: Returns either clock hardware or error+reason
 557 */
 558static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
 559                                                   int num_parents,
 560                                                   const char **parent_names)
 561{
 562        int j;
 563        u32 num_nodes, clk_dev_id;
 564        char *clk_out[MAX_NODES];
 565        struct clock_topology *nodes;
 566        struct clk_hw *hw = NULL;
 567
 568        nodes = clock[clk_id].node;
 569        num_nodes = clock[clk_id].num_nodes;
 570        clk_dev_id = clock[clk_id].clk_id;
 571
 572        for (j = 0; j < num_nodes; j++) {
 573                /*
 574                 * Clock name received from firmware is output clock name.
 575                 * Intermediate clock names are postfixed with type of clock.
 576                 */
 577                if (j != (num_nodes - 1)) {
 578                        clk_out[j] = kasprintf(GFP_KERNEL, "%s%s", clk_name,
 579                                            clk_type_postfix[nodes[j].type]);
 580                } else {
 581                        clk_out[j] = kasprintf(GFP_KERNEL, "%s", clk_name);
 582                }
 583
 584                if (!clk_topology[nodes[j].type])
 585                        continue;
 586
 587                hw = (*clk_topology[nodes[j].type])(clk_out[j], clk_dev_id,
 588                                                    parent_names,
 589                                                    num_parents,
 590                                                    &nodes[j]);
 591                if (IS_ERR(hw))
 592                        pr_warn_once("%s() 0x%x: %s register fail with %ld\n",
 593                                     __func__,  clk_dev_id, clk_name,
 594                                     PTR_ERR(hw));
 595
 596                parent_names[0] = clk_out[j];
 597        }
 598
 599        for (j = 0; j < num_nodes; j++)
 600                kfree(clk_out[j]);
 601
 602        return hw;
 603}
 604
 605/**
 606 * zynqmp_register_clocks() - Register clocks
 607 * @np:         Device node
 608 *
 609 * Return: 0 on success else error code
 610 */
 611static int zynqmp_register_clocks(struct device_node *np)
 612{
 613        int ret;
 614        u32 i, total_parents = 0, type = 0;
 615        const char *parent_names[MAX_PARENT];
 616
 617        for (i = 0; i < clock_max_idx; i++) {
 618                char clk_name[MAX_NAME_LEN];
 619
 620                /* get clock name, continue to next clock if name not found */
 621                if (zynqmp_get_clock_name(i, clk_name))
 622                        continue;
 623
 624                /* Check if clock is valid and output clock.
 625                 * Do not register invalid or external clock.
 626                 */
 627                ret = zynqmp_get_clock_type(i, &type);
 628                if (ret || type != CLK_TYPE_OUTPUT)
 629                        continue;
 630
 631                /* Get parents of clock*/
 632                if (zynqmp_get_parent_list(np, i, parent_names,
 633                                           &total_parents)) {
 634                        WARN_ONCE(1, "No parents found for %s\n",
 635                                  clock[i].clk_name);
 636                        continue;
 637                }
 638
 639                zynqmp_data->hws[i] =
 640                        zynqmp_register_clk_topology(i, clk_name,
 641                                                     total_parents,
 642                                                     parent_names);
 643        }
 644
 645        for (i = 0; i < clock_max_idx; i++) {
 646                if (IS_ERR(zynqmp_data->hws[i])) {
 647                        pr_err("Zynq Ultrascale+ MPSoC clk %s: register failed with %ld\n",
 648                               clock[i].clk_name, PTR_ERR(zynqmp_data->hws[i]));
 649                        WARN_ON(1);
 650                }
 651        }
 652        return 0;
 653}
 654
 655/**
 656 * zynqmp_get_clock_info() - Get clock information from firmware using PM_API
 657 */
 658static void zynqmp_get_clock_info(void)
 659{
 660        int i, ret;
 661        u32 type = 0;
 662        u32 nodetype, subclass, class;
 663        struct attr_resp attr;
 664        struct name_resp name;
 665
 666        for (i = 0; i < clock_max_idx; i++) {
 667                ret = zynqmp_pm_clock_get_attributes(i, &attr);
 668                if (ret)
 669                        continue;
 670
 671                clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]);
 672                /* skip query for Invalid clock */
 673                ret = zynqmp_is_valid_clock(i);
 674                if (ret != CLK_ATTR_VALID)
 675                        continue;
 676
 677                clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ?
 678                        CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;
 679
 680                nodetype = FIELD_GET(CLK_ATTR_NODE_TYPE, attr.attr[0]);
 681                subclass = FIELD_GET(CLK_ATTR_NODE_SUBCLASS, attr.attr[0]);
 682                class = FIELD_GET(CLK_ATTR_NODE_CLASS, attr.attr[0]);
 683
 684                clock[i].clk_id = FIELD_PREP(CLK_ATTR_NODE_CLASS, class) |
 685                                  FIELD_PREP(CLK_ATTR_NODE_SUBCLASS, subclass) |
 686                                  FIELD_PREP(CLK_ATTR_NODE_TYPE, nodetype) |
 687                                  FIELD_PREP(CLK_ATTR_NODE_INDEX, i);
 688
 689                zynqmp_pm_clock_get_name(clock[i].clk_id, &name);
 690                if (!strcmp(name.name, RESERVED_CLK_NAME))
 691                        continue;
 692                strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN);
 693        }
 694
 695        /* Get topology of all clock */
 696        for (i = 0; i < clock_max_idx; i++) {
 697                ret = zynqmp_get_clock_type(i, &type);
 698                if (ret || type != CLK_TYPE_OUTPUT)
 699                        continue;
 700
 701                ret = zynqmp_clock_get_topology(i, clock[i].node,
 702                                                &clock[i].num_nodes);
 703                if (ret)
 704                        continue;
 705
 706                ret = zynqmp_clock_get_parents(i, clock[i].parent,
 707                                               &clock[i].num_parents);
 708                if (ret)
 709                        continue;
 710        }
 711}
 712
 713/**
 714 * zynqmp_clk_setup() - Setup the clock framework and register clocks
 715 * @np:         Device node
 716 *
 717 * Return: 0 on success else error code
 718 */
 719static int zynqmp_clk_setup(struct device_node *np)
 720{
 721        int ret;
 722
 723        ret = zynqmp_pm_clock_get_num_clocks(&clock_max_idx);
 724        if (ret)
 725                return ret;
 726
 727        zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx),
 728                              GFP_KERNEL);
 729        if (!zynqmp_data)
 730                return -ENOMEM;
 731
 732        clock = kcalloc(clock_max_idx, sizeof(*clock), GFP_KERNEL);
 733        if (!clock) {
 734                kfree(zynqmp_data);
 735                return -ENOMEM;
 736        }
 737
 738        zynqmp_get_clock_info();
 739        zynqmp_register_clocks(np);
 740
 741        zynqmp_data->num = clock_max_idx;
 742        of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data);
 743
 744        return 0;
 745}
 746
 747static int zynqmp_clock_probe(struct platform_device *pdev)
 748{
 749        int ret;
 750        struct device *dev = &pdev->dev;
 751
 752        ret = zynqmp_clk_setup(dev->of_node);
 753
 754        return ret;
 755}
 756
 757static const struct of_device_id zynqmp_clock_of_match[] = {
 758        {.compatible = "xlnx,zynqmp-clk"},
 759        {.compatible = "xlnx,versal-clk"},
 760        {},
 761};
 762MODULE_DEVICE_TABLE(of, zynqmp_clock_of_match);
 763
 764static struct platform_driver zynqmp_clock_driver = {
 765        .driver = {
 766                .name = "zynqmp_clock",
 767                .of_match_table = zynqmp_clock_of_match,
 768        },
 769        .probe = zynqmp_clock_probe,
 770};
 771module_platform_driver(zynqmp_clock_driver);
 772