summaryrefslogtreecommitdiff
path: root/drivers/platform/sprd/dmc_freq_ap_28nm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/sprd/dmc_freq_ap_28nm.c')
-rwxr-xr-xdrivers/platform/sprd/dmc_freq_ap_28nm.c551
1 files changed, 551 insertions, 0 deletions
diff --git a/drivers/platform/sprd/dmc_freq_ap_28nm.c b/drivers/platform/sprd/dmc_freq_ap_28nm.c
new file mode 100755
index 00000000..f9b80a5c
--- /dev/null
+++ b/drivers/platform/sprd/dmc_freq_ap_28nm.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2012 Spreadtrum Communications Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/input/matrix_keypad.h>
+#include <soc/sprd/hardware.h>
+#include <soc/sprd/__sc8830_dmc_dfs.h>
+
+#include "soc/sprd/chip_x30g/dram_phy_28nm.h"
+
+#define REG32(x) (*((volatile uint32 *)(x)))
+
+#define DFS_PARAM_ADDR (0x1C0C)
+#define DFS_CALC_PARAM_ADDR (0x1F80)
+#define UMCTL_REG_BASE (0x30000000)
+#define PUBL_REG_BASE (0x30010000)
+#define UART1_PHYS_ADDR (0x70100000)
+
+//#define DPLL_CLK 800
+//#define DPLL_REFIN 26
+//#define NINT(FREQ,REFIN) (FREQ/REFIN)
+//#define KINT(FREQ,REFIN) ((FREQ-(FREQ/REFIN)*REFIN)*1048576/REFIN)
+
+typedef unsigned long int uint32;
+
+static inline void uart_putch(uint32 c)
+{
+ REG32(UART1_PHYS_ADDR) = c;
+}__attribute__((always_inline))
+
+static inline uint32 reg_bits_set(uint32 addr,uint32 start_bitpos,uint32 bit_num,uint32 value)
+{
+ /*create bit mask according to input param*/
+ volatile uint32 bit_mask = (1 << bit_num) - 1;
+ volatile uint32 reg_data = REG32(addr);
+
+ reg_data &= ~(bit_mask<<start_bitpos);
+ reg_data |= ((value&bit_mask)<<start_bitpos);
+
+ REG32(addr) = reg_data;
+
+ return 0;
+}__attribute__((always_inline))
+
+static inline void move_upctl_state_to_self_refresh(void)
+{
+ volatile uint32 val;
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+
+ p_umctl_reg->umctl_pwrctl = BIT_PWRCTL_SELFREF_SW;
+
+ /* wait umctl2 core is in self-refresh mode */
+ val = p_umctl_reg->umctl_stat;
+ while ((val & (BIT_STAT_SELFREF_TYPE | BIT_STAT_OP_MODE)) != 0x23) {
+ val = p_umctl_reg->umctl_stat;
+ }
+}__attribute__((always_inline))
+
+static inline void move_upctl_state_exit_self_refresh(void )
+{
+ volatile uint32 val;
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+
+ p_umctl_reg->umctl_pwrctl = 0x00;
+
+ /* wait umctl2 core is in self-refresh mode */
+ val = p_umctl_reg->umctl_stat;
+ while ((val & BIT_STAT_OP_MODE) != 0x1) {
+ val = p_umctl_reg->umctl_stat;
+ }
+
+}__attribute__((always_inline))
+
+#if 0
+static inline void disable_ddrphy_pll(void) {
+ DMC_PUBL_REG_INFO_PTR_T p_publ_reg = (DMC_PUBL_REG_INFO_PTR_T) PUBL_REG_BASE;
+ p_publ_reg->publ_pir |= BIT_PIR_PLLBYP;
+}__attribute__((always_inline))
+
+static inline void enable_ddrphy_pll(void) {
+ DMC_PUBL_REG_INFO_PTR_T p_publ_reg = (DMC_PUBL_REG_INFO_PTR_T) PUBL_REG_BASE;
+ p_publ_reg->publ_pir &= ~BIT_PIR_PLLBYP;
+}__attribute__((always_inline))
+
+static inline void disable_cam_command_deque(void)
+{
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+ p_umctl_reg->umctl_dbg[1] |= BIT_DBG1_DIS_DQ;
+}__attribute__((always_inline))
+
+static inline void enable_cam_command_deque(void)
+{
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+ p_umctl_reg->umctl_dbg[1] &= ~BIT_DBG1_DIS_DQ;
+}__attribute__((always_inline))
+
+static inline uint32 dqs_gating_training(uint32 new_clk)
+{
+ volatile uint32 s_pgcr, s_dsgcr, i;
+ DMC_PUBL_REG_INFO_PTR_T p_publ_reg = (DMC_PUBL_REG_INFO_PTR_T) PUBL_REG_BASE;
+
+ /* phy rst */
+ p_publ_reg->publ_pgcr[1] &= ~(0x1 << 25);
+ for(i = 0; i < 2; i++);
+ p_publ_reg->publ_pgcr[1] |= (0x1 << 25);
+
+ /* ACBVT, [4:3]:RX FIFO Read Mode,00 asynchronous. */
+ s_pgcr = p_publ_reg->publ_pgcr[3];
+ p_publ_reg->publ_pgcr[3] &= ~((0x3 << 3) | (0x1 << 24));
+
+ /* DQSGX: DQS Gate extention, do not extend the gate. */
+ s_dsgcr = p_publ_reg->publ_dsgcr;
+ p_publ_reg->publ_dsgcr &= ~(0x03 << 6);
+
+ if( new_clk == 200 ) {
+ p_publ_reg->publ_dtpr[3] = 0x1;
+ }
+ else if (new_clk == 400){
+ p_publ_reg->publ_dtpr[3] = 0xa;
+ }
+
+ /*do training*/
+ p_publ_reg->publ_pir |= ((1 << 10)|(1 << 0));
+
+ while( (p_publ_reg->publ_pgsr[0] & (0x1 << 0)) != 0x1 );
+ /*check ddr training status*/
+ if( p_publ_reg->publ_pgsr[0] & (1<<22) ){
+ while(1);
+ }
+
+ p_publ_reg->publ_pgcr[3] = s_pgcr;
+ p_publ_reg->publ_dsgcr = s_dsgcr;
+}__attribute__((always_inline))
+#endif
+
+static inline void wait_queue_complete(void)
+{
+ volatile uint32 value_temp;
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+
+ while(1) {
+ value_temp = p_umctl_reg->umctl_dbgcam;
+ if (((value_temp & BIT_DBGCAM_WR_PP_EPTY) != 0) &&
+ ((value_temp & BIT_DBGCAM_RD_PP_EPTY) != 0)) {
+
+ return;
+ }
+ }
+}__attribute__((always_inline))
+
+static inline void exit_lowpower_mode(uint32 *reg_store)
+{
+ volatile uint32 val;
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+#if 0
+ p_umctl_reg->umctl_pwrctl = BIT_PWRCTL_DFICLK_DIS;
+ val = p_umctl_reg->umctl_stat;
+ /* wait umctl2 core is in self-refresh mode */
+ while((val & 0x7) != 1) {
+ val = p_umctl_reg->umctl_stat;
+ }
+#endif
+
+ /* disable_cgm */
+ REG32(SPRD_PMU_PHYS + 0xF8) &= ~((3 << 30) );
+
+ /* disable lp interface. */
+ reg_store[0] = p_umctl_reg->umctl_hwlpctl;
+ p_umctl_reg->umctl_hwlpctl &= ~0x03;
+ //p_umctl_reg->umctl_dfilpcfg[0] = 0x0700f000;
+
+ /* disable_powerdown */
+ reg_store[1] = p_umctl_reg->umctl_pwrctl;
+ p_umctl_reg->umctl_pwrctl = 0;
+ /* wait status to normal mode */
+ val = p_umctl_reg->umctl_stat;
+ while ((val & BIT_STAT_OP_MODE) != 0x1) {
+ val = p_umctl_reg->umctl_stat;
+ }
+
+ /* disable dfi low power interface */
+ p_umctl_reg->umctl_dfilpcfg[0] &= ~(1 << 8);
+
+}__attribute__((always_inline))
+
+static inline void enable_lowpower_mode(uint32 *reg_store)
+{
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+
+ /* enable_sleep */
+ p_umctl_reg->umctl_dfilpcfg[0] |= (1 << 8);
+
+ /* enable lp interface. */
+ p_umctl_reg->umctl_hwlpctl = reg_store[0];
+
+ /* enable_powerdown */
+ p_umctl_reg->umctl_pwrctl = reg_store[1];
+
+ /* enable_cgm */
+ REG32(SPRD_PMU_PHYS + 0xF8) |= ((3 << 30) );
+
+}__attribute__((always_inline))
+
+static inline void ddr_cam_command_dequeue(uint32 isEnable)
+{
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+
+ if(isEnable) {
+ p_umctl_reg->umctl_dbg[1] &= ~BIT_DBG1_DIS_DQ;
+ }
+ else {
+ p_umctl_reg->umctl_dbg[1] |= BIT_DBG1_DIS_DQ;
+ }
+}__attribute__((always_inline))
+
+
+static inline void ddr_timing_update(ddr_dfs_v2_t *timing_param)
+{
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+ DMC_PUBL_REG_INFO_PTR_T p_publ_reg = (DMC_PUBL_REG_INFO_PTR_T) PUBL_REG_BASE;
+ publ_calc_t *calc = (publ_calc_t *)DFS_CALC_PARAM_ADDR;
+
+ /* minimum time from refresh to refresh or active */
+ //toggle this signel indicate refresh register has been update
+ p_umctl_reg->umctl_rfshtmg = timing_param->umctl_rfshtmg;
+ p_umctl_reg->umctl_rfshctl3 ^= (1<<1);
+
+ //update umctl & publ timing
+ p_umctl_reg->umctl_dramtmg[0] = timing_param->umctl_dramtmg0;
+ p_umctl_reg->umctl_dramtmg[1] = timing_param->umctl_dramtmg1;
+ p_umctl_reg->umctl_dramtmg[2] = timing_param->umctl_dramtmg2;
+ p_umctl_reg->umctl_dramtmg[3] = timing_param->umctl_dramtmg3;
+ p_umctl_reg->umctl_dramtmg[4] = timing_param->umctl_dramtmg4;
+ p_umctl_reg->umctl_dramtmg[5] = timing_param->umctl_dramtmg5;
+ p_umctl_reg->umctl_dramtmg[7] = timing_param->umctl_dramtmg7;
+ p_umctl_reg->umctl_dramtmg[8] = timing_param->umctl_dramtmg8;
+
+ p_umctl_reg->umctl_dfitmg[0] = timing_param->umctl_dfitmg0;
+ p_umctl_reg->umctl_init[3] = timing_param->umctl_init3;
+ p_umctl_reg->umctl_zqctl[0] = timing_param->umctl_zqctl0;
+ p_umctl_reg->umctl_zqctl[1] = timing_param->umctl_zqctl1;
+
+ p_publ_reg->publ_mr[2] = timing_param->publ_mr2;
+
+ p_publ_reg->publ_dx0gtr = timing_param->publ_dx0gtr;
+ p_publ_reg->publ_dx1gtr = timing_param->publ_dx1gtr;
+ p_publ_reg->publ_dx2gtr = timing_param->publ_dx2gtr;
+ p_publ_reg->publ_dx3gtr = timing_param->publ_dx3gtr;
+
+ p_publ_reg->publ_pgcr[3] = timing_param->publ_pgcr3;
+ p_publ_reg->publ_acmdlr = calc->publ_acmdlr;
+ p_publ_reg->publ_dx0mdlr = calc->publ_dx0mdlr;
+ p_publ_reg->publ_dx1mdlr = calc->publ_dx1mdlr;
+ p_publ_reg->publ_dx2mdlr = calc->publ_dx2mdlr;
+ p_publ_reg->publ_dx3mdlr = calc->publ_dx3mdlr;
+ p_publ_reg->publ_aclcdlr = calc->publ_aclcdlr;
+ p_publ_reg->publ_dx0lcdlr[0] = calc->publ_dx0lcdlr0;
+ p_publ_reg->publ_dx0lcdlr[1] = calc->publ_dx0lcdlr1;
+ p_publ_reg->publ_dx0lcdlr[2] = calc->publ_dx0lcdlr2;
+ p_publ_reg->publ_dx1lcdlr[0] = calc->publ_dx1lcdlr0;
+ p_publ_reg->publ_dx1lcdlr[1] = calc->publ_dx1lcdlr1;
+ p_publ_reg->publ_dx1lcdlr[2] = calc->publ_dx1lcdlr2;
+ p_publ_reg->publ_dx2lcdlr[0] = calc->publ_dx2lcdlr0;
+ p_publ_reg->publ_dx2lcdlr[1] = calc->publ_dx2lcdlr1;
+ p_publ_reg->publ_dx2lcdlr[2] = calc->publ_dx2lcdlr2;
+ p_publ_reg->publ_dx3lcdlr[0] = calc->publ_dx3lcdlr0;
+ p_publ_reg->publ_dx3lcdlr[1] = calc->publ_dx3lcdlr1;
+ p_publ_reg->publ_dx3lcdlr[2] = calc->publ_dx3lcdlr2;
+
+ p_publ_reg->publ_dsgcr = timing_param->publ_dsgcr;
+ p_publ_reg->publ_dtpr[0] = timing_param->publ_dtpr0;
+ p_publ_reg->publ_dtpr[1] = timing_param->publ_dtpr1;
+ p_publ_reg->publ_dtpr[2] = timing_param->publ_dtpr2;
+ p_publ_reg->publ_dtpr[3] = timing_param->publ_dtpr3;
+
+}__attribute__((always_inline))
+
+static inline void ddr_clk_set(uint32 new_clk, ddr_dfs_v2_t *timing)
+{
+ volatile uint32 i;
+ uint32 reg_store[3];
+
+ DMC_UMCTL_REG_INFO_PTR_T p_umctl_reg = (DMC_UMCTL_REG_INFO_PTR_T)UMCTL_REG_BASE;
+ DMC_PUBL_REG_INFO_PTR_T p_publ_reg = (DMC_PUBL_REG_INFO_PTR_T) PUBL_REG_BASE;
+
+ uart_putch('d');
+ exit_lowpower_mode(&(reg_store[0]));
+
+#if 0
+REG32(0x8F001000)= 0x11223344;
+
+for (i = 0; i < 0x20; i ++)
+{
+ REG32(0x1F00 + (i << 2)) = 0xAAAAAAAA;
+}
+#endif
+ /* step a: move dram into self-refresh. */
+ move_upctl_state_to_self_refresh();
+
+ /* step b: changing the input clock period. */
+ /* hold bus : set DBG1.dis_dq = 1 */
+ ddr_cam_command_dequeue(0);
+
+ /* DFIMISC.dfi_init_complete_en =0.hold not trigger sdram initialization */
+ p_umctl_reg->umctl_dfimisc &= ~BIT_DFIMISC_DFI_COMP_EN;
+ wait_queue_complete();
+
+ /* step c: change the clock frequency to the DWC_ddr_umctl2 and ensure no glitchs. */
+ /* phy clock close : DDR_PHY_AUTO_GATE_EN */
+ reg_store[2] = REG32(SPRD_PMU_PHYS+0x00D0);
+ REG32(SPRD_PMU_PHYS+0x00D0) &= ~((1 << 6) | 0x07);
+ for(i = 0; i < 0x2; i++);
+
+ switch(new_clk) {
+ case 192:
+ {
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x8, 2, 0x1);
+ for(i = 0; i < 0x2; i++);
+
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x0, 2, 0x2);
+ for(i = 0; i < 0x2; i++);
+ break;
+ }
+
+ case 200:
+ {
+ /* switch to dpll source */
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x8, 2, 0x1);
+ for(i = 0; i < 0x2; i++);
+
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x0, 2, 0x3);
+ for(i = 0; i < 0x2; i++);
+ break;
+ }
+
+ case 384:
+ {
+ /* set dpll clock to 192M : set DPLL_REFIN to 26M * 26 = 676*/
+ //reg_bits_set((SPRD_AONAPB_PHYS + 0x3004), 24, 2, 0x03);
+ //reg_bits_set((SPRD_AONAPB_PHYS + 0x3074), 0, 6, 26);
+
+ /* switch to dpll source */
+ /* reg[0x402D0024] :*/
+ /* [9:8] : clk_emc_div(clk_div= clk_src/(div+1)) */
+ /* [1:0] : clk_emc_sel (0:pub 26m, 1: CPLL, 2:TDPLL, 3:DPLL)*/
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x8, 2, 0x0);
+ for(i = 0; i < 0x2; i++);
+
+ reg_bits_set((SPRD_AONCKG_PHYS + 0x0024), 0x0, 2, 0x2);
+ for(i = 0; i < 0x2; i++);
+
+ break;
+ }
+
+ case 400:
+ case 466:
+ case 533:
+ {
+ /* set dpll clock to 400M : set DPLL_REFIN to 4M*/
+ /* reg[0x402E3004] :*/
+ /* [25:24] : DPLL_REFIN(00: 2M, 01 :4M, 10:13M, 11:26M) */
+ /* [10:0] : DPLL_N( dpll = dpll_refin * dpll_n)*/
+ /* reg[0x402E3074] :*/
+ /* [31:12] : DPLL_KINT */
+ /* [10] : DPLL_DIV_S */
+ /* [7] : DPLL_MOD_EN */
+ /* [6] : DPLL_SDM_EN */
+ /* [5:0] : DPLL_NINT */
+ #if 0
+ /* set dpll clock to 201M : set DPLL_REFIN to 26M * 31 = 806M*/
+ reg_val = REG32(REG_AON_APB_DPLL_CFG1);
+ reg_val |= 1 << 10; // fractional divider
+ reg_val &= ~(0xFFFFF << 12 | 0x3f);
+ reg_val |= (KINT(DPLL_CLK, DPLL_REFIN) & 0xFFFFF) << 12;
+ reg_val |= (NINT(DPLL_CLK, DPLL_REFIN)) & 0x3f;
+ REG32(REG_AON_APB_DPLL_CFG1)= reg_val;
+
+ reg_val = REG32(REG_AON_APB_DPLL_CFG);
+ reg_val &= ~(3 << 24);
+ reg_val |= (3 << 24);
+ REG32(REG_AON_APB_DPLL_CFG) = reg_val;
+ #endif
+
+ /* config dpll divider */
+ reg_bits_set((SPRD_AONCKG_PHYS+0x0024), 0x8, 2, 0x0);
+ for(i = 0; i < 0x2; i++);
+
+ /*switch to dpll source */
+ reg_bits_set((SPRD_AONCKG_PHYS+0x0024), 0x0, 2, 0x3);
+ for(i = 0; i < 0x2; i++);
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* phy clock open */
+ REG32(SPRD_PMU_PHYS+0x00D0) = reg_store[2];
+ for(i = 0; i < 0x2; i++);
+
+ /* step d: re-lock mode sequence. */
+ /* step e: set VT inhibit register pgcr1[26] and DCAL bypass PIR[29]. */
+ p_publ_reg->publ_pgcr[1] |= (0x1 << 26);
+ for(i = 0; i < 0x2; i++);
+ while((p_publ_reg->publ_pgsr[1] & (1<<30)) == 0);
+
+ p_publ_reg->publ_pir |= BIT_PIR_DCALBYP;
+ for(i = 0; i < 0x2; i++);
+ while ((p_publ_reg->publ_pgsr[0] & 0x01) != 1);
+
+ /* step f: update phy timing register. static and dynamic register */
+ ddr_timing_update(timing);
+
+ /* step g: trigger the initization PHY */
+ p_publ_reg->publ_pgcr[1] &= ~(0x1 << 26);
+ for(i = 0; i < 0x2; i++);
+ p_publ_reg->publ_pir &= ~BIT_PIR_DCALBYP;
+ for(i = 0; i < 0x2; i++);
+
+ /* dfi complete enable */
+ p_umctl_reg->umctl_dfimisc |= BIT_DFIMISC_DFI_COMP_EN;
+
+ uart_putch('f');
+ /* step i: require to exit sel_refresh by PWRCTL.selfref_sw. */
+ move_upctl_state_exit_self_refresh();
+
+ /* set ddr mr2 */
+ p_umctl_reg->umctl_mrctrl[1] = (2 << 8) | (timing->publ_mr2 & 0xFF);
+ p_umctl_reg->umctl_mrctrl[0] = (3 << 4) | (1 << 31);
+ while((p_umctl_reg->umctl_mrstat & 0x01) != 0);
+
+#if 0
+ /* step 9: do dqs traning. */
+ dqs_gating_training(new_clk);
+#endif
+
+ /* step j: FBG1.dis_dq = 0 */
+ ddr_cam_command_dequeue(1);
+
+ /* enable lowpower */
+ enable_lowpower_mode(&(reg_store[0]));
+#if 0
+for (i = 0; i < 0x20; i ++)
+{
+ REG32(0x1F00 + (i << 2)) = REG32(0x8F001000);
+}
+
+for (i = 0; i < 0x20; i ++)
+{
+ if (REG32(0x1F00 + (i << 2)) != 0x11223344) {
+
+ while(1);
+ }
+}
+#endif
+
+ uart_putch('s');
+}__attribute__((always_inline))
+
+static inline ddr_dfs_v2_t *get_clk_timing( uint32 clk )
+{
+ volatile uint32 i;
+ ddr_dfs_v2_t *timing;
+ publ_calc_t *calc;
+
+ timing = (ddr_dfs_v2_t *)(DFS_PARAM_ADDR);
+ calc = (publ_calc_t *)DFS_CALC_PARAM_ADDR;
+
+ for (i = 0; i < 5; i++) {
+ if (clk == timing->ddr_clk) {
+ if (clk == calc->ddr_clk) {
+ return timing;
+ }
+ }
+ timing++;
+ }
+
+ return (ddr_dfs_v2_t *)0;
+}__attribute__((always_inline))
+
+inline void dev_freq_set(unsigned long req)
+{
+ u32 clk;
+// u32 sene;
+ ddr_dfs_v2_t *timing;
+
+ //ddr_type = (req & EMC_DDR_TYPE_MASK) >> EMC_DDR_TYPE_OFFSET;
+ clk = (req & EMC_CLK_FREQ_MASK) >> EMC_CLK_FREQ_OFFSET;
+ //dll_mode = (req & EMC_DLL_MODE_MASK);
+ //sene = (req & EMC_FREQ_SENE_MASK) >> EMC_FREQ_SENE_OFFSET;
+
+ timing = get_clk_timing(clk);
+ if(timing->ddr_clk != clk) {
+ uart_putch('d');
+ uart_putch('f');
+ uart_putch('s');
+ uart_putch('e');
+ uart_putch('r');
+ uart_putch('r');
+ uart_putch('o');
+ uart_putch('r');
+ uart_putch('\n');
+ while(1);
+ }
+
+ ddr_clk_set(clk, timing);
+} __attribute__((always_inline))
+
+void emc_dfs_main(unsigned long flag)
+{
+ volatile uint32 reg, val;
+ /* disable mmu, cache */
+ /* SP : 0x1B00 ~ 0x1BFF */
+ /* ddr timing params : 0x1C00 ~ 0x1CFF */
+ asm volatile (
+ "mrc p15, 0, %0, c1, c0, 0 \n"
+ "ldr %1, =0x1005 \n"
+ "bic %0, %0, %1 \n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ "ldr sp, =0x1B00 \n"
+ "ldr r11, =0x1F00 \n"
+ : "=r"(reg), "=r"(val)
+ );
+
+ dev_freq_set(flag); /* call dfs freq set function */
+ /* jump back */
+ asm volatile (
+ "ldr r0, =cpu_resume \n"
+ "sub r0, r0, #0xc0000000 \n"
+ "add r0, r0, #0x80000000 \n"
+ "mov pc, r0 \n"
+ );
+}