blob: c695b69321e2ecb7cb6fbc35a6d9dedb735da97e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stephen Warrena9622432016-06-17 09:44:00 -06002/*
3 * Copyright (c) 2016, NVIDIA CORPORATION.
Stephen Warrena9622432016-06-17 09:44:00 -06004 */
5
6#include <common.h>
7#include <dm.h>
8#include <clk.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <malloc.h>
Stephen Warrena9622432016-06-17 09:44:00 -060010#include <asm/clk.h>
Simon Glass9bc15642020-02-03 07:36:16 -070011#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070012#include <linux/err.h>
Stephen Warrena9622432016-06-17 09:44:00 -060013
Stephen Warrena9622432016-06-17 09:44:00 -060014static const char * const sandbox_clk_test_names[] = {
15 [SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
16 [SANDBOX_CLK_TEST_ID_SPI] = "spi",
17 [SANDBOX_CLK_TEST_ID_I2C] = "i2c",
Yang Xiwene89289c2023-12-16 02:28:52 +080018 [SANDBOX_CLK_TEST_ID_I2C_ROOT] = "i2c_root",
Stephen Warrena9622432016-06-17 09:44:00 -060019};
20
21int sandbox_clk_test_get(struct udevice *dev)
22{
23 struct sandbox_clk_test *sbct = dev_get_priv(dev);
24 int i, ret;
25
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +020026 for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
Stephen Warrena9622432016-06-17 09:44:00 -060027 ret = clk_get_by_name(dev, sandbox_clk_test_names[i],
28 &sbct->clks[i]);
29 if (ret)
30 return ret;
31 }
32
33 return 0;
34}
35
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +020036int sandbox_clk_test_devm_get(struct udevice *dev)
37{
38 struct sandbox_clk_test *sbct = dev_get_priv(dev);
39 struct clk *clk;
40
41 clk = devm_clk_get(dev, "no-an-existing-clock");
42 if (!IS_ERR(clk)) {
43 dev_err(dev, "devm_clk_get() should have failed\n");
44 return -EINVAL;
45 }
46
47 clk = devm_clk_get(dev, "uart2");
48 if (IS_ERR(clk))
49 return PTR_ERR(clk);
50 sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1] = clk;
51
52 clk = devm_clk_get_optional(dev, "uart1");
53 if (IS_ERR(clk))
54 return PTR_ERR(clk);
55 sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM2] = clk;
56
57 sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM_NULL] = NULL;
58 clk = devm_clk_get_optional(dev, "not_an_existing_clock");
59 if (IS_ERR(clk))
60 return PTR_ERR(clk);
61 if (clk)
62 return -EINVAL;
63
64 return 0;
65}
66
Neil Armstrong567a38b2018-04-03 11:44:19 +020067int sandbox_clk_test_get_bulk(struct udevice *dev)
68{
69 struct sandbox_clk_test *sbct = dev_get_priv(dev);
70
71 return clk_get_bulk(dev, &sbct->bulk);
72}
73
Stephen Warrena9622432016-06-17 09:44:00 -060074ulong sandbox_clk_test_get_rate(struct udevice *dev, int id)
75{
76 struct sandbox_clk_test *sbct = dev_get_priv(dev);
77
78 if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
79 return -EINVAL;
80
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +020081 return clk_get_rate(sbct->clkps[id]);
Stephen Warrena9622432016-06-17 09:44:00 -060082}
83
Dario Binacchib7f85892020-12-30 00:06:31 +010084ulong sandbox_clk_test_round_rate(struct udevice *dev, int id, ulong rate)
85{
86 struct sandbox_clk_test *sbct = dev_get_priv(dev);
87
88 if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
89 return -EINVAL;
90
91 return clk_round_rate(sbct->clkps[id], rate);
92}
93
Stephen Warrena9622432016-06-17 09:44:00 -060094ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
95{
96 struct sandbox_clk_test *sbct = dev_get_priv(dev);
97
98 if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
99 return -EINVAL;
100
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200101 return clk_set_rate(sbct->clkps[id], rate);
Stephen Warrena9622432016-06-17 09:44:00 -0600102}
103
104int sandbox_clk_test_enable(struct udevice *dev, int id)
105{
106 struct sandbox_clk_test *sbct = dev_get_priv(dev);
107
108 if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
109 return -EINVAL;
110
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200111 return clk_enable(sbct->clkps[id]);
Stephen Warrena9622432016-06-17 09:44:00 -0600112}
113
Neil Armstrong567a38b2018-04-03 11:44:19 +0200114int sandbox_clk_test_enable_bulk(struct udevice *dev)
115{
116 struct sandbox_clk_test *sbct = dev_get_priv(dev);
117
118 return clk_enable_bulk(&sbct->bulk);
119}
120
Stephen Warrena9622432016-06-17 09:44:00 -0600121int sandbox_clk_test_disable(struct udevice *dev, int id)
122{
123 struct sandbox_clk_test *sbct = dev_get_priv(dev);
124
125 if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
126 return -EINVAL;
127
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200128 return clk_disable(sbct->clkps[id]);
Stephen Warrena9622432016-06-17 09:44:00 -0600129}
130
Neil Armstrong567a38b2018-04-03 11:44:19 +0200131int sandbox_clk_test_disable_bulk(struct udevice *dev)
132{
133 struct sandbox_clk_test *sbct = dev_get_priv(dev);
134
135 return clk_disable_bulk(&sbct->bulk);
136}
137
Stephen Warrena9622432016-06-17 09:44:00 -0600138int sandbox_clk_test_free(struct udevice *dev)
139{
140 struct sandbox_clk_test *sbct = dev_get_priv(dev);
Sean Anderson9a665722022-01-15 17:25:04 -0500141 int i;
Stephen Warrena9622432016-06-17 09:44:00 -0600142
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200143 devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]);
Sean Anderson9a665722022-01-15 17:25:04 -0500144 for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++)
145 clk_free(&sbct->clks[i]);
Stephen Warrena9622432016-06-17 09:44:00 -0600146
147 return 0;
148}
149
Neil Armstrong567a38b2018-04-03 11:44:19 +0200150int sandbox_clk_test_release_bulk(struct udevice *dev)
151{
152 struct sandbox_clk_test *sbct = dev_get_priv(dev);
153
154 return clk_release_bulk(&sbct->bulk);
155}
156
Fabrice Gasnier11192712018-07-24 16:31:28 +0200157int sandbox_clk_test_valid(struct udevice *dev)
158{
159 struct sandbox_clk_test *sbct = dev_get_priv(dev);
160 int i;
161
162 for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200163 if (!clk_valid(sbct->clkps[i]))
164 if (i != SANDBOX_CLK_TEST_ID_DEVM_NULL)
165 return -EINVAL;
Fabrice Gasnier11192712018-07-24 16:31:28 +0200166 }
167
168 return 0;
169}
170
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200171static int sandbox_clk_test_probe(struct udevice *dev)
172{
173 struct sandbox_clk_test *sbct = dev_get_priv(dev);
174 int i;
175
176 for (i = 0; i < SANDBOX_CLK_TEST_ID_DEVM1; i++)
177 sbct->clkps[i] = &sbct->clks[i];
178 for (i = SANDBOX_CLK_TEST_ID_DEVM1; i < SANDBOX_CLK_TEST_ID_COUNT; i++)
179 sbct->clkps[i] = NULL;
180
181 return 0;
182}
183
Stephen Warrena9622432016-06-17 09:44:00 -0600184static const struct udevice_id sandbox_clk_test_ids[] = {
185 { .compatible = "sandbox,clk-test" },
186 { }
187};
188
189U_BOOT_DRIVER(sandbox_clk_test) = {
190 .name = "sandbox_clk_test",
191 .id = UCLASS_MISC,
192 .of_match = sandbox_clk_test_ids,
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200193 .probe = sandbox_clk_test_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700194 .priv_auto = sizeof(struct sandbox_clk_test),
Stephen Warrena9622432016-06-17 09:44:00 -0600195};