uboot/drivers/clk/ti/clk-gate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * TI gate clock support
   4 *
   5 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
   6 *
   7 * Loosely based on Linux kernel drivers/clk/ti/gate.c
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <dm/device_compat.h>
  13#include <clk-uclass.h>
  14#include <asm/io.h>
  15#include <linux/clk-provider.h>
  16#include "clk.h"
  17
  18struct clk_ti_gate_priv {
  19        struct clk_ti_reg reg;
  20        u8 enable_bit;
  21        u32 flags;
  22        bool invert_enable;
  23};
  24
  25static int clk_ti_gate_disable(struct clk *clk)
  26{
  27        struct clk_ti_gate_priv *priv = dev_get_priv(clk->dev);
  28        u32 v;
  29
  30        v = clk_ti_readl(&priv->reg);
  31        if (priv->invert_enable)
  32                v |= (1 << priv->enable_bit);
  33        else
  34                v &= ~(1 << priv->enable_bit);
  35
  36        clk_ti_writel(v, &priv->reg);
  37        /* No OCP barrier needed here since it is a disable operation */
  38        return 0;
  39}
  40
  41static int clk_ti_gate_enable(struct clk *clk)
  42{
  43        struct clk_ti_gate_priv *priv = dev_get_priv(clk->dev);
  44        u32 v;
  45
  46        v = clk_ti_readl(&priv->reg);
  47        if (priv->invert_enable)
  48                v &= ~(1 << priv->enable_bit);
  49        else
  50                v |= (1 << priv->enable_bit);
  51
  52        clk_ti_writel(v, &priv->reg);
  53        /* OCP barrier */
  54        v = clk_ti_readl(&priv->reg);
  55        return 0;
  56}
  57
  58static int clk_ti_gate_of_to_plat(struct udevice *dev)
  59{
  60        struct clk_ti_gate_priv *priv = dev_get_priv(dev);
  61        int err;
  62
  63        err = clk_ti_get_reg_addr(dev, 0, &priv->reg);
  64        if (err) {
  65                dev_err(dev, "failed to get control register address\n");
  66                return err;
  67        }
  68
  69        priv->enable_bit = dev_read_u32_default(dev, "ti,bit-shift", 0);
  70        if (dev_read_bool(dev, "ti,set-rate-parent"))
  71                priv->flags |= CLK_SET_RATE_PARENT;
  72
  73        priv->invert_enable = dev_read_bool(dev, "ti,set-bit-to-disable");
  74        return 0;
  75}
  76
  77static struct clk_ops clk_ti_gate_ops = {
  78        .enable = clk_ti_gate_enable,
  79        .disable = clk_ti_gate_disable,
  80};
  81
  82static const struct udevice_id clk_ti_gate_of_match[] = {
  83        { .compatible = "ti,gate-clock" },
  84        { },
  85};
  86
  87U_BOOT_DRIVER(clk_ti_gate) = {
  88        .name = "ti_gate_clock",
  89        .id = UCLASS_CLK,
  90        .of_match = clk_ti_gate_of_match,
  91        .of_to_plat = clk_ti_gate_of_to_plat,
  92        .priv_auto = sizeof(struct clk_ti_gate_priv),
  93        .ops = &clk_ti_gate_ops,
  94};
  95