blob: 9a21367a5d06483f6918748443a8bf4a7aa2d80c [file] [log] [blame]
Jagan Teki1d150b42018-12-22 21:32:49 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Amarula Solutions.
4 * Author: Jagan Teki <jagan@amarulasolutions.com>
5 */
6
7#include <common.h>
8#include <clk-uclass.h>
9#include <dm.h>
10#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Andre Przywara030bab82019-01-29 15:54:08 +000012#include <reset.h>
Jagan Teki1d150b42018-12-22 21:32:49 +053013#include <asm/io.h>
Samuel Holland12e3faa2021-09-12 11:48:43 -050014#include <clk/sunxi.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060015#include <linux/bitops.h>
Jagan Teki1d150b42018-12-22 21:32:49 +053016#include <linux/log2.h>
17
18static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
19 unsigned long id)
20{
21 return &priv->desc->gates[id];
22}
23
24static int sunxi_set_gate(struct clk *clk, bool on)
25{
26 struct ccu_priv *priv = dev_get_priv(clk->dev);
27 const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
28 u32 reg;
29
Andre Przywara2d1864f2022-05-05 01:25:43 +010030 if ((gate->flags & CCU_CLK_F_DUMMY_GATE))
31 return 0;
32
Jagan Teki1d150b42018-12-22 21:32:49 +053033 if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
34 printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
35 return 0;
36 }
37
38 debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
39 clk->id, gate->off, ilog2(gate->bit));
40
41 reg = readl(priv->base + gate->off);
42 if (on)
43 reg |= gate->bit;
44 else
45 reg &= ~gate->bit;
46
47 writel(reg, priv->base + gate->off);
48
49 return 0;
50}
51
52static int sunxi_clk_enable(struct clk *clk)
53{
54 return sunxi_set_gate(clk, true);
55}
56
57static int sunxi_clk_disable(struct clk *clk)
58{
59 return sunxi_set_gate(clk, false);
60}
61
62struct clk_ops sunxi_clk_ops = {
63 .enable = sunxi_clk_enable,
64 .disable = sunxi_clk_disable,
65};
66
67int sunxi_clk_probe(struct udevice *dev)
68{
69 struct ccu_priv *priv = dev_get_priv(dev);
Andre Przywara030bab82019-01-29 15:54:08 +000070 struct clk_bulk clk_bulk;
71 struct reset_ctl_bulk rst_bulk;
72 int ret;
Jagan Teki1d150b42018-12-22 21:32:49 +053073
74 priv->base = dev_read_addr_ptr(dev);
75 if (!priv->base)
76 return -ENOMEM;
77
78 priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
79 if (!priv->desc)
80 return -EINVAL;
81
Andre Przywara030bab82019-01-29 15:54:08 +000082 ret = clk_get_bulk(dev, &clk_bulk);
83 if (!ret)
84 clk_enable_bulk(&clk_bulk);
85
86 ret = reset_get_bulk(dev, &rst_bulk);
87 if (!ret)
88 reset_deassert_bulk(&rst_bulk);
89
Jagan Teki1d150b42018-12-22 21:32:49 +053090 return 0;
91}