blob: 6d71c0c03ffe8fef35a356ae976cfcf607f3b2cd [file] [log] [blame]
Sébastien Szymanski8d163f52023-07-25 10:08:53 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2021 NXP
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7#include <common.h>
8#include <log.h>
9#include <asm/io.h>
10#include <malloc.h>
11#include <clk-uclass.h>
12#include <dm/device.h>
13#include <dm/devres.h>
14#include <linux/iopoll.h>
15#include <linux/clk-provider.h>
16#include <clk.h>
17#include "clk.h"
18#include <linux/err.h>
19
20#define TIMEOUT_US 500U
21
22#define CCM_DIV_SHIFT 0
23#define CCM_DIV_WIDTH 8
24#define CCM_MUX_SHIFT 8
25#define CCM_MUX_MASK 3
26#define CCM_OFF_SHIFT 24
27#define CCM_BUSY_SHIFT 28
28
29#define STAT_OFFSET 0x4
30#define AUTHEN_OFFSET 0x30
31#define TZ_NS_SHIFT 9
32#define TZ_NS_MASK BIT(9)
33
34#define WHITE_LIST_SHIFT 16
35
36#define readl_poll_timeout_atomic readl_poll_timeout
37
38static int imx93_clk_composite_wait_ready(struct clk *clk, void __iomem *reg)
39{
40 int ret;
41 u32 val;
42
43 ret = readl_poll_timeout_atomic(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)),
44 TIMEOUT_US);
45 if (ret)
46 pr_err("Slice[%s] busy timeout\n", "TODO");
47
48 return ret;
49}
50
51static void imx93_clk_composite_gate_endisable(struct clk *clk, int enable)
52{
53 struct clk_gate *gate = to_clk_gate(clk);
54 u32 reg;
55
56 reg = readl(gate->reg);
57
58 if (enable)
59 reg &= ~BIT(gate->bit_idx);
60 else
61 reg |= BIT(gate->bit_idx);
62
63 writel(reg, gate->reg);
64
65 imx93_clk_composite_wait_ready(clk, gate->reg);
66}
67
68static int imx93_clk_composite_gate_enable(struct clk *clk)
69{
70 imx93_clk_composite_gate_endisable(clk, 1);
71
72 return 0;
73}
74
75static int imx93_clk_composite_gate_disable(struct clk *clk)
76{
77 imx93_clk_composite_gate_endisable(clk, 0);
78
79 return 0;
80}
81
82static const struct clk_ops imx93_clk_composite_gate_ops = {
83 .enable = imx93_clk_composite_gate_enable,
84 .disable = imx93_clk_composite_gate_disable,
85};
86
87struct clk *imx93_clk_composite_flags(const char *name,
88 const char * const *parent_names,
89 int num_parents, void __iomem *reg, u32 domain_id,
90 unsigned long flags)
91{
92 struct clk *clk = ERR_PTR(-ENOMEM);
93 struct clk_divider *div = NULL;
94 struct clk_gate *gate = NULL;
95 struct clk_mux *mux = NULL;
96
97 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
98 if (!mux)
99 goto fail;
100
101 mux->reg = reg;
102 mux->shift = CCM_MUX_SHIFT;
103 mux->mask = CCM_MUX_MASK;
104 mux->num_parents = num_parents;
105 mux->parent_names = parent_names;
106 mux->flags = flags;
107
108 div = kzalloc(sizeof(*div), GFP_KERNEL);
109 if (!div)
110 goto fail;
111
112 div->reg = reg;
113 div->shift = CCM_DIV_SHIFT;
114 div->width = CCM_DIV_WIDTH;
115 div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
116
117 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
118 if (!gate)
119 goto fail;
120
121 gate->reg = reg;
122 gate->bit_idx = CCM_OFF_SHIFT;
123 gate->flags = flags;
124
125 clk = clk_register_composite(NULL, name,
126 parent_names, num_parents,
127 &mux->clk, &clk_mux_ops,
128 &div->clk, &clk_divider_ops,
129 &gate->clk, &imx93_clk_composite_gate_ops,
130 flags);
131
132 if (IS_ERR(clk))
133 goto fail;
134
135 return clk;
136
137fail:
138 kfree(gate);
139 kfree(div);
140 kfree(mux);
141 return ERR_CAST(clk);
142}