162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/***************************************************************************/
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci/*
562306a36Sopenharmony_ci *	clk.c -- general ColdFire CPU kernel clk handling
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/***************************************************************************/
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/platform_device.h>
1562306a36Sopenharmony_ci#include <linux/mutex.h>
1662306a36Sopenharmony_ci#include <linux/clk.h>
1762306a36Sopenharmony_ci#include <linux/io.h>
1862306a36Sopenharmony_ci#include <linux/err.h>
1962306a36Sopenharmony_ci#include <asm/coldfire.h>
2062306a36Sopenharmony_ci#include <asm/mcfsim.h>
2162306a36Sopenharmony_ci#include <asm/mcfclk.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic DEFINE_SPINLOCK(clk_lock);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#ifdef MCFPM_PPMCR0
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci *	For more advanced ColdFire parts that have clocks that can be enabled
2862306a36Sopenharmony_ci *	we supply enable/disable functions. These must properly define their
2962306a36Sopenharmony_ci *	clocks in their platform specific code.
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_civoid __clk_init_enabled(struct clk *clk)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	clk->enabled = 1;
3462306a36Sopenharmony_ci	clk->clk_ops->enable(clk);
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_civoid __clk_init_disabled(struct clk *clk)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	clk->enabled = 0;
4062306a36Sopenharmony_ci	clk->clk_ops->disable(clk);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic void __clk_enable0(struct clk *clk)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	__raw_writeb(clk->slot, MCFPM_PPMCR0);
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void __clk_disable0(struct clk *clk)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	__raw_writeb(clk->slot, MCFPM_PPMSR0);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistruct clk_ops clk_ops0 = {
5462306a36Sopenharmony_ci	.enable		= __clk_enable0,
5562306a36Sopenharmony_ci	.disable	= __clk_disable0,
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#ifdef MCFPM_PPMCR1
5962306a36Sopenharmony_cistatic void __clk_enable1(struct clk *clk)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	__raw_writeb(clk->slot, MCFPM_PPMCR1);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic void __clk_disable1(struct clk *clk)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	__raw_writeb(clk->slot, MCFPM_PPMSR1);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistruct clk_ops clk_ops1 = {
7062306a36Sopenharmony_ci	.enable		= __clk_enable1,
7162306a36Sopenharmony_ci	.disable	= __clk_disable1,
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci#endif /* MCFPM_PPMCR1 */
7462306a36Sopenharmony_ci#endif /* MCFPM_PPMCR0 */
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciint clk_enable(struct clk *clk)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	unsigned long flags;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (!clk)
8162306a36Sopenharmony_ci		return 0;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	spin_lock_irqsave(&clk_lock, flags);
8462306a36Sopenharmony_ci	if ((clk->enabled++ == 0) && clk->clk_ops)
8562306a36Sopenharmony_ci		clk->clk_ops->enable(clk);
8662306a36Sopenharmony_ci	spin_unlock_irqrestore(&clk_lock, flags);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	return 0;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ciEXPORT_SYMBOL(clk_enable);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_civoid clk_disable(struct clk *clk)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	unsigned long flags;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (!clk)
9762306a36Sopenharmony_ci		return;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	spin_lock_irqsave(&clk_lock, flags);
10062306a36Sopenharmony_ci	if ((--clk->enabled == 0) && clk->clk_ops)
10162306a36Sopenharmony_ci		clk->clk_ops->disable(clk);
10262306a36Sopenharmony_ci	spin_unlock_irqrestore(&clk_lock, flags);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ciEXPORT_SYMBOL(clk_disable);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciunsigned long clk_get_rate(struct clk *clk)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	if (!clk)
10962306a36Sopenharmony_ci		return 0;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	return clk->rate;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ciEXPORT_SYMBOL(clk_get_rate);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/* dummy functions, should not be called */
11662306a36Sopenharmony_cilong clk_round_rate(struct clk *clk, unsigned long rate)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	WARN_ON(clk);
11962306a36Sopenharmony_ci	return 0;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ciEXPORT_SYMBOL(clk_round_rate);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciint clk_set_rate(struct clk *clk, unsigned long rate)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	WARN_ON(clk);
12662306a36Sopenharmony_ci	return 0;
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ciEXPORT_SYMBOL(clk_set_rate);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciint clk_set_parent(struct clk *clk, struct clk *parent)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	WARN_ON(clk);
13362306a36Sopenharmony_ci	return 0;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ciEXPORT_SYMBOL(clk_set_parent);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistruct clk *clk_get_parent(struct clk *clk)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	WARN_ON(clk);
14062306a36Sopenharmony_ci	return NULL;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ciEXPORT_SYMBOL(clk_get_parent);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/***************************************************************************/
145