2005-11-10 17:26:48 +03:00
/*
* linux / arch / arm / mach - omap1 / clock . c
*
2010-02-23 08:09:26 +03:00
* Copyright ( C ) 2004 - 2005 , 2009 - 2010 Nokia Corporation
2005-11-10 17:26:48 +03:00
* Written by Tuukka Tikkanen < tuukka . tikkanen @ elektrobit . com >
*
* Modified to use omap shared clock framework by
* Tony Lindgren < tony @ atomide . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/errno.h>
# include <linux/err.h>
2006-01-07 19:15:52 +03:00
# include <linux/clk.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2010-11-17 12:04:33 +03:00
# include <linux/clkdev.h>
2005-11-10 17:26:48 +03:00
2006-09-25 14:27:20 +04:00
# include <asm/mach-types.h>
2005-11-10 17:26:48 +03:00
2009-10-20 20:40:47 +04:00
# include <plat/cpu.h>
# include <plat/usb.h>
# include <plat/clock.h>
# include <plat/sram.h>
2009-12-09 02:29:38 +03:00
# include <plat/clkdev_omap.h>
2008-11-04 17:02:46 +03:00
2005-11-10 17:26:48 +03:00
# include "clock.h"
2009-12-09 02:29:38 +03:00
# include "opp.h"
__u32 arm_idlect1_mask ;
struct clk * api_ck_p , * ck_dpll1_p , * ck_ref_p ;
2010-07-27 02:34:28 +04:00
/*
2009-12-09 02:29:38 +03:00
* Omap1 specific clock functions
2010-07-27 02:34:28 +04:00
*/
2005-11-10 17:26:48 +03:00
2009-12-09 02:29:38 +03:00
unsigned long omap1_uart_recalc ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
2009-01-28 22:18:48 +03:00
unsigned int val = __raw_readl ( clk - > enable_reg ) ;
2009-02-12 13:12:59 +03:00
return val & clk - > enable_bit ? 48000000 : 12000000 ;
2005-11-10 17:26:48 +03:00
}
2009-12-09 02:29:38 +03:00
unsigned long omap1_sossi_recalc ( struct clk * clk )
2007-03-05 18:22:58 +03:00
{
u32 div = omap_readl ( MOD_CONF_CTRL_1 ) ;
div = ( div > > 17 ) & 0x7 ;
div + + ;
2009-02-12 13:12:59 +03:00
return clk - > parent - > rate / div ;
2007-03-05 18:22:58 +03:00
}
2005-11-10 17:26:48 +03:00
static void omap1_clk_allow_idle ( struct clk * clk )
{
struct arm_idlect1_clk * iclk = ( struct arm_idlect1_clk * ) clk ;
if ( ! ( clk - > flags & CLOCK_IDLE_CONTROL ) )
return ;
if ( iclk - > no_idle_count > 0 & & ! ( - - iclk - > no_idle_count ) )
arm_idlect1_mask | = 1 < < iclk - > idlect_shift ;
}
static void omap1_clk_deny_idle ( struct clk * clk )
{
struct arm_idlect1_clk * iclk = ( struct arm_idlect1_clk * ) clk ;
if ( ! ( clk - > flags & CLOCK_IDLE_CONTROL ) )
return ;
if ( iclk - > no_idle_count + + = = 0 )
arm_idlect1_mask & = ~ ( 1 < < iclk - > idlect_shift ) ;
}
static __u16 verify_ckctl_value ( __u16 newval )
{
/* This function checks for following limitations set
* by the hardware ( all conditions must be true ) :
* DSPMMU_CK = = DSP_CK or DSPMMU_CK = = DSP_CK / 2
* ARM_CK > = TC_CK
* DSP_CK > = TC_CK
* DSPMMU_CK > = TC_CK
*
* In addition following rules are enforced :
* LCD_CK < = TC_CK
* ARMPER_CK < = TC_CK
*
* However , maximum frequencies are not checked for !
*/
__u8 per_exp ;
__u8 lcd_exp ;
__u8 arm_exp ;
__u8 dsp_exp ;
__u8 tc_exp ;
__u8 dspmmu_exp ;
per_exp = ( newval > > CKCTL_PERDIV_OFFSET ) & 3 ;
lcd_exp = ( newval > > CKCTL_LCDDIV_OFFSET ) & 3 ;
arm_exp = ( newval > > CKCTL_ARMDIV_OFFSET ) & 3 ;
dsp_exp = ( newval > > CKCTL_DSPDIV_OFFSET ) & 3 ;
tc_exp = ( newval > > CKCTL_TCDIV_OFFSET ) & 3 ;
dspmmu_exp = ( newval > > CKCTL_DSPMMUDIV_OFFSET ) & 3 ;
if ( dspmmu_exp < dsp_exp )
dspmmu_exp = dsp_exp ;
if ( dspmmu_exp > dsp_exp + 1 )
dspmmu_exp = dsp_exp + 1 ;
if ( tc_exp < arm_exp )
tc_exp = arm_exp ;
if ( tc_exp < dspmmu_exp )
tc_exp = dspmmu_exp ;
if ( tc_exp > lcd_exp )
lcd_exp = tc_exp ;
if ( tc_exp > per_exp )
per_exp = tc_exp ;
newval & = 0xf000 ;
newval | = per_exp < < CKCTL_PERDIV_OFFSET ;
newval | = lcd_exp < < CKCTL_LCDDIV_OFFSET ;
newval | = arm_exp < < CKCTL_ARMDIV_OFFSET ;
newval | = dsp_exp < < CKCTL_DSPDIV_OFFSET ;
newval | = tc_exp < < CKCTL_TCDIV_OFFSET ;
newval | = dspmmu_exp < < CKCTL_DSPMMUDIV_OFFSET ;
return newval ;
}
static int calc_dsor_exp ( struct clk * clk , unsigned long rate )
{
/* Note: If target frequency is too low, this function will return 4,
* which is invalid value . Caller must check for this value and act
* accordingly .
*
* Note : This function does not check for following limitations set
* by the hardware ( all conditions must be true ) :
* DSPMMU_CK = = DSP_CK or DSPMMU_CK = = DSP_CK / 2
* ARM_CK > = TC_CK
* DSP_CK > = TC_CK
* DSPMMU_CK > = TC_CK
*/
unsigned long realrate ;
struct clk * parent ;
unsigned dsor_exp ;
parent = clk - > parent ;
2008-09-05 18:10:27 +04:00
if ( unlikely ( parent = = NULL ) )
2005-11-10 17:26:48 +03:00
return - EIO ;
realrate = parent - > rate ;
for ( dsor_exp = 0 ; dsor_exp < 4 ; dsor_exp + + ) {
if ( realrate < = rate )
break ;
realrate / = 2 ;
}
return dsor_exp ;
}
2009-12-09 02:29:38 +03:00
unsigned long omap1_ckctl_recalc ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
/* Calculate divisor encoded as 2-bit exponent */
2009-02-12 13:12:59 +03:00
int dsor = 1 < < ( 3 & ( omap_readw ( ARM_CKCTL ) > > clk - > rate_offset ) ) ;
2005-11-10 17:26:48 +03:00
2009-02-12 13:12:59 +03:00
return clk - > parent - > rate / dsor ;
2005-11-10 17:26:48 +03:00
}
2009-12-09 02:29:38 +03:00
unsigned long omap1_ckctl_recalc_dsp_domain ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
int dsor ;
/* Calculate divisor encoded as 2-bit exponent
*
* The clock control bits are in DSP domain ,
* so api_ck is needed for access .
* Note that DSP_CKCTL virt addr = phys addr , so
* we must use __raw_readw ( ) instead of omap_readw ( ) .
*/
2009-12-09 02:29:38 +03:00
omap1_clk_enable ( api_ck_p ) ;
2005-11-10 17:26:48 +03:00
dsor = 1 < < ( 3 & ( __raw_readw ( DSP_CKCTL ) > > clk - > rate_offset ) ) ;
2009-12-09 02:29:38 +03:00
omap1_clk_disable ( api_ck_p ) ;
2005-11-10 17:26:48 +03:00
2009-02-12 13:12:59 +03:00
return clk - > parent - > rate / dsor ;
2005-11-10 17:26:48 +03:00
}
/* MPU virtual clock functions */
2009-12-09 02:29:38 +03:00
int omap1_select_table_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
/* Find the highest supported frequency <= rate and switch to it */
struct mpu_rate * ptr ;
2009-12-09 02:29:38 +03:00
unsigned long dpll1_rate , ref_rate ;
2010-01-20 03:30:55 +03:00
dpll1_rate = ck_dpll1_p - > rate ;
ref_rate = ck_ref_p - > rate ;
2005-11-10 17:26:48 +03:00
2009-12-09 02:29:38 +03:00
for ( ptr = omap1_rate_table ; ptr - > rate ; ptr + + ) {
2011-12-09 06:01:41 +04:00
if ( ! ( ptr - > flags & cpu_mask ) )
continue ;
2009-12-09 02:29:38 +03:00
if ( ptr - > xtal ! = ref_rate )
2005-11-10 17:26:48 +03:00
continue ;
/* Can check only after xtal frequency check */
if ( ptr - > rate < = rate )
break ;
}
if ( ! ptr - > rate )
return - EINVAL ;
/*
* In most cases we should not need to reprogram DPLL .
* Reprogramming the DPLL is tricky , it must be done from SRAM .
*/
2011-12-02 01:16:26 +04:00
omap_sram_reprogram_clock ( ptr - > dpllctl_val , ptr - > ckctl_val ) ;
2005-11-10 17:26:48 +03:00
2009-12-09 02:29:38 +03:00
/* XXX Do we need to recalculate the tree below DPLL1 at this point? */
ck_dpll1_p - > rate = ptr - > pll_rate ;
2005-11-10 17:26:48 +03:00
return 0 ;
}
2009-12-09 02:29:38 +03:00
int omap1_clk_set_rate_dsp_domain ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
2009-02-08 19:07:46 +03:00
int dsor_exp ;
u16 regval ;
2005-11-10 17:26:48 +03:00
2009-02-08 19:07:46 +03:00
dsor_exp = calc_dsor_exp ( clk , rate ) ;
if ( dsor_exp > 3 )
dsor_exp = - EINVAL ;
if ( dsor_exp < 0 )
return dsor_exp ;
regval = __raw_readw ( DSP_CKCTL ) ;
regval & = ~ ( 3 < < clk - > rate_offset ) ;
regval | = dsor_exp < < clk - > rate_offset ;
__raw_writew ( regval , DSP_CKCTL ) ;
clk - > rate = clk - > parent - > rate / ( 1 < < dsor_exp ) ;
return 0 ;
}
2009-12-09 02:29:38 +03:00
long omap1_clk_round_rate_ckctl_arm ( struct clk * clk , unsigned long rate )
2009-02-08 19:07:46 +03:00
{
int dsor_exp = calc_dsor_exp ( clk , rate ) ;
if ( dsor_exp < 0 )
return dsor_exp ;
if ( dsor_exp > 3 )
dsor_exp = 3 ;
return clk - > parent - > rate / ( 1 < < dsor_exp ) ;
}
2009-12-09 02:29:38 +03:00
int omap1_clk_set_rate_ckctl_arm ( struct clk * clk , unsigned long rate )
2009-02-08 19:07:46 +03:00
{
int dsor_exp ;
u16 regval ;
dsor_exp = calc_dsor_exp ( clk , rate ) ;
if ( dsor_exp > 3 )
dsor_exp = - EINVAL ;
if ( dsor_exp < 0 )
return dsor_exp ;
regval = omap_readw ( ARM_CKCTL ) ;
regval & = ~ ( 3 < < clk - > rate_offset ) ;
regval | = dsor_exp < < clk - > rate_offset ;
regval = verify_ckctl_value ( regval ) ;
omap_writew ( regval , ARM_CKCTL ) ;
clk - > rate = clk - > parent - > rate / ( 1 < < dsor_exp ) ;
return 0 ;
2005-11-10 17:26:48 +03:00
}
2009-12-09 02:29:38 +03:00
long omap1_round_to_table_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
/* Find the highest supported frequency <= rate */
struct mpu_rate * ptr ;
2009-12-09 02:29:38 +03:00
long highest_rate ;
unsigned long ref_rate ;
2010-01-20 03:30:55 +03:00
ref_rate = ck_ref_p - > rate ;
2005-11-10 17:26:48 +03:00
highest_rate = - EINVAL ;
2009-12-09 02:29:38 +03:00
for ( ptr = omap1_rate_table ; ptr - > rate ; ptr + + ) {
2011-12-09 06:01:41 +04:00
if ( ! ( ptr - > flags & cpu_mask ) )
continue ;
2009-12-09 02:29:38 +03:00
if ( ptr - > xtal ! = ref_rate )
2005-11-10 17:26:48 +03:00
continue ;
highest_rate = ptr - > rate ;
/* Can check only after xtal frequency check */
if ( ptr - > rate < = rate )
break ;
}
return highest_rate ;
}
static unsigned calc_ext_dsor ( unsigned long rate )
{
unsigned dsor ;
/* MCLK and BCLK divisor selection is not linear:
* freq = 96 MHz / dsor
*
* RATIO_SEL range : dsor < - > RATIO_SEL
* 0. .6 : ( RATIO_SEL + 2 ) < - > ( dsor - 2 )
* 6. .48 : ( 8 + ( RATIO_SEL - 6 ) * 2 ) < - > ( ( dsor - 8 ) / 2 + 6 )
* Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
* can not be used .
*/
for ( dsor = 2 ; dsor < 96 ; + + dsor ) {
if ( ( dsor & 1 ) & & dsor > 8 )
2006-04-02 20:46:20 +04:00
continue ;
2005-11-10 17:26:48 +03:00
if ( rate > = 96000000 / dsor )
break ;
}
return dsor ;
}
2009-12-09 02:29:38 +03:00
/* XXX Only needed on 1510 */
int omap1_set_uart_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
unsigned int val ;
2009-01-28 22:18:48 +03:00
val = __raw_readl ( clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
if ( rate = = 12000000 )
val & = ~ ( 1 < < clk - > enable_bit ) ;
else if ( rate = = 48000000 )
val | = ( 1 < < clk - > enable_bit ) ;
else
return - EINVAL ;
2009-01-28 22:18:48 +03:00
__raw_writel ( val , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
clk - > rate = rate ;
return 0 ;
}
/* External clock (MCLK & BCLK) functions */
2009-12-09 02:29:38 +03:00
int omap1_set_ext_clk_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
unsigned dsor ;
__u16 ratio_bits ;
dsor = calc_ext_dsor ( rate ) ;
clk - > rate = 96000000 / dsor ;
if ( dsor > 8 )
ratio_bits = ( ( dsor - 8 ) / 2 + 6 ) < < 2 ;
else
ratio_bits = ( dsor - 2 ) < < 2 ;
2009-01-28 22:18:48 +03:00
ratio_bits | = __raw_readw ( clk - > enable_reg ) & ~ 0xfd ;
__raw_writew ( ratio_bits , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
return 0 ;
}
2009-12-09 02:29:38 +03:00
int omap1_set_sossi_rate ( struct clk * clk , unsigned long rate )
2007-03-05 18:22:58 +03:00
{
u32 l ;
int div ;
unsigned long p_rate ;
p_rate = clk - > parent - > rate ;
/* Round towards slower frequency */
div = ( p_rate + rate - 1 ) / rate ;
div - - ;
if ( div < 0 | | div > 7 )
return - EINVAL ;
l = omap_readl ( MOD_CONF_CTRL_1 ) ;
l & = ~ ( 7 < < 17 ) ;
l | = div < < 17 ;
omap_writel ( l , MOD_CONF_CTRL_1 ) ;
clk - > rate = p_rate / ( div + 1 ) ;
return 0 ;
}
2009-12-09 02:29:38 +03:00
long omap1_round_ext_clk_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
return 96000000 / calc_ext_dsor ( rate ) ;
}
2009-12-09 02:29:38 +03:00
void omap1_init_ext_clk ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
unsigned dsor ;
__u16 ratio_bits ;
/* Determine current rate and ensure clock is based on 96MHz APLL */
2009-01-28 22:18:48 +03:00
ratio_bits = __raw_readw ( clk - > enable_reg ) & ~ 1 ;
__raw_writew ( ratio_bits , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
ratio_bits = ( ratio_bits & 0xfc ) > > 2 ;
if ( ratio_bits > 6 )
dsor = ( ratio_bits - 6 ) * 2 + 8 ;
else
dsor = ratio_bits + 2 ;
clk - > rate = 96000000 / dsor ;
}
2009-12-09 02:29:38 +03:00
int omap1_clk_enable ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
int ret = 0 ;
2009-04-05 15:27:24 +04:00
2005-11-10 17:26:48 +03:00
if ( clk - > usecount + + = = 0 ) {
2009-04-05 15:27:24 +04:00
if ( clk - > parent ) {
2006-01-18 02:30:42 +03:00
ret = omap1_clk_enable ( clk - > parent ) ;
2009-04-05 15:27:24 +04:00
if ( ret )
goto err ;
2005-11-10 17:26:48 +03:00
if ( clk - > flags & CLOCK_NO_IDLE_PARENT )
2006-12-07 04:13:51 +03:00
omap1_clk_deny_idle ( clk - > parent ) ;
2005-11-10 17:26:48 +03:00
}
2008-11-04 17:02:46 +03:00
ret = clk - > ops - > enable ( clk ) ;
2009-04-05 15:27:24 +04:00
if ( ret ) {
if ( clk - > parent )
omap1_clk_disable ( clk - > parent ) ;
goto err ;
2005-11-10 17:26:48 +03:00
}
}
2009-04-05 15:27:24 +04:00
return ret ;
2005-11-10 17:26:48 +03:00
2009-04-05 15:27:24 +04:00
err :
clk - > usecount - - ;
2005-11-10 17:26:48 +03:00
return ret ;
}
2009-12-09 02:29:38 +03:00
void omap1_clk_disable ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
if ( clk - > usecount > 0 & & ! ( - - clk - > usecount ) ) {
2008-11-04 17:02:46 +03:00
clk - > ops - > disable ( clk ) ;
2005-11-10 17:26:48 +03:00
if ( likely ( clk - > parent ) ) {
2006-01-18 02:30:42 +03:00
omap1_clk_disable ( clk - > parent ) ;
2005-11-10 17:26:48 +03:00
if ( clk - > flags & CLOCK_NO_IDLE_PARENT )
2006-12-07 04:13:51 +03:00
omap1_clk_allow_idle ( clk - > parent ) ;
2005-11-10 17:26:48 +03:00
}
}
}
2006-01-18 02:30:42 +03:00
static int omap1_clk_enable_generic ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
__u16 regval16 ;
__u32 regval32 ;
2008-09-05 18:10:27 +04:00
if ( unlikely ( clk - > enable_reg = = NULL ) ) {
2005-11-10 17:26:48 +03:00
printk ( KERN_ERR " clock.c: Enable for %s without enable code \n " ,
clk - > name ) ;
2006-12-07 04:13:51 +03:00
return - EINVAL ;
2005-11-10 17:26:48 +03:00
}
if ( clk - > flags & ENABLE_REG_32BIT ) {
2009-01-28 22:18:48 +03:00
regval32 = __raw_readl ( clk - > enable_reg ) ;
regval32 | = ( 1 < < clk - > enable_bit ) ;
__raw_writel ( regval32 , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
} else {
2009-01-28 22:18:48 +03:00
regval16 = __raw_readw ( clk - > enable_reg ) ;
regval16 | = ( 1 < < clk - > enable_bit ) ;
__raw_writew ( regval16 , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
}
2006-12-07 04:13:51 +03:00
return 0 ;
2005-11-10 17:26:48 +03:00
}
2006-01-18 02:30:42 +03:00
static void omap1_clk_disable_generic ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
__u16 regval16 ;
__u32 regval32 ;
2008-09-05 18:10:27 +04:00
if ( clk - > enable_reg = = NULL )
2005-11-10 17:26:48 +03:00
return ;
if ( clk - > flags & ENABLE_REG_32BIT ) {
2009-01-28 22:18:48 +03:00
regval32 = __raw_readl ( clk - > enable_reg ) ;
regval32 & = ~ ( 1 < < clk - > enable_bit ) ;
__raw_writel ( regval32 , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
} else {
2009-01-28 22:18:48 +03:00
regval16 = __raw_readw ( clk - > enable_reg ) ;
regval16 & = ~ ( 1 < < clk - > enable_bit ) ;
__raw_writew ( regval16 , clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
}
}
2009-12-09 02:29:38 +03:00
const struct clkops clkops_generic = {
. enable = omap1_clk_enable_generic ,
. disable = omap1_clk_disable_generic ,
} ;
static int omap1_clk_enable_dsp_domain ( struct clk * clk )
{
int retval ;
retval = omap1_clk_enable ( api_ck_p ) ;
if ( ! retval ) {
retval = omap1_clk_enable_generic ( clk ) ;
omap1_clk_disable ( api_ck_p ) ;
}
return retval ;
}
static void omap1_clk_disable_dsp_domain ( struct clk * clk )
{
if ( omap1_clk_enable ( api_ck_p ) = = 0 ) {
omap1_clk_disable_generic ( clk ) ;
omap1_clk_disable ( api_ck_p ) ;
}
}
const struct clkops clkops_dspck = {
. enable = omap1_clk_enable_dsp_domain ,
. disable = omap1_clk_disable_dsp_domain ,
2008-11-04 17:02:46 +03:00
} ;
2010-07-27 02:34:28 +04:00
/* XXX SYSC register handling does not belong in the clock framework */
static int omap1_clk_enable_uart_functional_16xx ( struct clk * clk )
2009-12-09 02:29:38 +03:00
{
int ret ;
struct uart_clk * uclk ;
ret = omap1_clk_enable_generic ( clk ) ;
if ( ret = = 0 ) {
/* Set smart idle acknowledgement mode */
uclk = ( struct uart_clk * ) clk ;
omap_writeb ( ( omap_readb ( uclk - > sysc_addr ) & ~ 0x10 ) | 8 ,
uclk - > sysc_addr ) ;
}
return ret ;
}
2010-07-27 02:34:28 +04:00
/* XXX SYSC register handling does not belong in the clock framework */
static void omap1_clk_disable_uart_functional_16xx ( struct clk * clk )
2009-12-09 02:29:38 +03:00
{
struct uart_clk * uclk ;
/* Set force idle acknowledgement mode */
uclk = ( struct uart_clk * ) clk ;
omap_writeb ( ( omap_readb ( uclk - > sysc_addr ) & ~ 0x18 ) , uclk - > sysc_addr ) ;
omap1_clk_disable_generic ( clk ) ;
}
2010-07-27 02:34:28 +04:00
/* XXX SYSC register handling does not belong in the clock framework */
const struct clkops clkops_uart_16xx = {
. enable = omap1_clk_enable_uart_functional_16xx ,
. disable = omap1_clk_disable_uart_functional_16xx ,
2009-12-09 02:29:38 +03:00
} ;
long omap1_clk_round_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
2008-09-05 18:10:27 +04:00
if ( clk - > round_rate ! = NULL )
2005-11-10 17:26:48 +03:00
return clk - > round_rate ( clk , rate ) ;
return clk - > rate ;
}
2009-12-09 02:29:38 +03:00
int omap1_clk_set_rate ( struct clk * clk , unsigned long rate )
2005-11-10 17:26:48 +03:00
{
int ret = - EINVAL ;
if ( clk - > set_rate )
ret = clk - > set_rate ( clk , rate ) ;
return ret ;
}
2010-07-27 02:34:28 +04:00
/*
2005-11-10 17:26:48 +03:00
* Omap1 clock reset and init functions
2010-07-27 02:34:28 +04:00
*/
2005-11-10 17:26:48 +03:00
# ifdef CONFIG_OMAP_RESET_CLOCKS
2010-05-20 22:31:04 +04:00
void omap1_clk_disable_unused ( struct clk * clk )
2005-11-10 17:26:48 +03:00
{
__u32 regval32 ;
2006-09-25 14:27:20 +04:00
/* Clocks in the DSP domain need api_ck. Just assume bootloader
* has not enabled any DSP clocks */
2008-09-05 18:46:19 +04:00
if ( clk - > enable_reg = = DSP_IDLECT2 ) {
2006-09-25 14:27:20 +04:00
printk ( KERN_INFO " Skipping reset check for DSP domain "
" clock \" %s \" \n " , clk - > name ) ;
return ;
}
2005-11-10 17:26:48 +03:00
2006-09-25 14:27:20 +04:00
/* Is the clock already disabled? */
2009-01-28 22:18:48 +03:00
if ( clk - > flags & ENABLE_REG_32BIT )
regval32 = __raw_readl ( clk - > enable_reg ) ;
else
regval32 = __raw_readw ( clk - > enable_reg ) ;
2005-11-10 17:26:48 +03:00
2006-09-25 14:27:20 +04:00
if ( ( regval32 & ( 1 < < clk - > enable_bit ) ) = = 0 )
return ;
2005-11-10 17:26:48 +03:00
2006-09-25 14:27:20 +04:00
printk ( KERN_INFO " Disabling unused clock \" %s \" ... " , clk - > name ) ;
2008-11-04 17:02:46 +03:00
clk - > ops - > disable ( clk ) ;
2006-09-25 14:27:20 +04:00
printk ( " done \n " ) ;
2005-11-10 17:26:48 +03:00
}
# endif