linux/drivers/clk/uniphier/clk-uniphier-gate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2016 Socionext Inc.
   4 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
   5 */
   6
   7#include <linux/clk-provider.h>
   8#include <linux/device.h>
   9#include <linux/regmap.h>
  10
  11#include "clk-uniphier.h"
  12
  13struct uniphier_clk_gate {
  14        struct clk_hw hw;
  15        struct regmap *regmap;
  16        unsigned int reg;
  17        unsigned int bit;
  18};
  19
  20#define to_uniphier_clk_gate(_hw) \
  21                                container_of(_hw, struct uniphier_clk_gate, hw)
  22
  23static int uniphier_clk_gate_endisable(struct clk_hw *hw, int enable)
  24{
  25        struct uniphier_clk_gate *gate = to_uniphier_clk_gate(hw);
  26
  27        return regmap_write_bits(gate->regmap, gate->reg, BIT(gate->bit),
  28                                 enable ? BIT(gate->bit) : 0);
  29}
  30
  31static int uniphier_clk_gate_enable(struct clk_hw *hw)
  32{
  33        return uniphier_clk_gate_endisable(hw, 1);
  34}
  35
  36static void uniphier_clk_gate_disable(struct clk_hw *hw)
  37{
  38        if (uniphier_clk_gate_endisable(hw, 0) < 0)
  39                pr_warn("failed to disable clk\n");
  40}
  41
  42static int uniphier_clk_gate_is_enabled(struct clk_hw *hw)
  43{
  44        struct uniphier_clk_gate *gate = to_uniphier_clk_gate(hw);
  45        unsigned int val;
  46
  47        if (regmap_read(gate->regmap, gate->reg, &val) < 0)
  48                pr_warn("is_enabled() may return wrong result\n");
  49
  50        return !!(val & BIT(gate->bit));
  51}
  52
  53static const struct clk_ops uniphier_clk_gate_ops = {
  54        .enable = uniphier_clk_gate_enable,
  55        .disable = uniphier_clk_gate_disable,
  56        .is_enabled = uniphier_clk_gate_is_enabled,
  57};
  58
  59struct clk_hw *uniphier_clk_register_gate(struct device *dev,
  60                                          struct regmap *regmap,
  61                                          const char *name,
  62                                const struct uniphier_clk_gate_data *data)
  63{
  64        struct uniphier_clk_gate *gate;
  65        struct clk_init_data init;
  66        int ret;
  67
  68        gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
  69        if (!gate)
  70                return ERR_PTR(-ENOMEM);
  71
  72        init.name = name;
  73        init.ops = &uniphier_clk_gate_ops;
  74        init.flags = data->parent_name ? CLK_SET_RATE_PARENT : 0;
  75        init.parent_names = data->parent_name ? &data->parent_name : NULL;
  76        init.num_parents = data->parent_name ? 1 : 0;
  77
  78        gate->regmap = regmap;
  79        gate->reg = data->reg;
  80        gate->bit = data->bit;
  81        gate->hw.init = &init;
  82
  83        ret = devm_clk_hw_register(dev, &gate->hw);
  84        if (ret)
  85                return ERR_PTR(ret);
  86
  87        return &gate->hw;
  88}
  89