cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gate.c (2935B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Spreadtrum gate clock driver
      4//
      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	else
     26		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 register
     42	 * common->reg + offset		- set register
     43	 * common->reg + 2 * offset	- clear register
     44	 */
     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);