diff options
Diffstat (limited to 'arch/arm/mach-mx23/emi.S')
-rw-r--r-- | arch/arm/mach-mx23/emi.S | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/arch/arm/mach-mx23/emi.S b/arch/arm/mach-mx23/emi.S new file mode 100644 index 000000000000..41e1ea6abe71 --- /dev/null +++ b/arch/arm/mach-mx23/emi.S @@ -0,0 +1,254 @@ +/* + * Freescale MX23 low level RAM frequency manipulation + * + * Author: Vitaly Wool <vital@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/system.h> +#include <asm/pgtable-hwdef.h> +#include <mach/hardware.h> +#include <mach/regs-power.h> +#include <mach/regs-emi.h> +#include "regs-clkctrl.h" +#include "regs-dram.h" +#include "regs-digctl.h" + +/* TODO should be move to clock.h */ +#define SCALING_DATA_EMI_DIV_OFFSET 0 +#define SCALING_DATA_FRAC_DIV_OFFSET 4 +#define SCALING_DATA_CUR_FREQ_OFFSET 8 +#define SCALING_DATA_NEW_FREQ_OFFSET 12 +#define REGS_CLKCTRL_BASE MX23_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) +#define HW_CLKCTRL_EMI_ADDR (REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI) +#define HW_CLKCTRL_FRAC_SET_ADDR (REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC_SET) +#define HW_CLKCTRL_FRAC_CLR_ADDR (REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC_CLR) +#define HW_CLKCTRL_FRAC_ADDR (REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC) +#define HW_EMI_CTRL_ADDR MX23_SOC_IO_ADDRESS(REGS_EMI_PHYS + HW_EMI_CTRL) +#define HW_DRAM_CTL04_ADDR MX23_SOC_IO_ADDRESS(REGS_DRAM_PHYS + HW_DRAM_CTL04) +#define HW_CLKCTRL_CLKSEQ_ADDR (REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ) +.global cpu_arm926_switch_mm + +.align 8 +ENTRY(mxs_ram_freq_scale) + stmfd sp!, {r1 - r9, lr} + + ldr r5, [r0, #SCALING_DATA_NEW_FREQ_OFFSET] + ldr r6, [r0, #SCALING_DATA_CUR_FREQ_OFFSET] + ldr r7, [r0, #SCALING_DATA_EMI_DIV_OFFSET] + ldr r8, [r0, #SCALING_DATA_FRAC_DIV_OFFSET] + + adr r9, __mxs_temp_stack + + @ clean cache + ldr r1, __mxs_flush_cache_addr + mov lr, pc + mov pc, r1 + + @ put DRAM into self refresh + ldr r0, __mx23_dram_ctl00 + ldr r1, [r0, #0x20] + orr r1, r1, #(1 << 8) + str r1, [r0, #0x20] + @ wait for it to actually happen + ldr r0, __mx23_dram_emi00 +1: ldr r1, [r0, #0x10] + tst r1, #(1 << 1) + beq 1b + nop + + + @ RAM to clk from xtal + mov r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0xFF000000) + mov r1, #(1<<6) + str r1, [r0, #4] + mov r0, #(HW_CLKCTRL_EMI_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0xFF000000) +101: ldr r1, [r0] + tst r1, #BM_CLKCTRL_EMI_BUSY_REF_XTAL + bne 101b + + @ Gate ref_emi + mov r0, #(HW_CLKCTRL_FRAC_SET_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_FRAC_SET_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_FRAC_SET_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_FRAC_SET_ADDR & 0xFF000000) + + mov r1, #(BM_CLKCTRL_FRAC_CLKGATEEMI) + str r1, [r0] + + + @ prepare for change + cmp r5, #24 + bgt 2f + bl mx23_ram_24M_set_timings + b 44f +2: cmp r5, #48 + bgt 3f + bl mx23_ram_48M_set_timings + b 55f +3: cmp r5, #60 + bgt 4f + bl mx23_ram_60M_set_timings + b 55f +4: cmp r5, #80 + bgt 5f + bl mx23_ram_80M_set_timings + b 55f +5: cmp r5, #96 + bgt 6f + bl mx23_ram_96M_set_timings + b 55f +6: cmp r5, #120 + bgt 7f + bl mx23_ram_120M_set_timings + b 55f +7: cmp r5, #133 + bgt 8f + bl mx23_ram_133M_set_timings + b 55f +8: bl mx23_ram_150M_set_timings + + +44: + + bl __mx23_emi_set_values_xtal + + @ resttore normal DRAM mode + ldr r0, __mx23_dram_ctl00 + ldr r1, [r0, #0x20] + bic r1, r1, #(1 << 8) + str r1, [r0, #0x20] + + @ wait for it to actually happen + ldr r0, __mx23_dram_emi00 +99: ldr r1, [r0, #0x10] + tst r1, #(1 << 1) + bne 99b + b 110f + +55: + @When are using the DLL, reset the DRAM controller and DLL + @start point logic (via DLL_SHIFT_RESET and DLL_RESET). + @After changing clock dividers and loading + @the new HW_DRAM_CTL* parameters, we will wait for a new DLL_LOCK + + @todo - for DRAM's that will use DLL bypass (non DDR1) + @ we should not use DLL_RESET and DLL_SHIFT_RESET. + + mov r0, #(HW_EMI_CTRL_ADDR & 0x000000FF) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0x0000FF00) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0x00FF0000) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0xFF000000) + ldr r1, [r0] @read values of HW_EMI_CTRL into R1 + orr r1, r1, #BM_EMI_CTRL_DLL_SHIFT_RESET @Set these 2 fields. + orr r1, r1, #BM_EMI_CTRL_DLL_RESET + str r1, [r0] @write back values to HW_EMI_CTRL register. + + bl __mx23_emi_set_values2 + + @ EMI back to PLL + mov r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_CLKSEQ_ADDR & 0xFF000000) + mov r1, #(BM_CLKCTRL_CLKSEQ_BYPASS_EMI) + @clear bypass bit + str r1, [r0, #8] + + @ Wait for BUSY_REF_EMI, to assure new clock dividers + @ are done transferring + mov r0, #(HW_CLKCTRL_EMI_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0xFF000000) +1: ldr r1, [r0] + tst r1, #BM_CLKCTRL_EMI_BUSY_REF_EMI + bne 1b + str r1, [r0] + +@todo - for DRAM's that will use DLL bypass (non DDR1) +@we should not use DLL_RESET and DLL_SHIFT_RESET. +@ if(HW_DRAM_CTL04.B.DLL_BYPASS_MODE==0) +@ { +@ +@ Clear the DLL_RESET and DLL_SHIFT_RESET bitfields +@ (\todo - is that necessary? +@ they were already set previously to reset +@ the controller/DLL start point, +@ so clearing should have no effect..) +@ +@ BF_CS2(EMI_CTRL, DLL_RESET, 0, DLL_SHIFT_RESET, 0); + + mov r0, #(HW_EMI_CTRL_ADDR & 0x000000FF) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0x0000FF00) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0x00FF0000) + orr r0, r0, #(HW_EMI_CTRL_ADDR & 0xFF000000) + ldr r1, [r0] + bic r1, #BM_EMI_CTRL_DLL_SHIFT_RESET + bic r1, #BM_EMI_CTRL_DLL_RESET + str r1, [r0] + +@ Wait for DLL locking. +@ while(HW_DRAM_CTL04.B.DLLLOCKREG==0); + + mov r0, #(HW_DRAM_CTL04_ADDR & 0x000000FF) + orr r0, r0, #(HW_DRAM_CTL04_ADDR & 0x0000FF00) + orr r0, r0, #(HW_DRAM_CTL04_ADDR & 0x00FF0000) + orr r0, r0, #(HW_DRAM_CTL04_ADDR & 0xFF000000) +77: ldr r1, [r0] + tst r1, #BM_DRAM_CTL04_DLLLOCKREG + beq 77b + +88: + @ resttore normal DRAM mode + ldr r0, __mx23_dram_ctl00 + ldr r1, [r0, #0x20] + bic r1, r1, #(1 << 8) + str r1, [r0, #0x20] + + @ wait for it to actually happen + ldr r0, __mx23_dram_emi00 +102: ldr r1, [r0, #0x10] + tst r1, #(1 << 1) + bne 102b + +110: +@ restore regs and return + ldmfd sp!, {r1 - r9, lr} + mov pc, lr + + .space 0x100 +__mxs_temp_stack: + .word 0 + +#include "emi.inc" + +__mxs_flush_cache_addr: + .word arm926_flush_kern_cache_all + +ENTRY(mxs_ram_funcs_sz) + .word . - mxs_ram_freq_scale + |