uboot/drivers/clk/sunxi/clk_sunxi.c
<<
>>
Prefs
   1// 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 <log.h>
  12#include <reset.h>
  13#include <asm/io.h>
  14#include <clk/sunxi.h>
  15#include <linux/bitops.h>
  16#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);
  67        struct clk_bulk clk_bulk;
  68        struct reset_ctl_bulk rst_bulk;
  69        int ret;
  70
  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
  79        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
  87        return 0;
  88}
  89