blob: 1b0b9818cdd4d410bb0abf4ad8c3c5401b875147 [file] [log] [blame]
Dario Binacchi6e6eb8b2020-12-30 00:06:34 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * TI DPLL x2 clock support
4 *
5 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
6 *
7 * Loosely based on Linux kernel drivers/clk/ti/dpll.c
8 */
9
Dario Binacchi6e6eb8b2020-12-30 00:06:34 +010010#include <clk-uclass.h>
11#include <dm.h>
12#include <dm/device_compat.h>
13#include <linux/clk-provider.h>
14
15struct clk_ti_am3_dpll_x2_priv {
16 struct clk parent;
17};
18
19static ulong clk_ti_am3_dpll_x2_get_rate(struct clk *clk)
20{
21 struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(clk->dev);
22 unsigned long rate;
23
24 rate = clk_get_rate(&priv->parent);
25 if (IS_ERR_VALUE(rate))
26 return rate;
27
28 rate *= 2;
29 dev_dbg(clk->dev, "rate=%ld\n", rate);
30 return rate;
31}
32
33const struct clk_ops clk_ti_am3_dpll_x2_ops = {
34 .get_rate = clk_ti_am3_dpll_x2_get_rate,
35};
36
37static int clk_ti_am3_dpll_x2_remove(struct udevice *dev)
38{
39 struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(dev);
40 int err;
41
42 err = clk_release_all(&priv->parent, 1);
43 if (err) {
44 dev_err(dev, "failed to release parent clock\n");
45 return err;
46 }
47
48 return 0;
49}
50
51static int clk_ti_am3_dpll_x2_probe(struct udevice *dev)
52{
53 struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(dev);
54 int err;
55
56 err = clk_get_by_index(dev, 0, &priv->parent);
57 if (err) {
58 dev_err(dev, "%s: failed to get parent clock\n", __func__);
59 return err;
60 }
61
62 return 0;
63}
64
65static const struct udevice_id clk_ti_am3_dpll_x2_of_match[] = {
66 {.compatible = "ti,am3-dpll-x2-clock"},
67 {}
68};
69
70U_BOOT_DRIVER(clk_ti_am3_dpll_x2) = {
71 .name = "ti_am3_dpll_x2_clock",
72 .id = UCLASS_CLK,
73 .of_match = clk_ti_am3_dpll_x2_of_match,
74 .probe = clk_ti_am3_dpll_x2_probe,
75 .remove = clk_ti_am3_dpll_x2_remove,
76 .priv_auto = sizeof(struct clk_ti_am3_dpll_x2_priv),
77 .ops = &clk_ti_am3_dpll_x2_ops,
78};