18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// OWL gate clock driver 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (c) 2014 Actions Semi Inc. 68c2ecf20Sopenharmony_ci// Author: David Liu <liuwei@actions-semi.com> 78c2ecf20Sopenharmony_ci// 88c2ecf20Sopenharmony_ci// Copyright (c) 2018 Linaro Ltd. 98c2ecf20Sopenharmony_ci// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "owl-gate.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_civoid owl_gate_set(const struct owl_clk_common *common, 178c2ecf20Sopenharmony_ci const struct owl_gate_hw *gate_hw, bool enable) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci int set = gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; 208c2ecf20Sopenharmony_ci u32 reg; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci set ^= enable; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci regmap_read(common->regmap, gate_hw->reg, ®); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (set) 278c2ecf20Sopenharmony_ci reg |= BIT(gate_hw->bit_idx); 288c2ecf20Sopenharmony_ci else 298c2ecf20Sopenharmony_ci reg &= ~BIT(gate_hw->bit_idx); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci regmap_write(common->regmap, gate_hw->reg, reg); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic void owl_gate_disable(struct clk_hw *hw) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct owl_gate *gate = hw_to_owl_gate(hw); 378c2ecf20Sopenharmony_ci struct owl_clk_common *common = &gate->common; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci owl_gate_set(common, &gate->gate_hw, false); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int owl_gate_enable(struct clk_hw *hw) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci struct owl_gate *gate = hw_to_owl_gate(hw); 458c2ecf20Sopenharmony_ci struct owl_clk_common *common = &gate->common; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci owl_gate_set(common, &gate->gate_hw, true); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint owl_gate_clk_is_enabled(const struct owl_clk_common *common, 538c2ecf20Sopenharmony_ci const struct owl_gate_hw *gate_hw) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci u32 reg; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci regmap_read(common->regmap, gate_hw->reg, ®); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE) 608c2ecf20Sopenharmony_ci reg ^= BIT(gate_hw->bit_idx); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci return !!(reg & BIT(gate_hw->bit_idx)); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int owl_gate_is_enabled(struct clk_hw *hw) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct owl_gate *gate = hw_to_owl_gate(hw); 688c2ecf20Sopenharmony_ci struct owl_clk_common *common = &gate->common; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return owl_gate_clk_is_enabled(common, &gate->gate_hw); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciconst struct clk_ops owl_gate_ops = { 748c2ecf20Sopenharmony_ci .disable = owl_gate_disable, 758c2ecf20Sopenharmony_ci .enable = owl_gate_enable, 768c2ecf20Sopenharmony_ci .is_enabled = owl_gate_is_enabled, 778c2ecf20Sopenharmony_ci}; 78