2011-01-04 23:28:14 +03:00
/*
* Atheros AR71XX / AR724X / AR913X common routines
*
2012-03-14 13:45:22 +04:00
* Copyright ( C ) 2010 - 2011 Jaiganesh Narayanan < jnarayanan @ atheros . com >
2011-01-04 23:28:14 +03:00
* Copyright ( C ) 2011 Gabor Juhos < juhosg @ openwrt . org >
*
2012-03-14 13:45:22 +04:00
* Parts of this file are based on Atheros ' 2.6 .15 / 2.6 .31 BSP
*
2011-01-04 23:28:14 +03:00
* 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/init.h>
# include <linux/err.h>
# include <linux/clk.h>
2013-08-28 12:41:47 +04:00
# include <linux/clkdev.h>
2015-04-19 15:30:04 +03:00
# include <linux/clk-provider.h>
2016-03-17 06:34:15 +03:00
# include <linux/of.h>
# include <linux/of_address.h>
2016-03-17 06:34:14 +03:00
# include <dt-bindings/clock/ath79-clk.h>
2011-01-04 23:28:14 +03:00
2012-09-08 16:02:21 +04:00
# include <asm/div64.h>
2011-01-04 23:28:14 +03:00
# include <asm/mach-ath79/ath79.h>
# include <asm/mach-ath79/ar71xx_regs.h>
# include "common.h"
2016-03-17 06:34:15 +03:00
# include "machtypes.h"
2011-01-04 23:28:14 +03:00
# define AR71XX_BASE_FREQ 40000000
2016-03-17 06:34:09 +03:00
# define AR724X_BASE_FREQ 40000000
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:14 +03:00
static struct clk * clks [ ATH79_CLK_END ] ;
2015-05-31 03:18:22 +03:00
static struct clk_onecell_data clk_data = {
. clks = clks ,
. clk_num = ARRAY_SIZE ( clks ) ,
} ;
static struct clk * __init ath79_add_sys_clkdev (
const char * id , unsigned long rate )
2013-08-28 12:41:47 +04:00
{
struct clk * clk ;
int err ;
2016-04-20 04:33:21 +03:00
clk = clk_register_fixed_rate ( NULL , id , NULL , 0 , rate ) ;
2016-10-30 11:25:46 +03:00
if ( IS_ERR ( clk ) )
2013-08-28 12:41:47 +04:00
panic ( " failed to allocate %s clock structure " , id ) ;
err = clk_register_clkdev ( clk , id , NULL ) ;
if ( err )
panic ( " unable to register %s clock device " , id ) ;
2015-05-31 03:18:22 +03:00
return clk ;
2013-08-28 12:41:47 +04:00
}
2011-01-04 23:28:14 +03:00
static void __init ar71xx_clocks_init ( void )
{
2013-08-28 12:41:46 +04:00
unsigned long ref_rate ;
unsigned long cpu_rate ;
unsigned long ddr_rate ;
unsigned long ahb_rate ;
2011-01-04 23:28:14 +03:00
u32 pll ;
u32 freq ;
u32 div ;
2013-08-28 12:41:46 +04:00
ref_rate = AR71XX_BASE_FREQ ;
2011-01-04 23:28:14 +03:00
pll = ath79_pll_rr ( AR71XX_PLL_REG_CPU_CONFIG ) ;
2015-04-19 15:30:02 +03:00
div = ( ( pll > > AR71XX_PLL_FB_SHIFT ) & AR71XX_PLL_FB_MASK ) + 1 ;
2013-08-28 12:41:46 +04:00
freq = div * ref_rate ;
2011-01-04 23:28:14 +03:00
div = ( ( pll > > AR71XX_CPU_DIV_SHIFT ) & AR71XX_CPU_DIV_MASK ) + 1 ;
2013-08-28 12:41:46 +04:00
cpu_rate = freq / div ;
2011-01-04 23:28:14 +03:00
div = ( ( pll > > AR71XX_DDR_DIV_SHIFT ) & AR71XX_DDR_DIV_MASK ) + 1 ;
2013-08-28 12:41:46 +04:00
ddr_rate = freq / div ;
2011-01-04 23:28:14 +03:00
div = ( ( ( pll > > AR71XX_AHB_DIV_SHIFT ) & AR71XX_AHB_DIV_MASK ) + 1 ) * 2 ;
2013-08-28 12:41:46 +04:00
ahb_rate = cpu_rate / div ;
2013-08-28 12:41:47 +04:00
ath79_add_sys_clkdev ( " ref " , ref_rate ) ;
2016-03-17 06:34:14 +03:00
clks [ ATH79_CLK_CPU ] = ath79_add_sys_clkdev ( " cpu " , cpu_rate ) ;
clks [ ATH79_CLK_DDR ] = ath79_add_sys_clkdev ( " ddr " , ddr_rate ) ;
clks [ ATH79_CLK_AHB ] = ath79_add_sys_clkdev ( " ahb " , ahb_rate ) ;
2011-01-04 23:28:14 +03:00
2013-08-28 12:41:47 +04:00
clk_add_alias ( " wdt " , NULL , " ahb " , NULL ) ;
clk_add_alias ( " uart " , NULL , " ahb " , NULL ) ;
2011-01-04 23:28:14 +03:00
}
2016-03-17 06:34:15 +03:00
static struct clk * __init ath79_reg_ffclk ( const char * name ,
const char * parent_name , unsigned int mult , unsigned int div )
2011-01-04 23:28:14 +03:00
{
2016-03-17 06:34:15 +03:00
struct clk * clk ;
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
clk = clk_register_fixed_factor ( NULL , name , parent_name , 0 , mult , div ) ;
2016-08-12 06:06:54 +03:00
if ( IS_ERR ( clk ) )
2016-03-17 06:34:15 +03:00
panic ( " failed to allocate %s clock structure " , name ) ;
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
return clk ;
}
static void __init ar724x_clk_init ( struct clk * ref_clk , void __iomem * pll_base )
{
u32 pll ;
u32 mult , div , ddr_div , ahb_div ;
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
pll = __raw_readl ( pll_base + AR724X_PLL_REG_CPU_CONFIG ) ;
mult = ( ( pll > > AR724X_PLL_FB_SHIFT ) & AR724X_PLL_FB_MASK ) ;
2016-03-17 06:34:09 +03:00
div = ( ( pll > > AR724X_PLL_REF_DIV_SHIFT ) & AR724X_PLL_REF_DIV_MASK ) * 2 ;
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
ddr_div = ( ( pll > > AR724X_DDR_DIV_SHIFT ) & AR724X_DDR_DIV_MASK ) + 1 ;
ahb_div = ( ( ( pll > > AR724X_AHB_DIV_SHIFT ) & AR724X_AHB_DIV_MASK ) + 1 ) * 2 ;
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
clks [ ATH79_CLK_CPU ] = ath79_reg_ffclk ( " cpu " , " ref " , mult , div ) ;
clks [ ATH79_CLK_DDR ] = ath79_reg_ffclk ( " ddr " , " ref " , mult , div * ddr_div ) ;
clks [ ATH79_CLK_AHB ] = ath79_reg_ffclk ( " ahb " , " ref " , mult , div * ahb_div ) ;
}
2011-01-04 23:28:14 +03:00
2016-03-17 06:34:15 +03:00
static void __init ar724x_clocks_init ( void )
{
struct clk * ref_clk ;
2013-08-28 12:41:46 +04:00
2016-03-17 06:34:15 +03:00
ref_clk = ath79_add_sys_clkdev ( " ref " , AR724X_BASE_FREQ ) ;
ar724x_clk_init ( ref_clk , ath79_pll_base ) ;
/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
clk_register_clkdev ( clks [ ATH79_CLK_CPU ] , " cpu " , NULL ) ;
clk_register_clkdev ( clks [ ATH79_CLK_DDR ] , " ddr " , NULL ) ;
clk_register_clkdev ( clks [ ATH79_CLK_AHB ] , " ahb " , NULL ) ;
2011-01-04 23:28:14 +03:00
2013-08-28 12:41:47 +04:00
clk_add_alias ( " wdt " , NULL , " ahb " , NULL ) ;
clk_add_alias ( " uart " , NULL , " ahb " , NULL ) ;
2011-01-04 23:28:14 +03:00
}
2016-03-17 06:34:18 +03:00
static void __init ar9330_clk_init ( struct clk * ref_clk , void __iomem * pll_base )
2011-06-20 23:26:04 +04:00
{
u32 clock_ctrl ;
2016-03-17 06:34:18 +03:00
u32 ref_div ;
u32 ninit_mul ;
u32 out_div ;
2011-06-20 23:26:04 +04:00
2016-03-17 06:34:18 +03:00
u32 cpu_div ;
u32 ddr_div ;
u32 ahb_div ;
2011-06-20 23:26:04 +04:00
2016-03-17 06:34:18 +03:00
clock_ctrl = __raw_readl ( pll_base + AR933X_PLL_CLOCK_CTRL_REG ) ;
2011-06-20 23:26:04 +04:00
if ( clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS ) {
2016-03-17 06:34:18 +03:00
ref_div = 1 ;
ninit_mul = 1 ;
out_div = 1 ;
cpu_div = 1 ;
ddr_div = 1 ;
ahb_div = 1 ;
2011-06-20 23:26:04 +04:00
} else {
2016-03-17 06:34:18 +03:00
u32 cpu_config ;
u32 t ;
cpu_config = __raw_readl ( pll_base + AR933X_PLL_CPU_CONFIG_REG ) ;
2011-06-20 23:26:04 +04:00
t = ( cpu_config > > AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT ) &
AR933X_PLL_CPU_CONFIG_REFDIV_MASK ;
2016-03-17 06:34:18 +03:00
ref_div = t ;
2011-06-20 23:26:04 +04:00
2016-03-17 06:34:18 +03:00
ninit_mul = ( cpu_config > > AR933X_PLL_CPU_CONFIG_NINT_SHIFT ) &
2011-06-20 23:26:04 +04:00
AR933X_PLL_CPU_CONFIG_NINT_MASK ;
t = ( cpu_config > > AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT ) &
AR933X_PLL_CPU_CONFIG_OUTDIV_MASK ;
if ( t = = 0 )
t = 1 ;
2016-03-17 06:34:18 +03:00
out_div = ( 1 < < t ) ;
2011-06-20 23:26:04 +04:00
2016-03-17 06:34:18 +03:00
cpu_div = ( ( clock_ctrl > > AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT ) &
2011-06-20 23:26:04 +04:00
AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK ) + 1 ;
2016-03-17 06:34:18 +03:00
ddr_div = ( ( clock_ctrl > > AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT ) &
2011-06-20 23:26:04 +04:00
AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK ) + 1 ;
2016-03-17 06:34:18 +03:00
ahb_div = ( ( clock_ctrl > > AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT ) &
2011-06-20 23:26:04 +04:00
AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK ) + 1 ;
}
2016-03-17 06:34:18 +03:00
clks [ ATH79_CLK_CPU ] = ath79_reg_ffclk ( " cpu " , " ref " ,
ninit_mul , ref_div * out_div * cpu_div ) ;
clks [ ATH79_CLK_DDR ] = ath79_reg_ffclk ( " ddr " , " ref " ,
ninit_mul , ref_div * out_div * ddr_div ) ;
clks [ ATH79_CLK_AHB ] = ath79_reg_ffclk ( " ahb " , " ref " ,
ninit_mul , ref_div * out_div * ahb_div ) ;
}
static void __init ar933x_clocks_init ( void )
{
struct clk * ref_clk ;
unsigned long ref_rate ;
u32 t ;
t = ath79_reset_rr ( AR933X_RESET_REG_BOOTSTRAP ) ;
if ( t & AR933X_BOOTSTRAP_REF_CLK_40 )
ref_rate = ( 40 * 1000 * 1000 ) ;
else
ref_rate = ( 25 * 1000 * 1000 ) ;
ref_clk = ath79_add_sys_clkdev ( " ref " , ref_rate ) ;
ar9330_clk_init ( ref_clk , ath79_pll_base ) ;
/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
clk_register_clkdev ( clks [ ATH79_CLK_CPU ] , " cpu " , NULL ) ;
clk_register_clkdev ( clks [ ATH79_CLK_DDR ] , " ddr " , NULL ) ;
clk_register_clkdev ( clks [ ATH79_CLK_AHB ] , " ahb " , NULL ) ;
2013-08-28 12:41:46 +04:00
2013-08-28 12:41:47 +04:00
clk_add_alias ( " wdt " , NULL , " ahb " , NULL ) ;
clk_add_alias ( " uart " , NULL , " ref " , NULL ) ;
2011-06-20 23:26:04 +04:00
}
2012-09-08 16:02:21 +04:00
static u32 __init ar934x_get_pll_freq ( u32 ref , u32 ref_div , u32 nint , u32 nfrac ,
u32 frac , u32 out_div )
{
u64 t ;
u32 ret ;
2013-08-28 12:41:43 +04:00
t = ref ;
2012-09-08 16:02:21 +04:00
t * = nint ;
do_div ( t , ref_div ) ;
ret = t ;
2013-08-28 12:41:43 +04:00
t = ref ;
2012-09-08 16:02:21 +04:00
t * = nfrac ;
do_div ( t , ref_div * frac ) ;
ret + = t ;
ret / = ( 1 < < out_div ) ;
return ret ;
}
2012-03-14 13:45:22 +04:00
static void __init ar934x_clocks_init ( void )
{
2013-08-28 12:41:46 +04:00
unsigned long ref_rate ;
unsigned long cpu_rate ;
unsigned long ddr_rate ;
unsigned long ahb_rate ;
2012-09-08 16:02:21 +04:00
u32 pll , out_div , ref_div , nint , nfrac , frac , clk_ctrl , postdiv ;
2012-03-14 13:45:22 +04:00
u32 cpu_pll , ddr_pll ;
u32 bootstrap ;
2012-09-08 16:02:21 +04:00
void __iomem * dpll_base ;
dpll_base = ioremap ( AR934X_SRIF_BASE , AR934X_SRIF_SIZE ) ;
2012-03-14 13:45:22 +04:00
bootstrap = ath79_reset_rr ( AR934X_RESET_REG_BOOTSTRAP ) ;
2013-01-22 15:59:30 +04:00
if ( bootstrap & AR934X_BOOTSTRAP_REF_CLK_40 )
2013-08-28 12:41:46 +04:00
ref_rate = 40 * 1000 * 1000 ;
2012-03-14 13:45:22 +04:00
else
2013-08-28 12:41:46 +04:00
ref_rate = 25 * 1000 * 1000 ;
2012-03-14 13:45:22 +04:00
2012-09-08 16:02:21 +04:00
pll = __raw_readl ( dpll_base + AR934X_SRIF_CPU_DPLL2_REG ) ;
if ( pll & AR934X_SRIF_DPLL2_LOCAL_PLL ) {
out_div = ( pll > > AR934X_SRIF_DPLL2_OUTDIV_SHIFT ) &
AR934X_SRIF_DPLL2_OUTDIV_MASK ;
pll = __raw_readl ( dpll_base + AR934X_SRIF_CPU_DPLL1_REG ) ;
nint = ( pll > > AR934X_SRIF_DPLL1_NINT_SHIFT ) &
AR934X_SRIF_DPLL1_NINT_MASK ;
nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK ;
ref_div = ( pll > > AR934X_SRIF_DPLL1_REFDIV_SHIFT ) &
AR934X_SRIF_DPLL1_REFDIV_MASK ;
frac = 1 < < 18 ;
} else {
pll = ath79_pll_rr ( AR934X_PLL_CPU_CONFIG_REG ) ;
out_div = ( pll > > AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT ) &
AR934X_PLL_CPU_CONFIG_OUTDIV_MASK ;
ref_div = ( pll > > AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT ) &
AR934X_PLL_CPU_CONFIG_REFDIV_MASK ;
nint = ( pll > > AR934X_PLL_CPU_CONFIG_NINT_SHIFT ) &
AR934X_PLL_CPU_CONFIG_NINT_MASK ;
nfrac = ( pll > > AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT ) &
AR934X_PLL_CPU_CONFIG_NFRAC_MASK ;
frac = 1 < < 6 ;
}
2013-08-28 12:41:46 +04:00
cpu_pll = ar934x_get_pll_freq ( ref_rate , ref_div , nint ,
2012-09-08 16:02:21 +04:00
nfrac , frac , out_div ) ;
pll = __raw_readl ( dpll_base + AR934X_SRIF_DDR_DPLL2_REG ) ;
if ( pll & AR934X_SRIF_DPLL2_LOCAL_PLL ) {
out_div = ( pll > > AR934X_SRIF_DPLL2_OUTDIV_SHIFT ) &
AR934X_SRIF_DPLL2_OUTDIV_MASK ;
pll = __raw_readl ( dpll_base + AR934X_SRIF_DDR_DPLL1_REG ) ;
nint = ( pll > > AR934X_SRIF_DPLL1_NINT_SHIFT ) &
AR934X_SRIF_DPLL1_NINT_MASK ;
nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK ;
ref_div = ( pll > > AR934X_SRIF_DPLL1_REFDIV_SHIFT ) &
AR934X_SRIF_DPLL1_REFDIV_MASK ;
frac = 1 < < 18 ;
} else {
pll = ath79_pll_rr ( AR934X_PLL_DDR_CONFIG_REG ) ;
out_div = ( pll > > AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT ) &
AR934X_PLL_DDR_CONFIG_OUTDIV_MASK ;
ref_div = ( pll > > AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT ) &
AR934X_PLL_DDR_CONFIG_REFDIV_MASK ;
nint = ( pll > > AR934X_PLL_DDR_CONFIG_NINT_SHIFT ) &
AR934X_PLL_DDR_CONFIG_NINT_MASK ;
nfrac = ( pll > > AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT ) &
AR934X_PLL_DDR_CONFIG_NFRAC_MASK ;
frac = 1 < < 10 ;
}
2013-08-28 12:41:46 +04:00
ddr_pll = ar934x_get_pll_freq ( ref_rate , ref_div , nint ,
2012-09-08 16:02:21 +04:00
nfrac , frac , out_div ) ;
2012-03-14 13:45:22 +04:00
clk_ctrl = ath79_pll_rr ( AR934X_PLL_CPU_DDR_CLK_CTRL_REG ) ;
postdiv = ( clk_ctrl > > AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT ) &
AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK ;
if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
cpu_rate = ref_rate ;
2012-03-14 13:45:22 +04:00
else if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL )
2013-08-28 12:41:46 +04:00
cpu_rate = cpu_pll / ( postdiv + 1 ) ;
2012-03-14 13:45:22 +04:00
else
2013-08-28 12:41:46 +04:00
cpu_rate = ddr_pll / ( postdiv + 1 ) ;
2012-03-14 13:45:22 +04:00
postdiv = ( clk_ctrl > > AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT ) &
AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK ;
if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
ddr_rate = ref_rate ;
2012-03-14 13:45:22 +04:00
else if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL )
2013-08-28 12:41:46 +04:00
ddr_rate = ddr_pll / ( postdiv + 1 ) ;
2012-03-14 13:45:22 +04:00
else
2013-08-28 12:41:46 +04:00
ddr_rate = cpu_pll / ( postdiv + 1 ) ;
2012-03-14 13:45:22 +04:00
postdiv = ( clk_ctrl > > AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT ) &
AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK ;
if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
ahb_rate = ref_rate ;
2012-03-14 13:45:22 +04:00
else if ( clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL )
2013-08-28 12:41:46 +04:00
ahb_rate = ddr_pll / ( postdiv + 1 ) ;
2012-03-14 13:45:22 +04:00
else
2013-08-28 12:41:46 +04:00
ahb_rate = cpu_pll / ( postdiv + 1 ) ;
2013-08-28 12:41:47 +04:00
ath79_add_sys_clkdev ( " ref " , ref_rate ) ;
2016-03-17 06:34:14 +03:00
clks [ ATH79_CLK_CPU ] = ath79_add_sys_clkdev ( " cpu " , cpu_rate ) ;
clks [ ATH79_CLK_DDR ] = ath79_add_sys_clkdev ( " ddr " , ddr_rate ) ;
clks [ ATH79_CLK_AHB ] = ath79_add_sys_clkdev ( " ahb " , ahb_rate ) ;
2012-03-14 13:45:22 +04:00
2013-08-28 12:41:47 +04:00
clk_add_alias ( " wdt " , NULL , " ref " , NULL ) ;
clk_add_alias ( " uart " , NULL , " ref " , NULL ) ;
2012-09-08 16:02:21 +04:00
iounmap ( dpll_base ) ;
2012-03-14 13:45:22 +04:00
}
2013-02-15 17:38:17 +04:00
static void __init qca955x_clocks_init ( void )
{
2013-08-28 12:41:46 +04:00
unsigned long ref_rate ;
unsigned long cpu_rate ;
unsigned long ddr_rate ;
unsigned long ahb_rate ;
2013-02-15 17:38:17 +04:00
u32 pll , out_div , ref_div , nint , frac , clk_ctrl , postdiv ;
u32 cpu_pll , ddr_pll ;
u32 bootstrap ;
bootstrap = ath79_reset_rr ( QCA955X_RESET_REG_BOOTSTRAP ) ;
if ( bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40 )
2013-08-28 12:41:46 +04:00
ref_rate = 40 * 1000 * 1000 ;
2013-02-15 17:38:17 +04:00
else
2013-08-28 12:41:46 +04:00
ref_rate = 25 * 1000 * 1000 ;
2013-02-15 17:38:17 +04:00
pll = ath79_pll_rr ( QCA955X_PLL_CPU_CONFIG_REG ) ;
out_div = ( pll > > QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT ) &
QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK ;
ref_div = ( pll > > QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT ) &
QCA955X_PLL_CPU_CONFIG_REFDIV_MASK ;
nint = ( pll > > QCA955X_PLL_CPU_CONFIG_NINT_SHIFT ) &
QCA955X_PLL_CPU_CONFIG_NINT_MASK ;
frac = ( pll > > QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT ) &
QCA955X_PLL_CPU_CONFIG_NFRAC_MASK ;
2013-08-28 12:41:46 +04:00
cpu_pll = nint * ref_rate / ref_div ;
cpu_pll + = frac * ref_rate / ( ref_div * ( 1 < < 6 ) ) ;
2013-02-15 17:38:17 +04:00
cpu_pll / = ( 1 < < out_div ) ;
pll = ath79_pll_rr ( QCA955X_PLL_DDR_CONFIG_REG ) ;
out_div = ( pll > > QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT ) &
QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK ;
ref_div = ( pll > > QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT ) &
QCA955X_PLL_DDR_CONFIG_REFDIV_MASK ;
nint = ( pll > > QCA955X_PLL_DDR_CONFIG_NINT_SHIFT ) &
QCA955X_PLL_DDR_CONFIG_NINT_MASK ;
frac = ( pll > > QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT ) &
QCA955X_PLL_DDR_CONFIG_NFRAC_MASK ;
2013-08-28 12:41:46 +04:00
ddr_pll = nint * ref_rate / ref_div ;
ddr_pll + = frac * ref_rate / ( ref_div * ( 1 < < 10 ) ) ;
2013-02-15 17:38:17 +04:00
ddr_pll / = ( 1 < < out_div ) ;
clk_ctrl = ath79_pll_rr ( QCA955X_PLL_CLK_CTRL_REG ) ;
postdiv = ( clk_ctrl > > QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT ) &
QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK ;
if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
cpu_rate = ref_rate ;
2013-02-15 17:38:17 +04:00
else if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL )
2013-08-28 12:41:46 +04:00
cpu_rate = ddr_pll / ( postdiv + 1 ) ;
2013-02-15 17:38:17 +04:00
else
2013-08-28 12:41:46 +04:00
cpu_rate = cpu_pll / ( postdiv + 1 ) ;
2013-02-15 17:38:17 +04:00
postdiv = ( clk_ctrl > > QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT ) &
QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK ;
if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
ddr_rate = ref_rate ;
2013-02-15 17:38:17 +04:00
else if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL )
2013-08-28 12:41:46 +04:00
ddr_rate = cpu_pll / ( postdiv + 1 ) ;
2013-02-15 17:38:17 +04:00
else
2013-08-28 12:41:46 +04:00
ddr_rate = ddr_pll / ( postdiv + 1 ) ;
2013-02-15 17:38:17 +04:00
postdiv = ( clk_ctrl > > QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT ) &
QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK ;
if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS )
2013-08-28 12:41:46 +04:00
ahb_rate = ref_rate ;
2013-02-15 17:38:17 +04:00
else if ( clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL )
2013-08-28 12:41:46 +04:00
ahb_rate = ddr_pll / ( postdiv + 1 ) ;
2013-02-15 17:38:17 +04:00
else
2013-08-28 12:41:46 +04:00
ahb_rate = cpu_pll / ( postdiv + 1 ) ;
2013-08-28 12:41:47 +04:00
ath79_add_sys_clkdev ( " ref " , ref_rate ) ;
2016-03-17 06:34:14 +03:00
clks [ ATH79_CLK_CPU ] = ath79_add_sys_clkdev ( " cpu " , cpu_rate ) ;
clks [ ATH79_CLK_DDR ] = ath79_add_sys_clkdev ( " ddr " , ddr_rate ) ;
clks [ ATH79_CLK_AHB ] = ath79_add_sys_clkdev ( " ahb " , ahb_rate ) ;
2013-02-15 17:38:17 +04:00
2013-08-28 12:41:47 +04:00
clk_add_alias ( " wdt " , NULL , " ref " , NULL ) ;
clk_add_alias ( " uart " , NULL , " ref " , NULL ) ;
2013-02-15 17:38:17 +04:00
}
2011-01-04 23:28:14 +03:00
void __init ath79_clocks_init ( void )
{
if ( soc_is_ar71xx ( ) )
ar71xx_clocks_init ( ) ;
2016-03-17 06:34:10 +03:00
else if ( soc_is_ar724x ( ) | | soc_is_ar913x ( ) )
2011-01-04 23:28:14 +03:00
ar724x_clocks_init ( ) ;
2011-06-20 23:26:04 +04:00
else if ( soc_is_ar933x ( ) )
ar933x_clocks_init ( ) ;
2012-03-14 13:45:22 +04:00
else if ( soc_is_ar934x ( ) )
ar934x_clocks_init ( ) ;
2013-02-15 17:38:17 +04:00
else if ( soc_is_qca955x ( ) )
qca955x_clocks_init ( ) ;
2011-01-04 23:28:14 +03:00
else
BUG ( ) ;
}
2013-08-28 12:41:44 +04:00
unsigned long __init
ath79_get_sys_clk_rate ( const char * id )
{
struct clk * clk ;
unsigned long rate ;
clk = clk_get ( NULL , id ) ;
if ( IS_ERR ( clk ) )
panic ( " unable to get %s clock, err=%d " , id , ( int ) PTR_ERR ( clk ) ) ;
rate = clk_get_rate ( clk ) ;
clk_put ( clk ) ;
return rate ;
}
2015-05-31 03:18:22 +03:00
# ifdef CONFIG_OF
static void __init ath79_clocks_init_dt ( struct device_node * np )
{
of_clk_add_provider ( np , of_clk_src_onecell_get , & clk_data ) ;
}
CLK_OF_DECLARE ( ar7100 , " qca,ar7100-pll " , ath79_clocks_init_dt ) ;
CLK_OF_DECLARE ( ar7240 , " qca,ar7240-pll " , ath79_clocks_init_dt ) ;
CLK_OF_DECLARE ( ar9340 , " qca,ar9340-pll " , ath79_clocks_init_dt ) ;
CLK_OF_DECLARE ( ar9550 , " qca,qca9550-pll " , ath79_clocks_init_dt ) ;
2016-03-17 06:34:15 +03:00
static void __init ath79_clocks_init_dt_ng ( struct device_node * np )
{
struct clk * ref_clk ;
void __iomem * pll_base ;
const char * dnfn = of_node_full_name ( np ) ;
ref_clk = of_clk_get ( np , 0 ) ;
if ( IS_ERR ( ref_clk ) ) {
pr_err ( " %s: of_clk_get failed \n " , dnfn ) ;
goto err ;
}
pll_base = of_iomap ( np , 0 ) ;
if ( ! pll_base ) {
pr_err ( " %s: can't map pll registers \n " , dnfn ) ;
goto err_clk ;
}
2016-03-17 06:34:18 +03:00
if ( of_device_is_compatible ( np , " qca,ar9130-pll " ) )
ar724x_clk_init ( ref_clk , pll_base ) ;
else if ( of_device_is_compatible ( np , " qca,ar9330-pll " ) )
ar9330_clk_init ( ref_clk , pll_base ) ;
else {
pr_err ( " %s: could not find any appropriate clk_init() \n " , dnfn ) ;
2017-01-02 12:48:21 +03:00
goto err_iounmap ;
2016-03-17 06:34:18 +03:00
}
2016-03-17 06:34:15 +03:00
if ( of_clk_add_provider ( np , of_clk_src_onecell_get , & clk_data ) ) {
pr_err ( " %s: could not register clk provider \n " , dnfn ) ;
2017-01-02 12:48:21 +03:00
goto err_iounmap ;
2016-03-17 06:34:15 +03:00
}
return ;
2017-01-02 12:48:21 +03:00
err_iounmap :
iounmap ( pll_base ) ;
2016-03-17 06:34:15 +03:00
err_clk :
clk_put ( ref_clk ) ;
err :
return ;
}
CLK_OF_DECLARE ( ar9130_clk , " qca,ar9130-pll " , ath79_clocks_init_dt_ng ) ;
2016-03-17 06:34:18 +03:00
CLK_OF_DECLARE ( ar9330_clk , " qca,ar9330-pll " , ath79_clocks_init_dt_ng ) ;
2015-05-31 03:18:22 +03:00
# endif