1/***************************************************************************/ 2 3/* 4 * linux/arch/m68knommu/platform/532x/config.c 5 * 6 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) 7 * Copyright (C) 2000, Lineo (www.lineo.com) 8 * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com 9 * Copyright Freescale Semiconductor, Inc 2006 10 * Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 */ 17 18/***************************************************************************/ 19 20#include <linux/kernel.h> 21#include <linux/sched.h> 22#include <linux/param.h> 23#include <linux/init.h> 24#include <linux/interrupt.h> 25#include <asm/irq.h> 26#include <asm/dma.h> 27#include <asm/traps.h> 28#include <asm/machdep.h> 29#include <asm/coldfire.h> 30#include <asm/mcftimer.h> 31#include <asm/mcfsim.h> 32#include <asm/mcfdma.h> 33#include <asm/mcfwdebug.h> 34 35/***************************************************************************/ 36 37void coldfire_tick(void); 38void coldfire_timer_init(irq_handler_t handler); 39unsigned long coldfire_timer_offset(void); 40void coldfire_trap_init(void); 41void coldfire_reset(void); 42 43extern unsigned int mcf_timervector; 44extern unsigned int mcf_profilevector; 45extern unsigned int mcf_timerlevel; 46 47/***************************************************************************/ 48 49/* 50 * DMA channel base address table. 51 */ 52unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { }; 53unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; 54 55/***************************************************************************/ 56 57void mcf_settimericr(unsigned int timer, unsigned int level) 58{ 59 volatile unsigned char *icrp; 60 unsigned int icr; 61 unsigned char irq; 62 63 if (timer <= 2) { 64 switch (timer) { 65 case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break; 66 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break; 67 } 68 69 icrp = (volatile unsigned char *) (MCF_MBAR + icr); 70 *icrp = level; 71 mcf_enable_irq0(irq); 72 } 73} 74 75/***************************************************************************/ 76 77int mcf_timerirqpending(int timer) 78{ 79 unsigned int imr = 0; 80 81 switch (timer) { 82 case 1: imr = 0x1; break; 83 case 2: imr = 0x2; break; 84 default: break; 85 } 86 return (mcf_getiprh() & imr); 87} 88 89/***************************************************************************/ 90 91void config_BSP(char *commandp, int size) 92{ 93 mcf_setimr(MCFSIM_IMR_MASKALL); 94 95#if defined(CONFIG_BOOTPARAM) 96 strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); 97 commandp[size-1] = 0; 98#else 99 /* Copy command line from FLASH to local buffer... */ 100 memcpy(commandp, (char *) 0x4000, 4); 101 if(strncmp(commandp, "kcl ", 4) == 0){ 102 memcpy(commandp, (char *) 0x4004, size); 103 commandp[size-1] = 0; 104 } else { 105 memset(commandp, 0, size); 106 } 107#endif 108 109 mcf_timervector = 64+32; 110 mcf_profilevector = 64+33; 111 mach_sched_init = coldfire_timer_init; 112 mach_tick = coldfire_tick; 113 mach_gettimeoffset = coldfire_timer_offset; 114 mach_trap_init = coldfire_trap_init; 115 mach_reset = coldfire_reset; 116 117#ifdef MCF_BDM_DISABLE 118 /* 119 * Disable the BDM clocking. This also turns off most of the rest of 120 * the BDM device. This is good for EMC reasons. This option is not 121 * incompatible with the memory protection option. 122 */ 123 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); 124#endif 125} 126 127/***************************************************************************/ 128/* Board initialization */ 129 130/********************************************************************/ 131/* 132 * PLL min/max specifications 133 */ 134#define MAX_FVCO 500000 /* KHz */ 135#define MAX_FSYS 80000 /* KHz */ 136#define MIN_FSYS 58333 /* KHz */ 137#define FREF 16000 /* KHz */ 138 139 140#define MAX_MFD 135 /* Multiplier */ 141#define MIN_MFD 88 /* Multiplier */ 142#define BUSDIV 6 /* Divider */ 143 144/* 145 * Low Power Divider specifications 146 */ 147#define MIN_LPD (1 << 0) /* Divider (not encoded) */ 148#define MAX_LPD (1 << 15) /* Divider (not encoded) */ 149#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */ 150 151#define SYS_CLK_KHZ 80000 152#define SYSTEM_PERIOD 12.5 153/* 154 * SDRAM Timing Parameters 155 */ 156#define SDRAM_BL 8 /* # of beats in a burst */ 157#define SDRAM_TWR 2 /* in clocks */ 158#define SDRAM_CASL 2.5 /* CASL in clocks */ 159#define SDRAM_TRCD 2 /* in clocks */ 160#define SDRAM_TRP 2 /* in clocks */ 161#define SDRAM_TRFC 7 /* in clocks */ 162#define SDRAM_TREFI 7800 /* in ns */ 163 164#define EXT_SRAM_ADDRESS (0xC0000000) 165#define FLASH_ADDRESS (0x00000000) 166#define SDRAM_ADDRESS (0x40000000) 167 168#define NAND_FLASH_ADDRESS (0xD0000000) 169 170int sys_clk_khz = 0; 171int sys_clk_mhz = 0; 172 173void wtm_init(void); 174void scm_init(void); 175void gpio_init(void); 176void fbcs_init(void); 177void sdramc_init(void); 178int clock_pll (int fsys, int flags); 179int clock_limp (int); 180int clock_exit_limp (void); 181int get_sys_clock (void); 182 183asmlinkage void __init sysinit(void) 184{ 185 sys_clk_khz = clock_pll(0, 0); 186 sys_clk_mhz = sys_clk_khz/1000; 187 188 wtm_init(); 189 scm_init(); 190 gpio_init(); 191 fbcs_init(); 192 sdramc_init(); 193} 194 195void wtm_init(void) 196{ 197 /* Disable watchdog timer */ 198 MCF_WTM_WCR = 0; 199} 200 201#define MCF_SCM_BCR_GBW (0x00000100) 202#define MCF_SCM_BCR_GBR (0x00000200) 203 204void scm_init(void) 205{ 206 /* All masters are trusted */ 207 MCF_SCM_MPR = 0x77777777; 208 209 /* Allow supervisor/user, read/write, and trusted/untrusted 210 access to all slaves */ 211 MCF_SCM_PACRA = 0; 212 MCF_SCM_PACRB = 0; 213 MCF_SCM_PACRC = 0; 214 MCF_SCM_PACRD = 0; 215 MCF_SCM_PACRE = 0; 216 MCF_SCM_PACRF = 0; 217 218 /* Enable bursts */ 219 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW); 220} 221 222 223void fbcs_init(void) 224{ 225 MCF_GPIO_PAR_CS = 0x0000003E; 226 227 /* Latch chip select */ 228 MCF_FBCS1_CSAR = 0x10080000; 229 230 MCF_FBCS1_CSCR = 0x002A3780; 231 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V); 232 233 /* Initialize latch to drive signals to inactive states */ 234 *((u16 *)(0x10080000)) = 0xFFFF; 235 236 /* External SRAM */ 237 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS; 238 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16 239 | MCF_FBCS_CSCR_AA 240 | MCF_FBCS_CSCR_SBM 241 | MCF_FBCS_CSCR_WS(1)); 242 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K 243 | MCF_FBCS_CSMR_V); 244 245 /* Boot Flash connected to FBCS0 */ 246 MCF_FBCS0_CSAR = FLASH_ADDRESS; 247 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16 248 | MCF_FBCS_CSCR_BEM 249 | MCF_FBCS_CSCR_AA 250 | MCF_FBCS_CSCR_SBM 251 | MCF_FBCS_CSCR_WS(7)); 252 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M 253 | MCF_FBCS_CSMR_V); 254} 255 256void sdramc_init(void) 257{ 258 /* 259 * Check to see if the SDRAM has already been initialized 260 * by a run control tool 261 */ 262 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) { 263 /* SDRAM chip select initialization */ 264 265 /* Initialize SDRAM chip select */ 266 MCF_SDRAMC_SDCS0 = (0 267 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) 268 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE)); 269 270 /* 271 * Basic configuration and initialization 272 */ 273 MCF_SDRAMC_SDCFG1 = (0 274 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 )) 275 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) 276 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2)) 277 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5)) 278 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5)) 279 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5)) 280 | MCF_SDRAMC_SDCFG1_WTLAT(3)); 281 MCF_SDRAMC_SDCFG2 = (0 282 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1) 283 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR) 284 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5)) 285 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1)); 286 287 288 /* 289 * Precharge and enable write to SDMR 290 */ 291 MCF_SDRAMC_SDCR = (0 292 | MCF_SDRAMC_SDCR_MODE_EN 293 | MCF_SDRAMC_SDCR_CKE 294 | MCF_SDRAMC_SDCR_DDR 295 | MCF_SDRAMC_SDCR_MUX(1) 296 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5)) 297 | MCF_SDRAMC_SDCR_PS_16 298 | MCF_SDRAMC_SDCR_IPALL); 299 300 /* 301 * Write extended mode register 302 */ 303 MCF_SDRAMC_SDMR = (0 304 | MCF_SDRAMC_SDMR_BNKAD_LEMR 305 | MCF_SDRAMC_SDMR_AD(0x0) 306 | MCF_SDRAMC_SDMR_CMD); 307 308 /* 309 * Write mode register and reset DLL 310 */ 311 MCF_SDRAMC_SDMR = (0 312 | MCF_SDRAMC_SDMR_BNKAD_LMR 313 | MCF_SDRAMC_SDMR_AD(0x163) 314 | MCF_SDRAMC_SDMR_CMD); 315 316 /* 317 * Execute a PALL command 318 */ 319 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL; 320 321 /* 322 * Perform two REF cycles 323 */ 324 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; 325 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; 326 327 /* 328 * Write mode register and clear reset DLL 329 */ 330 MCF_SDRAMC_SDMR = (0 331 | MCF_SDRAMC_SDMR_BNKAD_LMR 332 | MCF_SDRAMC_SDMR_AD(0x063) 333 | MCF_SDRAMC_SDMR_CMD); 334 335 /* 336 * Enable auto refresh and lock SDMR 337 */ 338 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN; 339 MCF_SDRAMC_SDCR |= (0 340 | MCF_SDRAMC_SDCR_REF 341 | MCF_SDRAMC_SDCR_DQS_OE(0xC)); 342 } 343} 344 345void gpio_init(void) 346{ 347 /* Enable UART0 pins */ 348 MCF_GPIO_PAR_UART = ( 0 349 | MCF_GPIO_PAR_UART_PAR_URXD0 350 | MCF_GPIO_PAR_UART_PAR_UTXD0); 351 352 /* Initialize TIN3 as a GPIO output to enable the write 353 half of the latch */ 354 MCF_GPIO_PAR_TIMER = 0x00; 355 MCF_GPIO_PDDR_TIMER = 0x08; 356 MCF_GPIO_PCLRR_TIMER = 0x0; 357 358} 359 360int clock_pll(int fsys, int flags) 361{ 362 int fref, temp, fout, mfd; 363 u32 i; 364 365 fref = FREF; 366 367 if (fsys == 0) { 368 /* Return current PLL output */ 369 mfd = MCF_PLL_PFDR; 370 371 return (fref * mfd / (BUSDIV * 4)); 372 } 373 374 /* Check bounds of requested system clock */ 375 if (fsys > MAX_FSYS) 376 fsys = MAX_FSYS; 377 if (fsys < MIN_FSYS) 378 fsys = MIN_FSYS; 379 380 /* Multiplying by 100 when calculating the temp value, 381 and then dividing by 100 to calculate the mfd allows 382 for exact values without needing to include floating 383 point libraries. */ 384 temp = 100 * fsys / fref; 385 mfd = 4 * BUSDIV * temp / 100; 386 387 /* Determine the output frequency for selected values */ 388 fout = (fref * mfd / (BUSDIV * 4)); 389 390 /* 391 * Check to see if the SDRAM has already been initialized. 392 * If it has then the SDRAM needs to be put into self refresh 393 * mode before reprogramming the PLL. 394 */ 395 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) 396 /* Put SDRAM into self refresh mode */ 397 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE; 398 399 /* 400 * Initialize the PLL to generate the new system clock frequency. 401 * The device must be put into LIMP mode to reprogram the PLL. 402 */ 403 404 /* Enter LIMP mode */ 405 clock_limp(DEFAULT_LPD); 406 407 /* Reprogram PLL for desired fsys */ 408 MCF_PLL_PODR = (0 409 | MCF_PLL_PODR_CPUDIV(BUSDIV/3) 410 | MCF_PLL_PODR_BUSDIV(BUSDIV)); 411 412 MCF_PLL_PFDR = mfd; 413 414 /* Exit LIMP mode */ 415 clock_exit_limp(); 416 417 /* 418 * Return the SDRAM to normal operation if it is in use. 419 */ 420 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) 421 /* Exit self refresh mode */ 422 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE; 423 424 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH; 425 426 /* wait for DQS logic to relock */ 427 for (i = 0; i < 0x200; i++) 428 ; 429 430 return fout; 431} 432 433int clock_limp(int div) 434{ 435 u32 temp; 436 437 /* Check bounds of divider */ 438 if (div < MIN_LPD) 439 div = MIN_LPD; 440 if (div > MAX_LPD) 441 div = MAX_LPD; 442 443 /* Save of the current value of the SSIDIV so we don't 444 overwrite the value*/ 445 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF)); 446 447 /* Apply the divider to the system clock */ 448 MCF_CCM_CDR = ( 0 449 | MCF_CCM_CDR_LPDIV(div) 450 | MCF_CCM_CDR_SSIDIV(temp)); 451 452 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP; 453 454 return (FREF/(3*(1 << div))); 455} 456 457int clock_exit_limp(void) 458{ 459 int fout; 460 461 /* Exit LIMP mode */ 462 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP); 463 464 /* Wait for PLL to lock */ 465 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK)) 466 ; 467 468 fout = get_sys_clock(); 469 470 return fout; 471} 472 473int get_sys_clock(void) 474{ 475 int divider; 476 477 /* Test to see if device is in LIMP mode */ 478 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) { 479 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF); 480 return (FREF/(2 << divider)); 481 } 482 else 483 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4)); 484} 485