@ -7,6 +7,7 @@
# include <common.h>
# include <linux/types.h>
# include <asm/arch/clock.h>
# include <asm/arch/mx6-ddr.h>
# include <asm/arch/sys_proto.h>
# include <asm/io.h>
@ -330,15 +331,20 @@ void mx6sdl_dram_iocfg(unsigned width,
* Configure mx6 mmdc registers based on :
* - board - specific memory configuration
* - board - specific calibration data
* - ddr3 chip details
* - ddr3 / lpddr2 chip details
*
* The various calculations here are derived from the Freescale
* i . Mx6DQSDL DDR3 Script Aid spreadsheet ( DOC - 94917 ) designed to generate MMDC
* configuration registers based on memory system and memory chip parameters .
* 1. i . Mx6DQSDL DDR3 Script Aid spreadsheet ( DOC - 94917 ) designed to generate
* MMDC configuration registers based on memory system and memory chip
* parameters .
*
* 2. i . Mx6SL LPDDR2 Script Aid spreadsheet V0 .04 designed to generate MMDC
* configuration registers based on memory system and memory chip
* parameters .
*
* The defaults here are those which were specified in the spreadsheet .
* For details on each register , refer to the IMX6DQRM and / or IMX6SDLRM
* section titled MMDC initialization
* and / or IMX6SLRM section titled MMDC initialization .
*/
# define MR(val, ba, cmd, cs1) \
( ( val < < 16 ) | ( 1 < < 15 ) | ( cmd < < 4 ) | ( cs1 < < 3 ) | ba )
@ -348,6 +354,290 @@ void mx6sdl_dram_iocfg(unsigned width,
mmdc1 - > entry = value ; \
} while ( 0 )
/*
* According JESD209 - 2 B - LPDDR2 : Table 103
* WL : write latency
*/
static int lpddr2_wl ( uint32_t mem_speed )
{
switch ( mem_speed ) {
case 1066 :
case 933 :
return 4 ;
case 800 :
return 3 ;
case 677 :
case 533 :
return 2 ;
case 400 :
case 333 :
return 1 ;
default :
puts ( " invalid memory speed \n " ) ;
hang ( ) ;
}
return 0 ;
}
/*
* According JESD209 - 2 B - LPDDR2 : Table 103
* RL : read latency
*/
static int lpddr2_rl ( uint32_t mem_speed )
{
switch ( mem_speed ) {
case 1066 :
return 8 ;
case 933 :
return 7 ;
case 800 :
return 6 ;
case 677 :
return 5 ;
case 533 :
return 4 ;
case 400 :
case 333 :
return 3 ;
default :
puts ( " invalid memory speed \n " ) ;
hang ( ) ;
}
return 0 ;
}
void mx6_lpddr2_cfg ( const struct mx6_ddr_sysinfo * sysinfo ,
const struct mx6_mmdc_calibration * calib ,
const struct mx6_lpddr2_cfg * lpddr2_cfg )
{
volatile struct mmdc_p_regs * mmdc0 ;
u32 val ;
u8 tcke , tcksrx , tcksre , trrd ;
u8 twl , txp , tfaw , tcl ;
u16 tras , twr , tmrd , trtp , twtr , trfc , txsr ;
u16 trcd_lp , trppb_lp , trpab_lp , trc_lp ;
u16 cs0_end ;
u8 coladdr ;
int clkper ; /* clock period in picoseconds */
int clock ; /* clock freq in mHz */
int cs ;
/* only support 16/32 bits */
if ( sysinfo - > dsize > 1 )
hang ( ) ;
mmdc0 = ( struct mmdc_p_regs * ) MMDC_P0_BASE_ADDR ;
clock = mxc_get_clock ( MXC_DDR_CLK ) / 1000000U ;
clkper = ( 1000 * 1000 ) / clock ; /* pico seconds */
twl = lpddr2_wl ( lpddr2_cfg - > mem_speed ) - 1 ;
/* LPDDR2-S2 and LPDDR2-S4 have the same tRFC value. */
switch ( lpddr2_cfg - > density ) {
case 1 :
case 2 :
case 4 :
trfc = DIV_ROUND_UP ( 130000 , clkper ) - 1 ;
txsr = DIV_ROUND_UP ( 140000 , clkper ) - 1 ;
break ;
case 8 :
trfc = DIV_ROUND_UP ( 210000 , clkper ) - 1 ;
txsr = DIV_ROUND_UP ( 220000 , clkper ) - 1 ;
break ;
default :
/*
* 64 Mb , 128 Mb , 256 Mb , 512 Mb are not supported currently .
*/
hang ( ) ;
break ;
}
/*
* txpdll , txpr , taonpd and taofpd are not relevant in LPDDR2 mode ,
* set them to 0. */
txp = DIV_ROUND_UP ( 7500 , clkper ) - 1 ;
tcke = 3 ;
if ( lpddr2_cfg - > mem_speed = = 333 )
tfaw = DIV_ROUND_UP ( 60000 , clkper ) - 1 ;
else
tfaw = DIV_ROUND_UP ( 50000 , clkper ) - 1 ;
trrd = DIV_ROUND_UP ( 10000 , clkper ) - 1 ;
/* tckesr for LPDDR2 */
tcksre = DIV_ROUND_UP ( 15000 , clkper ) ;
tcksrx = tcksre ;
twr = DIV_ROUND_UP ( 15000 , clkper ) - 1 ;
/*
* tMRR : 2 , tMRW : 5
* tMRD should be set to max ( tMRR , tMRW )
*/
tmrd = 5 ;
tras = DIV_ROUND_UP ( lpddr2_cfg - > trasmin , clkper / 10 ) - 1 ;
/* LPDDR2 mode use tRCD_LP filed in MDCFG3. */
trcd_lp = DIV_ROUND_UP ( lpddr2_cfg - > trcd_lp , clkper / 10 ) - 1 ;
trc_lp = DIV_ROUND_UP ( lpddr2_cfg - > trasmin + lpddr2_cfg - > trppb_lp ,
clkper / 10 ) - 1 ;
trppb_lp = DIV_ROUND_UP ( lpddr2_cfg - > trppb_lp , clkper / 10 ) - 1 ;
trpab_lp = DIV_ROUND_UP ( lpddr2_cfg - > trpab_lp , clkper / 10 ) - 1 ;
/* To LPDDR2, CL in MDCFG0 refers to RL */
tcl = lpddr2_rl ( lpddr2_cfg - > mem_speed ) - 3 ;
twtr = DIV_ROUND_UP ( 7500 , clkper ) - 1 ;
trtp = DIV_ROUND_UP ( 7500 , clkper ) - 1 ;
cs0_end = 4 * sysinfo - > cs_density - 1 ;
debug ( " density:%d Gb (%d Gb per chip) \n " ,
sysinfo - > cs_density , lpddr2_cfg - > density ) ;
debug ( " clock: %dMHz (%d ps) \n " , clock , clkper ) ;
debug ( " memspd:%d \n " , lpddr2_cfg - > mem_speed ) ;
debug ( " trcd_lp=%d \n " , trcd_lp ) ;
debug ( " trppb_lp=%d \n " , trppb_lp ) ;
debug ( " trpab_lp=%d \n " , trpab_lp ) ;
debug ( " trc_lp=%d \n " , trc_lp ) ;
debug ( " tcke=%d \n " , tcke ) ;
debug ( " tcksrx=%d \n " , tcksrx ) ;
debug ( " tcksre=%d \n " , tcksre ) ;
debug ( " trfc=%d \n " , trfc ) ;
debug ( " txsr=%d \n " , txsr ) ;
debug ( " txp=%d \n " , txp ) ;
debug ( " tfaw=%d \n " , tfaw ) ;
debug ( " tcl=%d \n " , tcl ) ;
debug ( " tras=%d \n " , tras ) ;
debug ( " twr=%d \n " , twr ) ;
debug ( " tmrd=%d \n " , tmrd ) ;
debug ( " twl=%d \n " , twl ) ;
debug ( " trtp=%d \n " , trtp ) ;
debug ( " twtr=%d \n " , twtr ) ;
debug ( " trrd=%d \n " , trrd ) ;
debug ( " cs0_end=%d \n " , cs0_end ) ;
debug ( " ncs=%d \n " , sysinfo - > ncs ) ;
/*
* board - specific configuration :
* These values are determined empirically and vary per board layout
*/
mmdc0 - > mpwldectrl0 = calib - > p0_mpwldectrl0 ;
mmdc0 - > mpwldectrl1 = calib - > p0_mpwldectrl1 ;
mmdc0 - > mpdgctrl0 = calib - > p0_mpdgctrl0 ;
mmdc0 - > mpdgctrl1 = calib - > p0_mpdgctrl1 ;
mmdc0 - > mprddlctl = calib - > p0_mprddlctl ;
mmdc0 - > mpwrdlctl = calib - > p0_mpwrdlctl ;
mmdc0 - > mpzqlp2ctl = calib - > mpzqlp2ctl ;
/* Read data DQ Byte0-3 delay */
mmdc0 - > mprddqby0dl = 0x33333333 ;
mmdc0 - > mprddqby1dl = 0x33333333 ;
if ( sysinfo - > dsize > 0 ) {
mmdc0 - > mprddqby2dl = 0x33333333 ;
mmdc0 - > mprddqby3dl = 0x33333333 ;
}
/* Write data DQ Byte0-3 delay */
mmdc0 - > mpwrdqby0dl = 0xf3333333 ;
mmdc0 - > mpwrdqby1dl = 0xf3333333 ;
if ( sysinfo - > dsize > 0 ) {
mmdc0 - > mpwrdqby2dl = 0xf3333333 ;
mmdc0 - > mpwrdqby3dl = 0xf3333333 ;
}
/*
* In LPDDR2 mode this register should be cleared ,
* so no termination will be activated .
*/
mmdc0 - > mpodtctrl = 0 ;
/* complete calibration */
val = ( 1 < < 11 ) ; /* Force measurement on delay-lines */
mmdc0 - > mpmur0 = val ;
/* Step 1: configuration request */
mmdc0 - > mdscr = ( u32 ) ( 1 < < 15 ) ; /* config request */
/* Step 2: Timing configuration */
mmdc0 - > mdcfg0 = ( trfc < < 24 ) | ( txsr < < 16 ) | ( txp < < 13 ) |
( tfaw < < 4 ) | tcl ;
mmdc0 - > mdcfg1 = ( tras < < 16 ) | ( twr < < 9 ) | ( tmrd < < 5 ) | twl ;
mmdc0 - > mdcfg2 = ( trtp < < 6 ) | ( twtr < < 3 ) | trrd ;
mmdc0 - > mdcfg3lp = ( trc_lp < < 16 ) | ( trcd_lp < < 8 ) |
( trppb_lp < < 4 ) | trpab_lp ;
mmdc0 - > mdotc = 0 ;
mmdc0 - > mdasp = cs0_end ; /* CS addressing */
/* Step 3: Configure DDR type */
mmdc0 - > mdmisc = ( sysinfo - > cs1_mirror < < 19 ) | ( sysinfo - > walat < < 16 ) |
( sysinfo - > bi_on < < 12 ) | ( sysinfo - > mif3_mode < < 9 ) |
( sysinfo - > ralat < < 6 ) | ( 1 < < 3 ) ;
/* Step 4: Configure delay while leaving reset */
mmdc0 - > mdor = ( sysinfo - > sde_to_rst < < 8 ) |
( sysinfo - > rst_to_cke < < 0 ) ;
/* Step 5: Configure DDR physical parameters (density and burst len) */
coladdr = lpddr2_cfg - > coladdr ;
if ( lpddr2_cfg - > coladdr = = 8 ) /* 8-bit COL is 0x3 */
coladdr + = 4 ;
else if ( lpddr2_cfg - > coladdr = = 12 ) /* 12-bit COL is 0x4 */
coladdr + = 1 ;
mmdc0 - > mdctl = ( lpddr2_cfg - > rowaddr - 11 ) < < 24 | /* ROW */
( coladdr - 9 ) < < 20 | /* COL */
( 0 < < 19 ) | /* Burst Length = 4 for LPDDR2 */
( sysinfo - > dsize < < 16 ) ; /* DDR data bus size */
/* Step 6: Perform ZQ calibration */
val = 0xa1390003 ; /* one-time HW ZQ calib */
mmdc0 - > mpzqhwctrl = val ;
/* Step 7: Enable MMDC with desired chip select */
mmdc0 - > mdctl | = ( 1 < < 31 ) | /* SDE_0 for CS0 */
( ( sysinfo - > ncs = = 2 ) ? 1 : 0 ) < < 30 ; /* SDE_1 for CS1 */
/* Step 8: Write Mode Registers to Init LPDDR2 devices */
for ( cs = 0 ; cs < sysinfo - > ncs ; cs + + ) {
/* MR63: reset */
mmdc0 - > mdscr = MR ( 63 , 0 , 3 , cs ) ;
/* MR10: calibration,
* 0xff is calibration command after intilization .
*/
val = 0xA | ( 0xff < < 8 ) ;
mmdc0 - > mdscr = MR ( val , 0 , 3 , cs ) ;
/* MR1 */
val = 0x1 | ( 0x82 < < 8 ) ;
mmdc0 - > mdscr = MR ( val , 0 , 3 , cs ) ;
/* MR2 */
val = 0x2 | ( 0x04 < < 8 ) ;
mmdc0 - > mdscr = MR ( val , 0 , 3 , cs ) ;
/* MR3 */
val = 0x3 | ( 0x02 < < 8 ) ;
mmdc0 - > mdscr = MR ( val , 0 , 3 , cs ) ;
}
/* Step 10: Power down control and self-refresh */
mmdc0 - > mdpdc = ( tcke & 0x7 ) < < 16 |
5 < < 12 | /* PWDT_1: 256 cycles */
5 < < 8 | /* PWDT_0: 256 cycles */
1 < < 6 | /* BOTH_CS_PD */
( tcksrx & 0x7 ) < < 3 |
( tcksre & 0x7 ) ;
mmdc0 - > mapsr = 0x00001006 ; /* ADOPT power down enabled */
/* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
val = 0xa1310003 ;
mmdc0 - > mpzqhwctrl = val ;
/* Step 12: Configure and activate periodic refresh */
mmdc0 - > mdref = ( 0 < < 14 ) | /* REF_SEL: Periodic refresh cycle: 64kHz */
( 3 < < 11 ) ; /* REFR: Refresh Rate - 4 refreshes */
/* Step 13: Deassert config request - init complete */
mmdc0 - > mdscr = 0x00000000 ;
/* wait for auto-ZQ calibration to complete */
mdelay ( 1 ) ;
}
void mx6_ddr3_cfg ( const struct mx6_ddr_sysinfo * sysinfo ,
const struct mx6_mmdc_calibration * calib ,
const struct mx6_ddr3_cfg * ddr3_cfg )
@ -662,6 +952,8 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
{
if ( sysinfo - > ddr_type = = DDR_TYPE_DDR3 ) {
mx6_ddr3_cfg ( sysinfo , calib , ddr_cfg ) ;
} else if ( sysinfo - > ddr_type = = DDR_TYPE_LPDDR2 ) {
mx6_lpddr2_cfg ( sysinfo , calib , ddr_cfg ) ;
} else {
puts ( " Unsupported ddr type \n " ) ;
hang ( ) ;