brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · a2115a2 Raw
131 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2016 Maxime Ripard4 * 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	writel(reg & ~gate, common->base + common->reg);24 25	spin_unlock_irqrestore(common->lock, flags);26}27EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, SUNXI_CCU);28 29static void ccu_gate_disable(struct clk_hw *hw)30{31	struct ccu_gate *cg = hw_to_ccu_gate(hw);32 33	return ccu_gate_helper_disable(&cg->common, cg->enable);34}35 36int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)37{38	unsigned long flags;39	u32 reg;40 41	if (!gate)42		return 0;43 44	spin_lock_irqsave(common->lock, flags);45 46	reg = readl(common->base + common->reg);47	writel(reg | gate, common->base + common->reg);48 49	spin_unlock_irqrestore(common->lock, flags);50 51	return 0;52}53EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, SUNXI_CCU);54 55static int ccu_gate_enable(struct clk_hw *hw)56{57	struct ccu_gate *cg = hw_to_ccu_gate(hw);58 59	return ccu_gate_helper_enable(&cg->common, cg->enable);60}61 62int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)63{64	if (!gate)65		return 1;66 67	return readl(common->base + common->reg) & gate;68}69EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, SUNXI_CCU);70 71static int ccu_gate_is_enabled(struct clk_hw *hw)72{73	struct ccu_gate *cg = hw_to_ccu_gate(hw);74 75	return ccu_gate_helper_is_enabled(&cg->common, cg->enable);76}77 78static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,79					  unsigned long parent_rate)80{81	struct ccu_gate *cg = hw_to_ccu_gate(hw);82	unsigned long rate = parent_rate;83 84	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)85		rate /= cg->common.prediv;86 87	return rate;88}89 90static long ccu_gate_round_rate(struct clk_hw *hw, unsigned long rate,91				unsigned long *prate)92{93	struct ccu_gate *cg = hw_to_ccu_gate(hw);94	int div = 1;95 96	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)97		div = cg->common.prediv;98 99	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {100		unsigned long best_parent = rate;101 102		if (cg->common.features & CCU_FEATURE_ALL_PREDIV)103			best_parent *= div;104		*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);105	}106 107	return *prate / div;108}109 110static int ccu_gate_set_rate(struct clk_hw *hw, unsigned long rate,111			     unsigned long parent_rate)112{113	/*114	 * We must report success but we can do so unconditionally because115	 * clk_factor_round_rate returns values that ensure this call is a116	 * nop.117	 */118 119	return 0;120}121 122const struct clk_ops ccu_gate_ops = {123	.disable	= ccu_gate_disable,124	.enable		= ccu_gate_enable,125	.is_enabled	= ccu_gate_is_enabled,126	.round_rate	= ccu_gate_round_rate,127	.set_rate	= ccu_gate_set_rate,128	.recalc_rate	= ccu_gate_recalc_rate,129};130EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, SUNXI_CCU);131