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