2011-05-09 20:56:46 +04:00
/*
* Broadcom specific AMBA
* ChipCommon Power Management Unit driver
*
2011-07-04 22:50:05 +04:00
* Copyright 2009 , Michael Buesch < m @ bues . ch >
2012-06-30 03:44:44 +04:00
* Copyright 2007 , 2011 , Broadcom Corporation
* Copyright 2011 , 2012 , Hauke Mehrtens < hauke @ hauke - m . de >
2011-05-09 20:56:46 +04:00
*
* Licensed under the GNU / GPL . See COPYING for details .
*/
# include "bcma_private.h"
2011-07-28 05:21:04 +04:00
# include <linux/export.h>
2011-05-09 20:56:46 +04:00
# include <linux/bcma/bcma.h>
2012-11-12 16:03:20 +04:00
u32 bcma_chipco_pll_read ( struct bcma_drv_cc * cc , u32 offset )
2011-07-23 03:20:11 +04:00
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR , offset ) ;
bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR ) ;
return bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_DATA ) ;
2011-07-23 03:20:11 +04:00
}
2012-11-12 16:03:20 +04:00
EXPORT_SYMBOL_GPL ( bcma_chipco_pll_read ) ;
2011-07-23 03:20:11 +04:00
2011-09-16 14:33:58 +04:00
void bcma_chipco_pll_write ( struct bcma_drv_cc * cc , u32 offset , u32 value )
2011-05-09 20:56:46 +04:00
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR , offset ) ;
bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR ) ;
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_DATA , value ) ;
2011-09-16 14:33:58 +04:00
}
EXPORT_SYMBOL_GPL ( bcma_chipco_pll_write ) ;
2011-05-09 20:56:46 +04:00
2011-09-16 14:33:58 +04:00
void bcma_chipco_pll_maskset ( struct bcma_drv_cc * cc , u32 offset , u32 mask ,
u32 set )
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR , offset ) ;
bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR ) ;
bcma_pmu_maskset32 ( cc , BCMA_CC_PMU_PLLCTL_DATA , mask , set ) ;
2011-09-16 14:33:58 +04:00
}
EXPORT_SYMBOL_GPL ( bcma_chipco_pll_maskset ) ;
void bcma_chipco_chipctl_maskset ( struct bcma_drv_cc * cc ,
u32 offset , u32 mask , u32 set )
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_CHIPCTL_ADDR , offset ) ;
bcma_pmu_read32 ( cc , BCMA_CC_PMU_CHIPCTL_ADDR ) ;
bcma_pmu_maskset32 ( cc , BCMA_CC_PMU_CHIPCTL_DATA , mask , set ) ;
2011-09-16 14:33:58 +04:00
}
EXPORT_SYMBOL_GPL ( bcma_chipco_chipctl_maskset ) ;
void bcma_chipco_regctl_maskset ( struct bcma_drv_cc * cc , u32 offset , u32 mask ,
u32 set )
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_REGCTL_ADDR , offset ) ;
bcma_pmu_read32 ( cc , BCMA_CC_PMU_REGCTL_ADDR ) ;
bcma_pmu_maskset32 ( cc , BCMA_CC_PMU_REGCTL_DATA , mask , set ) ;
2011-05-09 20:56:46 +04:00
}
2011-09-16 14:33:58 +04:00
EXPORT_SYMBOL_GPL ( bcma_chipco_regctl_maskset ) ;
2011-05-09 20:56:46 +04:00
2013-06-26 12:02:11 +04:00
static u32 bcma_pmu_xtalfreq ( struct bcma_drv_cc * cc )
{
u32 ilp_ctl , alp_hz ;
2016-01-19 10:45:26 +03:00
if ( ! ( bcma_pmu_read32 ( cc , BCMA_CC_PMU_STAT ) &
2013-06-26 12:02:11 +04:00
BCMA_CC_PMU_STAT_EXT_LPO_AVAIL ) )
return 0 ;
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_XTAL_FREQ ,
BIT ( BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT ) ) ;
2013-06-26 12:02:11 +04:00
usleep_range ( 1000 , 2000 ) ;
2016-01-19 10:45:26 +03:00
ilp_ctl = bcma_pmu_read32 ( cc , BCMA_CC_PMU_XTAL_FREQ ) ;
2013-06-26 12:02:11 +04:00
ilp_ctl & = BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK ;
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_XTAL_FREQ , 0 ) ;
2013-06-26 12:02:11 +04:00
alp_hz = ilp_ctl * 32768 / 4 ;
return ( alp_hz + 50000 ) / 100000 * 100 ;
}
static void bcma_pmu2_pll_init0 ( struct bcma_drv_cc * cc , u32 xtalfreq )
{
struct bcma_bus * bus = cc - > core - > bus ;
u32 freq_tgt_target = 0 , freq_tgt_current ;
u32 pll0 , mask ;
switch ( bus - > chipinfo . id ) {
case BCMA_CHIP_ID_BCM43142 :
/* pmu2_xtaltab0_adfll_485 */
switch ( xtalfreq ) {
case 12000 :
freq_tgt_target = 0x50D52 ;
break ;
case 20000 :
freq_tgt_target = 0x307FE ;
break ;
case 26000 :
freq_tgt_target = 0x254EA ;
break ;
case 37400 :
freq_tgt_target = 0x19EF8 ;
break ;
case 52000 :
freq_tgt_target = 0x12A75 ;
break ;
}
break ;
}
if ( ! freq_tgt_target ) {
bcma_err ( bus , " Unknown TGT frequency for xtalfreq %d \n " ,
xtalfreq ) ;
return ;
}
pll0 = bcma_chipco_pll_read ( cc , BCMA_CC_PMU15_PLL_PLLCTL0 ) ;
freq_tgt_current = ( pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK ) > >
BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT ;
if ( freq_tgt_current = = freq_tgt_target ) {
bcma_debug ( bus , " Target TGT frequency already set \n " ) ;
return ;
}
/* Turn off PLL */
switch ( bus - > chipinfo . id ) {
case BCMA_CHIP_ID_BCM43142 :
mask = ( u32 ) ~ ( BCMA_RES_4314_HT_AVAIL |
BCMA_RES_4314_MACPHY_CLK_AVAIL ) ;
2016-01-19 10:45:26 +03:00
bcma_pmu_mask32 ( cc , BCMA_CC_PMU_MINRES_MSK , mask ) ;
bcma_pmu_mask32 ( cc , BCMA_CC_PMU_MAXRES_MSK , mask ) ;
2013-06-26 12:02:11 +04:00
bcma_wait_value ( cc - > core , BCMA_CLKCTLST ,
BCMA_CLKCTLST_HAVEHT , 0 , 20000 ) ;
break ;
}
pll0 & = ~ BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK ;
pll0 | = freq_tgt_target < < BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT ;
bcma_chipco_pll_write ( cc , BCMA_CC_PMU15_PLL_PLLCTL0 , pll0 ) ;
/* Flush */
if ( cc - > pmu . rev > = 2 )
2016-01-19 10:45:26 +03:00
bcma_pmu_set32 ( cc , BCMA_CC_PMU_CTL , BCMA_CC_PMU_CTL_PLL_UPD ) ;
2013-06-26 12:02:11 +04:00
/* TODO: Do we need to update OTP? */
}
static void bcma_pmu_pll_init ( struct bcma_drv_cc * cc )
{
struct bcma_bus * bus = cc - > core - > bus ;
u32 xtalfreq = bcma_pmu_xtalfreq ( cc ) ;
switch ( bus - > chipinfo . id ) {
case BCMA_CHIP_ID_BCM43142 :
if ( xtalfreq = = 0 )
xtalfreq = 20000 ;
bcma_pmu2_pll_init0 ( cc , xtalfreq ) ;
break ;
}
}
2011-05-09 20:56:46 +04:00
static void bcma_pmu_resources_init ( struct bcma_drv_cc * cc )
{
struct bcma_bus * bus = cc - > core - > bus ;
u32 min_msk = 0 , max_msk = 0 ;
switch ( bus - > chipinfo . id ) {
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4313 :
2011-05-09 20:56:46 +04:00
min_msk = 0x200D ;
max_msk = 0xFFFF ;
break ;
2013-06-26 12:02:11 +04:00
case BCMA_CHIP_ID_BCM43142 :
min_msk = BCMA_RES_4314_LPLDO_PU |
BCMA_RES_4314_PMU_SLEEP_DIS |
BCMA_RES_4314_PMU_BG_PU |
BCMA_RES_4314_CBUCK_LPOM_PU |
BCMA_RES_4314_CBUCK_PFM_PU |
BCMA_RES_4314_CLDO_PU |
BCMA_RES_4314_LPLDO2_LVM |
BCMA_RES_4314_WL_PMU_PU |
BCMA_RES_4314_LDO3P3_PU |
BCMA_RES_4314_OTP_PU |
BCMA_RES_4314_WL_PWRSW_PU |
BCMA_RES_4314_LQ_AVAIL |
BCMA_RES_4314_LOGIC_RET |
BCMA_RES_4314_MEM_SLEEP |
BCMA_RES_4314_MACPHY_RET |
BCMA_RES_4314_WL_CORE_READY ;
max_msk = 0x3FFFFFFF ;
break ;
2011-05-09 20:56:46 +04:00
default :
2012-07-06 00:07:32 +04:00
bcma_debug ( bus , " PMU resource config unknown or not needed for device 0x%04X \n " ,
bus - > chipinfo . id ) ;
2011-05-09 20:56:46 +04:00
}
/* Set the resource masks. */
if ( min_msk )
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_MINRES_MSK , min_msk ) ;
2011-05-09 20:56:46 +04:00
if ( max_msk )
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_MAXRES_MSK , max_msk ) ;
2012-06-30 03:44:45 +04:00
2012-09-25 12:17:22 +04:00
/*
* Add some delay ; allow resources to come up and settle .
* Delay is required for SoC ( early init ) .
*/
2018-01-26 19:38:35 +03:00
usleep_range ( 2000 , 2500 ) ;
2011-05-09 20:56:46 +04:00
}
2011-08-12 01:46:44 +04:00
/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
void bcma_chipco_bcm4331_ext_pa_lines_ctl ( struct bcma_drv_cc * cc , bool enable )
{
struct bcma_bus * bus = cc - > core - > bus ;
u32 val ;
val = bcma_cc_read32 ( cc , BCMA_CC_CHIPCTL ) ;
if ( enable ) {
val | = BCMA_CHIPCTL_4331_EXTPA_EN ;
if ( bus - > chipinfo . pkg = = 9 | | bus - > chipinfo . pkg = = 11 )
val | = BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 ;
2012-06-30 03:44:37 +04:00
else if ( bus - > chipinfo . rev > 0 )
val | = BCMA_CHIPCTL_4331_EXTPA_EN2 ;
2011-08-12 01:46:44 +04:00
} else {
val & = ~ BCMA_CHIPCTL_4331_EXTPA_EN ;
2012-06-30 03:44:37 +04:00
val & = ~ BCMA_CHIPCTL_4331_EXTPA_EN2 ;
2011-08-12 01:46:44 +04:00
val & = ~ BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 ;
}
bcma_cc_write32 ( cc , BCMA_CC_CHIPCTL , val ) ;
}
2012-08-05 18:54:41 +04:00
static void bcma_pmu_workarounds ( struct bcma_drv_cc * cc )
2011-05-09 20:56:46 +04:00
{
struct bcma_bus * bus = cc - > core - > bus ;
switch ( bus - > chipinfo . id ) {
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4313 :
2019-10-21 21:05:13 +03:00
/*
* enable 12 mA drive strenth for 4313 and set chipControl
* register bit 1
*/
2012-06-30 03:44:41 +04:00
bcma_chipco_chipctl_maskset ( cc , 0 ,
2012-07-26 01:08:54 +04:00
~ BCMA_CCTRL_4313_12MA_LED_DRIVE ,
2012-06-30 03:44:41 +04:00
BCMA_CCTRL_4313_12MA_LED_DRIVE ) ;
2011-05-09 20:56:46 +04:00
break ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4331 :
case BCMA_CHIP_ID_BCM43431 :
2012-06-01 18:13:17 +04:00
/* Ext PA lines must be enabled for tx on BCM4331 */
bcma_chipco_bcm4331_ext_pa_lines_ctl ( cc , true ) ;
2011-05-09 20:56:46 +04:00
break ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM43224 :
2012-06-30 03:44:41 +04:00
case BCMA_CHIP_ID_BCM43421 :
2019-10-21 21:05:13 +03:00
/*
* enable 12 mA drive strenth for 43224 and set chipControl
* register bit 15
*/
2011-05-09 20:56:46 +04:00
if ( bus - > chipinfo . rev = = 0 ) {
2012-06-30 03:44:41 +04:00
bcma_cc_maskset32 ( cc , BCMA_CC_CHIPCTL ,
2012-07-26 01:08:54 +04:00
~ BCMA_CCTRL_43224_GPIO_TOGGLE ,
2012-06-30 03:44:41 +04:00
BCMA_CCTRL_43224_GPIO_TOGGLE ) ;
bcma_chipco_chipctl_maskset ( cc , 0 ,
2012-07-26 01:08:54 +04:00
~ BCMA_CCTRL_43224A0_12MA_LED_DRIVE ,
2012-06-30 03:44:41 +04:00
BCMA_CCTRL_43224A0_12MA_LED_DRIVE ) ;
2011-05-09 20:56:46 +04:00
} else {
2012-06-30 03:44:41 +04:00
bcma_chipco_chipctl_maskset ( cc , 0 ,
2012-07-26 01:08:54 +04:00
~ BCMA_CCTRL_43224B0_12MA_LED_DRIVE ,
2012-06-30 03:44:41 +04:00
BCMA_CCTRL_43224B0_12MA_LED_DRIVE ) ;
2011-05-09 20:56:46 +04:00
}
break ;
default :
2012-07-06 00:07:32 +04:00
bcma_debug ( bus , " Workarounds unknown or not needed for device 0x%04X \n " ,
bus - > chipinfo . id ) ;
2011-05-09 20:56:46 +04:00
}
}
2012-09-29 22:29:49 +04:00
void bcma_pmu_early_init ( struct bcma_drv_cc * cc )
2011-05-09 20:56:46 +04:00
{
2016-01-19 10:45:26 +03:00
struct bcma_bus * bus = cc - > core - > bus ;
2011-05-09 20:56:46 +04:00
u32 pmucap ;
2016-01-19 10:45:26 +03:00
if ( cc - > core - > id . rev > = 35 & &
cc - > capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT ) {
cc - > pmu . core = bcma_find_core ( bus , BCMA_CORE_PMU ) ;
if ( ! cc - > pmu . core )
bcma_warn ( bus , " Couldn't find expected PMU core " ) ;
}
if ( ! cc - > pmu . core )
cc - > pmu . core = cc - > core ;
pmucap = bcma_pmu_read32 ( cc , BCMA_CC_PMU_CAP ) ;
2011-05-09 20:56:46 +04:00
cc - > pmu . rev = ( pmucap & BCMA_CC_PMU_CAP_REVISION ) ;
2016-01-19 10:45:26 +03:00
bcma_debug ( bus , " Found rev %u PMU (capabilities 0x%08X) \n " , cc - > pmu . rev ,
pmucap ) ;
2012-09-29 22:29:49 +04:00
}
2011-05-09 20:56:46 +04:00
2012-09-29 22:29:49 +04:00
void bcma_pmu_init ( struct bcma_drv_cc * cc )
{
2011-05-09 20:56:46 +04:00
if ( cc - > pmu . rev = = 1 )
2016-01-19 10:45:26 +03:00
bcma_pmu_mask32 ( cc , BCMA_CC_PMU_CTL ,
~ BCMA_CC_PMU_CTL_NOILPONW ) ;
2011-05-09 20:56:46 +04:00
else
2016-01-19 10:45:26 +03:00
bcma_pmu_set32 ( cc , BCMA_CC_PMU_CTL ,
BCMA_CC_PMU_CTL_NOILPONW ) ;
2011-05-09 20:56:46 +04:00
2013-06-26 12:02:11 +04:00
bcma_pmu_pll_init ( cc ) ;
2011-05-09 20:56:46 +04:00
bcma_pmu_resources_init ( cc ) ;
bcma_pmu_workarounds ( cc ) ;
}
2011-07-23 03:20:10 +04:00
2012-12-07 15:56:56 +04:00
u32 bcma_pmu_get_alp_clock ( struct bcma_drv_cc * cc )
2011-07-23 03:20:10 +04:00
{
struct bcma_bus * bus = cc - > core - > bus ;
switch ( bus - > chipinfo . id ) {
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM4313 :
case BCMA_CHIP_ID_BCM43224 :
case BCMA_CHIP_ID_BCM43225 :
case BCMA_CHIP_ID_BCM43227 :
case BCMA_CHIP_ID_BCM43228 :
case BCMA_CHIP_ID_BCM4331 :
case BCMA_CHIP_ID_BCM43421 :
case BCMA_CHIP_ID_BCM43428 :
case BCMA_CHIP_ID_BCM43431 :
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4716 :
case BCMA_CHIP_ID_BCM47162 :
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM4748 :
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4749 :
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM5357 :
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM53572 :
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM6362 :
2011-07-23 03:20:10 +04:00
/* always 20Mhz */
return 20000 * 1000 ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4706 :
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM5356 :
2011-07-23 03:20:10 +04:00
/* always 25Mhz */
return 25000 * 1000 ;
2013-03-27 20:23:10 +04:00
case BCMA_CHIP_ID_BCM43460 :
case BCMA_CHIP_ID_BCM4352 :
case BCMA_CHIP_ID_BCM4360 :
if ( cc - > status & BCMA_CC_CHIPST_4360_XTAL_40MZ )
return 40000 * 1000 ;
else
return 20000 * 1000 ;
2011-07-23 03:20:10 +04:00
default :
2012-07-06 00:07:32 +04:00
bcma_warn ( bus , " No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz \n " ,
bus - > chipinfo . id , cc - > pmu . rev , BCMA_CC_PMU_ALP_CLOCK ) ;
2011-07-23 03:20:10 +04:00
}
return BCMA_CC_PMU_ALP_CLOCK ;
}
2011-07-23 03:20:11 +04:00
/* Find the output of the "m" pll divider given pll controls that start with
* pllreg " pll0 " i . e . 12 for main 6 for phy , 0 for misc .
*/
2012-12-07 15:56:56 +04:00
static u32 bcma_pmu_pll_clock ( struct bcma_drv_cc * cc , u32 pll0 , u32 m )
2011-07-23 03:20:11 +04:00
{
u32 tmp , div , ndiv , p1 , p2 , fc ;
struct bcma_bus * bus = cc - > core - > bus ;
BUG_ON ( ( pll0 & 3 ) | | ( pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0 ) ) ;
BUG_ON ( ! m | | m > 4 ) ;
2012-06-30 03:44:38 +04:00
if ( bus - > chipinfo . id = = BCMA_CHIP_ID_BCM5357 | |
bus - > chipinfo . id = = BCMA_CHIP_ID_BCM4749 ) {
2011-07-23 03:20:11 +04:00
/* Detect failure in clock setting */
tmp = bcma_cc_read32 ( cc , BCMA_CC_CHIPSTAT ) ;
if ( tmp & 0x40000 )
return 133 * 1000000 ;
}
tmp = bcma_chipco_pll_read ( cc , pll0 + BCMA_CC_PPL_P1P2_OFF ) ;
p1 = ( tmp & BCMA_CC_PPL_P1_MASK ) > > BCMA_CC_PPL_P1_SHIFT ;
p2 = ( tmp & BCMA_CC_PPL_P2_MASK ) > > BCMA_CC_PPL_P2_SHIFT ;
tmp = bcma_chipco_pll_read ( cc , pll0 + BCMA_CC_PPL_M14_OFF ) ;
div = ( tmp > > ( ( m - 1 ) * BCMA_CC_PPL_MDIV_WIDTH ) ) &
BCMA_CC_PPL_MDIV_MASK ;
tmp = bcma_chipco_pll_read ( cc , pll0 + BCMA_CC_PPL_NM5_OFF ) ;
ndiv = ( tmp & BCMA_CC_PPL_NDIV_MASK ) > > BCMA_CC_PPL_NDIV_SHIFT ;
/* Do calculation in Mhz */
2012-12-07 15:56:56 +04:00
fc = bcma_pmu_get_alp_clock ( cc ) / 1000000 ;
2011-07-23 03:20:11 +04:00
fc = ( p1 * ndiv * fc ) / p2 ;
/* Return clock in Hertz */
return ( fc / div ) * 1000000 ;
}
2012-12-07 15:56:56 +04:00
static u32 bcma_pmu_pll_clock_bcm4706 ( struct bcma_drv_cc * cc , u32 pll0 , u32 m )
2012-07-10 00:03:10 +04:00
{
u32 tmp , ndiv , p1div , p2div ;
u32 clock ;
BUG_ON ( ! m | | m > 4 ) ;
/* Get N, P1 and P2 dividers to determine CPU clock */
tmp = bcma_chipco_pll_read ( cc , pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF ) ;
ndiv = ( tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK )
> > BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT ;
p1div = ( tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK )
> > BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT ;
p2div = ( tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK )
> > BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT ;
tmp = bcma_cc_read32 ( cc , BCMA_CC_CHIPSTAT ) ;
if ( tmp & BCMA_CC_CHIPST_4706_PKG_OPTION )
/* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
clock = ( 25000000 / 4 ) * ndiv * p2div / p1div ;
else
/* Fixed reference clock 25MHz and m = 2 */
clock = ( 25000000 / 2 ) * ndiv * p2div / p1div ;
if ( m = = BCMA_CC_PMU5_MAINPLL_SSB )
clock = clock / 4 ;
return clock ;
}
2011-07-23 03:20:11 +04:00
/* query bus clock frequency for PMU-enabled chipcommon */
2013-01-09 00:06:23 +04:00
u32 bcma_pmu_get_bus_clock ( struct bcma_drv_cc * cc )
2011-07-23 03:20:11 +04:00
{
struct bcma_bus * bus = cc - > core - > bus ;
switch ( bus - > chipinfo . id ) {
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4716 :
case BCMA_CHIP_ID_BCM4748 :
case BCMA_CHIP_ID_BCM47162 :
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock ( cc , BCMA_CC_PMU4716_MAINPLL_PLL0 ,
BCMA_CC_PMU5_MAINPLL_SSB ) ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM5356 :
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock ( cc , BCMA_CC_PMU5356_MAINPLL_PLL0 ,
BCMA_CC_PMU5_MAINPLL_SSB ) ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM5357 :
case BCMA_CHIP_ID_BCM4749 :
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock ( cc , BCMA_CC_PMU5357_MAINPLL_PLL0 ,
BCMA_CC_PMU5_MAINPLL_SSB ) ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM4706 :
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock_bcm4706 ( cc ,
BCMA_CC_PMU4706_MAINPLL_PLL0 ,
BCMA_CC_PMU5_MAINPLL_SSB ) ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM53572 :
2011-07-23 03:20:11 +04:00
return 75000000 ;
default :
2012-12-07 15:56:56 +04:00
bcma_warn ( bus , " No bus clock specified for %04X device, pmu rev. %d, using default %d Hz \n " ,
2012-07-06 00:07:32 +04:00
bus - > chipinfo . id , cc - > pmu . rev , BCMA_CC_PMU_HT_CLOCK ) ;
2011-07-23 03:20:11 +04:00
}
return BCMA_CC_PMU_HT_CLOCK ;
}
2013-01-09 00:06:23 +04:00
EXPORT_SYMBOL_GPL ( bcma_pmu_get_bus_clock ) ;
2011-07-23 03:20:11 +04:00
/* query cpu clock frequency for PMU-enabled chipcommon */
2012-12-07 15:56:56 +04:00
u32 bcma_pmu_get_cpu_clock ( struct bcma_drv_cc * cc )
2011-07-23 03:20:11 +04:00
{
struct bcma_bus * bus = cc - > core - > bus ;
2012-06-30 03:44:38 +04:00
if ( bus - > chipinfo . id = = BCMA_CHIP_ID_BCM53572 )
2011-07-23 03:20:11 +04:00
return 300000000 ;
2012-12-07 15:56:56 +04:00
/* New PMUs can have different clock for bus and CPU */
2011-07-23 03:20:11 +04:00
if ( cc - > pmu . rev > = 5 ) {
u32 pll ;
switch ( bus - > chipinfo . id ) {
2012-07-10 00:03:10 +04:00
case BCMA_CHIP_ID_BCM4706 :
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock_bcm4706 ( cc ,
2012-07-10 00:03:10 +04:00
BCMA_CC_PMU4706_MAINPLL_PLL0 ,
BCMA_CC_PMU5_MAINPLL_CPU ) ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM5356 :
2011-07-23 03:20:11 +04:00
pll = BCMA_CC_PMU5356_MAINPLL_PLL0 ;
break ;
2012-06-30 03:44:38 +04:00
case BCMA_CHIP_ID_BCM5357 :
case BCMA_CHIP_ID_BCM4749 :
2011-07-23 03:20:11 +04:00
pll = BCMA_CC_PMU5357_MAINPLL_PLL0 ;
break ;
default :
pll = BCMA_CC_PMU4716_MAINPLL_PLL0 ;
break ;
}
2012-12-07 15:56:56 +04:00
return bcma_pmu_pll_clock ( cc , pll , BCMA_CC_PMU5_MAINPLL_CPU ) ;
2011-07-23 03:20:11 +04:00
}
2012-12-07 15:56:56 +04:00
/* On old PMUs CPU has the same clock as the bus */
return bcma_pmu_get_bus_clock ( cc ) ;
2011-07-23 03:20:11 +04:00
}
2012-06-30 03:44:44 +04:00
static void bcma_pmu_spuravoid_pll_write ( struct bcma_drv_cc * cc , u32 offset ,
u32 value )
{
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR , offset ) ;
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_DATA , value ) ;
2012-06-30 03:44:44 +04:00
}
void bcma_pmu_spuravoid_pllupdate ( struct bcma_drv_cc * cc , int spuravoid )
{
u32 tmp = 0 ;
u8 phypll_offset = 0 ;
u8 bcm5357_bcm43236_p1div [ ] = { 0x1 , 0x5 , 0x5 } ;
u8 bcm5357_bcm43236_ndiv [ ] = { 0x30 , 0xf6 , 0xfc } ;
struct bcma_bus * bus = cc - > core - > bus ;
switch ( bus - > chipinfo . id ) {
case BCMA_CHIP_ID_BCM5357 :
case BCMA_CHIP_ID_BCM4749 :
case BCMA_CHIP_ID_BCM53572 :
/* 5357[ab]0, 43236[ab]0, and 6362b0 */
2019-10-21 21:05:13 +03:00
/*
* BCM5357 needs to touch PLL1_PLLCTL [ 02 ] ,
* so offset PLL0_PLLCTL [ 02 ] by 6
*/
2012-06-30 03:44:44 +04:00
phypll_offset = ( bus - > chipinfo . id = = BCMA_CHIP_ID_BCM5357 | |
bus - > chipinfo . id = = BCMA_CHIP_ID_BCM4749 | |
bus - > chipinfo . id = = BCMA_CHIP_ID_BCM53572 ) ? 6 : 0 ;
/* RMW only the P1 divider */
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR ,
2012-06-30 03:44:44 +04:00
BCMA_CC_PMU_PLL_CTL0 + phypll_offset ) ;
2016-01-19 10:45:26 +03:00
tmp = bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_DATA ) ;
2012-06-30 03:44:44 +04:00
tmp & = ( ~ ( BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK ) ) ;
tmp | = ( bcm5357_bcm43236_p1div [ spuravoid ] < < BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT ) ;
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_DATA , tmp ) ;
2012-06-30 03:44:44 +04:00
/* RMW only the int feedback divider */
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_ADDR ,
2012-06-30 03:44:44 +04:00
BCMA_CC_PMU_PLL_CTL2 + phypll_offset ) ;
2016-01-19 10:45:26 +03:00
tmp = bcma_pmu_read32 ( cc , BCMA_CC_PMU_PLLCTL_DATA ) ;
2012-06-30 03:44:44 +04:00
tmp & = ~ ( BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK ) ;
tmp | = ( bcm5357_bcm43236_ndiv [ spuravoid ] ) < < BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT ;
2016-01-19 10:45:26 +03:00
bcma_pmu_write32 ( cc , BCMA_CC_PMU_PLLCTL_DATA , tmp ) ;
2012-06-30 03:44:44 +04:00
2013-03-27 20:23:09 +04:00
tmp = BCMA_CC_PMU_CTL_PLL_UPD ;
2012-06-30 03:44:44 +04:00
break ;
case BCMA_CHIP_ID_BCM4331 :
case BCMA_CHIP_ID_BCM43431 :
if ( spuravoid = = 2 ) {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11500014 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x0FC00a08 ) ;
} else if ( spuravoid = = 1 ) {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11500014 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x0F600a08 ) ;
} else {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11100014 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x03000a08 ) ;
}
2013-03-27 20:23:09 +04:00
tmp = BCMA_CC_PMU_CTL_PLL_UPD ;
2012-06-30 03:44:44 +04:00
break ;
case BCMA_CHIP_ID_BCM43224 :
case BCMA_CHIP_ID_BCM43225 :
case BCMA_CHIP_ID_BCM43421 :
if ( spuravoid = = 1 ) {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11500010 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x000C0C06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x0F600a08 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x2001E920 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
} else {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11100010 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x000c0c06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x03000a08 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x200005c0 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
}
2013-03-27 20:23:09 +04:00
tmp = BCMA_CC_PMU_CTL_PLL_UPD ;
2012-06-30 03:44:44 +04:00
break ;
case BCMA_CHIP_ID_BCM4716 :
case BCMA_CHIP_ID_BCM4748 :
case BCMA_CHIP_ID_BCM47162 :
if ( spuravoid = = 1 ) {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11500060 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x080C0C06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x0F600000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x2001E924 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
} else {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11100060 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x080c0c06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x03000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x200005c0 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
}
2013-03-27 20:23:09 +04:00
tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW ;
2012-06-30 03:44:44 +04:00
break ;
2014-07-24 17:29:19 +04:00
case BCMA_CHIP_ID_BCM43131 :
2014-07-15 21:44:28 +04:00
case BCMA_CHIP_ID_BCM43217 :
2012-06-30 03:44:44 +04:00
case BCMA_CHIP_ID_BCM43227 :
case BCMA_CHIP_ID_BCM43228 :
case BCMA_CHIP_ID_BCM43428 :
/* LCNXN */
2019-10-21 21:05:13 +03:00
/*
* PLL Settings for spur avoidance on / off mode ,
* no on2 support for 43228 A0
*/
2012-06-30 03:44:44 +04:00
if ( spuravoid = = 1 ) {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x01100014 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x040C0C06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x03140A08 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00333333 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x202C2820 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
} else {
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL0 ,
0x11100014 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL1 ,
0x040c0c06 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL2 ,
0x03000a08 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL3 ,
0x00000000 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL4 ,
0x200005c0 ) ;
bcma_pmu_spuravoid_pll_write ( cc , BCMA_CC_PMU_PLL_CTL5 ,
0x88888815 ) ;
}
2013-03-27 20:23:09 +04:00
tmp = BCMA_CC_PMU_CTL_PLL_UPD ;
2012-06-30 03:44:44 +04:00
break ;
default :
2012-07-06 00:07:32 +04:00
bcma_err ( bus , " Unknown spuravoidance settings for chip 0x%04X, not changing PLL \n " ,
bus - > chipinfo . id ) ;
2012-06-30 03:44:44 +04:00
break ;
}
2016-01-19 10:45:26 +03:00
tmp | = bcma_pmu_read32 ( cc , BCMA_CC_PMU_CTL ) ;
bcma_pmu_write32 ( cc , BCMA_CC_PMU_CTL , tmp ) ;
2012-06-30 03:44:44 +04:00
}
EXPORT_SYMBOL_GPL ( bcma_pmu_spuravoid_pllupdate ) ;