blob: 4ed14306575405f80ca5a6b05b281ec78b31fc3b [file] [log] [blame]
Marek Vasut59ee41c2023-08-14 01:51:27 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 Marek Vasut <marek.vasut+renesas@mailbox.org>
4 */
5
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +02006#include <clk.h>
Marek Vasut59ee41c2023-08-14 01:51:27 +02007#include <clk-uclass.h>
8#include <dm.h>
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +02009#include <linux/clk-provider.h>
10
11#include <asm/gpio.h>
Marek Vasut59ee41c2023-08-14 01:51:27 +020012
13struct clk_gpio_priv {
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020014 struct gpio_desc enable; /* GPIO, controlling the gate */
15 struct clk *clk; /* Gated clock */
Marek Vasut59ee41c2023-08-14 01:51:27 +020016};
17
18static int clk_gpio_enable(struct clk *clk)
19{
20 struct clk_gpio_priv *priv = dev_get_priv(clk->dev);
21
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020022 clk_enable(priv->clk);
Marek Vasut59ee41c2023-08-14 01:51:27 +020023 dm_gpio_set_value(&priv->enable, 1);
24
25 return 0;
26}
27
28static 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);
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020033 clk_disable(priv->clk);
Marek Vasut59ee41c2023-08-14 01:51:27 +020034
35 return 0;
36}
37
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020038static 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
Marek Vasut59ee41c2023-08-14 01:51:27 +020045const struct clk_ops clk_gpio_ops = {
46 .enable = clk_gpio_enable,
47 .disable = clk_gpio_disable,
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020048 .get_rate = clk_gpio_get_rate,
Marek Vasut59ee41c2023-08-14 01:51:27 +020049};
50
51static int clk_gpio_probe(struct udevice *dev)
52{
53 struct clk_gpio_priv *priv = dev_get_priv(dev);
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020054 int ret;
Marek Vasut59ee41c2023-08-14 01:51:27 +020055
Svyatoslav Ryhelf51a44a2024-01-10 18:09:56 +020056 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 }
62
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;
Marek Vasut59ee41c2023-08-14 01:51:27 +020072}
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 */
81static const struct udevice_id clk_gpio_match[] = {
82 { .compatible = "gpio-gate-clock" },
83 { /* sentinel */ }
84};
85
86U_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};