1/* 2 * linux/arch/arm/mach-mmp/clock.c 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/module.h> 10#include <linux/kernel.h> 11#include <linux/list.h> 12#include <linux/spinlock.h> 13#include <linux/clk.h> 14#include <linux/io.h> 15 16#include <mach/regs-apbc.h> 17#include "clock.h" 18 19static void apbc_clk_enable(struct clk *clk) 20{ 21 uint32_t clk_rst; 22 23 clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(clk->fnclksel); 24 __raw_writel(clk_rst, clk->clk_rst); 25} 26 27static void apbc_clk_disable(struct clk *clk) 28{ 29 __raw_writel(0, clk->clk_rst); 30} 31 32struct clkops apbc_clk_ops = { 33 .enable = apbc_clk_enable, 34 .disable = apbc_clk_disable, 35}; 36 37static void apmu_clk_enable(struct clk *clk) 38{ 39 __raw_writel(clk->enable_val, clk->clk_rst); 40} 41 42static void apmu_clk_disable(struct clk *clk) 43{ 44 __raw_writel(0, clk->clk_rst); 45} 46 47struct clkops apmu_clk_ops = { 48 .enable = apmu_clk_enable, 49 .disable = apmu_clk_disable, 50}; 51 52static DEFINE_SPINLOCK(clocks_lock); 53 54int clk_enable(struct clk *clk) 55{ 56 unsigned long flags; 57 58 spin_lock_irqsave(&clocks_lock, flags); 59 if (clk->enabled++ == 0) 60 clk->ops->enable(clk); 61 spin_unlock_irqrestore(&clocks_lock, flags); 62 return 0; 63} 64EXPORT_SYMBOL(clk_enable); 65 66void clk_disable(struct clk *clk) 67{ 68 unsigned long flags; 69 70 WARN_ON(clk->enabled == 0); 71 72 spin_lock_irqsave(&clocks_lock, flags); 73 if (--clk->enabled == 0) 74 clk->ops->disable(clk); 75 spin_unlock_irqrestore(&clocks_lock, flags); 76} 77EXPORT_SYMBOL(clk_disable); 78 79unsigned long clk_get_rate(struct clk *clk) 80{ 81 unsigned long rate; 82 83 if (clk->ops->getrate) 84 rate = clk->ops->getrate(clk); 85 else 86 rate = clk->rate; 87 88 return rate; 89} 90EXPORT_SYMBOL(clk_get_rate); 91 92int clk_set_rate(struct clk *clk, unsigned long rate) 93{ 94 unsigned long flags; 95 int ret = -EINVAL; 96 97 if (clk->ops->setrate) { 98 spin_lock_irqsave(&clocks_lock, flags); 99 ret = clk->ops->setrate(clk, rate); 100 spin_unlock_irqrestore(&clocks_lock, flags); 101 } 102 103 return ret; 104} 105EXPORT_SYMBOL(clk_set_rate); 106