brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 56e1714 Raw
136 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Spreadtrum gate clock driver4//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	else26		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 register42	 * common->reg + offset		- set register43	 * common->reg + 2 * offset	- clear register44	 */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}82 83static int sprd_pll_sc_gate_prepare(struct clk_hw *hw)84{85	struct sprd_gate *sg = hw_to_sprd_gate(hw);86 87	clk_sc_gate_toggle(sg, true);88	udelay(sg->udelay);89 90	return 0;91}92 93static int sprd_gate_is_enabled(struct clk_hw *hw)94{95	struct sprd_gate *sg = hw_to_sprd_gate(hw);96	struct sprd_clk_common *common = &sg->common;97	struct clk_hw *parent;98	unsigned int reg;99 100	if (sg->flags & SPRD_GATE_NON_AON) {101		parent = clk_hw_get_parent(hw);102		if (!parent || !clk_hw_is_enabled(parent))103			return 0;104	}105 106	regmap_read(common->regmap, common->reg, &reg);107 108	if (sg->flags & CLK_GATE_SET_TO_DISABLE)109		reg ^= sg->enable_mask;110 111	reg &= sg->enable_mask;112 113	return reg ? 1 : 0;114}115 116const struct clk_ops sprd_gate_ops = {117	.disable	= sprd_gate_disable,118	.enable		= sprd_gate_enable,119	.is_enabled	= sprd_gate_is_enabled,120};121EXPORT_SYMBOL_GPL(sprd_gate_ops);122 123const struct clk_ops sprd_sc_gate_ops = {124	.disable	= sprd_sc_gate_disable,125	.enable		= sprd_sc_gate_enable,126	.is_enabled	= sprd_gate_is_enabled,127};128EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);129 130const struct clk_ops sprd_pll_sc_gate_ops = {131	.unprepare	= sprd_sc_gate_disable,132	.prepare	= sprd_pll_sc_gate_prepare,133	.is_enabled	= sprd_gate_is_enabled,134};135EXPORT_SYMBOL_GPL(sprd_pll_sc_gate_ops);136