|
|
|
/*
|
|
|
|
* davinci.c - common DaVinci platform initialization
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Hugo Villeneuve <hugo@hugovil.com>
|
|
|
|
*
|
|
|
|
* Based on TI DaVinci Flash and Boot Utilities, original copyright follows:
|
|
|
|
* Copyright 2008 Texas Instruments, Inc. <www.ti.com>
|
|
|
|
*
|
|
|
|
* 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "davinci.h"
|
|
|
|
#include "ddr.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "uart.h"
|
|
|
|
#include "gpio.h"
|
|
|
|
|
|
|
|
extern enum bootmode_t bootmode;
|
|
|
|
extern const int8_t lpsc_en_list[];
|
|
|
|
extern const int8_t lpsc_emurstie_list[];
|
|
|
|
extern const size_t lpsc_en_list_len;
|
|
|
|
extern const size_t lpsc_emurstie_list_len;
|
|
|
|
|
|
|
|
/* Table of supported PLL settings */
|
|
|
|
#define PLL_DAVINCI_594_CFG 0
|
|
|
|
#define PLL_DAVINCI_810_CFG 1
|
|
|
|
static const struct pll_settings_t pll1_settings[] = {
|
|
|
|
{ 22 }, /* DSP=594 MHz ARM=297 MHz */
|
|
|
|
{ 30 }, /* DSP=810 MHz ARM=405 MHz */
|
|
|
|
};
|
|
|
|
static const struct pll_settings_t pll2_settings[] = {
|
|
|
|
{ 24 }, /* DDRPHY=324 MHz DDRCLK=162 MHz */
|
|
|
|
{ 28 }, /* DDRPHY=378 MHz DDRCLK=189 MHz */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Table of supported DDR devices */
|
|
|
|
#define DDR_MT47H32M16BN_3_162MHz_CFG 0
|
|
|
|
#define DDR_MT47H64M16HR_3IT_162MHz_CFG 1
|
|
|
|
#define DDR_MT47H64M16HR_3IT_189MHz_CFG 2
|
|
|
|
static const struct ddr_timing_infos_t ddr_timing_infos[] = {
|
|
|
|
{
|
|
|
|
/* Micron MT47H32M16BN-3 @ 162 MHz settings:
|
|
|
|
* TCK = 6.17 nS -> 1 / 162 MHz
|
|
|
|
* T_REF = 7.8 uS (varies with commercial vs industrial)
|
|
|
|
* T_RFC = 105 nS (varies with capacity)
|
|
|
|
* T_RP = 15 nS
|
|
|
|
* T_RCD = 15 nS
|
|
|
|
* T_WR = 15 nS
|
|
|
|
* T_RAS = 40 nS
|
|
|
|
* T_RASMAX = 70 uS
|
|
|
|
* T_RTP = 7.5 nS
|
|
|
|
* T_RC = 55 nS
|
|
|
|
* T_RRD = 10 nS
|
|
|
|
* T_WTR = 7.5 nS
|
|
|
|
* T_XSRD = 200 nS
|
|
|
|
* T_XSNR = 115 nS -> T_RFC(MIN) + 10
|
|
|
|
* T_CKE = 3 TCK
|
|
|
|
* T_XP = 2 TCK
|
|
|
|
*/
|
|
|
|
.SDBCR = SDBCR_DEFAULT
|
|
|
|
| (0 << 14) /* NM = 0; {32-bit bus with} */
|
|
|
|
| (3 << 9) /* CL = 3; */
|
|
|
|
| (2 << 4) /* IBANK = 2; {4 banks} */
|
|
|
|
| (2 << 0), /* PAGESIZE = 2; {1024-word} */
|
|
|
|
|
|
|
|
.SDTIMR = (16 << 25) /* T_RFC = 16; {(T_RFC * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 22) /* T_RP = 2; {(T_RP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 19) /* T_RCD = 2; {(T_RCD * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 16) /* T_WR = 2; {(T_WR * DDRCLK) - 1} */
|
|
|
|
| ( 6 << 11) /* T_RAS = 6; {(T_RAS * DDRCLK) - 1} */
|
|
|
|
| ( 8 << 6) /* T_RC = 8; {(T_RC * DDRCLK) - 1} */
|
|
|
|
| ( 1 << 3) /* T_RRD = 1; {(T_RRD * DDRCLK) - 1} */
|
|
|
|
| ( 1 << 0), /* T_WTR = 1; {(T_WTR * DDRCLK) - 1} */
|
|
|
|
|
|
|
|
.SDTIMR2 = ( 18 << 16) /* T_XSNR = 18; {(T_XSNR * DDRCLK) - 1} */
|
|
|
|
| (199 << 8) /* T_XSRD = 199; {T_XSRD - 1} */
|
|
|
|
| ( 1 << 5) /* T_RTP = 1; {(T_RTP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 0), /* T_CKE = 2; {T_CKE - 1} */
|
|
|
|
|
|
|
|
.SDRCR = 1265, /* RR = 1265; {DDRCLK * T_REF} */
|
|
|
|
|
|
|
|
.READ_Latency = 4,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Micron MT47H64M16HR-3IT @ 162 MHz settings:
|
|
|
|
* TCK = 6.17 nS -> 1 / 162 MHz
|
|
|
|
* T_REF = 3.9 uS (varies with commercial vs industrial)
|
|
|
|
* T_RFC = 127.5 nS (varies with capacity)
|
|
|
|
* T_RP = 15 nS
|
|
|
|
* T_RCD = 15 nS
|
|
|
|
* T_WR = 15 nS
|
|
|
|
* T_RAS = 40 nS
|
|
|
|
* T_RASMAX = 70 uS
|
|
|
|
* T_RTP = 7.5 nS
|
|
|
|
* T_RC = 55 nS
|
|
|
|
* T_RRD = 10 nS
|
|
|
|
* T_WTR = 7.5 nS
|
|
|
|
* T_XSRD = 200 nS
|
|
|
|
* T_XSNR = 138 nS -> T_RFC(MIN) + 10
|
|
|
|
* T_CKE = 3 TCK
|
|
|
|
* T_XP = 2 TCK
|
|
|
|
*/
|
|
|
|
.SDBCR = SDBCR_DEFAULT
|
|
|
|
| (0 << 14) /* NM = 0; {32-bit bus with} */
|
|
|
|
| (3 << 9) /* CL = 3; */
|
|
|
|
| (3 << 4) /* IBANK = 3; {8 banks} */
|
|
|
|
| (2 << 0), /* PAGESIZE = 2; {1024-word} */
|
|
|
|
|
|
|
|
.SDTIMR = (20 << 25) /* T_RFC = 20; {(T_RFC * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 22) /* T_RP = 2; {(T_RP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 19) /* T_RCD = 2; {(T_RCD * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 16) /* T_WR = 2; {(T_WR * DDRCLK) - 1} */
|
|
|
|
| ( 6 << 11) /* T_RAS = 6; {(T_RAS * DDRCLK) - 1} */
|
|
|
|
| ( 8 << 6) /* T_RC = 8; {(T_RC * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 3) /* T_RRD = 2; {[((4 * T_RRD) + (2 * TCK)) / (4 * TCK)] - 1} */
|
|
|
|
| ( 1 << 0), /* T_WTR = 1; {(T_WTR * DDRCLK) - 1} */
|
|
|
|
|
|
|
|
.SDTIMR2 = ( 32 << 16) /* T_XSNR = 32; {(T_XSNR * DDRCLK) - 1} */
|
|
|
|
| (199 << 8) /* T_XSRD = 199; {T_XSRD - 1} */
|
|
|
|
| ( 1 << 5) /* T_RTP = 1; {(T_RTP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 0), /* T_CKE = 2; {T_CKE - 1} */
|
|
|
|
|
|
|
|
.SDRCR = 632, /* RR = 632; {DDRCLK * T_REF} */
|
|
|
|
|
|
|
|
.READ_Latency = 4,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Micron MT47H64M16HR-3IT @ 189 MHz settings:
|
|
|
|
* TCK = 5.291 nS -> 1 / 189 MHz
|
|
|
|
* T_REF = 3.9 uS (varies with commercial vs industrial)
|
|
|
|
* T_RFC = 127.5 nS (varies with capacity)
|
|
|
|
* T_RP = 15 nS
|
|
|
|
* T_RCD = 15 nS
|
|
|
|
* T_WR = 15 nS
|
|
|
|
* T_RAS = 40 nS
|
|
|
|
* T_RASMAX = 70 uS
|
|
|
|
* T_RTP = 7.5 nS
|
|
|
|
* T_RC = 55 nS
|
|
|
|
* T_RRD = 10 nS
|
|
|
|
* T_WTR = 7.5 nS
|
|
|
|
* T_XSRD = 200 nS
|
|
|
|
* T_XSNR = 138 nS -> T_RFC(MIN) + 10
|
|
|
|
* T_CKE = 3 TCK
|
|
|
|
* T_XP = 2 TCK
|
|
|
|
*/
|
|
|
|
.SDBCR = SDBCR_DEFAULT
|
|
|
|
| (0 << 14) /* NM = 0; {32-bit bus with} */
|
|
|
|
| (3 << 9) /* CL = 3; */
|
|
|
|
| (3 << 4) /* IBANK = 3; {8 banks} */
|
|
|
|
| (2 << 0), /* PAGESIZE = 2; {1024-word} */
|
|
|
|
|
|
|
|
.SDTIMR = (24 << 25) /* T_RFC = 24; {(T_RFC * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 22) /* T_RP = 2; {(T_RP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 19) /* T_RCD = 2; {(T_RCD * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 16) /* T_WR = 2; {(T_WR * DDRCLK) - 1} */
|
|
|
|
| ( 7 << 11) /* T_RAS = 7; {(T_RAS * DDRCLK) - 1} */
|
|
|
|
| (10 << 6) /* T_RC = 10; {(T_RC * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 3) /* T_RRD = 2; {[((4 * T_RRD) + (2 * TCK)) / (4 * TCK)] - 1} */
|
|
|
|
| ( 1 << 0), /* T_WTR = 1; {(T_WTR * DDRCLK) - 1} */
|
|
|
|
|
|
|
|
.SDTIMR2 = ( 26 << 16) /* T_XSNR = 26; {(T_XSNR * DDRCLK) - 1} */
|
|
|
|
| (199 << 8) /* T_XSRD = 199; {T_XSRD - 1} */
|
|
|
|
| ( 1 << 5) /* T_RTP = 1; {(T_RTP * DDRCLK) - 1} */
|
|
|
|
| ( 2 << 0), /* T_CKE = 2; {T_CKE - 1} */
|
|
|
|
|
|
|
|
.SDRCR = 738, /* RR = 738; {DDRCLK * T_REF} */
|
|
|
|
|
|
|
|
.READ_Latency = 4,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Symbol from linker script */
|
|
|
|
extern uint32_t __DDR_START;
|
|
|
|
uint32_t DDR_SIZE = (128 << 20);
|
|
|
|
|
|
|
|
static void
|
|
|
|
pinmuxControl(uint32_t regOffset, uint32_t mask, uint32_t value)
|
|
|
|
{
|
|
|
|
SYSTEM->PINMUX[regOffset] &= ~mask;
|
|
|
|
SYSTEM->PINMUX[regOffset] |= (mask & value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lpsc_tansition(uint8_t module, uint8_t domain, uint8_t state)
|
|
|
|
{
|
|
|
|
/* Wait for any outstanding transition to complete */
|
|
|
|
while ((PSC->PTSTAT) & (0x00000001 << domain))
|
|
|
|
;
|
|
|
|
|
|
|
|
/* If we are already in that state, just return */
|
|
|
|
if (((PSC->MDSTAT[module]) & 0x1F) == state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Perform transition */
|
|
|
|
PSC->MDCTL[module] = ((PSC->MDCTL[module]) & (0xFFFFFFE0)) | (state);
|
|
|
|
PSC->PTCMD |= (0x00000001 << domain);
|
|
|
|
|
|
|
|
/* Wait for transition to complete */
|
|
|
|
while ((PSC->PTSTAT) & (0x00000001 << domain))
|
|
|
|
;
|
|
|
|
|
|
|
|
/* Wait and verify the state */
|
|
|
|
while (((PSC->MDSTAT[module]) & 0x1F) != state)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ivt_init(void)
|
|
|
|
{
|
|
|
|
volatile uint32_t *ivect;
|
|
|
|
extern uint32_t __IVT;
|
|
|
|
|
|
|
|
if (bootmode == NON_SECURE_NOR) {
|
|
|
|
ivect = &(__IVT);
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Reset @ 0x00*/
|
|
|
|
} else
|
|
|
|
ivect = &(__IVT) + 4;
|
|
|
|
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Undefined Address @ 0x04 */
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Software Interrupt @0x08 */
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Pre-Fetch Abort @ 0x0C */
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Data Abort @ 0x10 */
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* Reserved @ 0x14 */
|
|
|
|
*ivect++ = 0xEAFFFFFE; /* IRQ @ 0x18 */
|
|
|
|
*ivect = 0xEAFFFFFE; /* FIQ @ 0x1C */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
timer0_start(uint32_t period)
|
|
|
|
{
|
|
|
|
TIMER0->TGCR = 0x00000000; /* Reset timer */
|
|
|
|
TIMER0->TCR = 0x00000000; /* Disable timer */
|
|
|
|
TIMER0->PRD12 = period;
|
|
|
|
AINTC->IRQ1 |= 0x00000001; /* Clear interrupt */
|
|
|
|
TIMER0->TIM12 = 0x00000000; /* Reset timer count to zero */
|
|
|
|
TIMER0->TCR = 0x00000040; /* Setup for one-shot mode */
|
|
|
|
TIMER0->TGCR = 0x00000005; /* Start TIMER12 in 32-bits mode. */
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
timer0_status(void)
|
|
|
|
{
|
|
|
|
return AINTC->IRQ1 & 0x1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
uart0_init(void)
|
|
|
|
{
|
|
|
|
UART0->PWREMU_MGNT = 0; /* Reset UART TX & RX components */
|
|
|
|
waitloop(100);
|
|
|
|
|
|
|
|
/* Set DLAB bit - allows setting of clock divisors */
|
|
|
|
UART0->LCR |= 0x80;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute divisor value. Normally, we should simply return:
|
|
|
|
* SYSTEM_CLK_HZ / (16 * baudrate)
|
|
|
|
* but we need to round that value by adding 0.5.
|
|
|
|
* Rounding is especially important at high baud rates.
|
|
|
|
*/
|
|
|
|
UART0->DLL = (SYSTEM_CLK_HZ + (UART_BAUDRATE * (UART_BCLK_RATIO / 2))) /
|
|
|
|
(UART_BCLK_RATIO * UART_BAUDRATE);
|
|
|
|
UART0->DLH = 0x00;
|
|
|
|
|
|
|
|
UART0->FCR = 0x0007; /* Clear UART TX & RX FIFOs */
|
|
|
|
UART0->MCR = 0x0000; /* RTS & CTS disabled,
|
|
|
|
* Loopback mode disabled,
|
|
|
|
* Autoflow disabled
|
|
|
|
*/
|
|
|
|
|
|
|
|
UART0->LCR = 0x0003; /* Clear DLAB bit
|
|
|
|
* 8-bit words,
|
|
|
|
* 1 STOP bit generated,
|
|
|
|
* No Parity, No Stick paritiy,
|
|
|
|
* No Break control
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Enable receiver, transmitter, set to run. */
|
|
|
|
UART0->PWREMU_MGNT |= 0x6001;
|
|
|
|
|
|
|
|
return E_PASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pll_init(volatile struct pll_regs_t *pll, int pll_mult, int plldiv_ratio[5])
|
|
|
|
{
|
|
|
|
int k;
|
|
|
|
volatile uint32_t *plldiv_reg[5];
|
|
|
|
int pll_is_powered_up =
|
|
|
|
(pll->PLLCTL & DEVICE_PLLCTL_PLLPWRDN_MASK) >> 1;
|
|
|
|
|
|
|
|
plldiv_reg[0] = &pll->PLLDIV1;
|
|
|
|
plldiv_reg[1] = &pll->PLLDIV2;
|
|
|
|
plldiv_reg[2] = &pll->PLLDIV3;
|
|
|
|
plldiv_reg[3] = &pll->PLLDIV4;
|
|
|
|
plldiv_reg[4] = &pll->PLLDIV5;
|
|
|
|
|
|
|
|
/* Set PLL clock input to internal osc. */
|
|
|
|
pll->PLLCTL &= ~(DEVICE_PLLCTL_CLKMODE_MASK);
|
|
|
|
|
|
|
|
/* Set PLL to bypass, then wait for PLL to stabilize */
|
|
|
|
pll->PLLCTL &= ~(DEVICE_PLLCTL_PLLENSRC_MASK |
|
|
|
|
DEVICE_PLLCTL_PLLEN_MASK);
|
|
|
|
waitloop(150);
|
|
|
|
|
|
|
|
/* Reset PLL: Warning, bit state is inverted for DM644x vs DM35x. */
|
|
|
|
#if defined(DM644x)
|
|
|
|
pll->PLLCTL &= ~DEVICE_PLLCTL_PLLRST_MASK;
|
|
|
|
#elif defined(DM35x)
|
|
|
|
pll->PLLCTL |= DEVICE_PLLCTL_PLLRST_MASK;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (pll_is_powered_up) {
|
|
|
|
/* Disable PLL */
|
|
|
|
pll->PLLCTL |= DEVICE_PLLCTL_PLLDIS_MASK;
|
|
|
|
|
|
|
|
/* Powerup PLL */
|
|
|
|
pll->PLLCTL &= ~(DEVICE_PLLCTL_PLLPWRDN_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable PLL */
|
|
|
|
pll->PLLCTL &= ~(DEVICE_PLLCTL_PLLDIS_MASK);
|
|
|
|
|
|
|
|
/* Wait for PLL to stabilize */
|
|
|
|
waitloop(150);
|
|
|
|
|
|
|
|
/* Load PLL multiplier. */
|
|
|
|
pll->PLLM = (pll_mult - 1) & 0xff;
|
|
|
|
|
|
|
|
/* Set and enable dividers as needed. */
|
|
|
|
for (k = 0; k < 5; k++) {
|
|
|
|
if (plldiv_ratio[k] > 0)
|
|
|
|
*(plldiv_reg[k]) |= DEVICE_PLLDIV_EN_MASK |
|
|
|
|
(plldiv_ratio[k] - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(DM35x)
|
|
|
|
/* Set the processor AIM wait state and PLL1 post-divider to to 1 */
|
|
|
|
SYSTEM->MISC &= ~(DEVICE_MISC_PLL1POSTDIV_MASK |
|
|
|
|
DEVICE_MISC_AIMWAITST_MASK);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Initiate a new divider transition. */
|
|
|
|
pll->PLLCMD |= DEVICE_PLLCMD_GOSET_MASK;
|
|
|
|
|
|
|
|
/* Wait for completion of phase alignment. */
|
|
|
|
while ((pll->PLLSTAT & DEVICE_PLLSTAT_GOSTAT_MASK))
|
|
|
|
;
|
|
|
|
|
|
|
|
/* Wait for PLL to reset ( ~5 usec ) */
|
|
|
|
waitloop(5000);
|
|
|
|
|
|
|
|
/* Release PLL from reset */
|
|
|
|
|
|
|
|
/* Reset PLL: Warning, bit state is inverted for DM644x vs DM35x. */
|
|
|
|
#if defined(DM644x)
|
|
|
|
pll->PLLCTL |= DEVICE_PLLCTL_PLLRST_MASK;
|
|
|
|
#elif defined(DM35x)
|
|
|
|
pll->PLLCTL &= ~DEVICE_PLLCTL_PLLRST_MASK;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Wait for PLL to re-lock:
|
|
|
|
* DM644z: 2000P
|
|
|
|
* DM35x: 8000P
|
|
|
|
*/
|
|
|
|
waitloop(8000);
|
|
|
|
|
|
|
|
/* Switch out of BYPASS mode */
|
|
|
|
pll->PLLCTL |= DEVICE_PLLCTL_PLLEN_MASK;
|
|
|
|
|
|
|
|
return E_PASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pll1_init(int cfg)
|
|
|
|
{
|
|
|
|
int plldiv_ratio[5];
|
|
|
|
|
|
|
|
#if defined(DM644x)
|
|
|
|
plldiv_ratio[0] = 1; /* PLLDIV1 fixed */
|
|
|
|
plldiv_ratio[1] = 2; /* PLLDIV2 fixed */
|
|
|
|
plldiv_ratio[2] = 3; /* PLLDIV3 fixed */
|
|
|
|
plldiv_ratio[3] = -1; /* PLLDIV4 not used */
|
|
|
|
plldiv_ratio[4] = 6; /* PLLDIV5 fixed */
|
|
|
|
#elif defined(DM35x)
|
|
|
|
plldiv_ratio[0] = 2; /* PLLDIV1 fixed */
|
|
|
|
plldiv_ratio[1] = 4; /* PLLDIV2 fixed */
|
|
|
|
|
|
|
|
/* Calculate PLL divider ratio for divider 3 (feeds VPBE) */
|
|
|
|
plldiv_ratio[2] = 0;
|
|
|
|
while ((plldiv_ratio[2] * VPBE_CLK_HZ) <
|
|
|
|
(SYSTEM_CLK_HZ * (pll1_settings[cfg].mult >> 3)))
|
|
|
|
plldiv_ratio[2]++;
|
|
|
|
|
|
|
|
/* Check to make sure we can supply accurate VPBE clock */
|
|
|
|
if ((plldiv_ratio[2] * VPBE_CLK_HZ) !=
|
|
|
|
(SYSTEM_CLK_HZ * (pll1_settings[cfg].mult >> 3)))
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
/* See the device datasheet for more info (must be 2 or 4) */
|
|
|
|
plldiv_ratio[3] = 4;
|
|
|
|
plldiv_ratio[4] = -1; /* PLLDIV5 not used */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return pll_init(PLL1, pll1_settings[cfg].mult, plldiv_ratio);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pll2_init(int cfg)
|
|
|
|
{
|
|
|
|
int plldiv_ratio[5];
|
|
|
|
|
|
|
|
plldiv_ratio[0] = PLL2_Div1;
|
|
|
|
plldiv_ratio[1] = PLL2_Div2;
|
|
|
|
plldiv_ratio[2] = -1; /* PLLDIV3 not used */
|
|
|
|
plldiv_ratio[3] = -1; /* PLLDIV4 not used */
|
|
|
|
plldiv_ratio[4] = -1; /* PLLDIV5 not used */
|
|
|
|
|
|
|
|
return pll_init(PLL2, pll2_settings[cfg].mult, plldiv_ratio);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ddr_timing_setup(int cfg)
|
|
|
|
{
|
|
|
|
/* The configuration of DDRPHYCR is not dependent on the DDR2 device
|
|
|
|
* specification but rather on the board layout.
|
|
|
|
* Setup the read latency and clear DLLPWRDN */
|
|
|
|
DDR->DDRPHYCR = DDRPHYCR_DEFAULT |
|
|
|
|
(ddr_timing_infos[cfg].READ_Latency & DDRPHYCR_READLAT_MASK);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the PR_OLD_COUNT bits in the Bus Burst Priority Register (PBBPR)
|
|
|
|
* as suggested in TMS320DM6446 errata 2.1.2:
|
|
|
|
*
|
|
|
|
* On DM6446 Silicon Revision 2.1 and earlier, under certain conditions
|
|
|
|
* low priority modules can occupy the bus and prevent high priority
|
|
|
|
* modules like the VPSS from getting the required DDR2 throughput.
|
|
|
|
*/
|
|
|
|
DDR->PBBPR = DDR_PBBPR_PR_OLD_COUNT;
|
|
|
|
|
|
|
|
/* TIMUNLOCK (unlocked), CAS Latency, number of banks and page size */
|
|
|
|
DDR->SDBCR = SDBCR_TIMUNLOCK | ddr_timing_infos[cfg].SDBCR;
|
|
|
|
|
|
|
|
/* Program timing registers */
|
|
|
|
DDR->SDTIMR = ddr_timing_infos[cfg].SDTIMR;
|
|
|
|
DDR->SDTIMR2 = ddr_timing_infos[cfg].SDTIMR2;
|
|
|
|
|
|
|
|
/* Clear the TIMUNLOCK bit (locked) */
|
|
|
|
DDR->SDBCR &= ~SDBCR_TIMUNLOCK;
|
|
|
|
|
|
|
|
/* Set the refresh rate */
|
|
|
|
DDR->SDRCR = ddr_timing_infos[cfg].SDRCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ddr_reset(void)
|
|
|
|
{
|
|
|
|
/* Perform a soft reset to the DDR2 memory controller:
|
|
|
|
* Put in SYNCRESET and enable it again. */
|
|
|
|
lpsc_tansition(LPSC_DDR2, PD0, PSC_SYNCRESET);
|
|
|
|
lpsc_tansition(LPSC_DDR2, PD0, PSC_ENABLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ddr_init(int cfg)
|
|
|
|
{
|
|
|
|
volatile uint32_t *ddr_start = &__DDR_START;
|
|
|
|
/* For reading/writing dummy value in order to apply timing settings */
|
|
|
|
volatile uint32_t ddr_dummy_read;
|
|
|
|
|
|
|
|
/* Enable DDR2 module. */
|
|
|
|
lpsc_tansition(LPSC_DDR2, PD0, PSC_ENABLE);
|
|
|
|
|
|
|
|
#if defined(DM35x)
|
|
|
|
ddr_vtp_calibration();
|
|
|
|
ddr_reset();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ddr_timing_setup(cfg);
|
|
|
|
|
|
|
|
/* Dummy read to apply timing settings */
|
|
|
|
ddr_dummy_read = ddr_start[0];
|
|
|
|
|
|
|
|
#if defined(DM644x)
|
|
|
|
ddr_reset();
|
|
|
|
ddr_vtp_calibration();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Verify correct initialization. */
|
|
|
|
ddr_start[0] = DDR_TEST_PATTERN;
|
|
|
|
if (ddr_start[0] != DDR_TEST_PATTERN) {
|
|
|
|
log_fail("DDR init failed");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E_PASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psc_init(void)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
#if defined(DM35x)
|
|
|
|
/* Do always on power domain transitions */
|
|
|
|
while ((PSC->PTSTAT) & 0x00000001);
|
|
|
|
#elif defined(DM644x)
|
|
|
|
/*
|
|
|
|
* Workaround for TMS320DM6446 errata 1.3.22
|
|
|
|
* (Revision(s) Affected: 1.3 and earlier):
|
|
|
|
* PSC: PTSTAT Register Does Not Clear After Warm/Maximum Reset.
|
|
|
|
* Clear the reserved location at address 0x01C41A20
|
|
|
|
*/
|
|
|
|
PSC_PTSTAT_WORKAROUND_REG = 0;
|
|
|
|
|
|
|
|
/* Put the C64x+ Core into reset (if it's on) */
|
|
|
|
PSC->MDCTL[LPSC_DSP] &= (~0x00000100);
|
|
|
|
PSC->PTCMD |= 0x00000002;
|
|
|
|
while ((PSC->PTSTAT) & (0x00000002));
|
|
|
|
while ((PSC->MDSTAT[LPSC_DSP]) & (0x00000100));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Enable selected modules */
|
|
|
|
for (i = 0; i < lpsc_en_list_len; i++) {
|
|
|
|
int8_t k = lpsc_en_list[i];
|
|
|
|
|
|
|
|
PSC->MDCTL[k] = (PSC->MDCTL[k] & 0xFFFFFFE0) | PSC_ENABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set EMURSTIE on selected modules */
|
|
|
|
for (i = 0; i < lpsc_emurstie_list_len; i++) {
|
|
|
|
int8_t k = lpsc_emurstie_list[i];
|
|
|
|
|
|
|
|
PSC->MDCTL[k] |= EMURSTIE_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Do Always-On Power Domain Transitions */
|
|
|
|
PSC->PTCMD |= 0x00000001;
|
|
|
|
while ((PSC->PTSTAT) & 0x00000001);
|
|
|
|
|
|
|
|
#if defined(DM644x)
|
|
|
|
/* DO DSP Power Domain Transitions */
|
|
|
|
PSC->PTCMD |= 0x00000002;
|
|
|
|
while ((PSC->PTSTAT) & (0x00000002));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Clear EMURSTIE on selected modules */
|
|
|
|
for (i = 0; i < lpsc_emurstie_list_len; i++) {
|
|
|
|
int8_t k = lpsc_emurstie_list[i];
|
|
|
|
|
|
|
|
PSC->MDCTL[k] &= (~EMURSTIE_MASK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
davinci_platform_init(char *version, int *nwp_nand)
|
|
|
|
{
|
|
|
|
int pllCfg;
|
|
|
|
int ddrCfg;
|
|
|
|
int status = E_PASS;
|
|
|
|
unsigned *gpio01 = (unsigned *)(DAVINCI_GPIO_BASE + 0x20);
|
|
|
|
|
|
|
|
*nwp_nand = 0;
|
|
|
|
|
|
|
|
psc_init();
|
|
|
|
|
|
|
|
/* Disable ARM interrupts */
|
|
|
|
AINTC->INTCTL = 0x0;
|
|
|
|
AINTC->EABASE = 0x0;
|
|
|
|
AINTC->EINT0 = 0x0;
|
|
|
|
AINTC->EINT1 = 0x0;
|
|
|
|
|
|
|
|
AINTC->FIQ0 = 0xFFFFFFFF;
|
|
|
|
AINTC->FIQ1 = 0xFFFFFFFF;
|
|
|
|
AINTC->IRQ0 = 0xFFFFFFFF;
|
|
|
|
AINTC->IRQ1 = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
#ifdef PINMUX0_DEFAULT
|
|
|
|
pinmuxControl(0, 0xFFFFFFFF, PINMUX0_DEFAULT);
|
|
|
|
#endif
|
|
|
|
#ifdef PINMUX1_DEFAULT
|
|
|
|
pinmuxControl(1, 0xFFFFFFFF, PINMUX1_DEFAULT);
|
|
|
|
#endif
|
|
|
|
/* The folowing are only available on DM35x */
|
|
|
|
#ifdef PINMUX2_DEFAULT
|
|
|
|
pinmuxControl(2, 0xFFFFFFFF, PINMUX2_DEFAULT);
|
|
|
|
#endif
|
|
|
|
#ifdef PINMUX3_DEFAULT
|
|
|
|
pinmuxControl(3, 0xFFFFFFFF, PINMUX3_DEFAULT);
|
|
|
|
#endif
|
|
|
|
#ifdef PINMUX4_DEFAULT
|
|
|
|
pinmuxControl(4, 0xFFFFFFFF, PINMUX4_DEFAULT);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Init board configuration */
|
|
|
|
#if defined(board_sysmobts_v2)
|
|
|
|
char boardVer;
|
|
|
|
char boardCfg;
|
|
|
|
boardCfg = (*gpio01 >> 10) & 0x001F;
|
|
|
|
boardVer = (*gpio01 >> 15) & 0x0007;
|
|
|
|
if (boardVer >= 5)
|
|
|
|
{
|
|
|
|
uart_send_str_lf("Board needs GPIO for nWP");
|
|
|
|
*nwp_nand = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( boardVer > 1 )
|
|
|
|
{
|
|
|
|
/* Davinci @ 405/810 MHz */
|
|
|
|
pllCfg = PLL_DAVINCI_810_CFG;
|
|
|
|
|
|
|
|
/* Micron MT47H64M16HR-3IT @ 189 MHz */
|
|
|
|
ddrCfg = DDR_MT47H64M16HR_3IT_189MHz_CFG;
|
|
|
|
|
|
|
|
uart_send_str_lf("CPU: Davinci @ 405/810 MHz");
|
|
|
|
uart_send_str_lf("DDR: Micron MT47H64M16HR-3IT @ 189 MHz");
|
|
|
|
} else if ( (boardVer == 1) && ((boardCfg == 0x02) || (boardCfg == 0x04) || (boardCfg == 0x05)) )
|
|
|
|
{
|
|
|
|
/* Davinci @ 405/810 MHz */
|
|
|
|
pllCfg = PLL_DAVINCI_810_CFG;
|
|
|
|
|
|
|
|
/* Micron MT47H64M16HR-3IT @ 189 MHz */
|
|
|
|
ddrCfg = DDR_MT47H64M16HR_3IT_189MHz_CFG;
|
|
|
|
|
|
|
|
uart_send_str_lf("CPU: Davinci @ 405/810 MHz");
|
|
|
|
uart_send_str_lf("DDR: Micron MT47H64M16HR-3IT @ 189 MHz");
|
|
|
|
}
|
|
|
|
else if ( (boardVer == 0) && (boardCfg != 0x00) )
|
|
|
|
{
|
|
|
|
DDR_SIZE = (256 << 20);
|
|
|
|
|
|
|
|
/* Davinci @ 297/594 MHz */
|
|
|
|
pllCfg = PLL_DAVINCI_594_CFG;
|
|
|
|
|
|
|
|
/* Micron MT47H32M16BN-3 @ 162 MHz */
|
|
|
|
ddrCfg = DDR_MT47H64M16HR_3IT_162MHz_CFG;
|
|
|
|
|
|
|
|
uart_send_str_lf("CPU: Davinci @ 297/594 MHz");
|
|
|
|
uart_send_str_lf("DDR: Micron MT47H32M16BN-3 @ 162 MHz");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#if defined(board_sysmobts_v2)
|
|
|
|
DDR_SIZE = (256 << 20);
|
|
|
|
#else
|
|
|
|
DDR_SIZE = (128 << 20);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Davinci @ 297/594 MHz */
|
|
|
|
pllCfg = PLL_DAVINCI_594_CFG;
|
|
|
|
|
|
|
|
/* Micron MT47H32M16BN-3 @ 162 MHz */
|
|
|
|
ddrCfg = DDR_MT47H32M16BN_3_162MHz_CFG;
|
|
|
|
|
|
|
|
uart_send_str_lf("CPU: Davinci @ 297/594 MHz");
|
|
|
|
uart_send_str_lf("DDR: Micron MT47H32M16BN-3 @ 162 MHz");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == E_PASS)
|
|
|
|
status |= pll1_init(pllCfg);
|
|
|
|
|
|
|
|
if (status == E_PASS)
|
|
|
|
status |= uart0_init();
|
|
|
|
|
|
|
|
uart_send_lf();
|
|
|
|
log_info(version);
|
|
|
|
|
|
|
|
#if defined(board_sysmobts_v2)
|
|
|
|
char str[4];
|
|
|
|
uart_send_str("Board revision: ");
|
|
|
|
str[0] = 'A' + boardVer;
|
|
|
|
str[1] = '.';
|
|
|
|
str[2] = '0' + boardCfg;
|
|
|
|
str[3] = '\0';
|
|
|
|
uart_send_str_lf(str);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (status == E_PASS)
|
|
|
|
status |= pll2_init(pllCfg);
|
|
|
|
|
|
|
|
if (status == E_PASS)
|
|
|
|
status |= ddr_init(ddrCfg);
|
|
|
|
|
|
|
|
#ifdef STATUS_LED
|
|
|
|
gpio_direction_out(STATUS_LED, 1);
|
|
|
|
#endif /* STATUS_LED */
|
|
|
|
|
|
|
|
#ifdef board_minidas
|
|
|
|
gpio_direction_out(FAN, 0);
|
|
|
|
gpio_direction_out(BUZZER, 0);
|
|
|
|
|
|
|
|
/* Put all peripherals in RESET state */
|
|
|
|
gpio_direction_out(DSP1_PWR_ENA, 0);
|
|
|
|
gpio_direction_out(DSP2_PWR_ENA, 0);
|
|
|
|
gpio_direction_out(WIFI_RESETn, 0);
|
|
|
|
gpio_direction_out(GPS_RESETn, 0);
|
|
|
|
gpio_direction_out(CAN_RESETn, 0);
|
|
|
|
gpio_direction_out(ATA_RESETn, 0);
|
|
|
|
gpio_direction_out(CAMERA_RESETn, 0);
|
|
|
|
|
|
|
|
/* Enable power for hard disk */
|
|
|
|
gpio_direction_out(HDD_ENA, 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* IRQ Vector Table Setup */
|
|
|
|
ivt_init();
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|