summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxc/dvfs_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxc/dvfs_core.c')
-rw-r--r--arch/arm/plat-mxc/dvfs_core.c191
1 files changed, 111 insertions, 80 deletions
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
index 43d0a3a8adeb..143bc07834ed 100644
--- a/arch/arm/plat-mxc/dvfs_core.c
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -135,18 +135,19 @@ static void dvfs_load_config(int set_point)
reg |= dvfs_core_setpoint[set_point].downthr <<
MXC_DVFSTHRS_DNTHR_OFFSET;
reg |= dvfs_core_setpoint[set_point].panicthr;
- __raw_writel(reg, dvfs_data->dvfs_thrs_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_THRS);
reg = 0;
reg |= dvfs_core_setpoint[set_point].downcnt <<
MXC_DVFSCOUN_DNCNT_OFFSET;
reg |= dvfs_core_setpoint[set_point].upcnt << MXC_DVFSCOUN_UPCNT_OFFSET;
- __raw_writel(reg, dvfs_data->dvfs_coun_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_COUN);
/* Set EMAC value */
__raw_writel((dvfs_core_setpoint[set_point].emac <<
MXC_DVFSEMAC_EMAC_OFFSET),
- dvfs_data->dvfs_emac_reg_addr);
+ dvfs_data->membase
+ + MXC_DVFSCORE_EMAC);
}
@@ -187,14 +188,14 @@ static int set_cpu_freq(int wp)
}
spin_lock_irqsave(&mxc_dvfs_core_lock, flags);
/* PLL_RELOCK, set ARM_FREQ_SHIFT_DIVIDER */
- reg = __raw_readl(dvfs_data->ccm_cdcr_reg_addr);
+ reg = __raw_readl(ccm_base + dvfs_data->ccm_cdcr_offset);
reg &= 0xFFFFFFFB;
- __raw_writel(reg, dvfs_data->ccm_cdcr_reg_addr);
+ __raw_writel(reg, ccm_base + dvfs_data->ccm_cdcr_offset);
setup_pll();
/* START the GPC main control FSM */
/* set VINC */
- reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_vcr_offset);
reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
MXC_GPCVCR_VCNT_MASK);
@@ -202,18 +203,19 @@ static int set_cpu_freq(int wp)
reg |= 1 << MXC_GPCVCR_VINC_OFFSET;
reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) |
- (1 << MXC_GPCVCR_VCNT_OFFSET);
- __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
+ (1 << MXC_GPCVCR_VCNT_OFFSET);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_vcr_offset);
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg &= ~(MXC_GPCCNTR_ADU_MASK | MXC_GPCCNTR_FUPD_MASK);
reg |= MXC_GPCCNTR_FUPD;
reg |= MXC_GPCCNTR_ADU;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
reg |= MXC_GPCCNTR_STRT;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
- while (__raw_readl(dvfs_data->gpc_cntr_reg_addr) & 0x4000)
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
+ while (__raw_readl(gpc_base + dvfs_data->gpc_cntr_offset)
+ & 0x4000)
udelay(10);
spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
@@ -234,13 +236,13 @@ static int set_cpu_freq(int wp)
/* Change arm_podf only */
/* set ARM_FREQ_SHIFT_DIVIDER */
- reg = __raw_readl(dvfs_data->ccm_cdcr_reg_addr);
+ reg = __raw_readl(ccm_base + dvfs_data->ccm_cdcr_offset);
reg &= 0xFFFFFFFB;
reg |= 1 << 2;
- __raw_writel(reg, dvfs_data->ccm_cdcr_reg_addr);
+ __raw_writel(reg, ccm_base + dvfs_data->ccm_cdcr_offset);
/* Get ARM_PODF */
- reg = __raw_readl(dvfs_data->ccm_cacrr_reg_addr);
+ reg = __raw_readl(ccm_base + dvfs_data->ccm_cacrr_offset);
arm_podf = reg & 0x07;
if (podf == arm_podf) {
printk(KERN_DEBUG
@@ -268,37 +270,38 @@ static int set_cpu_freq(int wp)
reg &= 0xFFFFFFF8;
reg |= arm_podf;
- reg1 = __raw_readl(dvfs_data->ccm_cdhipr_reg_addr);
+ reg1 = __raw_readl(ccm_base + dvfs_data->ccm_cdhipr_offset);
if ((reg1 & 0x00010000) == 0)
- __raw_writel(reg, dvfs_data->ccm_cacrr_reg_addr);
+ __raw_writel(reg,
+ ccm_base + dvfs_data->ccm_cacrr_offset);
else {
printk(KERN_DEBUG "ARM_PODF still in busy!!!!\n");
return 0;
}
/* START the GPC main control FSM */
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg |= MXC_GPCCNTR_FUPD;
/* ADU=1, select ARM domain */
reg |= MXC_GPCCNTR_ADU;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
/* set VINC */
- reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_vcr_offset);
reg &=
~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
MXC_GPCVCR_VCNT_MASK);
reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) |
(100 << MXC_GPCVCR_VCNT_OFFSET) |
(vinc << MXC_GPCVCR_VINC_OFFSET);
- __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_vcr_offset);
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg &= (~(MXC_GPCCNTR_ADU | MXC_GPCCNTR_FUPD));
reg |= MXC_GPCCNTR_ADU | MXC_GPCCNTR_FUPD | MXC_GPCCNTR_STRT;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
/* Wait for arm podf Enable */
- while ((__raw_readl(dvfs_data->gpc_cntr_reg_addr) &
+ while ((__raw_readl(gpc_base + dvfs_data->gpc_cntr_offset) &
MXC_GPCCNTR_STRT) == MXC_GPCCNTR_STRT) {
printk(KERN_DEBUG "Waiting arm_podf enabled!\n");
udelay(10);
@@ -317,9 +320,9 @@ static int set_cpu_freq(int wp)
propagate_rate(pll1_sw_clk);
/* Clear the ARM_FREQ_SHIFT_DIVIDER */
- reg = __raw_readl(dvfs_data->ccm_cdcr_reg_addr);
+ reg = __raw_readl(ccm_base + dvfs_data->ccm_cdcr_offset);
reg &= 0xFFFFFFFB;
- __raw_writel(reg, dvfs_data->ccm_cdcr_reg_addr);
+ __raw_writel(reg, ccm_base + dvfs_data->ccm_cdcr_offset);
}
#if defined(CONFIG_CPU_FREQ_IMX)
cpufreq_trig_needed = 1;
@@ -344,23 +347,23 @@ static int start_dvfs(void)
dvfs_load_config(0);
/* config reg GPC_CNTR */
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg &= ~MXC_GPCCNTR_GPCIRQM;
/* GPCIRQ=1, select ARM IRQ */
reg |= MXC_GPCCNTR_GPCIRQ_ARM;
/* ADU=1, select ARM domain */
reg |= MXC_GPCCNTR_ADU;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
/* Set PREDIV bits */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
reg = (reg & ~(dvfs_data->prediv_mask));
reg |= (dvfs_data->prediv_val) << (dvfs_data->prediv_offset);
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
/* Enable DVFS interrupt */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
/* FSVAIM=0 */
reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
/* Set MAXF, MINF */
@@ -376,12 +379,12 @@ static int start_dvfs(void)
/* Set DIV3CK */
reg = (reg & ~(dvfs_data->div3ck_mask));
reg |= (dvfs_data->div3ck_val) << (dvfs_data->div3ck_offset);
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
/* Enable DVFS */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
reg |= MXC_DVFSCNTR_DVFEN;
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
dvfs_core_is_active = 1;
@@ -416,20 +419,20 @@ static irqreturn_t dvfs_irq(int irq, void *dev_id)
u32 reg;
/* Check if DVFS0 (ARM) id requesting for freqency/voltage update */
- if ((__raw_readl(dvfs_data->gpc_cntr_reg_addr) & MXC_GPCCNTR_DVFS0CR) ==
- 0)
+ if ((__raw_readl(gpc_base + dvfs_data->gpc_cntr_offset)
+ & MXC_GPCCNTR_DVFS0CR) == 0)
return IRQ_NONE;
/* Mask DVFS irq */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
/* FSVAIM=1 */
reg |= MXC_DVFSCNTR_FSVAIM;
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
/* Mask GPC1 irq */
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg |= MXC_GPCCNTR_GPCIRQM | 0x1000000;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
schedule_delayed_work(&dvfs_core_handler, 0);
return IRQ_HANDLED;
@@ -448,7 +451,7 @@ static void dvfs_core_work_handler(struct work_struct *work)
low_freq_bus_ready = low_freq_bus_used();
/* Check DVFS frequency adjustment interrupt status */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
fsvai = (reg & MXC_DVFSCNTR_FSVAI_MASK) >> MXC_DVFSCNTR_FSVAI_OFFSET;
/* Check FSVAI, FSVAI=0 is error */
if (fsvai == FSVAI_FREQ_NOCHANGE) {
@@ -520,7 +523,7 @@ static void dvfs_core_work_handler(struct work_struct *work)
END: /* Set MAXF, MINF */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
reg |= maxf << MXC_DVFSCNTR_MAXF_OFFSET;
reg |= minf << MXC_DVFSCNTR_MINF_OFFSET;
@@ -532,11 +535,11 @@ END: /* Set MAXF, MINF */
/* LBFL=1 */
reg = (reg & ~MXC_DVFSCNTR_LBFL);
reg |= MXC_DVFSCNTR_LBFL;
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
/*Unmask GPC1 IRQ */
- reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
reg &= ~MXC_GPCCNTR_GPCIRQM;
- __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);
#if defined(CONFIG_CPU_FREQ_IMX)
if (cpufreq_trig_needed == 1) {
@@ -559,10 +562,12 @@ static void stop_dvfs(void)
if (dvfs_core_is_active) {
/* Mask dvfs irq, disable DVFS */
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_CNTR);
/* FSVAIM=1 */
reg |= MXC_DVFSCNTR_FSVAIM;
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase
+ + MXC_DVFSCORE_CNTR);
curr_wp = 0;
if (!high_bus_freq_mode)
@@ -580,9 +585,11 @@ static void stop_dvfs(void)
}
spin_lock_irqsave(&mxc_dvfs_core_lock, flags);
- reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_CNTR);
reg = (reg & ~MXC_DVFSCNTR_DVFEN);
- __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ __raw_writel(reg, dvfs_data->membase
+ + MXC_DVFSCORE_CNTR);
spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
@@ -610,39 +617,56 @@ void dump_dvfs_core_regs()
printk(KERN_DEBUG "diff = %d\n", diff);
printk(KERN_INFO "THRS = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS));
printk(KERN_INFO "COUNT = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x04));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x04));
printk(KERN_INFO "SIG1 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x08));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x08));
printk(KERN_INFO "SIG0 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x0c));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x0c));
printk(KERN_INFO "GPC0 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x10));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x10));
printk(KERN_INFO "GPC1 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x14));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x14));
printk(KERN_INFO "GPBT = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x18));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x18));
printk(KERN_INFO "EMAC = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x1c));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x1c));
printk(KERN_INFO "CNTR = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x20));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x20));
printk(KERN_INFO "LTR0_0 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x24));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x24));
printk(KERN_INFO "LTR0_1 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x28));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x28));
printk(KERN_INFO "LTR1_0 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x2c));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x2c));
printk(KERN_DEBUG "LTR1_1 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x30));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x30));
printk(KERN_INFO "PT0 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x34));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x34));
printk(KERN_INFO "PT1 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x38));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x38));
printk(KERN_INFO "PT2 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x3c));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x3c));
printk(KERN_INFO "PT3 = 0x%08x\n",
- __raw_readl(dvfs_data->dvfs_thrs_reg_addr+0x40));
+ __raw_readl(dvfs_data->membase
+ + MXC_DVFSCORE_THRS + 0x40));
}
static ssize_t downthreshold_show(struct device *dev,
@@ -741,7 +765,6 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
{
int err = 0;
struct resource *res;
- int irq;
printk(KERN_INFO "mxc_dvfs_core_probe\n");
dvfs_dev = &pdev->dev;
@@ -780,22 +803,25 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
err = -ENODEV;
goto err1;
}
-
+ dvfs_data->membase = ioremap(res->start, res->end - res->start + 1);
/*
* Request the DVFS interrupt
*/
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- err = irq;
- goto err1;
+ dvfs_data->irq = platform_get_irq(pdev, 0);
+ if (dvfs_data->irq < 0) {
+ err = dvfs_data->irq;
+ goto err2;
}
/* request the DVFS interrupt */
- err = request_irq(irq, dvfs_irq, IRQF_SHARED, "dvfs", dvfs_dev);
- if (err)
+ err = request_irq(dvfs_data->irq, dvfs_irq, IRQF_SHARED, "dvfs",
+ dvfs_dev);
+ if (err) {
printk(KERN_ERR
"DVFS: Unable to attach to DVFS interrupt,err = %d",
err);
+ goto err2;
+ }
clk_enable(dvfs_clk);
err = init_dvfs_controller();
@@ -809,14 +835,14 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
if (err) {
printk(KERN_ERR
"DVFS: Unable to register sysdev entry for DVFS");
- return err;
+ goto err3;
}
err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_show_regs.attr);
if (err) {
printk(KERN_ERR
"DVFS: Unable to register sysdev entry for DVFS");
- return err;
+ goto err3;
}
@@ -824,14 +850,14 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
if (err) {
printk(KERN_ERR
"DVFS: Unable to register sysdev entry for DVFS");
- return err;
+ goto err3;
}
err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_down_count.attr);
if (err) {
printk(KERN_ERR
"DVFS: Unable to register sysdev entry for DVFS");
- return err;
+ goto err3;
}
/* Set the current working point. */
@@ -844,7 +870,10 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
#endif
return err;
-
+err3:
+ free_irq(dvfs_data->irq, dvfs_dev);
+err2:
+ iounmap(dvfs_data->membase);
err1:
dev_err(&pdev->dev, "Failed to probe DVFS CORE\n");
return err;
@@ -914,13 +943,15 @@ static void __exit dvfs_cleanup(void)
stop_dvfs();
/* release the DVFS interrupt */
- free_irq(MXC_INT_GPC1, NULL);
+ free_irq(dvfs_data->irq, dvfs_dev);
sysfs_remove_file(&dvfs_dev->kobj, &dev_attr_enable.attr);
/* Unregister the device structure */
platform_driver_unregister(&mxc_dvfs_core_driver);
+ iounmap(ccm_base);
+ iounmap(dvfs_data->membase);
clk_put(cpu_clk);
clk_put(dvfs_clk);