]>
Commit | Line | Data |
---|---|---|
92d5f996 MV |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2023 Marek Vasut <[email protected]> | |
4 | */ | |
5 | ||
a8dc4965 | 6 | #include <clk.h> |
92d5f996 MV |
7 | #include <clk-uclass.h> |
8 | #include <dm.h> | |
a8dc4965 SR |
9 | #include <linux/clk-provider.h> |
10 | ||
11 | #include <asm/gpio.h> | |
92d5f996 MV |
12 | |
13 | struct clk_gpio_priv { | |
a8dc4965 SR |
14 | struct gpio_desc enable; /* GPIO, controlling the gate */ |
15 | struct clk *clk; /* Gated clock */ | |
92d5f996 MV |
16 | }; |
17 | ||
18 | static int clk_gpio_enable(struct clk *clk) | |
19 | { | |
20 | struct clk_gpio_priv *priv = dev_get_priv(clk->dev); | |
21 | ||
a8dc4965 | 22 | clk_enable(priv->clk); |
92d5f996 MV |
23 | dm_gpio_set_value(&priv->enable, 1); |
24 | ||
25 | return 0; | |
26 | } | |
27 | ||
28 | static int clk_gpio_disable(struct clk *clk) | |
29 | { | |
30 | struct clk_gpio_priv *priv = dev_get_priv(clk->dev); | |
31 | ||
32 | dm_gpio_set_value(&priv->enable, 0); | |
a8dc4965 | 33 | clk_disable(priv->clk); |
92d5f996 MV |
34 | |
35 | return 0; | |
36 | } | |
37 | ||
a8dc4965 SR |
38 | static ulong clk_gpio_get_rate(struct clk *clk) |
39 | { | |
40 | struct clk_gpio_priv *priv = dev_get_priv(clk->dev); | |
41 | ||
42 | return clk_get_rate(priv->clk); | |
43 | } | |
44 | ||
92d5f996 MV |
45 | const struct clk_ops clk_gpio_ops = { |
46 | .enable = clk_gpio_enable, | |
47 | .disable = clk_gpio_disable, | |
a8dc4965 | 48 | .get_rate = clk_gpio_get_rate, |
92d5f996 MV |
49 | }; |
50 | ||
51 | static int clk_gpio_probe(struct udevice *dev) | |
52 | { | |
53 | struct clk_gpio_priv *priv = dev_get_priv(dev); | |
a8dc4965 SR |
54 | int ret; |
55 | ||
56 | priv->clk = devm_clk_get(dev, NULL); | |
57 | if (IS_ERR(priv->clk)) { | |
58 | log_debug("%s: Could not get gated clock: %ld\n", | |
59 | __func__, PTR_ERR(priv->clk)); | |
60 | return PTR_ERR(priv->clk); | |
61 | } | |
92d5f996 | 62 | |
a8dc4965 SR |
63 | ret = gpio_request_by_name(dev, "enable-gpios", 0, |
64 | &priv->enable, GPIOD_IS_OUT); | |
65 | if (ret) { | |
66 | log_debug("%s: Could not decode enable-gpios (%d)\n", | |
67 | __func__, ret); | |
68 | return ret; | |
69 | } | |
70 | ||
71 | return 0; | |
92d5f996 MV |
72 | } |
73 | ||
74 | /* | |
75 | * When implementing clk-mux-clock, use gpio_request_list_by_name | |
76 | * and implement get_rate/set_rate/set_parent ops. This should be | |
77 | * in a separate driver and with separate Kconfig option to enable | |
78 | * that driver, since unlike Linux implementation, the U-Boot DM | |
79 | * integration would be orthogonal to this driver. | |
80 | */ | |
81 | static const struct udevice_id clk_gpio_match[] = { | |
82 | { .compatible = "gpio-gate-clock" }, | |
83 | { /* sentinel */ } | |
84 | }; | |
85 | ||
86 | U_BOOT_DRIVER(gpio_gate_clock) = { | |
87 | .name = "gpio_clock", | |
88 | .id = UCLASS_CLK, | |
89 | .of_match = clk_gpio_match, | |
90 | .probe = clk_gpio_probe, | |
91 | .priv_auto = sizeof(struct clk_gpio_priv), | |
92 | .ops = &clk_gpio_ops, | |
93 | .flags = DM_FLAG_PRE_RELOC, | |
94 | }; |