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>
2012-03-02 16:44:23 +04:00
# include <linux/of_address.h>
2013-10-11 11:37:45 +04:00
# include <linux/clk/at91_pmc.h>
2006-01-09 20:05:41 +03:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
# include <mach/cpu.h>
2006-01-09 20:05:41 +03:00
2012-02-05 16:25:32 +04:00
# include <asm/proc-fns.h>
2006-09-27 13:50:59 +04:00
# include "clock.h"
2009-12-15 23:57:27 +03:00
# include "generic.h"
2006-01-09 20:05:41 +03:00
2011-11-25 05:59:46 +04:00
void __iomem * at91_pmc_base ;
2012-04-07 21:30:22 +04:00
EXPORT_SYMBOL_GPL ( at91_pmc_base ) ;
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
2009-03-31 20:13:15 +04:00
/*
* Chips have some kind of clocks : group them by functionality
*/
2012-01-26 17:07:09 +04:00
# define cpu_has_utmi() ( cpu_is_at91sam9rl() \
2011-03-10 21:08:54 +03:00
| | cpu_is_at91sam9g45 ( ) \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9x5 ( ) \
| | cpu_is_sama5d3 ( ) )
# define cpu_has_1056M_plla() (cpu_is_sama5d3())
2009-03-31 20:13:15 +04:00
2009-06-26 18:36:57 +04:00
# define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \
2011-03-10 21:08:54 +03:00
| | cpu_is_at91sam9g45 ( ) \
2012-04-17 10:26:31 +04:00
| | cpu_is_at91sam9x5 ( ) \
| | cpu_is_at91sam9n12 ( ) )
2009-03-31 20:13:15 +04:00
2009-06-26 18:37:00 +04:00
# define cpu_has_300M_plla() (cpu_is_at91sam9g10())
2009-03-31 20:13:15 +04:00
2012-07-09 23:06:25 +04:00
# define cpu_has_240M_plla() (cpu_is_at91sam9261() \
| | cpu_is_at91sam9263 ( ) \
| | cpu_is_at91sam9rl ( ) )
# define cpu_has_210M_plla() (cpu_is_at91sam9260())
2009-06-26 18:36:57 +04:00
# define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
2011-03-10 21:08:54 +03:00
| | cpu_is_at91sam9g45 ( ) \
2012-04-17 10:26:31 +04:00
| | cpu_is_at91sam9x5 ( ) \
2013-06-24 12:20:55 +04:00
| | cpu_is_sama5d3 ( ) ) )
2009-06-26 18:36:57 +04:00
2011-03-10 21:08:54 +03:00
# define cpu_has_upll() (cpu_is_at91sam9g45() \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9x5 ( ) \
| | cpu_is_sama5d3 ( ) )
2009-03-31 20:13:15 +04:00
/* USB host HS & FS */
# define cpu_has_uhp() (!cpu_is_at91sam9rl())
/* USB device FS only */
2009-06-26 18:36:57 +04:00
# define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \
2011-03-10 21:08:54 +03:00
| | cpu_is_at91sam9g45 ( ) \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9x5 ( ) \
| | cpu_is_sama5d3 ( ) ) )
2011-03-10 21:08:54 +03:00
# define cpu_has_plladiv2() (cpu_is_at91sam9g45() \
2012-04-17 10:26:31 +04:00
| | cpu_is_at91sam9x5 ( ) \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9n12 ( ) \
| | cpu_is_sama5d3 ( ) )
2011-03-10 21:08:54 +03:00
# define cpu_has_mdiv3() (cpu_is_at91sam9g45() \
2012-04-17 10:26:31 +04:00
| | cpu_is_at91sam9x5 ( ) \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9n12 ( ) \
| | cpu_is_sama5d3 ( ) )
2011-03-10 21:08:54 +03:00
2012-04-17 10:26:31 +04:00
# define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \
2013-03-22 17:24:12 +04:00
| | cpu_is_at91sam9n12 ( ) \
| | cpu_is_sama5d3 ( ) )
2009-03-31 20:13:15 +04:00
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 ?
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_CKGR_PLLBR , value ) ;
2006-01-09 20:05:41 +03:00
do {
cpu_relax ( ) ;
2011-11-25 05:59:46 +04:00
} while ( ( at91_pmc_read ( AT91_PMC_SR ) & AT91_PMC_LOCKB ) ! = is_on ) ;
2006-01-09 20:05:41 +03:00
}
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 )
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_SCER , clk - > pmc_mask ) ;
2006-01-09 20:05:41 +03:00
else
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_SCDR , clk - > pmc_mask ) ;
2006-01-09 20:05:41 +03:00
}
2008-04-06 00:14:03 +04:00
static void pmc_uckr_mode ( struct clk * clk , int is_on )
{
2011-11-25 05:59:46 +04:00
unsigned int uckr = at91_pmc_read ( AT91_CKGR_UCKR ) ;
2008-04-06 00:14:03 +04:00
if ( is_on ) {
is_on = AT91_PMC_LOCKU ;
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_CKGR_UCKR , uckr | clk - > pmc_mask ) ;
2008-04-06 00:14:03 +04:00
} else
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_CKGR_UCKR , uckr & ~ ( clk - > pmc_mask ) ) ;
2008-04-06 00:14:03 +04:00
do {
cpu_relax ( ) ;
2011-11-25 05:59:46 +04:00
} while ( ( at91_pmc_read ( AT91_PMC_SR ) & AT91_PMC_LOCKU ) ! = is_on ) ;
2008-04-06 00:14:03 +04:00
}
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 ,
} ;
2011-02-02 09:27:07 +03:00
struct clk utmi_clk = {
2008-04-06 00:14:03 +04:00
. 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 " ,
2009-03-31 20:13:15 +04:00
/*.parent = ... we choose parent at runtime */
2006-01-09 20:05:41 +03:00
. 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 .
*/
2011-02-02 09:27:07 +03:00
struct clk mck = {
2006-01-09 20:05:41 +03:00
. 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 )
{
2013-03-22 17:24:12 +04:00
u32 regval = 0 ;
/*
* With sama5d3 devices , we are managing clock division so we have to
* use the Peripheral Control Register introduced from at91sam9x5
* devices .
*/
if ( cpu_is_sama5d3 ( ) ) {
regval | = AT91_PMC_PCR_CMD ; /* write command */
regval | = clk - > pid & AT91_PMC_PCR_PID ; /* peripheral selection */
regval | = AT91_PMC_PCR_DIV ( clk - > div ) ;
if ( is_on )
regval | = AT91_PMC_PCR_EN ; /* enable clock */
at91_pmc_write ( AT91_PMC_PCR , regval ) ;
} else {
if ( is_on )
at91_pmc_write ( AT91_PMC_PCER , clk - > pmc_mask ) ;
else
at91_pmc_write ( AT91_PMC_PCDR , clk - > pmc_mask ) ;
}
2006-01-09 20:05:41 +03:00
}
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 :
2009-03-31 20:13:15 +04:00
if ( cpu_has_upll ( ) )
/* CSS_PLLB == CSS_UPLL */
return & utmi_clk ;
else if ( cpu_has_pllb ( ) )
return & pllb ;
2011-03-10 21:08:54 +03:00
break ;
/* alternate PMC: can use master clock */
case AT91_PMC_CSS_MASTER :
return & mck ;
2006-09-27 13:50:59 +04:00
}
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
2011-03-10 21:08:54 +03:00
static int pmc_prescaler_divider ( u32 reg )
{
if ( cpu_has_alt_prescaler ( ) ) {
return 1 < < ( ( reg & AT91_PMC_ALT_PRES ) > > PMC_ALT_PRES_OFFSET ) ;
} else {
return 1 < < ( ( reg & AT91_PMC_PRES ) > > PMC_PRES_OFFSET ) ;
}
}
2006-01-09 20:05:41 +03:00
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 ) ;
/*------------------------------------------------------------------------*/
/*
* 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 ;
2009-06-26 18:36:57 +04:00
unsigned long prev = ULONG_MAX ;
2006-01-09 20:05:41 +03:00
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 + + ) {
2009-06-26 18:36:57 +04:00
if ( actual > rate )
prev = actual ;
if ( actual & & actual < = rate ) {
if ( ( prev - rate ) < ( rate - actual ) ) {
actual = prev ;
prescale - - ;
}
2006-01-09 20:05:41 +03:00
break ;
2009-06-26 18:36:57 +04:00
}
2006-01-09 20:05:41 +03:00
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 ;
2011-03-10 21:08:54 +03:00
unsigned long prescale_offset , css_mask ;
2006-01-09 20:05:41 +03:00
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 ;
2011-03-10 21:08:54 +03:00
if ( cpu_has_alt_prescaler ( ) ) {
prescale_offset = PMC_ALT_PRES_OFFSET ;
css_mask = AT91_PMC_ALT_PCKR_CSS ;
} else {
prescale_offset = PMC_PRES_OFFSET ;
css_mask = AT91_PMC_CSS ;
}
2006-01-09 20:05:41 +03:00
spin_lock_irqsave ( & clk_lock , flags ) ;
actual = clk - > parent - > rate_hz ;
for ( prescale = 0 ; prescale < 7 ; prescale + + ) {
if ( actual & & actual < = rate ) {
u32 pckr ;
2011-11-25 05:59:46 +04:00
pckr = at91_pmc_read ( AT91_PMC_PCKR ( clk - > id ) ) ;
2011-03-10 21:08:54 +03:00
pckr & = css_mask ; /* keep clock selection */
pckr | = prescale < < prescale_offset ;
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_PCKR ( clk - > id ) , pckr ) ;
2006-01-09 20:05:41 +03:00
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 ;
2009-06-26 18:36:57 +04:00
if ( cpu_is_at91sam9rl ( ) & & parent - > id = = AT91_PMC_CSS_PLLB )
return - EINVAL ;
2006-01-09 20:05:41 +03:00
spin_lock_irqsave ( & clk_lock , flags ) ;
clk - > rate_hz = parent - > rate_hz ;
clk - > parent = parent ;
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_PCKR ( clk - > id ) , parent - > id ) ;
2006-01-09 20:05:41 +03:00
spin_unlock_irqrestore ( & clk_lock , flags ) ;
return 0 ;
}
EXPORT_SYMBOL ( clk_set_parent ) ;
2009-03-31 20:13:15 +04:00
/* establish PCK0..PCKN 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 ;
2011-03-10 21:08:54 +03:00
unsigned int css_mask ;
if ( cpu_has_alt_prescaler ( ) )
css_mask = AT91_PMC_ALT_PCKR_CSS ;
else
css_mask = AT91_PMC_CSS ;
2006-09-27 13:50:59 +04:00
2011-11-25 05:59:46 +04:00
pckr = at91_pmc_read ( AT91_PMC_PCKR ( clk - > id ) ) ;
2011-03-10 21:08:54 +03:00
parent = at91_css_to_clk ( pckr & css_mask ) ;
2006-09-27 13:50:59 +04:00
clk - > parent = parent ;
2011-03-10 21:08:54 +03:00
clk - > rate_hz = parent - > rate_hz / pmc_prescaler_divider ( pckr ) ;
2006-09-27 13:50:59 +04:00
}
2006-01-09 20:05:41 +03:00
/*------------------------------------------------------------------------*/
# ifdef CONFIG_DEBUG_FS
static int at91_clk_show ( struct seq_file * s , void * unused )
{
2013-03-22 17:24:12 +04:00
u32 scsr , pcsr , pcsr1 = 0 , uckr = 0 , sr ;
2006-09-27 13:50:59 +04:00
struct clk * clk ;
2006-01-09 20:05:41 +03:00
2011-11-25 05:59:46 +04:00
scsr = at91_pmc_read ( AT91_PMC_SCSR ) ;
pcsr = at91_pmc_read ( AT91_PMC_PCSR ) ;
2013-03-22 17:24:12 +04:00
if ( cpu_is_sama5d3 ( ) )
pcsr1 = at91_pmc_read ( AT91_PMC_PCSR1 ) ;
2011-11-25 05:59:46 +04:00
sr = at91_pmc_read ( AT91_PMC_SR ) ;
2012-02-23 12:44:37 +04:00
seq_printf ( s , " SCSR = %8x \n " , scsr ) ;
seq_printf ( s , " PCSR = %8x \n " , pcsr ) ;
2013-03-22 17:24:12 +04:00
if ( cpu_is_sama5d3 ( ) )
seq_printf ( s , " PCSR1 = %8x \n " , pcsr1 ) ;
2011-11-25 05:59:46 +04:00
seq_printf ( s , " MOR = %8x \n " , at91_pmc_read ( AT91_CKGR_MOR ) ) ;
seq_printf ( s , " MCFR = %8x \n " , at91_pmc_read ( AT91_CKGR_MCFR ) ) ;
seq_printf ( s , " PLLA = %8x \n " , at91_pmc_read ( AT91_CKGR_PLLAR ) ) ;
2009-03-31 20:13:15 +04:00
if ( cpu_has_pllb ( ) )
2011-11-25 05:59:46 +04:00
seq_printf ( s , " PLLB = %8x \n " , at91_pmc_read ( AT91_CKGR_PLLBR ) ) ;
2012-02-23 12:44:37 +04:00
if ( cpu_has_utmi ( ) ) {
2011-11-25 05:59:46 +04:00
uckr = at91_pmc_read ( AT91_CKGR_UCKR ) ;
2012-02-23 12:44:37 +04:00
seq_printf ( s , " UCKR = %8x \n " , uckr ) ;
}
2011-11-25 05:59:46 +04:00
seq_printf ( s , " MCKR = %8x \n " , at91_pmc_read ( AT91_PMC_MCKR ) ) ;
2013-06-24 20:07:34 +04:00
if ( cpu_has_upll ( ) | | cpu_is_at91sam9n12 ( ) )
2011-11-25 05:59:46 +04:00
seq_printf ( s , " USB = %8x \n " , at91_pmc_read ( AT91_PMC_USB ) ) ;
2012-02-23 12:44:37 +04:00
seq_printf ( s , " SR = %8x \n " , sr ) ;
2006-01-09 20:05:41 +03:00
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
2013-03-22 17:24:12 +04:00
if ( clk - > mode = = pmc_sys_mode ) {
2006-01-09 20:05:41 +03:00
state = ( scsr & clk - > pmc_mask ) ? " on " : " off " ;
2013-03-22 17:24:12 +04:00
} else if ( clk - > mode = = pmc_periph_mode ) {
if ( cpu_is_sama5d3 ( ) ) {
u32 pmc_mask = 1 < < ( clk - > pid % 32 ) ;
if ( clk - > pid > 31 )
state = ( pcsr1 & pmc_mask ) ? " on " : " off " ;
else
state = ( pcsr & pmc_mask ) ? " on " : " off " ;
} else {
state = ( pcsr & clk - > pmc_mask ) ? " on " : " off " ;
}
} else if ( clk - > mode = = pmc_uckr_mode ) {
2008-04-06 00:14:03 +04:00
state = ( uckr & clk - > pmc_mask ) ? " on " : " off " ;
2013-03-22 17:24:12 +04:00
} else if ( clk - > pmc_mask ) {
2006-01-09 20:05:41 +03:00
state = ( sr & clk - > pmc_mask ) ? " on " : " off " ;
2013-03-22 17:24:12 +04:00
} else if ( clk = = & clk32k | | clk = = & main_clk ) {
2006-01-09 20:05:41 +03:00
state = " on " ;
2013-03-22 17:24:12 +04:00
} else {
2006-01-09 20:05:41 +03:00
state = " " ;
2013-03-22 17:24:12 +04:00
}
2006-01-09 20:05:41 +03:00
2013-03-22 17:24:12 +04:00
seq_printf ( s , " %-10s users=%2d %-3s %9lu 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 */
2011-02-02 09:27:07 +03:00
static void __init at91_clk_add ( struct clk * clk )
{
list_add_tail ( & clk - > node , & clocks ) ;
clk - > cl . con_id = clk - > name ;
clk - > cl . clk = clk ;
clkdev_add ( & clk - > cl ) ;
}
2006-09-27 13:50:59 +04:00
int __init clk_register ( struct clk * clk )
{
if ( clk_is_peripheral ( clk ) ) {
2010-09-09 21:58:23 +04:00
if ( ! clk - > parent )
clk - > parent = & mck ;
2013-03-22 17:24:12 +04:00
if ( cpu_is_sama5d3 ( ) )
clk - > rate_hz = DIV_ROUND_UP ( clk - > parent - > rate_hz ,
1 < < clk - > div ) ;
2006-09-27 13:50:59 +04:00
clk - > mode = pmc_periph_mode ;
}
2006-12-01 13:27:31 +03:00
else if ( clk_is_sys ( clk ) ) {
clk - > parent = & mck ;
clk - > mode = pmc_sys_mode ;
}
2006-09-27 13:50:59 +04:00
else if ( clk_is_programmable ( clk ) ) {
clk - > mode = pmc_sys_mode ;
init_programmable_clock ( clk ) ;
}
2011-02-02 09:27:07 +03:00
at91_clk_add ( clk ) ;
2006-09-27 13:50:59 +04:00
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 ;
2013-03-22 17:24:12 +04:00
if ( cpu_is_sama5d3 ( ) )
mul = AT91_PMC3_MUL_GET ( reg ) ;
else
mul = AT91_PMC_MUL_GET ( reg ) ;
2006-01-09 20:05:41 +03:00
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 ;
2013-06-24 20:07:34 +04:00
else if ( pll = = & utmi_clk | | cpu_is_at91sam9n12 ( ) )
return freq / ( 1 + ( ( reg & AT91_PMC_OHCIUSBDIV ) > > 8 ) ) ;
2006-03-22 23:14:14 +03:00
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 ;
}
2012-10-05 04:11:28 +04:00
static struct clk * const standard_pmc_clocks [ ] __initconst = {
2006-09-27 13:50:59 +04:00
/* four primary clocks */
& clk32k ,
& main_clk ,
& plla ,
/* MCK */
& mck
} ;
2009-03-31 20:13:15 +04:00
/* PLLB generated USB full speed clock init */
static void __init at91_pllb_usbfs_clock_init ( unsigned long main_clock )
{
2013-06-24 20:07:34 +04:00
unsigned int reg ;
2009-03-31 20:13:15 +04:00
/*
* USB clock init : choose 48 MHz PLLB value ,
* disable 48 MHz clock during usb peripheral suspend .
*
* REVISIT : assumes MCK doesn ' t derive from PLLB !
*/
uhpck . parent = & pllb ;
2013-06-24 20:07:34 +04:00
reg = at91_pllb_usb_init = at91_pll_calc ( main_clock , 48000000 * 2 ) ;
2009-03-31 20:13:15 +04:00
pllb . rate_hz = at91_pll_rate ( & pllb , main_clock , at91_pllb_usb_init ) ;
if ( cpu_is_at91rm9200 ( ) ) {
2013-06-24 20:07:34 +04:00
reg = at91_pllb_usb_init | = AT91_PMC_USB96M ;
2009-03-31 20:13:15 +04:00
uhpck . pmc_mask = AT91RM9200_PMC_UHP ;
udpck . pmc_mask = AT91RM9200_PMC_UDP ;
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_SCER , AT91RM9200_PMC_MCKUDP ) ;
2009-06-26 18:37:00 +04:00
} else if ( cpu_is_at91sam9260 ( ) | | cpu_is_at91sam9261 ( ) | |
cpu_is_at91sam9263 ( ) | | cpu_is_at91sam9g20 ( ) | |
2011-05-17 16:51:14 +04:00
cpu_is_at91sam9g10 ( ) ) {
2013-06-24 20:07:34 +04:00
reg = at91_pllb_usb_init | = AT91_PMC_USB96M ;
uhpck . pmc_mask = AT91SAM926x_PMC_UHP ;
udpck . pmc_mask = AT91SAM926x_PMC_UDP ;
} else if ( cpu_is_at91sam9n12 ( ) ) {
/* Divider for USB clock is in USB clock register for 9n12 */
reg = AT91_PMC_USBS_PLLB ;
/* For PLLB output 96M, set usb divider 2 (USBDIV + 1) */
reg | = AT91_PMC_OHCIUSBDIV_2 ;
at91_pmc_write ( AT91_PMC_USB , reg ) ;
/* Still setup masks */
2009-03-31 20:13:15 +04:00
uhpck . pmc_mask = AT91SAM926x_PMC_UHP ;
udpck . pmc_mask = AT91SAM926x_PMC_UDP ;
}
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_CKGR_PLLBR , 0 ) ;
2009-03-31 20:13:15 +04:00
2013-06-24 20:07:34 +04:00
udpck . rate_hz = at91_usb_rate ( & pllb , pllb . rate_hz , reg ) ;
uhpck . rate_hz = at91_usb_rate ( & pllb , pllb . rate_hz , reg ) ;
2009-03-31 20:13:15 +04:00
}
/* UPLL generated USB full speed clock init */
static void __init at91_upll_usbfs_clock_init ( unsigned long main_clock )
{
/*
* USB clock init : choose 480 MHz from UPLL ,
*/
unsigned int usbr = AT91_PMC_USBS_UPLL ;
/* Setup divider by 10 to reach 48 MHz */
usbr | = ( ( 10 - 1 ) < < 8 ) & AT91_PMC_OHCIUSBDIV ;
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_USB , usbr ) ;
2009-03-31 20:13:15 +04:00
/* Now set uhpck values */
uhpck . parent = & utmi_clk ;
uhpck . pmc_mask = AT91SAM926x_PMC_UHP ;
2013-06-24 20:09:25 +04:00
uhpck . rate_hz = at91_usb_rate ( & utmi_clk , utmi_clk . rate_hz , usbr ) ;
2009-03-31 20:13:15 +04:00
}
2012-03-02 16:44:23 +04:00
static int __init at91_pmc_init ( unsigned long main_clock )
2006-01-09 20:05:41 +03:00
{
unsigned tmp , freq , mckr ;
2006-09-27 13:50:59 +04:00
int i ;
2009-06-26 18:36:57 +04:00
int pll_overclock = false ;
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 {
2011-11-25 05:59:46 +04:00
tmp = at91_pmc_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 */
2011-11-25 05:59:46 +04:00
plla . rate_hz = at91_pll_rate ( & plla , main_clock , at91_pmc_read ( AT91_CKGR_PLLAR ) ) ;
2013-03-22 17:24:12 +04:00
if ( cpu_has_1056M_plla ( ) ) {
if ( plla . rate_hz > 1056000000 )
2009-06-26 18:36:57 +04:00
pll_overclock = true ;
} else if ( cpu_has_800M_plla ( ) ) {
if ( plla . rate_hz > 800000000 )
pll_overclock = true ;
2013-03-22 17:24:12 +04:00
} else if ( cpu_has_300M_plla ( ) ) {
if ( plla . rate_hz > 300000000 )
pll_overclock = true ;
2012-07-09 23:06:25 +04:00
} else if ( cpu_has_240M_plla ( ) ) {
if ( plla . rate_hz > 240000000 )
pll_overclock = true ;
} else if ( cpu_has_210M_plla ( ) ) {
if ( plla . rate_hz > 210000000 )
pll_overclock = true ;
2009-06-26 18:36:57 +04:00
} else {
if ( plla . rate_hz > 209000000 )
pll_overclock = true ;
}
if ( pll_overclock )
2006-01-09 20:05:41 +03:00
pr_info ( " Clocks: PLLA overclocked, %ld MHz \n " , plla . rate_hz / 1000000 ) ;
2011-03-10 21:08:54 +03:00
if ( cpu_has_plladiv2 ( ) ) {
2011-11-25 05:59:46 +04:00
mckr = at91_pmc_read ( AT91_PMC_MCKR ) ;
2009-06-26 18:36:57 +04:00
plla . rate_hz / = ( 1 < < ( ( mckr & AT91_PMC_PLLADIV2 ) > > 12 ) ) ; /* plla divisor by 2 */
}
2009-03-31 20:13:15 +04:00
2009-06-26 18:36:57 +04:00
if ( ! cpu_has_pllb ( ) & & cpu_has_upll ( ) ) {
2009-03-31 20:13:15 +04:00
/* setup UTMI clock as the fourth primary clock
* ( instead of pllb ) */
utmi_clk . type | = CLK_TYPE_PRIMARY ;
utmi_clk . id = 3 ;
2006-12-01 13:27:31 +03:00
}
2006-01-09 20:05:41 +03:00
2006-03-22 23:14:14 +03:00
2008-04-06 00:14:03 +04:00
/*
* USB HS clock init
*/
2009-12-15 23:57:27 +03:00
if ( cpu_has_utmi ( ) ) {
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 ;
2011-03-10 21:08:54 +03:00
/* UTMI bias and PLL are managed at the same time */
if ( cpu_has_upll ( ) )
utmi_clk . pmc_mask | = AT91_PMC_BIASEN ;
2009-12-15 23:57:27 +03:00
}
2009-03-31 20:13:15 +04:00
/*
* USB FS clock init
*/
if ( cpu_has_pllb ( ) )
at91_pllb_usbfs_clock_init ( main_clock ) ;
if ( cpu_has_upll ( ) )
/* assumes that we choose UPLL for USB and not PLLA */
at91_upll_usbfs_clock_init ( main_clock ) ;
2008-04-06 00:14:03 +04:00
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 .
*/
2011-11-25 05:59:46 +04:00
mckr = at91_pmc_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 ;
2011-03-10 21:08:54 +03:00
freq / = pmc_prescaler_divider ( mckr ) ; /* prescale */
2009-03-31 20:13:15 +04:00
if ( cpu_is_at91rm9200 ( ) ) {
2007-11-19 13:52:09 +03:00
mck . rate_hz = freq / ( 1 + ( ( mckr & AT91_PMC_MDIV ) > > 8 ) ) ; /* mdiv */
2009-03-31 20:13:15 +04:00
} else if ( cpu_is_at91sam9g20 ( ) ) {
2008-07-10 13:15:35 +04:00
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 */
2011-03-10 21:08:54 +03:00
} else if ( cpu_has_mdiv3 ( ) ) {
2009-06-26 18:36:57 +04:00
mck . rate_hz = ( mckr & AT91_PMC_MDIV ) = = AT91SAM9_PMC_MDIV_3 ?
freq / 3 : freq / ( 1 < < ( ( mckr & AT91_PMC_MDIV ) > > 8 ) ) ; /* mdiv */
2009-03-31 20:13:15 +04:00
} else {
2009-12-15 23:57:27 +03:00
mck . rate_hz = freq / ( 1 < < ( ( mckr & AT91_PMC_MDIV ) > > 8 ) ) ; /* mdiv */
2009-03-31 20:13:15 +04:00
}
2006-01-09 20:05:41 +03:00
2011-03-10 21:08:54 +03:00
if ( cpu_has_alt_prescaler ( ) ) {
/* Programmable clocks can use MCK */
mck . type | = CLK_TYPE_PRIMARY ;
mck . id = 4 ;
}
2006-09-27 13:50:59 +04:00
/* Register the PMC's standard clocks */
for ( i = 0 ; i < ARRAY_SIZE ( standard_pmc_clocks ) ; i + + )
2011-02-02 09:27:07 +03:00
at91_clk_add ( standard_pmc_clocks [ i ] ) ;
2006-09-27 13:50:59 +04:00
2009-03-31 20:13:15 +04:00
if ( cpu_has_pllb ( ) )
2011-02-02 09:27:07 +03:00
at91_clk_add ( & pllb ) ;
2009-03-31 20:13:15 +04:00
if ( cpu_has_uhp ( ) )
2011-02-02 09:27:07 +03:00
at91_clk_add ( & uhpck ) ;
2009-03-31 20:13:15 +04:00
if ( cpu_has_udpfs ( ) )
2011-02-02 09:27:07 +03:00
at91_clk_add ( & udpck ) ;
2009-03-31 20:13:15 +04:00
if ( cpu_has_utmi ( ) )
2011-02-02 09:27:07 +03:00
at91_clk_add ( & utmi_clk ) ;
2008-04-06 00:14:03 +04:00
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 ;
}
2012-03-02 16:44:23 +04:00
# if defined(CONFIG_OF)
static struct of_device_id pmc_ids [ ] = {
{ . compatible = " atmel,at91rm9200-pmc " } ,
2013-10-11 15:49:10 +04:00
{ . compatible = " atmel,at91sam9260-pmc " } ,
{ . compatible = " atmel,at91sam9g45-pmc " } ,
{ . compatible = " atmel,at91sam9n12-pmc " } ,
{ . compatible = " atmel,at91sam9x5-pmc " } ,
{ . compatible = " atmel,sama5d3-pmc " } ,
2012-03-02 16:44:23 +04:00
{ /*sentinel*/ }
} ;
static struct of_device_id osc_ids [ ] = {
{ . compatible = " atmel,osc " } ,
{ /*sentinel*/ }
} ;
int __init at91_dt_clock_init ( void )
{
struct device_node * np ;
u32 main_clock = 0 ;
np = of_find_matching_node ( NULL , pmc_ids ) ;
if ( ! np )
panic ( " unable to find compatible pmc node in dtb \n " ) ;
at91_pmc_base = of_iomap ( np , 0 ) ;
if ( ! at91_pmc_base )
panic ( " unable to map pmc cpu registers \n " ) ;
of_node_put ( np ) ;
/* retrieve the freqency of fixed clocks from device tree */
np = of_find_matching_node ( NULL , osc_ids ) ;
if ( np ) {
u32 rate ;
if ( ! of_property_read_u32 ( np , " clock-frequency " , & rate ) )
main_clock = rate ;
}
of_node_put ( np ) ;
return at91_pmc_init ( main_clock ) ;
}
# endif
int __init at91_clock_init ( unsigned long main_clock )
{
at91_pmc_base = ioremap ( AT91_PMC , 256 ) ;
if ( ! at91_pmc_base )
panic ( " Impossible to ioremap AT91_PMC 0x%x \n " , AT91_PMC ) ;
return at91_pmc_init ( main_clock ) ;
}
2007-02-08 19:36:34 +03:00
/*
* Several unused clocks may be active . Turn them off .
*/
static int __init at91_clock_reset ( void )
{
unsigned long pcdr = 0 ;
2013-03-22 17:24:12 +04:00
unsigned long pcdr1 = 0 ;
2007-02-08 19:36:34 +03:00
unsigned long scdr = 0 ;
struct clk * clk ;
list_for_each_entry ( clk , & clocks , node ) {
if ( clk - > users > 0 )
continue ;
2013-03-22 17:24:12 +04:00
if ( clk - > mode = = pmc_periph_mode ) {
if ( cpu_is_sama5d3 ( ) ) {
u32 pmc_mask = 1 < < ( clk - > pid % 32 ) ;
if ( clk - > pid > 31 )
pcdr1 | = pmc_mask ;
else
pcdr | = pmc_mask ;
} else
pcdr | = clk - > pmc_mask ;
}
2007-02-08 19:36:34 +03:00
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
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_SCDR , scdr ) ;
2013-03-22 17:24:12 +04:00
if ( cpu_is_sama5d3 ( ) )
at91_pmc_write ( AT91_PMC_PCDR1 , pcdr1 ) ;
2006-01-09 20:05:41 +03:00
return 0 ;
}
2007-02-08 19:36:34 +03:00
late_initcall ( at91_clock_reset ) ;
2012-02-05 16:25:32 +04:00
void at91sam9_idle ( void )
{
2011-11-25 05:59:46 +04:00
at91_pmc_write ( AT91_PMC_SCDR , AT91_PMC_PCK ) ;
2012-02-05 16:25:32 +04:00
cpu_do_idle ( ) ;
}