Commit 514d2c27 authored by Alexander Potashev's avatar Alexander Potashev
Browse files

RT75957. twr-k70f120m: configure the DDR controller for synchronous mode

There are 3 ports (port 0, port 1, port 2) between the AHB bus and the
DDR controller. All of these ports are switched to the synchronous mode
in this patch.

Any of these 3 ports can work in the synchronous mode only when the
system clock is sourced from PLL1. Since the DDR clock is also sourced
from the PLL1 and the CPU clock rate is limited to 120 MHz, we have to
lower the DDR clock to the same 120 MHz.

The source code is configurable so that you can easily switch back to
the DDR asynchronous mode:
 * Synchronous mode configuration (see include/configs/twr-k70f120m.h):
    * KINETIS_PLL1_VDIV = 24 (we have to limit DDR clock to 120 MHz)
    * KINETIS_MCGOUT_PLL1 is set (system clock is sourced from PLL1)
    * CONFIG_KINETIS_DDR_SYNC is set
 * Asynchronous mode configuration (see include/configs/twr-k70f120m.h):
    * KINETIS_PLL1_VDIV = 30 (we want the maximum DDR clock: 150 MHz)
    * KINETIS_MCGOUT_PLL1 is not set (system clock is sourced from PLL0)
    * CONFIG_KINETIS_DDR_SYNC is not set

