uboot/drivers/clk/imx/clk-gate2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019 DENX Software Engineering
   4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
   5 *
   6 * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
   7 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 * Gated clock implementation
  14 *
  15 */
  16
  17#include <common.h>
  18#include <asm/io.h>
  19#include <malloc.h>
  20#include <clk-uclass.h>
  21#include <dm/device.h>
  22#include <dm/devres.h>
  23#include <linux/clk-provider.h>
  24#include <clk.h>
  25#include "clk.h"
  26#include <linux/err.h>
  27
  28#define UBOOT_DM_CLK_IMX_GATE2 "imx_clk_gate2"
  29
  30struct clk_gate2 {
  31        struct clk clk;
  32        void __iomem    *reg;
  33        u8              bit_idx;
  34        u8              cgr_val;
  35        u8              flags;
  36};
  37
  38#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk)
  39
  40static int clk_gate2_enable(struct clk *clk)
  41{
  42        struct clk_gate2 *gate = to_clk_gate2(clk);
  43        u32 reg;
  44
  45        reg = readl(gate->reg);
  46        reg &= ~(3 << gate->bit_idx);
  47        reg |= gate->cgr_val << gate->bit_idx;
  48        writel(reg, gate->reg);
  49
  50        return 0;
  51}
  52
  53static int clk_gate2_disable(struct clk *clk)
  54{
  55        struct clk_gate2 *gate = to_clk_gate2(clk);
  56        u32 reg;
  57
  58        reg = readl(gate->reg);
  59        reg &= ~(3 << gate->bit_idx);
  60        writel(reg, gate->reg);
  61
  62        return 0;
  63}
  64
  65static ulong clk_gate2_set_rate(struct clk *clk, ulong rate)
  66{
  67        struct clk *parent = clk_get_parent(clk);
  68
  69        if (parent)
  70                return clk_set_rate(parent, rate);
  71
  72        return -ENODEV;
  73}
  74
  75static const struct clk_ops clk_gate2_ops = {
  76        .set_rate = clk_gate2_set_rate,
  77        .enable = clk_gate2_enable,
  78        .disable = clk_gate2_disable,
  79        .get_rate = clk_generic_get_rate,
  80};
  81
  82struct clk *clk_register_gate2(struct device *dev, const char *name,
  83                const char *parent_name, unsigned long flags,
  84                void __iomem *reg, u8 bit_idx, u8 cgr_val,
  85                u8 clk_gate2_flags)
  86{
  87        struct clk_gate2 *gate;
  88        struct clk *clk;
  89        int ret;
  90
  91        gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  92        if (!gate)
  93                return ERR_PTR(-ENOMEM);
  94
  95        gate->reg = reg;
  96        gate->bit_idx = bit_idx;
  97        gate->cgr_val = cgr_val;
  98        gate->flags = clk_gate2_flags;
  99
 100        clk = &gate->clk;
 101
 102        ret = clk_register(clk, UBOOT_DM_CLK_IMX_GATE2, name, parent_name);
 103        if (ret) {
 104                kfree(gate);
 105                return ERR_PTR(ret);
 106        }
 107
 108        return clk;
 109}
 110
 111U_BOOT_DRIVER(clk_gate2) = {
 112        .name   = UBOOT_DM_CLK_IMX_GATE2,
 113        .id     = UCLASS_CLK,
 114        .ops    = &clk_gate2_ops,
 115        .flags = DM_FLAG_PRE_RELOC,
 116};
 117