blob: 6d4aeb5315d47dd83aa79077a612c18d391ba07e [file] [log] [blame]
Jagan Teki0d47bc72018-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>
Andre Przywara13b08672019-01-29 15:54:08 +000011#include <reset.h>
Jagan Teki0d47bc72018-12-22 21:32:49 +053012#include <asm/io.h>
13#include <asm/arch/ccu.h>
14#include <linux/log2.h>
15
16static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
17 unsigned long id)
18{
19 return &priv->desc->gates[id];
20}
21
22static int sunxi_set_gate(struct clk *clk, bool on)
23{
24 struct ccu_priv *priv = dev_get_priv(clk->dev);
25 const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
26 u32 reg;
27
28 if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
29 printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
30 return 0;
31 }
32
33 debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
34 clk->id, gate->off, ilog2(gate->bit));
35
36 reg = readl(priv->base + gate->off);
37 if (on)
38 reg |= gate->bit;
39 else
40 reg &= ~gate->bit;
41
42 writel(reg, priv->base + gate->off);
43
44 return 0;
45}
46
47static int sunxi_clk_enable(struct clk *clk)
48{
49 return sunxi_set_gate(clk, true);
50}
51
52static int sunxi_clk_disable(struct clk *clk)
53{
54 return sunxi_set_gate(clk, false);
55}
56
57struct clk_ops sunxi_clk_ops = {
58 .enable = sunxi_clk_enable,
59 .disable = sunxi_clk_disable,
60};
61
62int sunxi_clk_probe(struct udevice *dev)
63{
64 struct ccu_priv *priv = dev_get_priv(dev);
Andre Przywara13b08672019-01-29 15:54:08 +000065 struct clk_bulk clk_bulk;
66 struct reset_ctl_bulk rst_bulk;
67 int ret;
Jagan Teki0d47bc72018-12-22 21:32:49 +053068
69 priv->base = dev_read_addr_ptr(dev);
70 if (!priv->base)
71 return -ENOMEM;
72
73 priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
74 if (!priv->desc)
75 return -EINVAL;
76
Andre Przywara13b08672019-01-29 15:54:08 +000077 ret = clk_get_bulk(dev, &clk_bulk);
78 if (!ret)
79 clk_enable_bulk(&clk_bulk);
80
81 ret = reset_get_bulk(dev, &rst_bulk);
82 if (!ret)
83 reset_deassert_bulk(&rst_bulk);
84
Jagan Teki0d47bc72018-12-22 21:32:49 +053085 return 0;
86}