blob: 880dd4f6ece9fde3ef3dd9d457e717ce4c237e29 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stephen Warren3b940fa2016-09-13 10:45:59 -06002/*
3 * Copyright (c) 2016, NVIDIA CORPORATION.
Stephen Warren3b940fa2016-09-13 10:45:59 -06004 */
5
Stephen Warren3b940fa2016-09-13 10:45:59 -06006#include <clk-uclass.h>
7#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <malloc.h>
Stephen Warren3b940fa2016-09-13 10:45:59 -060010#include <asm/arch/clock.h>
11#include <asm/arch-tegra/clk_rst.h>
12
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020013#define TEGRA_CAR_CLK_PLL BIT(0)
14#define TEGRA_CAR_CLK_PERIPH BIT(1)
15
Stephen Warren3b940fa2016-09-13 10:45:59 -060016static int tegra_car_clk_request(struct clk *clk)
17{
18 debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
19 clk->id);
20
21 /*
22 * Note that the first PERIPH_ID_COUNT clock IDs (where the value
23 * varies per SoC) are the peripheral clocks, which use a numbering
24 * scheme that matches HW registers 1:1. There are other clock IDs
25 * beyond this that are assigned arbitrarily by the Tegra CAR DT
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020026 * binding.
Stephen Warren3b940fa2016-09-13 10:45:59 -060027 */
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020028 if (clk->id < PERIPH_ID_COUNT) {
29 clk->data |= TEGRA_CAR_CLK_PERIPH;
30 return 0;
31 }
Stephen Warren3b940fa2016-09-13 10:45:59 -060032
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020033 /* If check for periph failed, then check for PLL clock id */
34 int id = clk_id_to_pll_id(clk->id);
35
36 if (clock_id_is_pll(id)) {
37 clk->id = id;
38 clk->data |= TEGRA_CAR_CLK_PLL;
39 return 0;
40 }
41
42 return -EINVAL;
Stephen Warren3b940fa2016-09-13 10:45:59 -060043}
44
Stephen Warren3b940fa2016-09-13 10:45:59 -060045static ulong tegra_car_clk_get_rate(struct clk *clk)
46{
Stephen Warren3b940fa2016-09-13 10:45:59 -060047 debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
48 clk->id);
49
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020050 if (clk->data & TEGRA_CAR_CLK_PLL)
51 return clock_get_rate(clk->id);
52
53 if (clk->data & TEGRA_CAR_CLK_PERIPH) {
54 enum clock_id parent;
55
56 parent = clock_get_periph_parent(clk->id);
57 return clock_get_periph_rate(clk->id, parent);
58 }
59
60 return -1U;
Stephen Warren3b940fa2016-09-13 10:45:59 -060061}
62
63static ulong tegra_car_clk_set_rate(struct clk *clk, ulong rate)
64{
65 enum clock_id parent;
66
67 debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate,
68 clk->dev, clk->id);
69
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020070 if (clk->data & TEGRA_CAR_CLK_PLL)
71 return 0;
72
Stephen Warren3b940fa2016-09-13 10:45:59 -060073 parent = clock_get_periph_parent(clk->id);
74 return clock_adjust_periph_pll_div(clk->id, parent, rate, NULL);
75}
76
77static int tegra_car_clk_enable(struct clk *clk)
78{
79 debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
80 clk->id);
81
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020082 if (clk->data & TEGRA_CAR_CLK_PLL)
83 return 0;
84
Stephen Warren3b940fa2016-09-13 10:45:59 -060085 clock_enable(clk->id);
86
87 return 0;
88}
89
90static int tegra_car_clk_disable(struct clk *clk)
91{
92 debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
93 clk->id);
94
Svyatoslav Ryhel1f198592024-12-13 16:53:18 +020095 if (clk->data & TEGRA_CAR_CLK_PLL)
96 return 0;
97
Stephen Warren3b940fa2016-09-13 10:45:59 -060098 clock_disable(clk->id);
99
100 return 0;
101}
102
103static struct clk_ops tegra_car_clk_ops = {
104 .request = tegra_car_clk_request,
Stephen Warren3b940fa2016-09-13 10:45:59 -0600105 .get_rate = tegra_car_clk_get_rate,
106 .set_rate = tegra_car_clk_set_rate,
107 .enable = tegra_car_clk_enable,
108 .disable = tegra_car_clk_disable,
109};
110
111static int tegra_car_clk_probe(struct udevice *dev)
112{
113 debug("%s(dev=%p)\n", __func__, dev);
114
Svyatoslav Ryhel1673fb82024-12-13 16:53:19 +0200115 clock_init();
116 clock_verify();
117
Stephen Warren3b940fa2016-09-13 10:45:59 -0600118 return 0;
119}
120
121U_BOOT_DRIVER(tegra_car_clk) = {
122 .name = "tegra_car_clk",
123 .id = UCLASS_CLK,
124 .probe = tegra_car_clk_probe,
125 .ops = &tegra_car_clk_ops,
126};