2006-03-15 15:54:37 +00:00
/*
* linux / arch / arm / mach - sa1100 / clock . c
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/errno.h>
# include <linux/err.h>
# include <linux/string.h>
# include <linux/clk.h>
# include <linux/spinlock.h>
2007-08-20 10:18:02 +01:00
# include <linux/platform_device.h>
# include <linux/delay.h>
2006-03-15 15:54:37 +00:00
# include <asm/arch/pxa-regs.h>
2008-03-03 09:44:25 +08:00
# include <asm/arch/pxa2xx-gpio.h>
2006-03-15 15:54:37 +00:00
# include <asm/hardware.h>
2007-08-20 10:18:02 +01:00
# include "devices.h"
# include "generic.h"
# include "clock.h"
2006-03-15 15:54:37 +00:00
static LIST_HEAD ( clocks ) ;
2007-05-15 16:49:02 +01:00
static DEFINE_MUTEX ( clocks_mutex ) ;
2006-03-15 15:54:37 +00:00
static DEFINE_SPINLOCK ( clocks_lock ) ;
2008-02-17 10:35:15 +00:00
static struct clk * clk_lookup ( struct device * dev , const char * id )
{
struct clk * p ;
list_for_each_entry ( p , & clocks , node )
if ( strcmp ( id , p - > name ) = = 0 & & p - > dev = = dev )
return p ;
return NULL ;
}
2006-03-15 15:54:37 +00:00
struct clk * clk_get ( struct device * dev , const char * id )
{
struct clk * p , * clk = ERR_PTR ( - ENOENT ) ;
2007-05-15 16:49:02 +01:00
mutex_lock ( & clocks_mutex ) ;
2008-02-17 10:35:15 +00:00
p = clk_lookup ( dev , id ) ;
if ( ! p )
p = clk_lookup ( NULL , id ) ;
if ( p )
clk = p ;
2007-05-15 16:49:02 +01:00
mutex_unlock ( & clocks_mutex ) ;
2006-03-15 15:54:37 +00:00
return clk ;
}
EXPORT_SYMBOL ( clk_get ) ;
void clk_put ( struct clk * clk )
{
}
EXPORT_SYMBOL ( clk_put ) ;
int clk_enable ( struct clk * clk )
{
unsigned long flags ;
spin_lock_irqsave ( & clocks_lock , flags ) ;
if ( clk - > enabled + + = = 0 )
2007-08-20 10:18:02 +01:00
clk - > ops - > enable ( clk ) ;
2006-03-15 15:54:37 +00:00
spin_unlock_irqrestore ( & clocks_lock , flags ) ;
2007-08-20 10:18:02 +01:00
if ( clk - > delay )
udelay ( clk - > delay ) ;
2006-03-15 15:54:37 +00:00
return 0 ;
}
EXPORT_SYMBOL ( clk_enable ) ;
void clk_disable ( struct clk * clk )
{
unsigned long flags ;
WARN_ON ( clk - > enabled = = 0 ) ;
spin_lock_irqsave ( & clocks_lock , flags ) ;
if ( - - clk - > enabled = = 0 )
2007-08-20 10:18:02 +01:00
clk - > ops - > disable ( clk ) ;
2006-03-15 15:54:37 +00:00
spin_unlock_irqrestore ( & clocks_lock , flags ) ;
}
EXPORT_SYMBOL ( clk_disable ) ;
unsigned long clk_get_rate ( struct clk * clk )
{
2007-08-20 10:18:02 +01:00
unsigned long rate ;
rate = clk - > rate ;
if ( clk - > ops - > getrate )
rate = clk - > ops - > getrate ( clk ) ;
return rate ;
2006-03-15 15:54:37 +00:00
}
EXPORT_SYMBOL ( clk_get_rate ) ;
2007-08-20 10:18:02 +01:00
static void clk_gpio27_enable ( struct clk * clk )
2006-03-15 15:54:37 +00:00
{
pxa_gpio_mode ( GPIO11_3_6MHz_MD ) ;
}
2007-08-20 10:18:02 +01:00
static void clk_gpio27_disable ( struct clk * clk )
2006-03-15 15:54:37 +00:00
{
}
2007-08-20 10:18:02 +01:00
static const struct clkops clk_gpio27_ops = {
2006-03-15 15:54:37 +00:00
. enable = clk_gpio27_enable ,
. disable = clk_gpio27_disable ,
} ;
2007-08-20 10:18:02 +01:00
void clk_cken_enable ( struct clk * clk )
2006-03-15 15:54:37 +00:00
{
2007-08-20 10:18:02 +01:00
CKEN | = 1 < < clk - > cken ;
2006-03-15 15:54:37 +00:00
}
2007-08-20 10:18:02 +01:00
void clk_cken_disable ( struct clk * clk )
2006-03-15 15:54:37 +00:00
{
2007-08-20 10:18:02 +01:00
CKEN & = ~ ( 1 < < clk - > cken ) ;
}
const struct clkops clk_cken_ops = {
. enable = clk_cken_enable ,
. disable = clk_cken_disable ,
} ;
static struct clk common_clks [ ] = {
{
. name = " GPIO27_CLK " ,
. ops = & clk_gpio27_ops ,
. rate = 3686400 ,
} ,
} ;
void clks_register ( struct clk * clks , size_t num )
{
int i ;
2007-05-15 16:49:02 +01:00
mutex_lock ( & clocks_mutex ) ;
2007-08-20 10:18:02 +01:00
for ( i = 0 ; i < num ; i + + )
list_add ( & clks [ i ] . node , & clocks ) ;
2007-05-15 16:49:02 +01:00
mutex_unlock ( & clocks_mutex ) ;
2006-03-15 15:54:37 +00:00
}
static int __init clk_init ( void )
{
2007-08-20 10:18:02 +01:00
clks_register ( common_clks , ARRAY_SIZE ( common_clks ) ) ;
2006-03-15 15:54:37 +00:00
return 0 ;
}
arch_initcall ( clk_init ) ;