162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// OWL gate clock driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (c) 2014 Actions Semi Inc.
662306a36Sopenharmony_ci// Author: David Liu <liuwei@actions-semi.com>
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Copyright (c) 2018 Linaro Ltd.
962306a36Sopenharmony_ci// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/clk-provider.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "owl-gate.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_civoid owl_gate_set(const struct owl_clk_common *common,
1762306a36Sopenharmony_ci		 const struct owl_gate_hw *gate_hw, bool enable)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	int set = gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
2062306a36Sopenharmony_ci	u32 reg;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	set ^= enable;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	regmap_read(common->regmap, gate_hw->reg, &reg);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (set)
2762306a36Sopenharmony_ci		reg |= BIT(gate_hw->bit_idx);
2862306a36Sopenharmony_ci	else
2962306a36Sopenharmony_ci		reg &= ~BIT(gate_hw->bit_idx);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	regmap_write(common->regmap, gate_hw->reg, reg);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic void owl_gate_disable(struct clk_hw *hw)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	struct owl_gate *gate = hw_to_owl_gate(hw);
3762306a36Sopenharmony_ci	struct owl_clk_common *common = &gate->common;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	owl_gate_set(common, &gate->gate_hw, false);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic int owl_gate_enable(struct clk_hw *hw)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	struct owl_gate *gate = hw_to_owl_gate(hw);
4562306a36Sopenharmony_ci	struct owl_clk_common *common = &gate->common;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	owl_gate_set(common, &gate->gate_hw, true);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return 0;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciint owl_gate_clk_is_enabled(const struct owl_clk_common *common,
5362306a36Sopenharmony_ci		   const struct owl_gate_hw *gate_hw)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	u32 reg;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	regmap_read(common->regmap, gate_hw->reg, &reg);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	if (gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE)
6062306a36Sopenharmony_ci		reg ^= BIT(gate_hw->bit_idx);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return !!(reg & BIT(gate_hw->bit_idx));
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic int owl_gate_is_enabled(struct clk_hw *hw)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	struct owl_gate *gate = hw_to_owl_gate(hw);
6862306a36Sopenharmony_ci	struct owl_clk_common *common = &gate->common;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return owl_gate_clk_is_enabled(common, &gate->gate_hw);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciconst struct clk_ops owl_gate_ops = {
7462306a36Sopenharmony_ci	.disable	= owl_gate_disable,
7562306a36Sopenharmony_ci	.enable		= owl_gate_enable,
7662306a36Sopenharmony_ci	.is_enabled	= owl_gate_is_enabled,
7762306a36Sopenharmony_ci};
78