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

clk-gate-exclusive.c (2261B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2014 Freescale Semiconductor, Inc.
      4 */
      5
      6#include <linux/clk-provider.h>
      7#include <linux/err.h>
      8#include <linux/io.h>
      9#include <linux/slab.h>
     10#include "clk.h"
     11
     12/**
     13 * struct clk_gate_exclusive - i.MX specific gate clock which is mutually
     14 * exclusive with other gate clocks
     15 *
     16 * @gate: the parent class
     17 * @exclusive_mask: mask of gate bits which are mutually exclusive to this
     18 *	gate clock
     19 *
     20 * The imx exclusive gate clock is a subclass of basic clk_gate
     21 * with an addtional mask to indicate which other gate bits in the same
     22 * register is mutually exclusive to this gate clock.
     23 */
     24struct clk_gate_exclusive {
     25	struct clk_gate gate;
     26	u32 exclusive_mask;
     27};
     28
     29static int clk_gate_exclusive_enable(struct clk_hw *hw)
     30{
     31	struct clk_gate *gate = to_clk_gate(hw);
     32	struct clk_gate_exclusive *exgate = container_of(gate,
     33					struct clk_gate_exclusive, gate);
     34	u32 val = readl(gate->reg);
     35
     36	if (val & exgate->exclusive_mask)
     37		return -EBUSY;
     38
     39	return clk_gate_ops.enable(hw);
     40}
     41
     42static void clk_gate_exclusive_disable(struct clk_hw *hw)
     43{
     44	clk_gate_ops.disable(hw);
     45}
     46
     47static int clk_gate_exclusive_is_enabled(struct clk_hw *hw)
     48{
     49	return clk_gate_ops.is_enabled(hw);
     50}
     51
     52static const struct clk_ops clk_gate_exclusive_ops = {
     53	.enable = clk_gate_exclusive_enable,
     54	.disable = clk_gate_exclusive_disable,
     55	.is_enabled = clk_gate_exclusive_is_enabled,
     56};
     57
     58struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
     59	 void __iomem *reg, u8 shift, u32 exclusive_mask)
     60{
     61	struct clk_gate_exclusive *exgate;
     62	struct clk_gate *gate;
     63	struct clk_hw *hw;
     64	struct clk_init_data init;
     65	int ret;
     66
     67	if (exclusive_mask == 0)
     68		return ERR_PTR(-EINVAL);
     69
     70	exgate = kzalloc(sizeof(*exgate), GFP_KERNEL);
     71	if (!exgate)
     72		return ERR_PTR(-ENOMEM);
     73	gate = &exgate->gate;
     74
     75	init.name = name;
     76	init.ops = &clk_gate_exclusive_ops;
     77	init.flags = CLK_SET_RATE_PARENT;
     78	init.parent_names = parent ? &parent : NULL;
     79	init.num_parents = parent ? 1 : 0;
     80
     81	gate->reg = reg;
     82	gate->bit_idx = shift;
     83	gate->lock = &imx_ccm_lock;
     84	gate->hw.init = &init;
     85	exgate->exclusive_mask = exclusive_mask;
     86
     87	hw = &gate->hw;
     88
     89	ret = clk_hw_register(NULL, hw);
     90	if (ret) {
     91		kfree(gate);
     92		return ERR_PTR(ret);
     93	}
     94
     95	return hw;
     96}