diff options
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
| -rw-r--r-- | drivers/mfd/db8500-prcmu.c | 44 | 
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7040a008113..6b67edbdbd0 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -418,6 +418,9 @@ static struct {  static atomic_t ac_wake_req_state = ATOMIC_INIT(0); +/* Functions definition */ +static void compute_armss_rate(void); +  /* Spinlocks */  static DEFINE_SPINLOCK(prcmu_lock);  static DEFINE_SPINLOCK(clkout_lock); @@ -517,6 +520,7 @@ static struct dsiescclk dsiescclk[3] = {  	}  }; +  /*  * Used by MCDE to setup all necessary PRCMU registers  */ @@ -1013,6 +1017,7 @@ int db8500_prcmu_set_arm_opp(u8 opp)  		(mb1_transfer.ack.arm_opp != opp))  		r = -EIO; +	compute_armss_rate();  	mutex_unlock(&mb1_transfer.lock);  	return r; @@ -1612,6 +1617,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,  	if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&  		(val & PRCM_PLL_FREQ_DIV2EN) &&  		((reg == PRCM_PLLSOC0_FREQ) || +		 (reg == PRCM_PLLARM_FREQ) ||  		 (reg == PRCM_PLLDDR_FREQ))))  		div *= 2; @@ -1661,6 +1667,39 @@ static unsigned long clock_rate(u8 clock)  	else  		return 0;  } +static unsigned long latest_armss_rate; +static unsigned long armss_rate(void) +{ +	return latest_armss_rate; +} + +static void compute_armss_rate(void) +{ +	u32 r; +	unsigned long rate; + +	r = readl(PRCM_ARM_CHGCLKREQ); + +	if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) { +		/* External ARMCLKFIX clock */ + +		rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX); + +		/* Check PRCM_ARM_CHGCLKREQ divider */ +		if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL)) +			rate /= 2; + +		/* Check PRCM_ARMCLKFIX_MGT divider */ +		r = readl(PRCM_ARMCLKFIX_MGT); +		r &= PRCM_CLK_MGT_CLKPLLDIV_MASK; +		rate /= r; + +	} else {/* ARM PLL */ +		rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV); +	} + +	latest_armss_rate = rate; +}  static unsigned long dsiclk_rate(u8 n)  { @@ -1707,6 +1746,8 @@ unsigned long prcmu_clock_rate(u8 clock)  		return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);  	else if (clock == PRCMU_PLLSOC1)  		return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); +	else if (clock == PRCMU_ARMSS) +		return armss_rate();  	else if (clock == PRCMU_PLLDDR)  		return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);  	else if (clock == PRCMU_PLLDSI) @@ -2693,6 +2734,7 @@ void __init db8500_prcmu_early_init(void)  					 handle_simple_irq);  		set_irq_flags(irq, IRQF_VALID);  	} +	compute_armss_rate();  }  static void __init init_prcm_registers(void) @@ -3010,7 +3052,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)  		prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);  	err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, -			ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); +			      ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);  	if (err) {  		pr_err("prcmu: Failed to add subdevices\n");  		return err;  |