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