summaryrefslogtreecommitdiffstats
path: root/arch/mips/mach-ar231x
diff options
context:
space:
mode:
authorOleksij Rempel <linux@rempel-privat.de>2013-06-19 11:11:29 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-06-21 09:33:18 +0200
commited61198836b84924ddc81a5a2c93471ceebba6b6 (patch)
tree6da3795eb0e5e4a160be0e780b6f46d021c50a08 /arch/mips/mach-ar231x
parent24b0d2effdb8575faa28c95b65830070e034b86e (diff)
downloadbarebox-ed61198836b84924ddc81a5a2c93471ceebba6b6.tar.gz
barebox-ed61198836b84924ddc81a5a2c93471ceebba6b6.tar.xz
MIPS: mach-ar231x: add lowlevel init pbl macros
Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/mips/mach-ar231x')
-rw-r--r--arch/mips/mach-ar231x/include/mach/pbl_macros.h177
1 files changed, 177 insertions, 0 deletions
diff --git a/arch/mips/mach-ar231x/include/mach/pbl_macros.h b/arch/mips/mach-ar231x/include/mach/pbl_macros.h
new file mode 100644
index 0000000000..cb72dbe466
--- /dev/null
+++ b/arch/mips/mach-ar231x/include/mach/pbl_macros.h
@@ -0,0 +1,177 @@
+#ifndef __ASM_MACH_AR2312_PBL_MACROS_H
+#define __ASM_MACH_AR2312_PBL_MACROS_H
+
+#include <asm/regdef.h>
+#include <mach/ar2312_regs.h>
+
+.macro pbl_ar2312_pll
+ .set push
+ .set noreorder
+
+ mfc0 k0, CP0_STATUS
+ li k1, ST0_NMI
+ and k1, k1, k0
+ bnez k1, pllskip
+ nop
+
+ /* Clear any prior AHB errors by reading both addr registers */
+ li t0, KSEG1 | AR2312_PROCADDR
+ lw zero, 0(t0)
+ li t0, KSEG1 | AR2312_DMAADDR
+ lw zero, 0(t0)
+
+ pbl_sleep t2, 4000
+
+ li t0, KSEG1 | AR2312_CLOCKCTL2
+ lw t1, (t0)
+ bgez t1, pllskip /* upper bit guaranteed non-0 at reset */
+ nop
+
+ /* For Viper 0xbc003064 register has to be programmed with 0x91000 to
+ * get 180Mhz Processor clock
+ * Set /2 clocking and turn OFF AR2312_CLOCKCTL2_STATUS_PLL_BYPASS.
+ * Processor RESETs at this point; the CLOCKCTL registers retain
+ * their new values across the reset.
+ */
+
+ li t0, KSEG1 | AR2312_CLOCKCTL1
+ li t1, AR2313_CLOCKCTL1_SELECTION
+ sw t1, (t0)
+
+ li t0, KSEG1 | AR2312_CLOCKCTL2
+ li t1, AR2312_CLOCKCTL2_WANT_RESET
+ sw t1, (t0) /* reset CPU */
+1: b 1b /* NOTREACHED */
+ nop
+pllskip:
+
+ .set pop
+.endm
+
+.macro pbl_ar2312_rst_uart0
+ .set push
+ .set noreorder
+
+ li a0, KSEG1 | AR2312_RESET
+ lw t0, 0(a0)
+ and t0, ~AR2312_RESET_APB
+ or t0, AR2312_RESET_UART0
+ sw t0, 0(a0)
+ lw zero, 0(a0) /* flush */
+
+ and t0, ~AR2312_RESET_UART0
+ sw t0, 0(a0)
+ lw zero, 0(a0) /* flush */
+
+1: /* Use internal clocking */
+ li a0, KSEG1 | AR2312_CLOCKCTL0
+ lw t0, 0(a0)
+ and t0, ~AR2312_CLOCKCTL_UART0
+ sw t0, 0(a0)
+
+ .set pop
+.endm
+
+.macro pbl_ar2312_x16_sdram
+ .set push
+ .set noreorder
+
+ li a0, KSEG1 | AR2312_MEM_CFG0
+ li a1, KSEG1 | AR2312_MEM_CFG1
+ li a2, KSEG1 | AR2312_MEM_REF
+
+ li a3, MEM_CFG1_E0 | (MEM_CFG1_AC_128 << MEM_CFG1_AC0_S)
+
+ /* Set the I and M bits to issue an SDRAM nop */
+ ori t0, a3, MEM_CFG1_M | MEM_CFG1_I
+ sw t0, 0(a1) /* AR2312_MEM_CFG1 */
+
+ pbl_sleep t2, 50
+
+ /* Reset the M bit to issue an SDRAM PRE-ALL */
+ ori t0, a3, MEM_CFG1_I
+ sw t0, 0(a1) /* AR2312_MEM_CFG1 */
+ sync
+
+ /* Generate a refresh every 16 clocks (spec says 10) */
+ li t0, 16 /* very fast refresh for now */
+ sw t0, 0(a2) /* AR2312_MEM_REF */
+
+ pbl_sleep t2, 5
+
+ /* Set command write mode, and read SDRAM */
+ ori t0, a3, MEM_CFG1_M
+ sw t0, 0(a1) /* AR2312_MEM_CFG1 */
+ sync
+
+ li t0, KSEG1 | AR2312_SDRAM0
+ or t0, 0x23000 /* 16bit burst */
+ lw zero, 0(t0)
+
+ /* Program configuration register */
+ li t0, MEM_CFG0_C | MEM_CFG0_C2 | MEM_CFG0_R1 | \
+ MEM_CFG0_B0 | MEM_CFG0_X
+ sw t0, 0(a0) /* AR2312_MEM_CFG0 */
+ sync
+
+ li t0, AR2312_SDRAM_MEMORY_REFRESH_VALUE
+ sw t0, 0(a2) /* AR2312_MEM_REF */
+ sync
+
+ /* Clear I and M and set cfg1 to the normal operational value */
+ sw a3, 0(a1) /* AR2312_MEM_CFG1 */
+ sync
+
+ pbl_sleep t2, 10
+
+ /* Now we need to set size of RAM to prevent some wired errors.
+ * Since I do not have access to any board with two SDRAM chips, or
+ * any was registered in the wild - we will support only one. */
+ /* So, lets find the beef */
+ li a0, KSEG1 | AR2312_MEM_CFG1
+ li a1, KSEG1 | AR2312_SDRAM0
+ li a2, 0xdeadbeef
+ li t0, 0x200000
+ li t1, MEM_CFG1_AC_2
+
+ /* We will write some magic word to the beginning of RAM,
+ * and see if it appears somewhere else. If yes, we made
+ * a travel around the world. */
+
+ /* But first of all save original state of the first RAM word. */
+ lw a3, 0(a1)
+ sw a2, 0(a1)
+
+find_the_beef:
+ or t2, a1, t0
+ lw t3, 0(t2)
+ beq a2, t3, 1f
+ nop
+ sll t0, 1
+ add t1, 1
+ /* we should have some limit here. */
+ blt t1, MEM_CFG1_AC_64, find_the_beef
+ nop
+ b make_beefsteak
+ nop
+
+ /* additional paranoid check */
+1:
+ sw zero, 0(a1)
+ lw t3, 0(t2)
+ bne zero, t3, find_the_beef
+ nop
+
+make_beefsteak:
+ /* create new config for AR2312_MEM_CFG1 and overwrite it */
+ sll t1, MEM_CFG1_AC0_S
+ or t2, t1, MEM_CFG1_E0
+ sw t2, 0(a0) /* AR2312_MEM_CFG1 */
+
+ /* restore original state of the first RAM word */
+ sw a3, 0(a1)
+
+ .set pop
+.endm
+
+#endif /* __ASM_MACH_AR2312_PBL_MACROS_H */