linux/drivers/clk/sprd/gate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Spreadtrum gate clock driver
   4//
   5// Copyright (C) 2017 Spreadtrum, Inc.
   6// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
   7
   8#include <linux/clk-provider.h>
   9#include <linux/regmap.h>
  10
  11#include "gate.h"
  12
  13static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
  14{
  15        const struct sprd_clk_common *common = &sg->common;
  16        unsigned int reg;
  17        bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
  18
  19        set ^= en;
  20
  21        regmap_read(common->regmap, common->reg, &reg);
  22
  23        if (set)
  24                reg |= sg->enable_mask;
  25        else
  26                reg &= ~sg->enable_mask;
  27
  28        regmap_write(common->regmap, common->reg, reg);
  29}
  30
  31static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
  32{
  33        const struct sprd_clk_common *common = &sg->common;
  34        bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
  35        unsigned int offset;
  36
  37        set ^= en;
  38
  39        /*
  40         * Each set/clear gate clock has three registers:
  41         * common->reg                  - base register
  42         * common->reg + offset         - set register
  43         * common->reg + 2 * offset     - clear register
  44         */
  45        offset = set ? sg->sc_offset : sg->sc_offset * 2;
  46
  47        regmap_write(common->regmap, common->reg + offset,
  48                          sg->enable_mask);
  49}
  50
  51static void sprd_gate_disable(struct clk_hw *hw)
  52{
  53        struct sprd_gate *sg = hw_to_sprd_gate(hw);
  54
  55        clk_gate_toggle(sg, false);
  56}
  57
  58static int sprd_gate_enable(struct clk_hw *hw)
  59{
  60        struct sprd_gate *sg = hw_to_sprd_gate(hw);
  61
  62        clk_gate_toggle(sg, true);
  63
  64        return 0;
  65}
  66
  67static void sprd_sc_gate_disable(struct clk_hw *hw)
  68{
  69        struct sprd_gate *sg = hw_to_sprd_gate(hw);
  70
  71        clk_sc_gate_toggle(sg, false);
  72}
  73
  74static int sprd_sc_gate_enable(struct clk_hw *hw)
  75{
  76        struct sprd_gate *sg = hw_to_sprd_gate(hw);
  77
  78        clk_sc_gate_toggle(sg, true);
  79
  80        return 0;
  81}
  82static int sprd_gate_is_enabled(struct clk_hw *hw)
  83{
  84        struct sprd_gate *sg = hw_to_sprd_gate(hw);
  85        struct sprd_clk_common *common = &sg->common;
  86        unsigned int reg;
  87
  88        regmap_read(common->regmap, common->reg, &reg);
  89
  90        if (sg->flags & CLK_GATE_SET_TO_DISABLE)
  91                reg ^= sg->enable_mask;
  92
  93        reg &= sg->enable_mask;
  94
  95        return reg ? 1 : 0;
  96}
  97
  98const struct clk_ops sprd_gate_ops = {
  99        .disable        = sprd_gate_disable,
 100        .enable         = sprd_gate_enable,
 101        .is_enabled     = sprd_gate_is_enabled,
 102};
 103EXPORT_SYMBOL_GPL(sprd_gate_ops);
 104
 105const struct clk_ops sprd_sc_gate_ops = {
 106        .disable        = sprd_sc_gate_disable,
 107        .enable         = sprd_sc_gate_enable,
 108        .is_enabled     = sprd_gate_is_enabled,
 109};
 110EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
 111
 112