blob: 9673b58a49293bffa9fe7e237ff80122b267581f [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>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Andre Przywara13b08672019-01-29 15:54:08 +000012#include <reset.h>
Jagan Teki0d47bc72018-12-22 21:32:49 +053013#include <asm/io.h>
Samuel Holland21d314a2021-09-12 11:48:43 -050014#include <clk/sunxi.h>
Simon Glasscd93d622020-05-10 11:40:13 -060015#include <linux/bitops.h>
Jagan Teki0d47bc72018-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
30 if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
31 printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
32 return 0;
33 }
34
35 debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
36 clk->id, gate->off, ilog2(gate->bit));
37
38 reg = readl(priv->base + gate->off);
39 if (on)
40 reg |= gate->bit;
41 else
42 reg &= ~gate->bit;
43
44 writel(reg, priv->base + gate->off);
45
46 return 0;
47}
48
49static int sunxi_clk_enable(struct clk *clk)
50{
51 return sunxi_set_gate(clk, true);
52}
53
54static int sunxi_clk_disable(struct clk *clk)
55{
56 return sunxi_set_gate(clk, false);
57}
58
59struct clk_ops sunxi_clk_ops = {
60 .enable = sunxi_clk_enable,
61 .disable = sunxi_clk_disable,
62};
63
64int sunxi_clk_probe(struct udevice *dev)
65{
66 struct ccu_priv *priv = dev_get_priv(dev);
Andre Przywara13b08672019-01-29 15:54:08 +000067 struct clk_bulk clk_bulk;
68 struct reset_ctl_bulk rst_bulk;
69 int ret;
Jagan Teki0d47bc72018-12-22 21:32:49 +053070
71 priv->base = dev_read_addr_ptr(dev);
72 if (!priv->base)
73 return -ENOMEM;
74
75 priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
76 if (!priv->desc)
77 return -EINVAL;
78
Andre Przywara13b08672019-01-29 15:54:08 +000079 ret = clk_get_bulk(dev, &clk_bulk);
80 if (!ret)
81 clk_enable_bulk(&clk_bulk);
82
83 ret = reset_get_bulk(dev, &rst_bulk);
84 if (!ret)
85 reset_deassert_bulk(&rst_bulk);
86
Jagan Teki0d47bc72018-12-22 21:32:49 +053087 return 0;
88}