]> Git Repo - J-u-boot.git/blob - drivers/clk/clk-composite.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / drivers / clk / clk-composite.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2013 NVIDIA CORPORATION.  All rights reserved.
4  * Copyright 2019 NXP
5  */
6
7 #define LOG_CATEGORY UCLASS_CLK
8
9 #include <clk.h>
10 #include <clk-uclass.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <asm/io.h>
14 #include <dm/device.h>
15 #include <dm/devres.h>
16 #include <linux/clk-provider.h>
17 #include <linux/err.h>
18
19 #include "clk.h"
20
21 #define UBOOT_DM_CLK_COMPOSITE "clk_composite"
22
23 static u8 clk_composite_get_parent(struct clk *clk)
24 {
25         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
26                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
27         struct clk *mux = composite->mux;
28
29         if (mux)
30                 return clk_mux_get_parent(mux);
31         else
32                 return 0;
33 }
34
35 static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
36 {
37         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
38                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
39         const struct clk_ops *mux_ops = composite->mux_ops;
40         struct clk *mux = composite->mux;
41
42         if (!mux || !mux_ops)
43                 return -ENOSYS;
44
45         return mux_ops->set_parent(mux, parent);
46 }
47
48 static unsigned long clk_composite_recalc_rate(struct clk *clk)
49 {
50         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
51                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
52         const struct clk_ops *rate_ops = composite->rate_ops;
53         struct clk *rate = composite->rate;
54
55         if (rate && rate_ops)
56                 return rate_ops->get_rate(rate);
57         else
58                 return clk_get_parent_rate(clk);
59 }
60
61 static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
62 {
63         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
64                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
65         const struct clk_ops *rate_ops = composite->rate_ops;
66         struct clk *clk_rate = composite->rate;
67
68         if (rate && rate_ops && rate_ops->set_rate)
69                 return rate_ops->set_rate(clk_rate, rate);
70         else
71                 return clk_get_rate(clk);
72 }
73
74 static int clk_composite_enable(struct clk *clk)
75 {
76         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
77                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
78         const struct clk_ops *gate_ops = composite->gate_ops;
79         struct clk *gate = composite->gate;
80
81         if (gate && gate_ops)
82                 return gate_ops->enable(gate);
83         else
84                 return 0;
85 }
86
87 static int clk_composite_disable(struct clk *clk)
88 {
89         struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
90                 (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
91         const struct clk_ops *gate_ops = composite->gate_ops;
92         struct clk *gate = composite->gate;
93
94         if (gate && gate_ops)
95                 return gate_ops->disable(gate);
96         else
97                 return 0;
98 }
99
100 struct clk *clk_register_composite(struct device *dev, const char *name,
101                                    const char * const *parent_names,
102                                    int num_parents, struct clk *mux,
103                                    const struct clk_ops *mux_ops,
104                                    struct clk *rate,
105                                    const struct clk_ops *rate_ops,
106                                    struct clk *gate,
107                                    const struct clk_ops *gate_ops,
108                                    unsigned long flags)
109 {
110         struct clk *clk;
111         struct clk_composite *composite;
112         int ret;
113
114         if (!num_parents || (num_parents != 1 && !mux))
115                 return ERR_PTR(-EINVAL);
116
117         composite = kzalloc(sizeof(*composite), GFP_KERNEL);
118         if (!composite)
119                 return ERR_PTR(-ENOMEM);
120
121         if (mux && mux_ops) {
122                 composite->mux = mux;
123                 composite->mux_ops = mux_ops;
124                 mux->data = (ulong)composite;
125         }
126
127         if (rate && rate_ops) {
128                 if (!rate_ops->get_rate) {
129                         clk = ERR_PTR(-EINVAL);
130                         goto err;
131                 }
132
133                 composite->rate = rate;
134                 composite->rate_ops = rate_ops;
135                 rate->data = (ulong)composite;
136         }
137
138         if (gate && gate_ops) {
139                 if (!gate_ops->enable || !gate_ops->disable) {
140                         clk = ERR_PTR(-EINVAL);
141                         goto err;
142                 }
143
144                 composite->gate = gate;
145                 composite->gate_ops = gate_ops;
146                 gate->data = (ulong)composite;
147         }
148
149         clk = &composite->clk;
150         clk->flags = flags;
151         ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
152                            parent_names[clk_composite_get_parent(clk)]);
153         if (ret) {
154                 clk = ERR_PTR(ret);
155                 goto err;
156         }
157
158         if (composite->mux)
159                 composite->mux->dev = clk->dev;
160         if (composite->rate)
161                 composite->rate->dev = clk->dev;
162         if (composite->gate)
163                 composite->gate->dev = clk->dev;
164
165         return clk;
166
167 err:
168         kfree(composite);
169         return clk;
170 }
171
172 static const struct clk_ops clk_composite_ops = {
173         .set_parent = clk_composite_set_parent,
174         .get_rate = clk_composite_recalc_rate,
175         .set_rate = clk_composite_set_rate,
176         .enable = clk_composite_enable,
177         .disable = clk_composite_disable,
178 };
179
180 U_BOOT_DRIVER(clk_composite) = {
181         .name   = UBOOT_DM_CLK_COMPOSITE,
182         .id     = UCLASS_CLK,
183         .ops    = &clk_composite_ops,
184         .flags = DM_FLAG_PRE_RELOC,
185 };
This page took 0.033438 seconds and 4 git commands to generate.