Commit e49e9103 authored by Ranjani Vaidyanathan's avatar Ranjani Vaidyanathan Committed by Jason Liu

ENGR00179574: MX6- Add bus frequency scaling support

Add support for scaling the bus frequency (both DDR
and ahb_clk).
The DDR and AHB_CLK are dropped to 24MHz when all devices
that need high AHB frequency are disabled and the CORE
frequency is at the lowest setpoint.
The DDR is dropped to 400MHz for the video playback usecase.
In this mode the GPU, FEC, SATA etc are disabled.

To scale the bus frequency, its necessary that all cores
except the core that is executing the DDR frequency change
are in WFE. This is achieved by generating interrupts on
un-used interrupts (Int no 139, 144, 145 and 146).
Signed-off-by: default avatarRanjani Vaidyanathan <ra5478@freescale.com>
parent 6079ec04
/*
* Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
......@@ -148,11 +148,6 @@ static int _clk_enable(struct clk *clk)
reg |= MXC_CCM_CCGRx_CG_MASK << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
if (clk->flags & AHB_HIGH_SET_POINT)
lp_high_freq++;
else if (clk->flags & AHB_MED_SET_POINT)
lp_med_freq++;
return 0;
}
......@@ -173,11 +168,6 @@ static void _clk_disable(struct clk *clk)
reg = __raw_readl(clk->enable_reg);
reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
if (clk->flags & AHB_HIGH_SET_POINT)
lp_high_freq--;
else if (clk->flags & AHB_MED_SET_POINT)
lp_med_freq--;
}
static void _clk_disable_inwait(struct clk *clk)
......
......@@ -3,7 +3,9 @@
#
# Object file lists.
obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h1.o usb_h2.o usb_h3.o pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o
obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h1.o usb_h2.o usb_h3.o \
pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \
mx6_mmdc.o mx6_ddr_freq.o
obj-$(CONFIG_ARCH_MX6) += clock.o mx6q_suspend.o
obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o
......
......@@ -2051,6 +2051,8 @@ static void __init mx6_arm2_init(void)
gp_reg_id = arm2_dvfscore_data.reg_id;
mx6_arm2_init_uart();
imx6q_add_mipi_csi2(&mipi_csi2_pdata);
imx6q_add_mxc_hdmi_core(&hdmi_core_data);
......@@ -2177,6 +2179,7 @@ static void __init mx6_arm2_init(void)
imx6dl_add_imx_epdc(&epdc_data);
}
imx6q_add_pcie(&mx6_arm2_pcie_data);
imx6q_add_busfreq();
}
extern void __iomem *twd_base;
......
......@@ -1497,6 +1497,7 @@ static void __init mx6_board_init(void)
mxc_register_device(&si4763_codec_device, NULL);
mxc_register_device(&mxc_si4763_audio_device, &si4763_audio_data);
imx6q_add_busfreq();
}
extern void __iomem *twd_base;
......
......@@ -1162,6 +1162,7 @@ static void __init mx6_sabrelite_board_init(void)
rate = clk_round_rate(clko2, 24000000);
clk_set_rate(clko2, rate);
clk_enable(clko2);
imx6q_add_busfreq();
}
extern void __iomem *twd_base;
......
......@@ -1664,6 +1664,7 @@ static void __init mx6_sabresd_board_init(void)
/* Register charger chips */
platform_device_register(&sabresd_max8903_charger_1);
pm_power_off = mx6_snvs_poweroff;
imx6q_add_busfreq();
imx6q_add_pcie(&mx6_sabresd_pcie_data);
}
......
/*
* Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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
......@@ -43,58 +43,36 @@
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
#include <asm/tlb.h>
#include "crm_regs.h"
#define LP_LOW_VOLTAGE 1050000
#define LP_NORMAL_VOLTAGE 1250000
#define LP_APM_CLK 24000000
#define NAND_LP_APM_CLK 12000000
#define AXI_A_NORMAL_CLK 166250000
#define AXI_A_CLK_NORMAL_DIV 4
#define AXI_B_CLK_NORMAL_DIV 5
#define AHB_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV
#define EMI_SLOW_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV
#define NFC_CLK_NORMAL_DIV 4
#define SPIN_DELAY 1000000 /* in nanoseconds */
#define DDR_TYPE_DDR3 0x0
#define DDR_TYPE_DDR2 0x1
DEFINE_SPINLOCK(ddr_freq_lock);
unsigned long lp_normal_rate;
unsigned long lp_med_rate;
unsigned long ddr_normal_rate;
unsigned long ddr_med_rate;
unsigned long ddr_low_rate;
#define LPAPM_CLK 24000000
#define DDR_MED_CLK 400000000
#define DDR3_NORMAL_CLK 528000000
struct regulator *pll_regulator;
DEFINE_SPINLOCK(ddr_freq_lock);
struct regulator *lp_regulator;
int low_bus_freq_mode;
int high_bus_freq_mode;
int med_bus_freq_mode;
int bus_freq_scaling_initialized;
char *lp_reg_id;
static struct device *busfreq_dev;
static int busfreq_suspended;
/* True if bus_frequency is scaled not using DVFS-PER */
int bus_freq_scaling_is_active;
int cpu_op_nr;
int lp_high_freq;
int lp_med_freq;
struct workqueue_struct *voltage_wq;
struct completion voltage_change_cmpl;
unsigned int ddr_low_rate;
unsigned int ddr_med_rate;
unsigned int ddr_normal_rate;
int low_freq_bus_used(void);
void set_ddr_freq(int ddr_freq);
extern struct cpu_op *(*get_cpu_op)(int *op);
extern void __iomem *ccm_base;
extern void __iomem *databahn_base;
extern int update_ddr_freq(int ddr_rate);
......@@ -103,29 +81,140 @@ struct mutex bus_freq_mutex;
struct timeval start_time;
struct timeval end_time;
int set_low_bus_freq(void)
static int cpu_op_nr;
static struct cpu_op *cpu_op_tbl;
static struct clk *pll2_400;
static struct clk *cpu_clk;
static unsigned int org_ldo;
static struct clk *pll3;
static struct delayed_work low_bus_freq_handler;
static void reduce_bus_freq_handler(struct work_struct *work)
{
return 0;
unsigned long reg;
if (low_bus_freq_mode || !low_freq_bus_used())
return;
while (!mutex_trylock(&bus_freq_mutex))
msleep(1);
/* PLL3 is used in the DDR freq change process, enable it. */
if (low_bus_freq_mode || !low_freq_bus_used()) {
mutex_unlock(&bus_freq_mutex);
return;
}
clk_enable(pll3);
update_ddr_freq(24000000);
if (med_bus_freq_mode)
clk_disable(pll2_400);
low_bus_freq_mode = 1;
high_bus_freq_mode = 0;
med_bus_freq_mode = 0;
/* Power gate the PU LDO. */
org_ldo = reg = __raw_readl(ANADIG_REG_CORE);
reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
__raw_writel(reg, ANADIG_REG_CORE);
mutex_unlock(&bus_freq_mutex);
clk_disable(pll3);
}
int set_high_bus_freq(int high_bus_freq)
/* Set the DDR, AHB to 24MHz.
* This mode will be activated only when none of the modules that
* need a higher DDR or AHB frequency are active.
*/
int set_low_bus_freq(void)
{
if (busfreq_suspended)
return 0;
if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
return 0;
/* Don't lower the frequency immediately. Instead scheduled a delayed work
* and drop the freq if the conditions still remain the same.
*/
schedule_delayed_work(&low_bus_freq_handler, usecs_to_jiffies(3000000));
return 0;
}
void exit_lpapm_mode_mx6q(int high_bus_freq)
/* Set the DDR to either 528MHz or 400MHz for MX6q
* or 400MHz for MX6DL.
*/
int set_high_bus_freq(int high_bus_freq)
{
if (busfreq_suspended)
return 0;
}
if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
return 0;
if (high_bus_freq_mode && high_bus_freq)
return 0;
void set_ddr_freq(int ddr_rate)
{
if (med_bus_freq_mode && !high_bus_freq)
return 0;
while (!mutex_trylock(&bus_freq_mutex))
msleep(1);
if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
(med_bus_freq_mode && !high_bus_freq && lp_med_freq && !lp_high_freq)) {
mutex_unlock(&bus_freq_mutex);
return 0;
}
clk_enable(pll3);
/* Enable the PU LDO */
if (low_bus_freq_mode)
__raw_writel(org_ldo, ANADIG_REG_CORE);
if (high_bus_freq) {
update_ddr_freq(ddr_normal_rate);
if (med_bus_freq_mode)
clk_disable(pll2_400);
low_bus_freq_mode = 0;
high_bus_freq_mode = 1;
med_bus_freq_mode = 0;
} else {
clk_enable(pll2_400);
update_ddr_freq(ddr_med_rate);
low_bus_freq_mode = 0;
high_bus_freq_mode = 0;
med_bus_freq_mode = 1;
}
mutex_unlock(&bus_freq_mutex);
clk_disable(pll3);
return 0;
}
int low_freq_bus_used(void)
{
if (!bus_freq_scaling_initialized)
return 0;
/* We only go the lowest setpoint if ARM is also
* at the lowest setpoint.
*/
if ((clk_get_rate(cpu_clk) >
cpu_op_tbl[cpu_op_nr - 1].cpu_rate)
|| (cpu_op_nr == 1)) {
return 0;
}
if ((lp_high_freq == 0)
&& (lp_med_freq == 0))
return 1;
......@@ -150,6 +239,14 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
if (strncmp(buf, "1", 1) == 0) {
bus_freq_scaling_is_active = 1;
set_high_bus_freq(0);
} else if (strncmp(buf, "0", 1) == 0) {
if (bus_freq_scaling_is_active)
set_high_bus_freq(1);
bus_freq_scaling_is_active = 0;
}
return size;
}
......@@ -180,6 +277,54 @@ static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
*/
static int __devinit busfreq_probe(struct platform_device *pdev)
{
u32 err;
busfreq_dev = &pdev->dev;
pll2_400 = clk_get(NULL, "pll2_pfd_400M");
if (IS_ERR(pll2_400)) {
printk(KERN_DEBUG "%s: failed to get axi_clk\n",
__func__);
return PTR_ERR(pll2_400);
}
cpu_clk = clk_get(NULL, "cpu_clk");
if (IS_ERR(cpu_clk)) {
printk(KERN_DEBUG "%s: failed to get cpu_clk\n",
__func__);
return PTR_ERR(cpu_clk);
}
pll3 = clk_get(NULL, "pll3_main_clk");
err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
if (err) {
printk(KERN_ERR
"Unable to register sysdev entry for BUSFREQ");
return err;
}
cpu_op_tbl = get_cpu_op(&cpu_op_nr);
low_bus_freq_mode = 0;
high_bus_freq_mode = 1;
med_bus_freq_mode = 0;
bus_freq_scaling_is_active = 0;
bus_freq_scaling_initialized = 1;
if (cpu_is_mx6q()) {
ddr_low_rate = LPAPM_CLK;
ddr_med_rate = DDR_MED_CLK;
ddr_normal_rate = DDR3_NORMAL_CLK;
}
if (cpu_is_mx6dl()) {
ddr_low_rate = LPAPM_CLK;
ddr_normal_rate = ddr_med_rate = DDR_MED_CLK;
}
INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
mutex_init(&bus_freq_mutex);
return 0;
}
......@@ -218,7 +363,7 @@ static void __exit busfreq_cleanup(void)
bus_freq_scaling_initialized = 0;
}
module_init(busfreq_init);
late_initcall(busfreq_init);
module_exit(busfreq_cleanup);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
......
......@@ -170,11 +170,6 @@ static int _clk_enable(struct clk *clk)
reg |= MXC_CCM_CCGRx_CG_MASK << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
if (clk->flags & AHB_HIGH_SET_POINT)
lp_high_freq++;
else if (clk->flags & AHB_MED_SET_POINT)
lp_med_freq++;
return 0;
}
......@@ -184,11 +179,6 @@ static void _clk_disable(struct clk *clk)
reg = __raw_readl(clk->enable_reg);
reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
if (clk->flags & AHB_HIGH_SET_POINT)
lp_high_freq--;
else if (clk->flags & AHB_MED_SET_POINT)
lp_med_freq--;
}
static void _clk_disable_inwait(struct clk *clk)
......@@ -2228,7 +2218,6 @@ static struct clk ipu2_clk = {
static struct clk usdhc_dep_clk = {
.parent = &mmdc_ch0_axi_clk[0],
.secondary = &mx6per1_clk,
.flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
};
static unsigned long _clk_usdhc_round_rate(struct clk *clk,
......@@ -2306,7 +2295,6 @@ static struct clk usdhc1_clk = {
.round_rate = _clk_usdhc_round_rate,
.set_rate = _clk_usdhc1_set_rate,
.get_rate = _clk_usdhc1_get_rate,
.flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
};
static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent)
......@@ -2364,7 +2352,6 @@ static struct clk usdhc2_clk = {
.round_rate = _clk_usdhc_round_rate,
.set_rate = _clk_usdhc2_set_rate,
.get_rate = _clk_usdhc2_get_rate,
.flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
};
static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent)
......@@ -2423,7 +2410,6 @@ static struct clk usdhc3_clk = {
.round_rate = _clk_usdhc_round_rate,
.set_rate = _clk_usdhc3_set_rate,
.get_rate = _clk_usdhc3_get_rate,
.flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
};
static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent)
......@@ -2482,7 +2468,6 @@ static struct clk usdhc4_clk = {
.round_rate = _clk_usdhc_round_rate,
.set_rate = _clk_usdhc4_set_rate,
.get_rate = _clk_usdhc4_get_rate,
.flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
};
static unsigned long _clk_ssi_round_rate(struct clk *clk,
......@@ -5144,7 +5129,7 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2)
{
__iomem void *base;
int i;
int i, reg;
external_low_reference = ckil;
external_high_reference = ckih1;
......@@ -5278,8 +5263,8 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc,
__raw_writel(0, MXC_CCM_CCGR6);
/* Lower the ipg_perclk frequency to 8.25MHz. */
clk_set_rate(&ipg_perclk, 8250000);
/* Lower the ipg_perclk frequency to 6MHz. */
clk_set_rate(&ipg_perclk, 6000000);
/* S/PDIF */
clk_set_parent(&spdif0_clk[0], &pll3_pfd_454M);
......@@ -5310,6 +5295,33 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc,
lp_high_freq = 0;
lp_med_freq = 0;
/* Turn OFF all unnecessary PHYs. */
/* Turn off SATA PHY. */
base = ioremap(MX6Q_SATA_BASE_ADDR, SZ_8K);
reg = __raw_readl(base + PORT_PHY_CTL);
__raw_writel(reg | PORT_PHY_CTL_PDDQ_LOC, base + PORT_PHY_CTL);
/* Turn off HDMI PHY. */
base = ioremap(MX6Q_HDMI_ARB_BASE_ADDR, SZ_128K);
reg = __raw_readb(base + HDMI_PHY_CONF0);
__raw_writeb(reg | HDMI_PHY_CONF0_GEN2_PDDQ_MASK, base + HDMI_PHY_CONF0);
reg = __raw_readb(base + HDMI_MC_PHYRSTZ);
__raw_writeb(reg | HDMI_MC_PHYRSTZ_DEASSERT, base + HDMI_MC_PHYRSTZ);
iounmap(base);
base = ioremap(MX6Q_IOMUXC_BASE_ADDR, SZ_4K);
/* Close PLL inside SATA PHY. */
reg = __raw_readl(base + 0x34);
__raw_writel(reg | (1 << 1), base + 0x34);
/* Close PCIE PHY. */
reg = __raw_readl(base + 0x04);
reg |= (1 << 18);
__raw_writel(reg, base + 0x04);
iounmap(base);
return 0;
}
......@@ -33,6 +33,11 @@
extern unsigned int num_cpu_idle_lock;
void *mx6_wait_in_iram_base;
void (*mx6_wait_in_iram)(void);
extern void mx6_wait(void);
extern int init_mmdc_settings(void);
struct cpu_op *(*get_cpu_op)(int *op);
bool enable_wait_mode;
u32 arm_max_freq = CPU_AT_1GHz;
......@@ -87,8 +92,6 @@ static int __init post_cpu_init(void)
{
unsigned int reg;
void __iomem *base;
unsigned long iram_paddr, cpaddr;
iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE);
......@@ -129,6 +132,7 @@ static int __init post_cpu_init(void)
num_cpu_idle_lock = 0x0;
init_mmdc_settings();
return 0;
}
postcore_initcall(post_cpu_init);
......
......@@ -213,3 +213,6 @@ extern const struct imx_vdoa_data imx6q_vdoa_data __initconst;
extern const struct imx_pcie_data imx6q_pcie_data __initconst;
#define imx6q_add_pcie(pdata) imx_add_pcie(&imx6q_pcie_data, pdata)
#define imx6q_add_busfreq(pdata) imx_add_busfreq(pdata)
This diff is collapsed.
/*
* Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file mx6_mmdc.c
*
* @brief MX6 MMDC specific file.
*
* @ingroup PM
*/
#include <asm/io.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/iram_alloc.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/cpumask.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <mach/hardware.h>
#include <mach/clock.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
#include <asm/tlb.h>
#include <asm/hardware/gic.h>
#include "crm_regs.h"
/* DDR settings */
unsigned long (*iram_ddr_settings)[2];
unsigned long (*normal_mmdc_settings)[2];
unsigned long (*iram_iomux_settings)[2];
void __iomem *mmdc_base;
void __iomem *iomux_base;
void __iomem *gic_dist_base;
void __iomem *gic_cpu_base;
void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings, bool dll_mode, void* iomux_offsets) = NULL;
extern unsigned int ddr_low_rate;
extern unsigned int ddr_med_rate;
extern unsigned int ddr_normal_rate;
extern int low_bus_freq_mode;
extern int mmdc_med_rate;
extern void __iomem *ccm_base;
extern void mx6_ddr_freq_change(u32 freq, void *ddr_settings, bool dll_mode, void *iomux_offsets);
static void *ddr_freq_change_iram_base;
static int ddr_settings_size;
static int iomux_settings_size;
static volatile unsigned int cpus_in_wfe;
static volatile bool wait_for_ddr_freq_update;
#define MIN_DLL_ON_FREQ 333000000
#define MAX_DLL_OFF_FREQ 125000000
unsigned long ddr3_mmdc_regs_offsets[][2] = {
{0x83c, 0x0},
{0x840, 0x0},
{0x483c, 0x0},
{0x4840, 0x0},
{0x848, 0x0},
{0x4848, 0x0},
{0x850, 0x0},
{0x4850, 0x0},
};
unsigned long iomux_offsets_mx6q[][2] = {
{0x5A8, 0x0},
{0x5B0, 0x0},
{0x524, 0x0},
{0x51C, 0x0},
{0x518, 0x0},
{0x50C, 0x0},
{0x5B8, 0x0},
{0x5C0, 0x0},
};
unsigned long iomux_offsets_mx6dl[][2] = {
{0x4BC, 0x0},
{0x4C0, 0x0},
{0x4C4, 0x0},
{0x4C8, 0x0},
{0x4CC, 0x0},
{0x4D0, 0x0},
{0x4D4, 0x0},
{0x4D8, 0x0},
};
unsigned long ddr3_400[][2] = {
{0x83c, 0x42490249},
{0x840, 0x02470247},
{0x483c, 0x42570257},
{0x4840, 0x02400240},
{0x848, 0x4039363C},
{0x4848, 0x3A39333F},
{0x850, 0x38414441},
{0x4850, 0x472D4833}
};
unsigned long *irq_used;
unsigned long irqs_used_mx6q[] = {
MXC_INT_INTERRUPT_139_NUM,
MX6Q_INT_PERFMON1,
MX6Q_INT_PERFMON2,
MX6Q_INT_PERFMON3,
};
unsigned long irqs_used_mx6dl[] = {
MXC_INT_INTERRUPT_139_NUM,
MX6Q_INT_PERFMON1,
};
int can_change_ddr_freq(void)
{
return 1;
}
/* Each active core apart from the one changing the DDR frequency will execute
* this function. The rest of the cores have to remain in WFE state until the frequency
* is changed.
*/
irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
{
u32 me = smp_processor_id();
*((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
while (wait_for_ddr_freq_update)
wfe();
*((char *)(&cpus_in_wfe) + (u8)me) = 0;
return IRQ_HANDLED;
}
/* Change the DDR frequency. */
int update_ddr_freq(int ddr_rate)
{
int i;
unsigned int reg;
bool dll_off = false;
unsigned int online_cpus = 0;
int cpu = 0;
int me;
if (!can_change_ddr_freq())
return -1;
if (low_bus_freq_mode)
dll_off = true;
iram_ddr_settings[0][0] = ddr_settings_size;
iram_iomux_settings[0][0] = iomux_settings_size;
if (ddr_rate == ddr_med_rate) {
for (i = 0; i < iram_ddr_settings[0][0]; i++) {
iram_ddr_settings[i + 1][0] =
ddr3_400[i][0];
iram_ddr_settings[i + 1][1] =
ddr3_400[i][1];
}
} else if (ddr_rate == ddr_normal_rate) {
for (i = 0; i < iram_ddr_settings[0][0]; i++) {
iram_ddr_settings[i + 1][0] =
normal_mmdc_settings[i][0];
iram_ddr_settings[i + 1][1] =
normal_mmdc_settings[i][1];
}
}
/* Ensure that all Cores are in WFE. */
local_irq_disable();
me = smp_processor_id();
*((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
wait_for_ddr_freq_update = true;