1/* 2 * File: arch/blackfin/mach-bf537/head.S 3 * Based on: arch/blackfin/mach-bf533/head.S 4 * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne 5 * 6 * Created: 1998 7 * Description: Startup code for Blackfin BF537 8 * 9 * Modified: 10 * Copyright 2004-2006 Analog Devices Inc. 11 * 12 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, see the file COPYING, or write 26 * to the Free Software Foundation, Inc., 27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 28 */ 29 30#include <linux/linkage.h> 31#include <linux/init.h> 32#include <asm/blackfin.h> 33#if CONFIG_BFIN_KERNEL_CLOCK 34#include <asm/mach/mem_init.h> 35#endif 36 37.global __rambase 38.global __ramstart 39.global __ramend 40.extern ___bss_stop 41.extern ___bss_start 42.extern _bf53x_relocate_l1_mem 43 44#define INITIAL_STACK 0xFFB01000 45 46__INIT 47 48ENTRY(__start) 49 /* R0: argument of command line string, passed from uboot, save it */ 50 R7 = R0; 51 /* Set the SYSCFG register: 52 * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) 53 */ 54 R0 = 0x36; 55 SYSCFG = R0; 56 R0 = 0; 57 58 /* Clear Out All the data and pointer Registers */ 59 R1 = R0; 60 R2 = R0; 61 R3 = R0; 62 R4 = R0; 63 R5 = R0; 64 R6 = R0; 65 66 P0 = R0; 67 P1 = R0; 68 P2 = R0; 69 P3 = R0; 70 P4 = R0; 71 P5 = R0; 72 73 LC0 = r0; 74 LC1 = r0; 75 L0 = r0; 76 L1 = r0; 77 L2 = r0; 78 L3 = r0; 79 80 /* Clear Out All the DAG Registers */ 81 B0 = r0; 82 B1 = r0; 83 B2 = r0; 84 B3 = r0; 85 86 I0 = r0; 87 I1 = r0; 88 I2 = r0; 89 I3 = r0; 90 91 M0 = r0; 92 M1 = r0; 93 M2 = r0; 94 M3 = r0; 95 96 /* Turn off the icache */ 97 p0.l = (IMEM_CONTROL & 0xFFFF); 98 p0.h = (IMEM_CONTROL >> 16); 99 R1 = [p0]; 100 R0 = ~ENICPLB; 101 R0 = R0 & R1; 102 103 /* Anomaly 05000125 */ 104#ifdef ANOMALY_05000125 105 CLI R2; 106 SSYNC; 107#endif 108 [p0] = R0; 109 SSYNC; 110#ifdef ANOMALY_05000125 111 STI R2; 112#endif 113 114 /* Turn off the dcache */ 115 p0.l = (DMEM_CONTROL & 0xFFFF); 116 p0.h = (DMEM_CONTROL >> 16); 117 R1 = [p0]; 118 R0 = ~ENDCPLB; 119 R0 = R0 & R1; 120 121 /* Anomaly 05000125 */ 122#ifdef ANOMALY_05000125 123 CLI R2; 124 SSYNC; 125#endif 126 [p0] = R0; 127 SSYNC; 128#ifdef ANOMALY_05000125 129 STI R2; 130#endif 131 132 /* Initialise General-Purpose I/O Modules on BF537 */ 133 /* Rev 0.0 Anomaly 05000212 - PORTx_FER, 134 * PORT_MUX Registers Do Not accept "writes" correctly: 135 */ 136 p0.h = hi(BFIN_PORT_MUX); 137 p0.l = lo(BFIN_PORT_MUX); 138#ifdef ANOMALY_05000212 139 R0.L = W[P0]; /* Read */ 140 SSYNC; 141#endif 142 R0 = (PGDE_UART | PFTE_UART)(Z); 143#ifdef ANOMALY_05000212 144 W[P0] = R0.L; /* Write */ 145 SSYNC; 146#endif 147 W[P0] = R0.L; /* Enable both UARTS */ 148 SSYNC; 149 150 p0.h = hi(PORTF_FER); 151 p0.l = lo(PORTF_FER); 152#ifdef ANOMALY_05000212 153 R0.L = W[P0]; /* Read */ 154 SSYNC; 155#endif 156 R0 = 0x000F(Z); 157#ifdef ANOMALY_05000212 158 W[P0] = R0.L; /* Write */ 159 SSYNC; 160#endif 161 /* Enable peripheral function of PORTF for UART0 and UART1 */ 162 W[P0] = R0.L; 163 SSYNC; 164 165#if !defined(CONFIG_BF534) 166 p0.h = hi(EMAC_SYSTAT); 167 p0.l = lo(EMAC_SYSTAT); 168 R0.h = 0xFFFF; /* Clear EMAC Interrupt Status bits */ 169 R0.l = 0xFFFF; 170 [P0] = R0; 171 SSYNC; 172#endif 173 174#ifdef CONFIG_BF537_PORT_H 175 p0.h = hi(PORTH_FER); 176 p0.l = lo(PORTH_FER); 177 R0.L = W[P0]; /* Read */ 178 SSYNC; 179 R0 = 0x0000; 180 W[P0] = R0.L; /* Write */ 181 SSYNC; 182 W[P0] = R0.L; /* Disable peripheral function of PORTH */ 183 SSYNC; 184#endif 185 186 /* Initialise UART - when booting from u-boot, the UART is not disabled 187 * so if we dont initalize here, our serial console gets hosed */ 188 p0.h = hi(UART_LCR); 189 p0.l = lo(UART_LCR); 190 r0 = 0x0(Z); 191 w[p0] = r0.L; /* To enable DLL writes */ 192 ssync; 193 194 p0.h = hi(UART_DLL); 195 p0.l = lo(UART_DLL); 196 r0 = 0x0(Z); 197 w[p0] = r0.L; 198 ssync; 199 200 p0.h = hi(UART_DLH); 201 p0.l = lo(UART_DLH); 202 r0 = 0x00(Z); 203 w[p0] = r0.L; 204 ssync; 205 206 p0.h = hi(UART_GCTL); 207 p0.l = lo(UART_GCTL); 208 r0 = 0x0(Z); 209 w[p0] = r0.L; /* To enable UART clock */ 210 ssync; 211 212 /* Initialize stack pointer */ 213 sp.l = lo(INITIAL_STACK); 214 sp.h = hi(INITIAL_STACK); 215 fp = sp; 216 usp = sp; 217 218 /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ 219 call _bf53x_relocate_l1_mem; 220#if CONFIG_BFIN_KERNEL_CLOCK 221 call _start_dma_code; 222#endif 223 224 /* Code for initializing Async memory banks */ 225 226 p2.h = hi(EBIU_AMBCTL1); 227 p2.l = lo(EBIU_AMBCTL1); 228 r0.h = hi(AMBCTL1VAL); 229 r0.l = lo(AMBCTL1VAL); 230 [p2] = r0; 231 ssync; 232 233 p2.h = hi(EBIU_AMBCTL0); 234 p2.l = lo(EBIU_AMBCTL0); 235 r0.h = hi(AMBCTL0VAL); 236 r0.l = lo(AMBCTL0VAL); 237 [p2] = r0; 238 ssync; 239 240 p2.h = hi(EBIU_AMGCTL); 241 p2.l = lo(EBIU_AMGCTL); 242 r0 = AMGCTLVAL; 243 w[p2] = r0; 244 ssync; 245 246 /* This section keeps the processor in supervisor mode 247 * during kernel boot. Switches to user mode at end of boot. 248 * See page 3-9 of Hardware Reference manual for documentation. 249 */ 250 251 /* EVT15 = _real_start */ 252 253 p0.l = lo(EVT15); 254 p0.h = hi(EVT15); 255 p1.l = _real_start; 256 p1.h = _real_start; 257 [p0] = p1; 258 csync; 259 260 p0.l = lo(IMASK); 261 p0.h = hi(IMASK); 262 p1.l = IMASK_IVG15; 263 p1.h = 0x0; 264 [p0] = p1; 265 csync; 266 267 raise 15; 268 p0.l = .LWAIT_HERE; 269 p0.h = .LWAIT_HERE; 270 reti = p0; 271#if defined(ANOMALY_05000281) 272 nop; nop; nop; 273#endif 274 rti; 275 276.LWAIT_HERE: 277 jump .LWAIT_HERE; 278ENDPROC(__start) 279 280ENTRY(_real_start) 281 [ -- sp ] = reti; 282 p0.l = lo(WDOG_CTL); 283 p0.h = hi(WDOG_CTL); 284 r0 = 0xAD6(z); 285 w[p0] = r0; /* watchdog off for now */ 286 ssync; 287 288 /* Code update for BSS size == 0 289 * Zero out the bss region. 290 */ 291 292 p1.l = ___bss_start; 293 p1.h = ___bss_start; 294 p2.l = ___bss_stop; 295 p2.h = ___bss_stop; 296 r0 = 0; 297 p2 -= p1; 298 lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2; 299.L_clear_bss: 300 B[p1++] = r0; 301 302 /* In case there is a NULL pointer reference 303 * Zero out region before stext 304 */ 305 306 p1.l = 0x0; 307 p1.h = 0x0; 308 r0.l = __stext; 309 r0.h = __stext; 310 r0 = r0 >> 1; 311 p2 = r0; 312 r0 = 0; 313 lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2; 314.L_clear_zero: 315 W[p1++] = r0; 316 317 /* pass the uboot arguments to the global value command line */ 318 R0 = R7; 319 call _cmdline_init; 320 321 p1.l = __rambase; 322 p1.h = __rambase; 323 r0.l = __sdata; 324 r0.h = __sdata; 325 [p1] = r0; 326 327 p1.l = __ramstart; 328 p1.h = __ramstart; 329 p3.l = ___bss_stop; 330 p3.h = ___bss_stop; 331 332 r1 = p3; 333 [p1] = r1; 334 335 /* 336 * load the current thread pointer and stack 337 */ 338 r1.l = _init_thread_union; 339 r1.h = _init_thread_union; 340 341 r2.l = 0x2000; 342 r2.h = 0x0000; 343 r1 = r1 + r2; 344 sp = r1; 345 usp = sp; 346 fp = sp; 347 jump.l _start_kernel; 348ENDPROC(_real_start) 349 350__FINIT 351 352.section .l1.text 353#if CONFIG_BFIN_KERNEL_CLOCK 354ENTRY(_start_dma_code) 355 356 /* Enable PHY CLK buffer output */ 357 p0.h = hi(VR_CTL); 358 p0.l = lo(VR_CTL); 359 r0.l = w[p0]; 360 bitset(r0, 14); 361 w[p0] = r0.l; 362 ssync; 363 364 p0.h = hi(SIC_IWR); 365 p0.l = lo(SIC_IWR); 366 r0.l = 0x1; 367 r0.h = 0x0; 368 [p0] = r0; 369 SSYNC; 370 371 /* 372 * Set PLL_CTL 373 * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors 374 * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK 375 * - [7] = output delay (add 200ps of delay to mem signals) 376 * - [6] = input delay (add 200ps of input delay to mem signals) 377 * - [5] = PDWN : 1=All Clocks off 378 * - [3] = STOPCK : 1=Core Clock off 379 * - [1] = PLL_OFF : 1=Disable Power to PLL 380 * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL 381 * all other bits set to zero 382 */ 383 384 p0.h = hi(PLL_LOCKCNT); 385 p0.l = lo(PLL_LOCKCNT); 386 r0 = 0x300(Z); 387 w[p0] = r0.l; 388 ssync; 389 390 P2.H = hi(EBIU_SDGCTL); 391 P2.L = lo(EBIU_SDGCTL); 392 R0 = [P2]; 393 BITSET (R0, 24); 394 [P2] = R0; 395 SSYNC; 396 397 r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */ 398 r0 = r0 << 9; /* Shift it over, */ 399 r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/ 400 r0 = r1 | r0; 401 r1 = PLL_BYPASS; /* Bypass the PLL? */ 402 r1 = r1 << 8; /* Shift it over */ 403 r0 = r1 | r0; /* add them all together */ 404 405 p0.h = hi(PLL_CTL); 406 p0.l = lo(PLL_CTL); /* Load the address */ 407 cli r2; /* Disable interrupts */ 408 ssync; 409 w[p0] = r0.l; /* Set the value */ 410 idle; /* Wait for the PLL to stablize */ 411 sti r2; /* Enable interrupts */ 412 413.Lcheck_again: 414 p0.h = hi(PLL_STAT); 415 p0.l = lo(PLL_STAT); 416 R0 = W[P0](Z); 417 CC = BITTST(R0,5); 418 if ! CC jump .Lcheck_again; 419 420 /* Configure SCLK & CCLK Dividers */ 421 r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); 422 p0.h = hi(PLL_DIV); 423 p0.l = lo(PLL_DIV); 424 w[p0] = r0.l; 425 ssync; 426 427 p0.l = lo(EBIU_SDRRC); 428 p0.h = hi(EBIU_SDRRC); 429 r0 = mem_SDRRC; 430 w[p0] = r0.l; 431 ssync; 432 433 p0.l = (EBIU_SDBCTL & 0xFFFF); 434 p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */ 435 r0 = mem_SDBCTL; 436 w[p0] = r0.l; 437 ssync; 438 439 P2.H = hi(EBIU_SDGCTL); 440 P2.L = lo(EBIU_SDGCTL); 441 R0 = [P2]; 442 BITCLR (R0, 24); 443 p0.h = hi(EBIU_SDSTAT); 444 p0.l = lo(EBIU_SDSTAT); 445 r2.l = w[p0]; 446 cc = bittst(r2,3); 447 if !cc jump .Lskip; 448 NOP; 449 BITSET (R0, 23); 450.Lskip: 451 [P2] = R0; 452 SSYNC; 453 454 R0.L = lo(mem_SDGCTL); 455 R0.H = hi(mem_SDGCTL); 456 R1 = [p2]; 457 R1 = R1 | R0; 458 [P2] = R1; 459 SSYNC; 460 461 p0.h = hi(SIC_IWR); 462 p0.l = lo(SIC_IWR); 463 r0.l = lo(IWR_ENABLE_ALL); 464 r0.h = hi(IWR_ENABLE_ALL); 465 [p0] = r0; 466 SSYNC; 467 468 RTS; 469ENDPROC(_start_dma_code) 470#endif /* CONFIG_BFIN_KERNEL_CLOCK */ 471 472ENTRY(_bfin_reset) 473 /* No more interrupts to be handled*/ 474 CLI R6; 475 SSYNC; 476 477#if defined(CONFIG_MTD_M25P80) 478 /* 479 * The following code fix the SPI flash reboot issue, 480 * /CS signal of the chip which is using PF10 return to GPIO mode 481 */ 482 p0.h = hi(PORTF_FER); 483 p0.l = lo(PORTF_FER); 484 r0.l = 0x0000; 485 w[p0] = r0.l; 486 SSYNC; 487 488 /* /CS return to high */ 489 p0.h = hi(PORTFIO); 490 p0.l = lo(PORTFIO); 491 r0.l = 0xFFFF; 492 w[p0] = r0.l; 493 SSYNC; 494 495 /* Delay some time, This is necessary */ 496 r1.h = 0; 497 r1.l = 0x400; 498 p1 = r1; 499 lsetup (.L_delay_lab1, .L_delay_lab1_end) lc1 = p1; 500.L_delay_lab1: 501 r0.h = 0; 502 r0.l = 0x8000; 503 p0 = r0; 504 lsetup (.L_delay_lab0, .L_delay_lab0_end) lc0 = p0; 505.L_delay_lab0: 506 nop; 507.L_delay_lab0_end: 508 nop; 509.L_delay_lab1_end: 510 nop; 511#endif 512 513 /* Clear the IMASK register */ 514 p0.h = hi(IMASK); 515 p0.l = lo(IMASK); 516 r0 = 0x0; 517 [p0] = r0; 518 519 /* Clear the ILAT register */ 520 p0.h = hi(ILAT); 521 p0.l = lo(ILAT); 522 r0 = [p0]; 523 [p0] = r0; 524 SSYNC; 525 526 /* make sure SYSCR is set to use BMODE */ 527 P0.h = hi(SYSCR); 528 P0.l = lo(SYSCR); 529 R0.l = 0x0; 530 W[P0] = R0.l; 531 SSYNC; 532 533 /* issue a system soft reset */ 534 P1.h = hi(SWRST); 535 P1.l = lo(SWRST); 536 R1.l = 0x0007; 537 W[P1] = R1; 538 SSYNC; 539 540 /* clear system soft reset */ 541 R0.l = 0x0000; 542 W[P0] = R0; 543 SSYNC; 544 545 /* issue core reset */ 546 raise 1; 547 548 RTS; 549ENDPROC(_bfin_reset) 550 551.data 552 553/* 554 * Set up the usable of RAM stuff. Size of RAM is determined then 555 * an initial stack set up at the end. 556 */ 557 558.align 4 559__rambase: 560.long 0 561__ramstart: 562.long 0 563__ramend: 564.long 0 565