File Index
Files and directories
Sign in
FILE

ccu_gate.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sunxi-ng/ccu_gate.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2016 Maxime Ripard
  4 * Maxime Ripard <maxime.ripard@free-electrons.com>
  5 */
  6
  7#include <linux/clk-provider.h>
  8#include <linux/io.h>
  9
 10#include "ccu_gate.h"
 11
 12void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
 13{
 14	unsigned long flags;
 15	u32 reg;
 16
 17	if (!gate)
 18		return;
 19
 20	spin_lock_irqsave(common->lock, flags);
 21
 22	reg = readl(common->base + common->reg);
 23	if (common->features & CCU_FEATURE_UPDATE_BIT)
 24		reg |= CCU_SUNXI_UPDATE_BIT;
 25	writel(reg & ~gate, common->base + common->reg);
 26
 27	spin_unlock_irqrestore(common->lock, flags);
 28}
 29EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, "SUNXI_CCU");
 30
 31static void ccu_gate_disable(struct clk_hw *hw)
 32{
 33	struct ccu_gate *cg = hw_to_ccu_gate(hw);
 34
 35	return ccu_gate_helper_disable(&cg->common, cg->enable);
 36}
 37
 38int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
 39{
 40	unsigned long flags;
 41	u32 reg;
 42
 43	if (!gate)
 44		return 0;
 45
 46	spin_lock_irqsave(common->lock, flags);
 47
 48	reg = readl(common->base + common->reg);
 49	if (common->features & CCU_FEATURE_UPDATE_BIT)
 50		reg |= CCU_SUNXI_UPDATE_BIT;
 51	writel(reg | gate, common->base + common->reg);
 52
 53	spin_unlock_irqrestore(common->lock, flags);
 54
 55	return 0;
 56}
 57EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, "SUNXI_CCU");
 58
 59static int ccu_gate_enable(struct clk_hw *hw)
 60{
 61	struct ccu_gate *cg = hw_to_ccu_gate(hw);
 62
 63	return ccu_gate_helper_enable(&cg->common, cg->enable);
 64}
 65
 66int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
 67{
 68	if (!gate)
 69		return 1;
 70
 71	return readl(common->base + common->reg) & gate;
 72}
 73EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, "SUNXI_CCU");
 74
 75static int ccu_gate_is_enabled(struct clk_hw *hw)
 76{
 77	struct ccu_gate *cg = hw_to_ccu_gate(hw);
 78
 79	return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
 80}
 81
 82static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,
 83					  unsigned long parent_rate)
 84{
 85	struct ccu_gate *cg = hw_to_ccu_gate(hw);
 86	unsigned long rate = parent_rate;
 87
 88	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
 89		rate /= cg->common.prediv;
 90
 91	return rate;
 92}
 93
 94static int ccu_gate_determine_rate(struct clk_hw *hw,
 95				   struct clk_rate_request *req)
 96{
 97	struct ccu_gate *cg = hw_to_ccu_gate(hw);
 98	int div = 1;
 99
100	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
101		div = cg->common.prediv;
102
103	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
104		unsigned long best_parent = req->rate;
105
106		if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
107			best_parent *= div;
108		req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
109	}
110
111	req->rate = req->best_parent_rate / div;
112
113	return 0;
114}
115
116static int ccu_gate_set_rate(struct clk_hw *hw, unsigned long rate,
117			     unsigned long parent_rate)
118{
119	/*
120	 * We must report success but we can do so unconditionally because
121	 * clk_factor_round_rate returns values that ensure this call is a
122	 * nop.
123	 */
124
125	return 0;
126}
127
128const struct clk_ops ccu_gate_ops = {
129	.disable	= ccu_gate_disable,
130	.enable		= ccu_gate_enable,
131	.is_enabled	= ccu_gate_is_enabled,
132	.determine_rate = ccu_gate_determine_rate,
133	.set_rate	= ccu_gate_set_rate,
134	.recalc_rate	= ccu_gate_recalc_rate,
135};
136EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, "SUNXI_CCU");
~/ Read-only file preview.