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