2009-11-17 01:32:59 +08:00
/*
2015-07-07 20:56:04 +02:00
* Copyright ( C ) 2006 - 2008 Lemote Inc . & Institute of Computing Technology
2009-11-17 01:32:59 +08:00
* Author : Yanhua , yanh @ lemote . com
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
2012-08-01 17:15:32 +02:00
# include <linux/clk.h>
2009-11-17 01:32:59 +08:00
# include <linux/cpufreq.h>
2012-08-01 17:15:32 +02:00
# include <linux/errno.h>
# include <linux/export.h>
# include <linux/list.h>
# include <linux/mutex.h>
# include <linux/spinlock.h>
2009-11-17 01:32:59 +08:00
# include <asm/clock.h>
2015-07-07 20:49:03 +02:00
# include <asm/mach-loongson64/loongson.h>
2009-11-17 01:32:59 +08:00
static LIST_HEAD ( clock_list ) ;
static DEFINE_SPINLOCK ( clock_lock ) ;
static DEFINE_MUTEX ( clock_list_sem ) ;
/* Minimum CLK support */
enum {
DC_ZERO , DC_25PT = 2 , DC_37PT , DC_50PT , DC_62PT , DC_75PT ,
DC_87PT , DC_DISABLE , DC_RESV
} ;
struct cpufreq_frequency_table loongson2_clockmod_table [ ] = {
2014-03-28 19:11:47 +05:30
{ 0 , DC_RESV , CPUFREQ_ENTRY_INVALID } ,
{ 0 , DC_ZERO , CPUFREQ_ENTRY_INVALID } ,
{ 0 , DC_25PT , 0 } ,
{ 0 , DC_37PT , 0 } ,
{ 0 , DC_50PT , 0 } ,
{ 0 , DC_62PT , 0 } ,
{ 0 , DC_75PT , 0 } ,
{ 0 , DC_87PT , 0 } ,
{ 0 , DC_DISABLE , 0 } ,
{ 0 , DC_RESV , CPUFREQ_TABLE_END } ,
2009-11-17 01:32:59 +08:00
} ;
EXPORT_SYMBOL_GPL ( loongson2_clockmod_table ) ;
static struct clk cpu_clk = {
. name = " cpu_clk " ,
. flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES ,
. rate = 800000000 ,
} ;
struct clk * clk_get ( struct device * dev , const char * id )
{
return & cpu_clk ;
}
EXPORT_SYMBOL ( clk_get ) ;
static void propagate_rate ( struct clk * clk )
{
struct clk * clkp ;
list_for_each_entry ( clkp , & clock_list , node ) {
if ( likely ( clkp - > parent ! = clk ) )
continue ;
if ( likely ( clkp - > ops & & clkp - > ops - > recalc ) )
clkp - > ops - > recalc ( clkp ) ;
if ( unlikely ( clkp - > flags & CLK_RATE_PROPAGATES ) )
propagate_rate ( clkp ) ;
}
}
int clk_enable ( struct clk * clk )
{
return 0 ;
}
EXPORT_SYMBOL ( clk_enable ) ;
void clk_disable ( struct clk * clk )
{
}
EXPORT_SYMBOL ( clk_disable ) ;
unsigned long clk_get_rate ( struct clk * clk )
{
return ( unsigned long ) clk - > rate ;
}
EXPORT_SYMBOL ( clk_get_rate ) ;
void clk_put ( struct clk * clk )
{
}
EXPORT_SYMBOL ( clk_put ) ;
int clk_set_rate ( struct clk * clk , unsigned long rate )
{
2014-09-21 15:38:43 +03:00
unsigned int rate_khz = rate / 1000 ;
2014-04-25 23:16:25 +03:00
struct cpufreq_frequency_table * pos ;
2009-11-17 01:32:59 +08:00
int ret = 0 ;
int regval ;
if ( likely ( clk - > ops & & clk - > ops - > set_rate ) ) {
unsigned long flags ;
spin_lock_irqsave ( & clock_lock , flags ) ;
2012-08-01 17:15:32 +02:00
ret = clk - > ops - > set_rate ( clk , rate , 0 ) ;
2009-11-17 01:32:59 +08:00
spin_unlock_irqrestore ( & clock_lock , flags ) ;
}
if ( unlikely ( clk - > flags & CLK_RATE_PROPAGATES ) )
propagate_rate ( clk ) ;
2014-04-25 23:16:25 +03:00
cpufreq_for_each_valid_entry ( pos , loongson2_clockmod_table )
2014-09-21 15:38:43 +03:00
if ( rate_khz = = pos - > frequency )
2009-11-17 01:32:59 +08:00
break ;
2014-09-21 15:38:43 +03:00
if ( rate_khz ! = pos - > frequency )
2009-11-17 01:32:59 +08:00
return - ENOTSUPP ;
clk - > rate = rate ;
2014-06-26 11:41:27 +08:00
regval = LOONGSON_CHIPCFG ( 0 ) ;
2014-04-25 23:16:25 +03:00
regval = ( regval & ~ 0x7 ) | ( pos - > driver_data - 1 ) ;
2014-06-26 11:41:27 +08:00
LOONGSON_CHIPCFG ( 0 ) = regval ;
2009-11-17 01:32:59 +08:00
return ret ;
}
2012-08-01 17:15:32 +02:00
EXPORT_SYMBOL_GPL ( clk_set_rate ) ;
2009-11-17 01:32:59 +08:00
long clk_round_rate ( struct clk * clk , unsigned long rate )
{
if ( likely ( clk - > ops & & clk - > ops - > round_rate ) ) {
unsigned long flags , rounded ;
spin_lock_irqsave ( & clock_lock , flags ) ;
rounded = clk - > ops - > round_rate ( clk , rate ) ;
spin_unlock_irqrestore ( & clock_lock , flags ) ;
return rounded ;
}
return rate ;
}
EXPORT_SYMBOL_GPL ( clk_round_rate ) ;