2006-01-09 20:05:41 +03:00
/*
2007-02-05 13:42:07 +03:00
* linux / arch / arm / mach - at91 / clock . c
2006-01-09 20:05:41 +03:00
*
* Copyright ( C ) 2005 David Brownell
* Copyright ( C ) 2005 Ivan Kokshaysky
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/fs.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
# include <linux/list.h>
# include <linux/errno.h>
# include <linux/err.h>
# include <linux/spinlock.h>
# include <linux/delay.h>
# include <linux/clk.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2006-01-09 20:05:41 +03:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
# include <mach/at91_pmc.h>
# include <mach/cpu.h>
2006-01-09 20:05:41 +03:00
2006-09-27 13:50:59 +04:00
# include "clock.h"
2006-01-09 20:05:41 +03:00
2006-06-20 22:31:39 +04:00
2006-01-09 20:05:41 +03:00
/*
* There ' s a lot more which can be done with clocks , including cpufreq
* integration , slow clock mode support ( for system suspend ) , letting
* PLLB be used at other rates ( on boards that don ' t need USB ) , etc .
*/
2006-09-27 13:50:59 +04:00
# define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
# define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
# define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL)
2006-12-01 13:27:31 +03:00
# define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM)
2006-09-27 13:50:59 +04:00
static LIST_HEAD ( clocks ) ;
static DEFINE_SPINLOCK ( clk_lock ) ;
2006-01-09 20:05:41 +03:00
2006-09-27 13:50:59 +04:00
static u32 at91_pllb_usb_init ;
2006-01-09 20:05:41 +03:00
/*
* Four primary clock sources : two crystal oscillators ( 32 K , main ) , and
* two PLLs . PLLA usually runs the master clock ; and PLLB must run at
* 48 MHz ( unless no USB function clocks are needed ) . The main clock and
* both PLLs are turned off to run in " slow clock mode " ( system suspend ) .
*/
static struct clk clk32k = {
. name = " clk32k " ,
. rate_hz = AT91_SLOW_CLOCK ,
. users = 1 , /* always on */
. id = 0 ,
2006-09-27 13:50:59 +04:00
. type = CLK_TYPE_PRIMARY ,
2006-01-09 20:05:41 +03:00
} ;
static struct clk main_clk = {
. name = " main " ,
2006-06-19 16:20:23 +04:00
. pmc_mask = AT91_PMC_MOSCS , /* in PMC_SR */
2006-01-09 20:05:41 +03:00
. id = 1 ,
2006-09-27 13:50:59 +04:00
. type = CLK_TYPE_PRIMARY ,
2006-01-09 20:05:41 +03:00
} ;
static struct clk plla = {
. name = " plla " ,
. parent = & main_clk ,
2006-06-19 16:20:23 +04:00
. pmc_mask = AT91_PMC_LOCKA , /* in PMC_SR */
2006-01-09 20:05:41 +03:00
. id = 2 ,
2006-09-27 13:50:59 +04:00
. type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL ,
2006-01-09 20:05:41 +03:00
} ;
static void pllb_mode ( struct clk * clk , int is_on )
{
u32 value ;
if ( is_on ) {
is_on = AT91_PMC_LOCKB ;
value = at91_pllb_usb_init ;
} else
value = 0 ;
2006-09-27 13:50:59 +04:00
// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
2006-01-09 20:05:41 +03:00
at91_sys_write ( AT91_CKGR_PLLBR , value ) ;
do {
cpu_relax ( ) ;
} while ( ( at91_sys_read ( AT91_PMC_SR ) & AT91_PMC_LOCKB ) ! = is_on ) ;
}
static struct clk pllb = {
. name = " pllb " ,
. parent = & main_clk ,
2006-06-19 16:20:23 +04:00
. pmc_mask = AT91_PMC_LOCKB , /* in PMC_SR */
2006-01-09 20:05:41 +03:00
. mode = pllb_mode ,
. id = 3 ,
2006-09-27 13:50:59 +04:00
. type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL ,
2006-01-09 20:05:41 +03:00
} ;
static void pmc_sys_mode ( struct clk * clk , int is_on )
{
if ( is_on )
at91_sys_write ( AT91_PMC_SCER , clk - > pmc_mask ) ;
else
at91_sys_write ( AT91_PMC_SCDR , clk - > pmc_mask ) ;
}
2008-04-06 00:14:03 +04:00
static void pmc_uckr_mode ( struct clk * clk , int is_on )
{
unsigned int uckr = at91_sys_read ( AT91_CKGR_UCKR ) ;
if ( is_on ) {
is_on = AT91_PMC_LOCKU ;
at91_sys_write ( AT91_CKGR_UCKR , uckr | clk - > pmc_mask ) ;
} else
at91_sys_write ( AT91_CKGR_UCKR , uckr & ~ ( clk - > pmc_mask ) ) ;
do {
cpu_relax ( ) ;
} while ( ( at91_sys_read ( AT91_PMC_SR ) & AT91_PMC_LOCKU ) ! = is_on ) ;
}
2006-01-09 20:05:41 +03:00
/* USB function clocks (PLLB must be 48 MHz) */
static struct clk udpck = {
. name = " udpck " ,
. parent = & pllb ,
. mode = pmc_sys_mode ,
} ;
2008-04-06 00:14:03 +04:00
static struct clk utmi_clk = {
. name = " utmi_clk " ,
. parent = & main_clk ,
. pmc_mask = AT91_PMC_UPLLEN , /* in CKGR_UCKR */
. mode = pmc_uckr_mode ,
. type = CLK_TYPE_PLL ,
} ;
2006-01-09 20:05:41 +03:00
static struct clk uhpck = {
. name = " uhpck " ,
. parent = & pllb ,
. mode = pmc_sys_mode ,
} ;
/*
* The master clock is divided from the CPU clock ( by 1 - 4 ) . It ' s used for
* memory , interfaces to on - chip peripherals , the AIC , and sometimes more
* ( e . g baud rate generation ) . It ' s sourced from one of the primary clocks .
*/
static struct clk mck = {
. name = " mck " ,
2006-06-19 16:20:23 +04:00
. pmc_mask = AT91_PMC_MCKRDY , /* in PMC_SR */
2006-01-09 20:05:41 +03:00
} ;
static void pmc_periph_mode ( struct clk * clk , int is_on )
{
if ( is_on )
at91_sys_write ( AT91_PMC_PCER , clk - > pmc_mask ) ;
else
at91_sys_write ( AT91_PMC_PCDR , clk - > pmc_mask ) ;
}
2006-09-27 13:50:59 +04:00
static struct clk __init * at91_css_to_clk ( unsigned long css )
{
switch ( css ) {
case AT91_PMC_CSS_SLOW :
return & clk32k ;
case AT91_PMC_CSS_MAIN :
return & main_clk ;
case AT91_PMC_CSS_PLLA :
return & plla ;
case AT91_PMC_CSS_PLLB :
return & pllb ;
}
2006-01-09 20:05:41 +03:00
2006-09-27 13:50:59 +04:00
return NULL ;
}
2006-01-09 20:05:41 +03:00
2006-06-19 16:20:23 +04:00
/*
* Associate a particular clock with a function ( eg , " uart " ) and device .
* The drivers can then request the same ' function ' with several different
* devices and not care about which clock name to use .
*/
void __init at91_clock_associate ( const char * id , struct device * dev , const char * func )
{
struct clk * clk = clk_get ( NULL , id ) ;
if ( ! dev | | ! clk | | ! IS_ERR ( clk_get ( dev , func ) ) )
return ;
clk - > function = func ;
clk - > dev = dev ;
}
2006-09-27 13:50:59 +04:00
/* clocks cannot be de-registered no refcounting necessary */
2006-01-09 20:05:41 +03:00
struct clk * clk_get ( struct device * dev , const char * id )
{
2006-09-27 13:50:59 +04:00
struct clk * clk ;
2006-06-19 16:20:23 +04:00
2006-09-27 13:50:59 +04:00
list_for_each_entry ( clk , & clocks , node ) {
2006-06-19 16:20:23 +04:00
if ( strcmp ( id , clk - > name ) = = 0 )
return clk ;
if ( clk - > function & & ( dev = = clk - > dev ) & & strcmp ( id , clk - > function ) = = 0 )
return clk ;
2006-01-09 20:05:41 +03:00
}
return ERR_PTR ( - ENOENT ) ;
}
EXPORT_SYMBOL ( clk_get ) ;
void clk_put ( struct clk * clk )
{
}
EXPORT_SYMBOL ( clk_put ) ;
static void __clk_enable ( struct clk * clk )
{
if ( clk - > parent )
__clk_enable ( clk - > parent ) ;
if ( clk - > users + + = = 0 & & clk - > mode )
clk - > mode ( clk , 1 ) ;
}
int clk_enable ( struct clk * clk )
{
unsigned long flags ;
spin_lock_irqsave ( & clk_lock , flags ) ;
__clk_enable ( clk ) ;
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return 0 ;
}
EXPORT_SYMBOL ( clk_enable ) ;
static void __clk_disable ( struct clk * clk )
{
BUG_ON ( clk - > users = = 0 ) ;
if ( - - clk - > users = = 0 & & clk - > mode )
clk - > mode ( clk , 0 ) ;
if ( clk - > parent )
__clk_disable ( clk - > parent ) ;
}
void clk_disable ( struct clk * clk )
{
unsigned long flags ;
spin_lock_irqsave ( & clk_lock , flags ) ;
__clk_disable ( clk ) ;
spin_unlock_irqrestore ( & clk_lock , flags ) ;
}
EXPORT_SYMBOL ( clk_disable ) ;
unsigned long clk_get_rate ( struct clk * clk )
{
unsigned long flags ;
unsigned long rate ;
spin_lock_irqsave ( & clk_lock , flags ) ;
for ( ; ; ) {
rate = clk - > rate_hz ;
if ( rate | | ! clk - > parent )
break ;
clk = clk - > parent ;
}
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return rate ;
}
EXPORT_SYMBOL ( clk_get_rate ) ;
/*------------------------------------------------------------------------*/
# ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
/*
* For now , only the programmable clocks support reparenting ( MCK could
* do this too , with care ) or rate changing ( the PLLs could do this too ,
* ditto MCK but that ' s more for cpufreq ) . Drivers may reparent to get
* a better rate match ; we don ' t .
*/
long clk_round_rate ( struct clk * clk , unsigned long rate )
{
unsigned long flags ;
unsigned prescale ;
unsigned long actual ;
2006-09-27 13:50:59 +04:00
if ( ! clk_is_programmable ( clk ) )
2006-01-09 20:05:41 +03:00
return - EINVAL ;
spin_lock_irqsave ( & clk_lock , flags ) ;
actual = clk - > parent - > rate_hz ;
for ( prescale = 0 ; prescale < 7 ; prescale + + ) {
if ( actual & & actual < = rate )
break ;
actual > > = 1 ;
}
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return ( prescale < 7 ) ? actual : - ENOENT ;
}
EXPORT_SYMBOL ( clk_round_rate ) ;
int clk_set_rate ( struct clk * clk , unsigned long rate )
{
unsigned long flags ;
unsigned prescale ;
unsigned long actual ;
2006-09-27 13:50:59 +04:00
if ( ! clk_is_programmable ( clk ) )
2006-01-09 20:05:41 +03:00
return - EINVAL ;
if ( clk - > users )
return - EBUSY ;
spin_lock_irqsave ( & clk_lock , flags ) ;
actual = clk - > parent - > rate_hz ;
for ( prescale = 0 ; prescale < 7 ; prescale + + ) {
if ( actual & & actual < = rate ) {
u32 pckr ;
pckr = at91_sys_read ( AT91_PMC_PCKR ( clk - > id ) ) ;
2006-03-22 23:14:14 +03:00
pckr & = AT91_PMC_CSS_PLLB ; /* clock selection */
2006-01-09 20:05:41 +03:00
pckr | = prescale < < 2 ;
at91_sys_write ( AT91_PMC_PCKR ( clk - > id ) , pckr ) ;
clk - > rate_hz = actual ;
break ;
}
actual > > = 1 ;
}
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return ( prescale < 7 ) ? actual : - ENOENT ;
}
EXPORT_SYMBOL ( clk_set_rate ) ;
struct clk * clk_get_parent ( struct clk * clk )
{
return clk - > parent ;
}
EXPORT_SYMBOL ( clk_get_parent ) ;
int clk_set_parent ( struct clk * clk , struct clk * parent )
{
unsigned long flags ;
if ( clk - > users )
return - EBUSY ;
2006-09-27 13:50:59 +04:00
if ( ! clk_is_primary ( parent ) | | ! clk_is_programmable ( clk ) )
2006-01-09 20:05:41 +03:00
return - EINVAL ;
spin_lock_irqsave ( & clk_lock , flags ) ;
clk - > rate_hz = parent - > rate_hz ;
clk - > parent = parent ;
at91_sys_write ( AT91_PMC_PCKR ( clk - > id ) , parent - > id ) ;
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return 0 ;
}
EXPORT_SYMBOL ( clk_set_parent ) ;
2006-09-27 13:50:59 +04:00
/* establish PCK0..PCK3 parentage and rate */
2008-02-07 00:03:42 +03:00
static void __init init_programmable_clock ( struct clk * clk )
2006-09-27 13:50:59 +04:00
{
struct clk * parent ;
u32 pckr ;
pckr = at91_sys_read ( AT91_PMC_PCKR ( clk - > id ) ) ;
parent = at91_css_to_clk ( pckr & AT91_PMC_CSS ) ;
clk - > parent = parent ;
2007-11-19 13:52:09 +03:00
clk - > rate_hz = parent - > rate_hz / ( 1 < < ( ( pckr & AT91_PMC_PRES ) > > 2 ) ) ;
2006-09-27 13:50:59 +04:00
}
2006-01-09 20:05:41 +03:00
# endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
/*------------------------------------------------------------------------*/
# ifdef CONFIG_DEBUG_FS
static int at91_clk_show ( struct seq_file * s , void * unused )
{
2008-04-06 00:14:03 +04:00
u32 scsr , pcsr , uckr = 0 , sr ;
2006-09-27 13:50:59 +04:00
struct clk * clk ;
2006-01-09 20:05:41 +03:00
seq_printf ( s , " SCSR = %8x \n " , scsr = at91_sys_read ( AT91_PMC_SCSR ) ) ;
seq_printf ( s , " PCSR = %8x \n " , pcsr = at91_sys_read ( AT91_PMC_PCSR ) ) ;
seq_printf ( s , " MOR = %8x \n " , at91_sys_read ( AT91_CKGR_MOR ) ) ;
seq_printf ( s , " MCFR = %8x \n " , at91_sys_read ( AT91_CKGR_MCFR ) ) ;
seq_printf ( s , " PLLA = %8x \n " , at91_sys_read ( AT91_CKGR_PLLAR ) ) ;
2008-04-08 16:59:18 +04:00
if ( ! cpu_is_at91sam9rl ( ) )
seq_printf ( s , " PLLB = %8x \n " , at91_sys_read ( AT91_CKGR_PLLBR ) ) ;
if ( cpu_is_at91cap9 ( ) | | cpu_is_at91sam9rl ( ) )
2008-04-06 00:14:03 +04:00
seq_printf ( s , " UCKR = %8x \n " , uckr = at91_sys_read ( AT91_CKGR_UCKR ) ) ;
2006-01-09 20:05:41 +03:00
seq_printf ( s , " MCKR = %8x \n " , at91_sys_read ( AT91_PMC_MCKR ) ) ;
seq_printf ( s , " SR = %8x \n " , sr = at91_sys_read ( AT91_PMC_SR ) ) ;
seq_printf ( s , " \n " ) ;
2006-09-27 13:50:59 +04:00
list_for_each_entry ( clk , & clocks , node ) {
char * state ;
2006-01-09 20:05:41 +03:00
if ( clk - > mode = = pmc_sys_mode )
state = ( scsr & clk - > pmc_mask ) ? " on " : " off " ;
else if ( clk - > mode = = pmc_periph_mode )
state = ( pcsr & clk - > pmc_mask ) ? " on " : " off " ;
2008-04-06 00:14:03 +04:00
else if ( clk - > mode = = pmc_uckr_mode )
state = ( uckr & clk - > pmc_mask ) ? " on " : " off " ;
2006-01-09 20:05:41 +03:00
else if ( clk - > pmc_mask )
state = ( sr & clk - > pmc_mask ) ? " on " : " off " ;
else if ( clk = = & clk32k | | clk = = & main_clk )
state = " on " ;
else
state = " " ;
2006-03-22 23:14:14 +03:00
seq_printf ( s , " %-10s users=%2d %-3s %9ld Hz %s \n " ,
2006-01-09 20:05:41 +03:00
clk - > name , clk - > users , state , clk_get_rate ( clk ) ,
clk - > parent ? clk - > parent - > name : " " ) ;
}
return 0 ;
}
static int at91_clk_open ( struct inode * inode , struct file * file )
{
return single_open ( file , at91_clk_show , NULL ) ;
}
2007-02-12 11:55:31 +03:00
static const struct file_operations at91_clk_operations = {
2006-01-09 20:05:41 +03:00
. open = at91_clk_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int __init at91_clk_debugfs_init ( void )
{
/* /sys/kernel/debug/at91_clk */
( void ) debugfs_create_file ( " at91_clk " , S_IFREG | S_IRUGO , NULL , NULL , & at91_clk_operations ) ;
return 0 ;
}
postcore_initcall ( at91_clk_debugfs_init ) ;
# endif
2006-09-27 13:50:59 +04:00
/*------------------------------------------------------------------------*/
/* Register a new clock */
int __init clk_register ( struct clk * clk )
{
if ( clk_is_peripheral ( clk ) ) {
clk - > parent = & mck ;
clk - > mode = pmc_periph_mode ;
list_add_tail ( & clk - > node , & clocks ) ;
}
2006-12-01 13:27:31 +03:00
else if ( clk_is_sys ( clk ) ) {
clk - > parent = & mck ;
clk - > mode = pmc_sys_mode ;
list_add_tail ( & clk - > node , & clocks ) ;
}
2006-09-27 13:50:59 +04:00
# ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
else if ( clk_is_programmable ( clk ) ) {
clk - > mode = pmc_sys_mode ;
init_programmable_clock ( clk ) ;
list_add_tail ( & clk - > node , & clocks ) ;
}
# endif
return 0 ;
}
2006-01-09 20:05:41 +03:00
/*------------------------------------------------------------------------*/
static u32 __init at91_pll_rate ( struct clk * pll , u32 freq , u32 reg )
{
unsigned mul , div ;
div = reg & 0xff ;
mul = ( reg > > 16 ) & 0x7ff ;
if ( div & & mul ) {
freq / = div ;
freq * = mul + 1 ;
} else
freq = 0 ;
2006-03-22 23:14:14 +03:00
2006-01-09 20:05:41 +03:00
return freq ;
}
2006-03-22 23:14:14 +03:00
static u32 __init at91_usb_rate ( struct clk * pll , u32 freq , u32 reg )
{
if ( pll = = & pllb & & ( reg & AT91_PMC_USB96M ) )
return freq / 2 ;
else
return freq ;
}
2006-01-09 20:05:41 +03:00
static unsigned __init at91_pll_calc ( unsigned main_freq , unsigned out_freq )
{
unsigned i , div = 0 , mul = 0 , diff = 1 < < 30 ;
unsigned ret = ( out_freq > 155000000 ) ? 0xbe00 : 0x3e00 ;
/* PLL output max 240 MHz (or 180 MHz per errata) */
if ( out_freq > 240000000 )
goto fail ;
for ( i = 1 ; i < 256 ; i + + ) {
int diff1 ;
unsigned input , mul1 ;
/*
* PLL input between 1 MHz and 32 MHz per spec , but lower
* frequences seem necessary in some cases so allow 100 K .
2008-07-10 13:15:35 +04:00
* Warning : some newer products need 2 MHz min .
2006-01-09 20:05:41 +03:00
*/
input = main_freq / i ;
2008-07-10 13:15:35 +04:00
if ( cpu_is_at91sam9g20 ( ) & & input < 2000000 )
continue ;
2006-01-09 20:05:41 +03:00
if ( input < 100000 )
continue ;
if ( input > 32000000 )
continue ;
mul1 = out_freq / input ;
2008-07-10 13:15:35 +04:00
if ( cpu_is_at91sam9g20 ( ) & & mul > 63 )
continue ;
2006-01-09 20:05:41 +03:00
if ( mul1 > 2048 )
continue ;
if ( mul1 < 2 )
goto fail ;
diff1 = out_freq - input * mul1 ;
if ( diff1 < 0 )
diff1 = - diff1 ;
if ( diff > diff1 ) {
diff = diff1 ;
div = i ;
mul = mul1 ;
if ( diff = = 0 )
break ;
}
}
if ( i = = 256 & & diff > ( out_freq > > 5 ) )
goto fail ;
return ret | ( ( mul - 1 ) < < 16 ) | div ;
fail :
return 0 ;
}
2006-09-27 13:50:59 +04:00
static struct clk * const standard_pmc_clocks [ ] __initdata = {
/* four primary clocks */
& clk32k ,
& main_clk ,
& plla ,
& pllb ,
/* PLLB children (USB) */
& udpck ,
& uhpck ,
/* MCK */
& mck
} ;
2006-01-09 20:05:41 +03:00
int __init at91_clock_init ( unsigned long main_clock )
{
unsigned tmp , freq , mckr ;
2006-09-27 13:50:59 +04:00
int i ;
2006-01-09 20:05:41 +03:00
/*
* When the bootloader initialized the main oscillator correctly ,
* there ' s no problem using the cycle counter . But if it didn ' t ,
* or when using oscillator bypass mode , we must be told the speed
* of the main clock .
*/
if ( ! main_clock ) {
do {
tmp = at91_sys_read ( AT91_CKGR_MCFR ) ;
2006-03-22 23:14:14 +03:00
} while ( ! ( tmp & AT91_PMC_MAINRDY ) ) ;
main_clock = ( tmp & AT91_PMC_MAINF ) * ( AT91_SLOW_CLOCK / 16 ) ;
2006-01-09 20:05:41 +03:00
}
main_clk . rate_hz = main_clock ;
/* report if PLLA is more than mildly overclocked */
plla . rate_hz = at91_pll_rate ( & plla , main_clock , at91_sys_read ( AT91_CKGR_PLLAR ) ) ;
2008-07-10 13:15:35 +04:00
if ( ( ! cpu_is_at91sam9g20 ( ) & & plla . rate_hz > 209000000 )
| | ( cpu_is_at91sam9g20 ( ) & & plla . rate_hz > 800000000 ) )
2006-01-09 20:05:41 +03:00
pr_info ( " Clocks: PLLA overclocked, %ld MHz \n " , plla . rate_hz / 1000000 ) ;
/*
2007-02-08 19:36:34 +03:00
* USB clock init : choose 48 MHz PLLB value ,
2006-01-09 20:05:41 +03:00
* disable 48 MHz clock during usb peripheral suspend .
*
* REVISIT : assumes MCK doesn ' t derive from PLLB !
*/
2006-03-22 23:14:14 +03:00
at91_pllb_usb_init = at91_pll_calc ( main_clock , 48000000 * 2 ) | AT91_PMC_USB96M ;
2006-01-09 20:05:41 +03:00
pllb . rate_hz = at91_pll_rate ( & pllb , main_clock , at91_pllb_usb_init ) ;
2006-12-01 13:27:31 +03:00
if ( cpu_is_at91rm9200 ( ) ) {
uhpck . pmc_mask = AT91RM9200_PMC_UHP ;
udpck . pmc_mask = AT91RM9200_PMC_UDP ;
at91_sys_write ( AT91_PMC_SCER , AT91RM9200_PMC_MCKUDP ) ;
2008-07-10 13:15:35 +04:00
} else if ( cpu_is_at91sam9260 ( ) | | cpu_is_at91sam9261 ( ) | | cpu_is_at91sam9263 ( ) | | cpu_is_at91sam9g20 ( ) ) {
2006-12-01 13:27:31 +03:00
uhpck . pmc_mask = AT91SAM926x_PMC_UHP ;
udpck . pmc_mask = AT91SAM926x_PMC_UDP ;
2008-01-24 17:10:39 +03:00
} else if ( cpu_is_at91cap9 ( ) ) {
uhpck . pmc_mask = AT91CAP9_PMC_UHP ;
2006-12-01 13:27:31 +03:00
}
2006-01-09 20:05:41 +03:00
at91_sys_write ( AT91_CKGR_PLLBR , 0 ) ;
2006-03-22 23:14:14 +03:00
udpck . rate_hz = at91_usb_rate ( & pllb , pllb . rate_hz , at91_pllb_usb_init ) ;
uhpck . rate_hz = at91_usb_rate ( & pllb , pllb . rate_hz , at91_pllb_usb_init ) ;
2008-04-06 00:14:03 +04:00
/*
* USB HS clock init
*/
2008-04-08 16:59:18 +04:00
if ( cpu_is_at91cap9 ( ) | | cpu_is_at91sam9rl ( ) ) {
2008-04-06 00:14:03 +04:00
/*
* multiplier is hard - wired to 40
* ( obtain the USB High Speed 480 MHz when input is 12 MHz )
*/
utmi_clk . rate_hz = 40 * utmi_clk . parent - > rate_hz ;
}
2006-01-09 20:05:41 +03:00
/*
* MCK and CPU derive from one of those primary clocks .
* For now , assume this parentage won ' t change .
*/
mckr = at91_sys_read ( AT91_PMC_MCKR ) ;
2006-09-27 13:50:59 +04:00
mck . parent = at91_css_to_clk ( mckr & AT91_PMC_CSS ) ;
2006-01-09 20:05:41 +03:00
freq = mck . parent - > rate_hz ;
2007-11-19 13:52:09 +03:00
freq / = ( 1 < < ( ( mckr & AT91_PMC_PRES ) > > 2 ) ) ; /* prescale */
if ( cpu_is_at91rm9200 ( ) )
mck . rate_hz = freq / ( 1 + ( ( mckr & AT91_PMC_MDIV ) > > 8 ) ) ; /* mdiv */
2008-07-10 13:15:35 +04:00
else if ( cpu_is_at91sam9g20 ( ) ) {
mck . rate_hz = ( mckr & AT91_PMC_MDIV ) ?
freq / ( ( mckr & AT91_PMC_MDIV ) > > 7 ) : freq ; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
if ( mckr & AT91_PMC_PDIV )
freq / = 2 ; /* processor clock division */
} else
mck . rate_hz = freq / ( 1 < < ( ( mckr & AT91_PMC_MDIV ) > > 8 ) ) ; /* mdiv */
2006-01-09 20:05:41 +03:00
2006-09-27 13:50:59 +04:00
/* Register the PMC's standard clocks */
for ( i = 0 ; i < ARRAY_SIZE ( standard_pmc_clocks ) ; i + + )
list_add_tail ( & standard_pmc_clocks [ i ] - > node , & clocks ) ;
2008-04-08 16:59:18 +04:00
if ( cpu_is_at91cap9 ( ) | | cpu_is_at91sam9rl ( ) )
2008-04-06 00:14:03 +04:00
list_add_tail ( & utmi_clk . node , & clocks ) ;
2006-06-19 16:20:23 +04:00
/* MCK and CPU clock are "always on" */
clk_enable ( & mck ) ;
2006-01-09 20:05:41 +03:00
printk ( " Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz \n " ,
freq / 1000000 , ( unsigned ) mck . rate_hz / 1000000 ,
( unsigned ) main_clock / 1000000 ,
( ( unsigned ) main_clock % 1000000 ) / 1000 ) ;
2007-02-08 19:36:34 +03:00
return 0 ;
}
/*
* Several unused clocks may be active . Turn them off .
*/
static int __init at91_clock_reset ( void )
{
unsigned long pcdr = 0 ;
unsigned long scdr = 0 ;
struct clk * clk ;
list_for_each_entry ( clk , & clocks , node ) {
if ( clk - > users > 0 )
continue ;
if ( clk - > mode = = pmc_periph_mode )
pcdr | = clk - > pmc_mask ;
if ( clk - > mode = = pmc_sys_mode )
scdr | = clk - > pmc_mask ;
pr_debug ( " Clocks: disable unused %s \n " , clk - > name ) ;
}
2006-06-19 16:20:23 +04:00
2007-02-08 19:36:34 +03:00
at91_sys_write ( AT91_PMC_PCDR , pcdr ) ;
at91_sys_write ( AT91_PMC_SCDR , scdr ) ;
2006-01-09 20:05:41 +03:00
return 0 ;
}
2007-02-08 19:36:34 +03:00
late_initcall ( at91_clock_reset ) ;