at91rm9200_lowlevel.c revision 157924
1139804Simp/*- 21541Srgrimes * Copyright (c) 2006 M. Warner Losh. All rights reserved. 31541Srgrimes * 41541Srgrimes * Redistribution and use in source and binary forms, with or without 51541Srgrimes * modification, are permitted provided that the following conditions 61541Srgrimes * are met: 71541Srgrimes * 1. Redistributions of source code must retain the above copyright 81541Srgrimes * notice, this list of conditions and the following disclaimer. 91541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 101541Srgrimes * notice, this list of conditions and the following disclaimer in the 111541Srgrimes * documentation and/or other materials provided with the distribution. 121541Srgrimes * 131541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 141541Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 151541Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 161541Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 171541Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 181541Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 191541Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 201541Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 211541Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 221541Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 231541Srgrimes * 241541Srgrimes * This software is derived from software provide by Kwikbyte who specifically 251541Srgrimes * disclaimed copyright on the code. 261541Srgrimes * 271541Srgrimes * $FreeBSD: head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c 157924 2006-04-21 07:29:14Z imp $ 281541Srgrimes */ 291541Srgrimes 301541Srgrimes#include "at91rm9200.h" 311541Srgrimes#include "at91rm9200_lowlevel.h" 321541Srgrimes 331541Srgrimes#define BAUD 115200 341541Srgrimes#define AT91C_US_ASYNC_MODE (AT91C_US_USMODE_NORMAL | AT91C_US_NBSTOP_1_BIT | \ 351541Srgrimes AT91C_US_PAR_NONE | AT91C_US_CHRL_8_BITS | AT91C_US_CLKS_CLOCK) 361541Srgrimes 37116182Sobrien/* 38116182Sobrien * void DefaultSystemInit(void) 39116182Sobrien * Load the system with sane values based on how the system is configured. 4013203Swollman * at91rm9200_lowlevel.h is expected to define the necessary parameters. 41101127Srwatson */ 42144613Sjeffvoid 4313203Swollman_init(void) 441541Srgrimes{ 452112Swollman AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU; 4669664Speter AT91PS_PDC pPDC = (AT91PS_PDC)&(pUSART->US_RPR); 4776166Smarkm 48101127Srwatson register unsigned value; 4989316Salfred volatile sdram_size_t *p = (sdram_size_t *)SDRAM_BASE; 501541Srgrimes 511541Srgrimes#ifdef BOOT_TSC 521541Srgrimes // For the TSC board, we turn ON the one LED we have while 531541Srgrimes // early in boot. 541541Srgrimes AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC10; 55141471Sjhb AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC10; 56144613Sjeff AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC10; 571541Srgrimes#endif 581541Srgrimes 591541Srgrimes // configure clocks 601541Srgrimes // assume: 61155334Srwatson // main osc = 10Mhz 62155334Srwatson // PLLB configured for 96MHz (48MHz after div) 6392751Sjeff // CSS = PLLB 6432011Sbde // set PLLA = 180MHz 65155168Sjeff // assume main osc = 10Mhz 66138345Sphk // div = 5 , out = 2 (150MHz = 240MHz) 67138345Sphk value = AT91C_BASE_CKGR->CKGR_PLLAR; 681541Srgrimes value &= ~(AT91C_CKGR_DIVA | AT91C_CKGR_OUTA | AT91C_CKGR_MULA); 6969664Speter value |= OSC_MAIN_FREQ_DIV | AT91C_CKGR_OUTA_2 | AT91C_CKGR_SRCA | 7069664Speter ((OSC_MAIN_MULT - 1) << 16); 7192751Sjeff AT91C_BASE_CKGR->CKGR_PLLAR = value; 7269664Speter 7369664Speter // wait for lock 7469664Speter while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA)) 7569664Speter continue; 7692654Sjeff 7792654Sjeff // change divider = 3, pres = 1 7869664Speter value = AT91C_BASE_PMC->PMC_MCKR; 7969664Speter value &= ~(AT91C_PMC_MDIV | AT91C_PMC_PRES); 8069664Speter value |= AT91C_PMC_MDIV_3 | AT91C_PMC_PRES_CLK; 8169664Speter AT91C_BASE_PMC->PMC_MCKR = value; 82144613Sjeff 83144613Sjeff // wait for update 84144613Sjeff while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) 85144613Sjeff continue; 86144613Sjeff 87144613Sjeff // change CSS = PLLA 88144613Sjeff value &= ~AT91C_PMC_CSS; 89144613Sjeff value |= AT91C_PMC_CSS_PLLA_CLK; 9069664Speter AT91C_BASE_PMC->PMC_MCKR = value; 91161010Srwatson 921541Srgrimes // wait for update 931541Srgrimes while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) 941541Srgrimes continue; 951541Srgrimes 961541Srgrimes#ifdef BOOT_KB9202 971541Srgrimes // setup flash access (allow ample margin) 981541Srgrimes // 9 wait states, 1 setup, 1 hold, 1 float for 8-bit device 991541Srgrimes ((AT91PS_SMC2)AT91C_BASE_SMC2)->SMC2_CSR[0] = 1001541Srgrimes AT91C_SMC2_WSEN | 1011541Srgrimes (9 & AT91C_SMC2_NWS) | 1021541Srgrimes ((1 << 8) & AT91C_SMC2_TDF) | 1031541Srgrimes AT91C_SMC2_DBW_8 | 1041541Srgrimes ((1 << 24) & AT91C_SMC2_RWSETUP) | 1051541Srgrimes ((1 << 29) & AT91C_SMC2_RWHOLD); 1061541Srgrimes#endif 1071541Srgrimes 1081541Srgrimes // setup SDRAM access 1091541Srgrimes // EBI chip-select register (CS1 = SDRAM controller) 1101541Srgrimes // 9 col, 13row, 4 bank, CAS2 111161011Srwatson // write recovery = 2 (Twr) 1121541Srgrimes // row cycle = 5 (Trc) 113161011Srwatson // precharge delay = 2 (Trp) 114161011Srwatson // row to col delay 2 (Trcd) 115161011Srwatson // active to precharge = 4 (Tras) 1161541Srgrimes // exit self refresh to active = 6 (Txsr) 1171541Srgrimes value = ((AT91PS_EBI)AT91C_BASE_EBI)->EBI_CSA; 1181541Srgrimes value &= ~AT91C_EBI_CS1A; 1191541Srgrimes value |= AT91C_EBI_CS1A_SDRAMC; 12083366Sjulian AT91C_BASE_EBI->EBI_CSA = value; 12183366Sjulian 122140714Sjeff AT91C_BASE_SDRC->SDRC_CR = 1231541Srgrimes AT91C_SDRC_NC_9 | 124150164Scsjp AT91C_SDRC_NR_13 | 125150164Scsjp AT91C_SDRC_NB_4_BANKS | 12691419Sjhb AT91C_SDRC_CAS_2 | 12783366Sjulian ((2 << 7) & AT91C_SDRC_TWR) | 12842408Seivind ((5 << 11) & AT91C_SDRC_TRC) | 12942453Seivind ((2 << 15) & AT91C_SDRC_TRP) | 13042408Seivind ((2 << 19) & AT91C_SDRC_TRCD) | 13142453Seivind ((4 << 23) & AT91C_SDRC_TRAS) | 132144613Sjeff ((6 << 27) & AT91C_SDRC_TXSR); 133144613Sjeff 13483366Sjulian // Step 1: We assume 200us of idle time. 1351541Srgrimes // Step 2: Issue an all banks precharge command 1361541Srgrimes AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_PRCGALL_CMD; 1371541Srgrimes *p = 0; 1381541Srgrimes 1391541Srgrimes // Step 3: Issue 8 Auto-refresh (CBR) cycles 1401541Srgrimes AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_RFSH_CMD; 141111119Simp *p = 0; 1421541Srgrimes *p = 0; 1431541Srgrimes *p = 0; 14436735Sdfr *p = 0; 1451541Srgrimes *p = 0; 1461541Srgrimes *p = 0; 14736735Sdfr *p = 0; 14820069Sbde *p = 0; 149155334Srwatson 150155334Srwatson // Step 4: Issue an Mode Set Register (MRS) cycle to program in 151155334Srwatson // the parameters that we setup in the SDRC_CR register above. 152155334Srwatson AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_LMR_CMD; 153155334Srwatson *p = 0; 154155334Srwatson 15520069Sbde // Step 5: set the refresh timer and access memory to start it 15620069Sbde // running. We have to wait 3 clocks after the LMR_CMD above, 15720069Sbde // and this fits the bill nicely. 15820069Sbde AT91C_BASE_SDRC->SDRC_TR = 7 * AT91C_MASTER_CLOCK / 1000000; 15920069Sbde *p = 0; 16020069Sbde 1611541Srgrimes // Step 6: Set normal mode. 16292751Sjeff AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_NORMAL_CMD; 163100613Srwatson *p = 0; 164100613Srwatson 165100613Srwatson#if SDRAM_WIDTH == AT91C_SDRC_DBW_32_BITS 166100613Srwatson // Turn on the upper 16 bits on the SDRAM bus. 1671541Srgrimes AT91C_BASE_PIOC->PIO_ASR = 0xffff0000; 1681541Srgrimes AT91C_BASE_PIOC->PIO_PDR = 0xffff0000; 1691541Srgrimes#endif 1701541Srgrimes // Configure DBGU -use local routine optimized for space 1711541Srgrimes AT91C_BASE_PIOA->PIO_ASR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; 17297994Sjhb AT91C_BASE_PIOA->PIO_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; 17397994Sjhb pUSART->US_IDR = (unsigned int) -1; 17497994Sjhb pUSART->US_CR = 17597994Sjhb AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS; 17697994Sjhb pUSART->US_BRGR = ((((AT91C_MASTER_CLOCK*10)/(BAUD*16))+5)/10); 1771541Srgrimes pUSART->US_TTGR = 0; 1781541Srgrimes pPDC->PDC_PTCR = AT91C_PDC_RXTDIS; 1791541Srgrimes pPDC->PDC_PTCR = AT91C_PDC_TXTDIS; 1801541Srgrimes pPDC->PDC_TNPR = 0; 1811541Srgrimes pPDC->PDC_TNCR = 0; 18289306Salfred 18333360Sdyson pPDC->PDC_RNPR = 0; 18451649Sphk pPDC->PDC_RNCR = 0; 18533360Sdyson 1861541Srgrimes pPDC->PDC_TPR = 0; 187140714Sjeff pPDC->PDC_TCR = 0; 1881541Srgrimes 18989306Salfred pPDC->PDC_RPR = 0; 1901541Srgrimes pPDC->PDC_RCR = 0; 1911541Srgrimes 1921541Srgrimes pPDC->PDC_PTCR = AT91C_PDC_RXTEN; 1931541Srgrimes pPDC->PDC_PTCR = AT91C_PDC_TXTEN; 1941541Srgrimes 1951541Srgrimes pUSART->US_MR = AT91C_US_ASYNC_MODE; 1961541Srgrimes pUSART->US_CR = AT91C_US_TXEN; 1971541Srgrimes pUSART->US_CR = AT91C_US_RXEN; 198140714Sjeff} 1991541Srgrimes