blob: 62ce2994e4fb3cfef34c295a7a2afe9da7d51561 [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>
11#include <asm/io.h>
12#include <asm/arch/ccu.h>
13#include <linux/log2.h>
14
15static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
16 unsigned long id)
17{
18 return &priv->desc->gates[id];
19}
20
21static int sunxi_set_gate(struct clk *clk, bool on)
22{
23 struct ccu_priv *priv = dev_get_priv(clk->dev);
24 const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
25 u32 reg;
26
27 if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
28 printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
29 return 0;
30 }
31
32 debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
33 clk->id, gate->off, ilog2(gate->bit));
34
35 reg = readl(priv->base + gate->off);
36 if (on)
37 reg |= gate->bit;
38 else
39 reg &= ~gate->bit;
40
41 writel(reg, priv->base + gate->off);
42
43 return 0;
44}
45
46static int sunxi_clk_enable(struct clk *clk)
47{
48 return sunxi_set_gate(clk, true);
49}
50
51static int sunxi_clk_disable(struct clk *clk)
52{
53 return sunxi_set_gate(clk, false);
54}
55
56struct clk_ops sunxi_clk_ops = {
57 .enable = sunxi_clk_enable,
58 .disable = sunxi_clk_disable,
59};
60
61int sunxi_clk_probe(struct udevice *dev)
62{
63 struct ccu_priv *priv = dev_get_priv(dev);
64
65 priv->base = dev_read_addr_ptr(dev);
66 if (!priv->base)
67 return -ENOMEM;
68
69 priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
70 if (!priv->desc)
71 return -EINVAL;
72
73 return 0;
74}