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-apmu.c (2120B)


      1/*
      2 * mmp AXI peripharal clock operation source file
      3 *
      4 * Copyright (C) 2012 Marvell
      5 * Chao Xie <xiechao.mail@gmail.com>
      6 *
      7 * This file is licensed under the terms of the GNU General Public
      8 * License version 2. This program is licensed "as is" without any
      9 * warranty of any kind, whether express or implied.
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/io.h>
     14#include <linux/err.h>
     15#include <linux/delay.h>
     16#include <linux/slab.h>
     17
     18#include "clk.h"
     19
     20#define to_clk_apmu(clk) (container_of(clk, struct clk_apmu, clk))
     21struct clk_apmu {
     22	struct clk_hw   hw;
     23	void __iomem    *base;
     24	u32		rst_mask;
     25	u32		enable_mask;
     26	spinlock_t	*lock;
     27};
     28
     29static int clk_apmu_enable(struct clk_hw *hw)
     30{
     31	struct clk_apmu *apmu = to_clk_apmu(hw);
     32	unsigned long data;
     33	unsigned long flags = 0;
     34
     35	if (apmu->lock)
     36		spin_lock_irqsave(apmu->lock, flags);
     37
     38	data = readl_relaxed(apmu->base) | apmu->enable_mask;
     39	writel_relaxed(data, apmu->base);
     40
     41	if (apmu->lock)
     42		spin_unlock_irqrestore(apmu->lock, flags);
     43
     44	return 0;
     45}
     46
     47static void clk_apmu_disable(struct clk_hw *hw)
     48{
     49	struct clk_apmu *apmu = to_clk_apmu(hw);
     50	unsigned long data;
     51	unsigned long flags = 0;
     52
     53	if (apmu->lock)
     54		spin_lock_irqsave(apmu->lock, flags);
     55
     56	data = readl_relaxed(apmu->base) & ~apmu->enable_mask;
     57	writel_relaxed(data, apmu->base);
     58
     59	if (apmu->lock)
     60		spin_unlock_irqrestore(apmu->lock, flags);
     61}
     62
     63static const struct clk_ops clk_apmu_ops = {
     64	.enable = clk_apmu_enable,
     65	.disable = clk_apmu_disable,
     66};
     67
     68struct clk *mmp_clk_register_apmu(const char *name, const char *parent_name,
     69		void __iomem *base, u32 enable_mask, spinlock_t *lock)
     70{
     71	struct clk_apmu *apmu;
     72	struct clk *clk;
     73	struct clk_init_data init;
     74
     75	apmu = kzalloc(sizeof(*apmu), GFP_KERNEL);
     76	if (!apmu)
     77		return NULL;
     78
     79	init.name = name;
     80	init.ops = &clk_apmu_ops;
     81	init.flags = CLK_SET_RATE_PARENT;
     82	init.parent_names = (parent_name ? &parent_name : NULL);
     83	init.num_parents = (parent_name ? 1 : 0);
     84
     85	apmu->base = base;
     86	apmu->enable_mask = enable_mask;
     87	apmu->lock = lock;
     88	apmu->hw.init = &init;
     89
     90	clk = clk_register(NULL, &apmu->hw);
     91
     92	if (IS_ERR(clk))
     93		kfree(apmu);
     94
     95	return clk;
     96}