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