The DDR synchronous mode improves performance: 37.27 BogoMIPS in
synchronous mode (DDR @ 120 MHz) against 11.03 BogoMIPS in asynchronous
mode (DDR @ 150 MHz) in Linux.
parent 75b99c96
......@@ -213,6 +213,7 @@ struct kinetis_ddr_regs {
* DDR Control Register 40 (DDR_CR40)
*/
#define KINETIS_DDR_CR40_P1WRCNT_BITS 8
#define KINETIS_DDR_CR40_P0TYP_BITS 0
/*
* DDR Control Register 41 (DDR_CR41)
*/
......@@ -223,12 +224,17 @@ struct kinetis_ddr_regs {
* DDR Control Register 42 (DDR_CR42)
*/
#define KINETIS_DDR_CR42_P2WRCNT_BITS 8
#define KINETIS_DDR_CR42_P1TYP_BITS 0
/*
* DDR Control Register 43 (DDR_CR43)
*/
#define KINETIS_DDR_CR43_WP2_BITS 24
#define KINETIS_DDR_CR43_RP2_BITS 16
#define KINETIS_DDR_CR43_P2RDCNT_BITS 0
/*
* DDR Control Register 44 (DDR_CR44)
*/
#define KINETIS_DDR_CR44_P2TYP_BITS 0
/*
* DDR Control Register 45 (DDR_CR45)
*/
......@@ -517,6 +523,26 @@ int misc_init_r(void)
#define KINETIS_DDR_P2PRI2 1
#define KINETIS_DDR_P2PRIRLX 100
/*
* Port types: synchronous, asynchronous.
* See DDR registers bit fields: CR40[P0TYP], CR42[P1TYP], CR44[P2TYP].
*/
#define KINETIS_DDR_PORT_ASYNC 0
#define KINETIS_DDR_PORT_SYNC 3
/*
* Actual port types
*/
#ifdef CONFIG_KINETIS_DDR_SYNC
#define KINETIS_DDR_P0TYP KINETIS_DDR_PORT_SYNC
#define KINETIS_DDR_P1TYP KINETIS_DDR_PORT_SYNC
#define KINETIS_DDR_P2TYP KINETIS_DDR_PORT_SYNC
#else
#define KINETIS_DDR_P0TYP KINETIS_DDR_PORT_ASYNC
#define KINETIS_DDR_P1TYP KINETIS_DDR_PORT_ASYNC
#define KINETIS_DDR_P2TYP KINETIS_DDR_PORT_ASYNC
#endif /* CONFIG_KINETIS_DDR_SYNC */
/*
* Other SDRAM configuration options
*/
......@@ -734,18 +760,21 @@ int dram_init(void)
(KINETIS_DDR_RP0 << KINETIS_DDR_CR39_RP0_BITS) |
(KINETIS_DDR_P0RDCNT << KINETIS_DDR_CR39_P0RDCNT_BITS);
KINETIS_DDR->cr[40] =
(KINETIS_DDR_P1WRCNT << KINETIS_DDR_CR40_P1WRCNT_BITS);
(KINETIS_DDR_P1WRCNT << KINETIS_DDR_CR40_P1WRCNT_BITS) |
(KINETIS_DDR_P0TYP << KINETIS_DDR_CR40_P0TYP_BITS);
KINETIS_DDR->cr[41] =
(KINETIS_DDR_WP1 << KINETIS_DDR_CR41_WP1_BITS) |
(KINETIS_DDR_RP1 << KINETIS_DDR_CR41_RP1_BITS) |
(KINETIS_DDR_P1RDCNT << KINETIS_DDR_CR41_P1RDCNT_BITS);
KINETIS_DDR->cr[42] =
(KINETIS_DDR_P2WRCNT << KINETIS_DDR_CR42_P2WRCNT_BITS);
(KINETIS_DDR_P2WRCNT << KINETIS_DDR_CR42_P2WRCNT_BITS) |
(KINETIS_DDR_P1TYP << KINETIS_DDR_CR42_P1TYP_BITS);
KINETIS_DDR->cr[43] =
(KINETIS_DDR_WP2 << KINETIS_DDR_CR43_WP2_BITS) |
(KINETIS_DDR_RP2 << KINETIS_DDR_CR43_RP2_BITS) |
(KINETIS_DDR_P2RDCNT << KINETIS_DDR_CR43_P2RDCNT_BITS);
KINETIS_DDR->cr[44] = 0;
KINETIS_DDR->cr[44] =
(KINETIS_DDR_P2TYP << KINETIS_DDR_CR44_P2TYP_BITS);
KINETIS_DDR->cr[45] =
(KINETIS_DDR_P0PRI3 << KINETIS_DDR_CR45_P0PRI3_BITS) |
(KINETIS_DDR_P0PRI2 << KINETIS_DDR_CR45_P0PRI2_BITS) |
......
......@@ -94,6 +94,10 @@
#undef KINETIS_MCG_PLLREFSEL /* No support for multiple oscillators */
#ifdef KINETIS_MCGOUT_PLL1
#error There is no PLL1 on the Kinetis K60@100MHz MCUs
#endif
#elif defined(CONFIG_KINETIS_K70_120MHZ)
#define KINETIS_PLL_PRDIV_MAX 8
#define KINETIS_PLL_VDIV_MIN 16
......@@ -110,7 +114,7 @@
#define KINETIS_FLASH_RATE_MAX (25 * 1000 * 1000) /* 25 MHz */
#define KINETIS_DDR_RATE_MAX (150 * 1000 * 1000) /* 150 MHz */
#define KINETIS_MCG_PLLREFSEL 0 /* PLL0 input: EXTAL0 through OSC0 */
#define KINETIS_MCG_PLLREFSEL 0 /* PLL0/1 input: EXTAL0 through OSC0 */
#else
#error Unsupported Freescale Kinetis MCU series
......@@ -146,9 +150,15 @@
/*
* MCGOUTCLK rate
*/
#ifdef KINETIS_MCGOUT_PLL1
#define KINETIS_MCGOUT_RATE \
(KINETIS_MCG_PLL_IN_RATE / KINETIS_PLL1_PRDIV * KINETIS_PLL1_VDIV / \
KINETIS_PLL_VCO_DIV)
#else
#define KINETIS_MCGOUT_RATE \
(KINETIS_MCG_PLL_IN_RATE / KINETIS_PLL_PRDIV * KINETIS_PLL_VDIV / \
KINETIS_PLL_VCO_DIV)
#endif /* KINETIS_MCGOUT_PLL1 */
#if !defined(CONFIG_KINETIS_K60_100MHZ)
/*
......@@ -274,6 +284,8 @@
#define KINETIS_MCG_C5_PRDIV_BITS 0
/* PLL Stop Enable */
#define KINETIS_MCG_C5_PLLSTEN_MSK (1 << 5)
/* PLL0 Clock Enable */
#define KINETIS_MCG_C5_PLLCLKEN_MSK (1 << 6)
/* PLL External Reference Select (for K70@120MHz) */
#define KINETIS_MCG_C5_PLLREFSEL_BIT 7
#define KINETIS_MCG_C5_PLLREFSEL_MSK (1 << KINETIS_MCG_C5_PLLREFSEL_BIT)
......@@ -289,10 +301,15 @@
*/
/* PLL1 External Reference Divider */
#define KINETIS_MCG_C11_PRDIV_BITS 0
/* PLL Clock Select: PLL0 or PLL1 */
#define KINETIS_MCG_C11_PLLCS_MSK (1 << 4)
/* PLL1 Stop Enable */
#define KINETIS_MCG_C11_PLLSTEN1_MSK (1 << 5)
/* PLL1 Clock Enable */
#define KINETIS_MCG_C11_PLLCLKEN1_MSK (1 << 6)
/* PLL1 External Reference Select (for K70@120MHz) */
#define KINETIS_MCG_C11_PLLREFSEL1_BIT 7
#define KINETIS_MCG_C11_PLLREFSEL1_MSK (1 << KINETIS_MCG_C11_PLLREFSEL1_BIT)
/*
* MCG Control 12 Register
*/
......@@ -325,6 +342,27 @@
/*
* SIM registers
*/
/*
* System Options Register 2
*/
/*
* Selects the clock divider source for NFC flash clock
*/
#define KINETIS_SIM_SOPT2_NFCSRC_BITS 30
#define KINETIS_SIM_SOPT2_NFCSRC_MSK (3 << KINETIS_SIM_SOPT2_NFCSRC_BITS)
/* MCGPLL0CLK */
#define KINETIS_SIM_SOPT2_NFCSRC_PLL0 (1 << KINETIS_SIM_SOPT2_NFCSRC_BITS)
/* MCGPLL1CLK */
#define KINETIS_SIM_SOPT2_NFCSRC_PLL1 (2 << KINETIS_SIM_SOPT2_NFCSRC_BITS)
/*
* NFC Flash clock select
*/
#define KINETIS_SIM_SOPT2_NFC_CLKSEL_MSK (1 << 15)
/* Clock divider NFC clock */
#define KINETIS_SIM_SOPT2_NFC_CLKSEL_NFCDIV 0
/* EXTAL1 clock */
#define KINETIS_SIM_SOPT2_NFC_CLKSEL_EXTAL1 KINETIS_SIM_SOPT2_NFC_CLKSEL_MSK
/*
* System Clock Divider Register 1
*/
......@@ -336,6 +374,7 @@
#define KINETIS_SIM_CLKDIV1_OUTDIV3_BITS 20
/* Clock 4 output divider value (for the flash clock) */
#define KINETIS_SIM_CLKDIV1_OUTDIV4_BITS 16
/*
* System Clock Divider Register 4
*/
......@@ -352,6 +391,27 @@
(((1 << KINETIS_SIM_CLKDIV4_NFCFRAC_BITWIDTH) - 1) << \
KINETIS_SIM_CLKDIV4_NFCFRAC_BITS)
/*
* Set configuration options based on usage of PLL0 or PLL1 for the CPU clock
*/
#ifdef KINETIS_MCGOUT_PLL1
#define KINETIS_SIM_SOPT2_NFCSRC KINETIS_SIM_SOPT2_NFCSRC_PLL1
#else
#define KINETIS_SIM_SOPT2_NFCSRC KINETIS_SIM_SOPT2_NFCSRC_PLL0
#endif /* KINETIS_MCGOUT_PLL1 */
/*
* Check the requirements for the synchronous mode of the DDR controller
*/
#ifdef CONFIG_KINETIS_DDR_SYNC
#ifndef KINETIS_MCGOUT_PLL1
#error DDR synchronous mode requires that the system clock is sourced from PLL1
#endif /* !KINETIS_MCGOUT_PLL1 */
#ifndef CONFIG_KINETIS_DDR
#error CONFIG_KINETIS_DDR_SYNC requires CONFIG_KINETIS_DDR
#endif /* !CONFIG_KINETIS_DDR */
#endif /* CONFIG_KINETIS_DDR_SYNC */
/*
* Multipurpose Clock Generator (MCG) register map
*
......@@ -443,15 +503,11 @@ static void clock_fei_to_fbe(void)
KINETIS_MCG_S_CLKST_EXT_REF);
}
/*
* Transition from the FBE (FLL Bypassed External) to
* the PBE (PLL Bypassed External) mode.
*/
static void clock_fbe_to_pbe(void)
static void clock_setup_pll0(void)
{
/*
* Configure the PLL input divider.
* Also, enable the PLL clock during Normal Stop.
* Configure the PLL0 input divider.
* Also, enable the PLL0 clock during Normal Stop.
*/
KINETIS_MCG->c5 =
((KINETIS_PLL_PRDIV - 1) << KINETIS_MCG_C5_PRDIV_BITS) |
......@@ -474,6 +530,76 @@ static void clock_fbe_to_pbe(void)
KINETIS_MCG->c6 = (KINETIS_PLL_VDIV - KINETIS_PLL_VDIV_MIN) <<
KINETIS_MCG_C6_VDIV_BITS;
/*
* Enable the PLL0
*/
KINETIS_MCG->c5 |= KINETIS_MCG_C5_PLLCLKEN_MSK;
/*
* Wait for the PLL0 to acquire lock
*/
while (!(KINETIS_MCG->status & KINETIS_MCG_S_LOCK_MSK));
}
static void clock_setup_pll1(void)
{
/*
* Configure the PLL1 input divider.
* Also, enable the PLL1 clock during Normal Stop.
*/
KINETIS_MCG->c11 =
((KINETIS_PLL1_PRDIV - 1) << KINETIS_MCG_C11_PRDIV_BITS) |
KINETIS_MCG_C11_PLLSTEN1_MSK;
/*
* If the Multipurpose Clock Generator (MCG) supports multiple
* oscillators (e.g. on K70 @ 120 MHz), select the necessary
* oscillator as the external reference clock for the PLL1.
*/
#ifdef KINETIS_MCG_PLLREFSEL
KINETIS_MCG->c11 =
(KINETIS_MCG->c11 & ~KINETIS_MCG_C11_PLLREFSEL1_MSK) |
(KINETIS_MCG_PLLREFSEL << KINETIS_MCG_C11_PLLREFSEL1_BIT);
#endif
/*
* Set the PLL1 multiplication factor
*/
KINETIS_MCG->c12 = (KINETIS_PLL1_VDIV - KINETIS_PLL_VDIV_MIN) <<
KINETIS_MCG_C12_VDIV1_BITS;
/*
* Enable the PLL1
*/
KINETIS_MCG->c11 |= KINETIS_MCG_C11_PLLCLKEN1_MSK;
/*
* Wait for the PLL1 to acquire lock
*/
while (!(KINETIS_MCG->status2 & KINETIS_MCG_S2_LOCK1_MSK));
}
/*
* Transition from the FBE (FLL Bypassed External) to
* the PBE (PLL Bypassed External) mode.
*/
static void clock_fbe_to_pbe(void)
{
/*
* Configure the PLL that we will use for the MCGOUTCLK
*/
#ifdef KINETIS_MCGOUT_PLL1
clock_setup_pll1();
/* Select PLL1 output as the MCG source clock */
KINETIS_MCG->c11 |= KINETIS_MCG_C11_PLLCS_MSK;
#else
clock_setup_pll0();
/* Select PLL0 output as the MCG source clock */
KINETIS_MCG->c11 &= ~KINETIS_MCG_C11_PLLCS_MSK;
#endif /* KINETIS_MCGOUT_PLL1 */
/*
* Switch to the PBE mode
*/
......@@ -483,11 +609,6 @@ static void clock_fbe_to_pbe(void)
* Wait for the source for the PLLS clock to switch to PLL
*/
while (!(KINETIS_MCG->status & KINETIS_MCG_S_PLLST_MSK));
/*
* Wait for the PLL to acquire lock
*/
while (!(KINETIS_MCG->status & KINETIS_MCG_S_LOCK_MSK));
}
/*
......@@ -511,38 +632,15 @@ static void clock_pbe_to_pee(void)
KINETIS_MCG_S_CLKST_PLL);
}
#ifdef CONFIG_KINETIS_DDR
#if defined(CONFIG_KINETIS_DDR) && !defined(CONFIG_KINETIS_DDR_SYNC)
/*
* Configure the DDR clock for the DDR asynchronous mode
*/
static void clock_setup_ddr_async(void)
{
/*
* Configure the PLL1 input divider.
* Also, enable the PLL1 clock during Normal Stop.
* The input for the PLL1 is OSC0 (50 MHz from the PHY clock).
*/
KINETIS_MCG->c11 =
((KINETIS_PLL1_PRDIV - 1) << KINETIS_MCG_C11_PRDIV_BITS) |
KINETIS_MCG_C11_PLLSTEN1_MSK;
/*
* Set the PLL multiplication factor
*/
KINETIS_MCG->c12 = (KINETIS_PLL1_VDIV - KINETIS_PLL_VDIV_MIN) <<
KINETIS_MCG_C12_VDIV1_BITS;
/*
* Enable the PLL1
*/
KINETIS_MCG->c11 |= KINETIS_MCG_C11_PLLCLKEN1_MSK;
/*
* Wait for the PLL1 to acquire lock
*/
while (!(KINETIS_MCG->status2 & KINETIS_MCG_S2_LOCK1_MSK));
clock_setup_pll1();
}
#endif /* CONFIG_KINETIS_DDR */
#endif /* CONFIG_KINETIS_DDR && !CONFIG_KINETIS_DDR_SYNC */
/*
* Set-up clocks
......@@ -586,6 +684,14 @@ static void clock_setup(void)
KINETIS_SIM_CLKDIV4_NFCFRAC_MSK)) |
((KINETIS_NFCCLK_DIV - 1) << KINETIS_SIM_CLKDIV4_NFCDIV_BITS) |
((KINETIS_NFCCLK_FRAC - 1) << KINETIS_SIM_CLKDIV4_NFCFRAC_BITS);
/*
* Select the NAND Flash Controller clock source
*/
KINETIS_SIM->sopt2 =
(KINETIS_SIM->sopt2 & ~(KINETIS_SIM_SOPT2_NFCSRC_MSK |
KINETIS_SIM_SOPT2_NFC_CLKSEL_MSK)) |
KINETIS_SIM_SOPT2_NFCSRC |
KINETIS_SIM_SOPT2_NFC_CLKSEL_NFCDIV;
/*
* TBD: Configure clock dividers for USB and I2S here
......@@ -602,12 +708,15 @@ static void clock_setup(void)
*/
clock_pbe_to_pee();
#ifdef CONFIG_KINETIS_DDR
#if defined(CONFIG_KINETIS_DDR) && !defined(CONFIG_KINETIS_DDR_SYNC)
/*
* Configure the DDR clock for the DDR asynchronous mode
*
* If we use the DDR synchronous mode, then the PLL1 is already
* configured.
*/
clock_setup_ddr_async();
#endif /* CONFIG_KINETIS_DDR */
#endif /* CONFIG_KINETIS_DDR && !CONFIG_KINETIS_DDR_SYNC */
/*
* TBD: Configure the USB clock via KINETIS_SIM->sopt2::PLLFLLSEL
......
......@@ -108,8 +108,10 @@
#define KINETIS_PLL_VDIV 24
/* PLL1 input divider: 50/5 = 10 MHz */
#define KINETIS_PLL1_PRDIV 5
/* PLL1 multiplier: 10*30/2 = 150 MHz */
#define KINETIS_PLL1_VDIV 30
/* PLL1 multiplier: 10*24/2 = 120 MHz */
#define KINETIS_PLL1_VDIV 24
/* Use PLL1 for MCGOUT (required for synchronous mode of the DDR controller) */
#define KINETIS_MCGOUT_PLL1
/*
* Number of clock ticks in 1 sec
*/
......@@ -135,6 +137,7 @@
* Configuration of the external DDR2 SDRAM memory
*/
#define CONFIG_KINETIS_DDR
#define CONFIG_KINETIS_DDR_SYNC /* DDR synchronous mode */
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_SYS_RAM_CS 0
#define CONFIG_SYS_RAM_BASE 0x80000000
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment