brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 350eeb3 Raw
128 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * mmp gate clock operation source file4 *5 * Copyright (C) 2014 Marvell6 * Chao Xie <chao.xie@marvell.com>7 */8 9#include <linux/clk-provider.h>10#include <linux/slab.h>11#include <linux/io.h>12#include <linux/err.h>13#include <linux/delay.h>14 15#include "clk.h"16 17/*18 * Some clocks will have mutiple bits to enable the clocks, and19 * the bits to disable the clock is not same as enabling bits.20 */21 22#define to_clk_mmp_gate(hw)	container_of(hw, struct mmp_clk_gate, hw)23 24static int mmp_clk_gate_enable(struct clk_hw *hw)25{26	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);27	unsigned long flags = 0;28	unsigned long rate;29	u32 tmp;30 31	if (gate->lock)32		spin_lock_irqsave(gate->lock, flags);33 34	tmp = readl(gate->reg);35	tmp &= ~gate->mask;36	tmp |= gate->val_enable;37	writel(tmp, gate->reg);38 39	if (gate->lock)40		spin_unlock_irqrestore(gate->lock, flags);41 42	if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {43		rate = clk_hw_get_rate(hw);44		/* Need delay 2 cycles. */45		udelay(2000000/rate);46	}47 48	return 0;49}50 51static void mmp_clk_gate_disable(struct clk_hw *hw)52{53	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);54	unsigned long flags = 0;55	u32 tmp;56 57	if (gate->lock)58		spin_lock_irqsave(gate->lock, flags);59 60	tmp = readl(gate->reg);61	tmp &= ~gate->mask;62	tmp |= gate->val_disable;63	writel(tmp, gate->reg);64 65	if (gate->lock)66		spin_unlock_irqrestore(gate->lock, flags);67}68 69static int mmp_clk_gate_is_enabled(struct clk_hw *hw)70{71	struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);72	unsigned long flags = 0;73	u32 tmp;74 75	if (gate->lock)76		spin_lock_irqsave(gate->lock, flags);77 78	tmp = readl(gate->reg);79 80	if (gate->lock)81		spin_unlock_irqrestore(gate->lock, flags);82 83	return (tmp & gate->mask) == gate->val_enable;84}85 86const struct clk_ops mmp_clk_gate_ops = {87	.enable = mmp_clk_gate_enable,88	.disable = mmp_clk_gate_disable,89	.is_enabled = mmp_clk_gate_is_enabled,90};91 92struct clk *mmp_clk_register_gate(struct device *dev, const char *name,93		const char *parent_name, unsigned long flags,94		void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,95		unsigned int gate_flags, spinlock_t *lock)96{97	struct mmp_clk_gate *gate;98	struct clk *clk;99	struct clk_init_data init;100 101	/* allocate the gate */102	gate = kzalloc(sizeof(*gate), GFP_KERNEL);103	if (!gate)104		return ERR_PTR(-ENOMEM);105 106	init.name = name;107	init.ops = &mmp_clk_gate_ops;108	init.flags = flags;109	init.parent_names = (parent_name ? &parent_name : NULL);110	init.num_parents = (parent_name ? 1 : 0);111 112	/* struct clk_gate assignments */113	gate->reg = reg;114	gate->mask = mask;115	gate->val_enable = val_enable;116	gate->val_disable = val_disable;117	gate->flags = gate_flags;118	gate->lock = lock;119	gate->hw.init = &init;120 121	clk = clk_register(dev, &gate->hw);122 123	if (IS_ERR(clk))124		kfree(gate);125 126	return clk;127}128