From df188547a95accdc26369edfdcb84cd5785f4a80 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:09:58 +0000 Subject: ppc: add SoC support for Freescale P1022 CPU, DDR, and LBC definitions are added to support the Freescale P1022. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/include/asm/fsl_lbc.h | 3 ++ arch/ppc/include/asm/processor.h | 1 + arch/ppc/mach-mpc85xx/cpuid.c | 1 + .../ppc/mach-mpc85xx/include/mach/config_mpc85xx.h | 9 ++++++ arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h | 34 ++++++++++++++++++++-- 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/arch/ppc/include/asm/fsl_lbc.h b/arch/ppc/include/asm/fsl_lbc.h index a59725cf3a..27d194ee74 100644 --- a/arch/ppc/include/asm/fsl_lbc.h +++ b/arch/ppc/include/asm/fsl_lbc.h @@ -25,8 +25,10 @@ #define BR_PS_8 0x00000800 /* Port Size 8 bit */ #define BR_PS_16 0x00001000 /* Port Size 16 bit */ #define BR_PS_32 0x00001800 /* Port Size 32 bit */ +#define BR_DECC_SHIFT 9 #define BR_V 0x00000001 #define BR_V_SHIFT 0 +#define BR_MS_FCM 0x00000020 #define BR_MS_UPMA 0x00000080 /* Convert an address into the right format for the BR registers */ @@ -61,6 +63,7 @@ #define FSL_LBC_MDR_OFFSET 0x88 #define FSL_LBC_LTESR_OFFSET 0xB0 #define FSL_LBC_LTEIR_OFFSET 0xB8 +#define FSL_LBC_LBCR_OFFSET 0xD0 #define MxMR_MAD_MSK 0x0000003f /* Machine Address Mask */ #define MxMR_GPL_x4DIS 0x00040000 /* GPL_A4 Ouput Line Disable */ diff --git a/arch/ppc/include/asm/processor.h b/arch/ppc/include/asm/processor.h index 819babb675..c9633fe507 100644 --- a/arch/ppc/include/asm/processor.h +++ b/arch/ppc/include/asm/processor.h @@ -867,6 +867,7 @@ #define SVR_8641 0x8090 #define SVR_8544 0x803401 #define SVR_8544_E 0x803C01 +#define SVR_P1022 0x80E600 #define SVR_P2020 0x80E200 #define SVR_P2020_E 0x80EA00 diff --git a/arch/ppc/mach-mpc85xx/cpuid.c b/arch/ppc/mach-mpc85xx/cpuid.c index 809497859a..21892e3ff1 100644 --- a/arch/ppc/mach-mpc85xx/cpuid.c +++ b/arch/ppc/mach-mpc85xx/cpuid.c @@ -29,6 +29,7 @@ struct cpu_type cpu_type_list[] = { CPU_TYPE_ENTRY(8544, 8544, 1), CPU_TYPE_ENTRY(8544, 8544_E, 1), + CPU_TYPE_ENTRY(P1022, P1022, 2), CPU_TYPE_ENTRY(P2020, P2020, 2), CPU_TYPE_ENTRY(P2020, P2020_E, 2), }; diff --git a/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h b/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h index 27358e83f9..f9d8299b6d 100644 --- a/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h +++ b/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h @@ -39,6 +39,15 @@ #define FSL_ERRATUM_A005125 #define PPC_E500_DEBUG_TLB 0 +#elif defined(CONFIG_P1022) +#define MAX_CPUS 2 +#define FSL_NUM_LAWS 12 +#define FSL_NUM_TSEC 2 +#define FSL_SEC_COMPAT 2 +#define PPC_E500_DEBUG_TLB 2 +#define FSL_TSECV2 +#define FSL_ERRATUM_A005125 + #else #error Processor type not defined for this platform #endif diff --git a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h index d5a9c9704c..87bc5c7c63 100644 --- a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h +++ b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h @@ -36,7 +36,7 @@ #define MPC85xx_GPIO_OFFSET 0xf000 #define MPC85xx_L2_OFFSET 0x20000 -#ifdef CONFIG_TSECV2 +#ifdef FSL_TSECV2 #define TSEC1_OFFSET 0xB0000 #else #define TSEC1_OFFSET 0x24000 @@ -75,6 +75,11 @@ #define MPC85xx_DDR_CS1_CONFIG_OFFSET 0x084 #define MPC85xx_DDR_CS2_CONFIG_OFFSET 0x088 #define MPC85xx_DDR_CS3_CONFIG_OFFSET 0x08c +/* Chip Select 0, 1, 2, 3 Configuration 2 */ +#define MPC85xx_DDR_CS0_CONFIG_2_OFFSET 0x0c0 +#define MPC85xx_DDR_CS1_CONFIG_2_OFFSET 0x0c4 +#define MPC85xx_DDR_CS2_CONFIG_2_OFFSET 0x0c8 +#define MPC85xx_DDR_CS3_CONFIG_2_OFFSET 0x0cc /* SDRAM Timing Configuration 0, 1, 2, 3 */ #define MPC85xx_DDR_TIMING_CFG_3_OFFSET 0x100 #define MPC85xx_DDR_TIMING_CFG_0_OFFSET 0x104 @@ -97,9 +102,30 @@ /* training init and extended addr */ #define MPC85xx_DDR_SDRAM_INIT_ADDR_OFFSET 0x148 #define MPC85xx_DDR_SDRAM_INIT_ADDR_EXT_OFFSET 0x14c +/* SDRAM Timing Configuration 4,5 */ +#define MPC85xx_DDR_TIMING_CFG_4_OFFSET 0x160 +#define MPC85xx_DDR_TIMING_CFG_5_OFFSET 0x164 +/* DDR ZQ calibration control */ +#define MPC85xx_DDR_ZQ_CNTL_OFFSET 0x170 +/* DDR write leveling control */ +#define MPC85xx_DDR_WRLVL_CNTL_OFFSET 0x174 +/* Self Refresh Counter */ +#define MPC85xx_DDR_SR_CNTL_OFFSET 0x17c +/* DDR SDRAM Register Control Word */ +#define MPC85xx_DDR_SDRAM_RCW_1_OFFSET 0x180 +#define MPC85xx_DDR_SDRAM_RCW_2_OFFSET 0x184 +/* DDR write leveling control */ +#define MPC85xx_DDR_WRLVL_CNTL_2_OFFSET 0x190 +#define MPC85xx_DDR_WRLVL_CNTL_3_OFFSET 0x194 +/* DDR Control Driver */ +#define MPC85xx_DDR_DDRCDR1_OFFSET 0xb28 +#define MPC85xx_DDR_DDRCDR2_OFFSET 0xb2c /* DDR IP block revision */ -#define MPC85xx_DDR_IP_REV1_OFFSET 0xbf8 -#define MPC85xx_DDR_IP_REV2_OFFSET 0xbfc +#define MPC85xx_DDR_IP_REV1_OFFSET 0xbf8 +#define MPC85xx_DDR_IP_REV2_OFFSET 0xbfc +/* Memory Error Disable */ +#define MPC85xx_DDR_ERR_DISABLE_OFFSET 0xe44 +#define MPC85xx_DDR_ERR_INT_EN_OFFSET 0xe48 #define DDR_OFF(REGNAME) (MPC85xx_DDR_##REGNAME##_OFFSET) @@ -147,6 +173,8 @@ #define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT 9 #define MPC85xx_GUTS_PORDEVSR2_OFFSET 0x14 #define MPC85xx_PORDEVSR2_SEC_CFG 0x00000080 +#define MPC85xx_GUTS_PMUXCR_OFFSET 0x60 +#define MPC85xx_GUTS_PMUXCR2_OFFSET 0x64 #define MPC85xx_GUTS_DEVDISR_OFFSET 0x70 #define MPC85xx_DEVDISR_TB0 0x00004000 #define MPC85xx_DEVDISR_TB1 0x00001000 -- cgit v1.2.3 From 64e38721cde4d9bf6cca0b9e92a5900da1dd9577 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:09:59 +0000 Subject: common: DDR3 SPD verification support Add DDR3 SPD verification support for use by the PPC 8xxx DDR driver. This is based on the equivalent files from U-Boot version git-be937b5. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/mach-mpc85xx/Kconfig | 1 + common/ddr_spd.c | 24 +++++++++ include/ddr_spd.h | 116 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig index 74bad76667..0b76204519 100644 --- a/arch/ppc/mach-mpc85xx/Kconfig +++ b/arch/ppc/mach-mpc85xx/Kconfig @@ -57,6 +57,7 @@ config MPC8544 config DDR_SPD bool + select CRC16 default y config FSL_DDR2 diff --git a/common/ddr_spd.c b/common/ddr_spd.c index c8b73ff56c..ea0b529eed 100644 --- a/common/ddr_spd.c +++ b/common/ddr_spd.c @@ -7,6 +7,7 @@ */ #include +#include #include uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd) @@ -37,3 +38,26 @@ uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd) error: return 1; } + +uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd) +{ + char crc_lsb, crc_msb; + int csum16, len; + + /* + * SPD byte0[7] - CRC coverage + * 0 = CRC covers bytes 0~125 + * 1 = CRC covers bytes 0~116 + */ + + len = !(spd->info_size_crc & 0x80) ? 126 : 117; + csum16 = cyg_crc16((char *)spd, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->crc[0] != crc_lsb || spd->crc[1] != crc_msb) + return 1; + + return 0; +} diff --git a/include/ddr_spd.h b/include/ddr_spd.h index c8762a28df..fc03bacc56 100644 --- a/include/ddr_spd.h +++ b/include/ddr_spd.h @@ -114,13 +114,126 @@ struct ddr2_spd_eeprom_s { uint8_t mdate[2]; /* 93 Manufacturing Date */ uint8_t sernum[4]; /* 95 Assembly Serial Number */ uint8_t mspec[27]; /* 99-127 Manufacturer Specific Data */ +}; + +struct ddr3_spd_eeprom_s { + /* General Section: Bytes 0-59 */ + uint8_t info_size_crc; /* 0 # bytes written into serial memory, + CRC coverage */ + uint8_t spd_rev; /* 1 Total # bytes of SPD mem device */ + uint8_t mem_type; /* 2 Key Byte / Fundamental mem type */ + uint8_t module_type; /* 3 Key Byte / Module Type */ + uint8_t density_banks; /* 4 SDRAM Density and Banks */ + uint8_t addressing; /* 5 SDRAM Addressing */ + uint8_t module_vdd; /* 6 Module nominal voltage, VDD */ + uint8_t organization; /* 7 Module Organization */ + uint8_t bus_width; /* 8 Module Memory Bus Width */ + uint8_t ftb_div; /* 9 Fine Timebase (FTB) + Dividend / Divisor */ + uint8_t mtb_dividend; /* 10 Medium Timebase (MTB) Dividend */ + uint8_t mtb_divisor; /* 11 Medium Timebase (MTB) Divisor */ + uint8_t tck_min; /* 12 SDRAM Minimum Cycle Time */ + uint8_t res_13; /* 13 Reserved */ + uint8_t caslat_lsb; /* 14 CAS Latencies Supported, + Least Significant Byte */ + uint8_t caslat_msb; /* 15 CAS Latencies Supported, + Most Significant Byte */ + uint8_t taa_min; /* 16 Min CAS Latency Time */ + uint8_t twr_min; /* 17 Min Write REcovery Time */ + uint8_t trcd_min; /* 18 Min RAS# to CAS# Delay Time */ + uint8_t trrd_min; /* 19 Min Row Active to + Row Active Delay Time */ + uint8_t trp_min; /* 20 Min Row Precharge Delay Time */ + uint8_t tras_trc_ext; /* 21 Upper Nibbles for tRAS and tRC */ + uint8_t tras_min_lsb; /* 22 Min Active to Precharge + Delay Time */ + uint8_t trc_min_lsb; /* 23 Min Active to Active/Refresh + Delay Time, LSB */ + uint8_t trfc_min_lsb; /* 24 Min Refresh Recovery Delay Time */ + uint8_t trfc_min_msb; /* 25 Min Refresh Recovery Delay Time */ + uint8_t twtr_min; /* 26 Min Internal Write to + Read Command Delay Time */ + uint8_t trtp_min; /* 27 Min Internal Read to Precharge + Command Delay Time */ + uint8_t tfaw_msb; /* 28 Upper Nibble for tFAW */ + uint8_t tfaw_min; /* 29 Min Four Activate Window + Delay Time*/ + uint8_t opt_features; /* 30 SDRAM Optional Features */ + uint8_t therm_ref_opt; /* 31 SDRAM Thermal and Refresh Opts */ + uint8_t therm_sensor; /* 32 Module Thermal Sensor */ + uint8_t device_type; /* 33 SDRAM device type */ + int8_t fine_tck_min; /* 34 Fine offset for tCKmin */ + int8_t fine_taa_min; /* 35 Fine offset for tAAmin */ + int8_t fine_trcd_min; /* 36 Fine offset for tRCDmin */ + int8_t fine_trp_min; /* 37 Fine offset for tRPmin */ + int8_t fine_trc_min; /* 38 Fine offset for tRCmin */ + uint8_t res_39_59[21]; /* 39-59 Reserved, General Section */ + + /* Module-Specific Section: Bytes 60-116 */ + union { + struct { + /* 60 (Unbuffered) Module Nominal Height */ + uint8_t mod_height; + /* 61 (Unbuffered) Module Maximum Thickness */ + uint8_t mod_thickness; + /* 62 (Unbuffered) Reference Raw Card Used */ + uint8_t ref_raw_card; + /* 63 (Unbuffered) Address Mapping from + Edge Connector to DRAM */ + uint8_t addr_mapping; + /* 64-116 (Unbuffered) Reserved */ + uint8_t res_64_116[53]; + } unbuffered; + struct { + /* 60 (Registered) Module Nominal Height */ + uint8_t mod_height; + /* 61 (Registered) Module Maximum Thickness */ + uint8_t mod_thickness; + /* 62 (Registered) Reference Raw Card Used */ + uint8_t ref_raw_card; + /* 63 DIMM Module Attributes */ + uint8_t modu_attr; + /* 64 RDIMM Thermal Heat Spreader Solution */ + uint8_t thermal; + /* 65 Register Manufacturer ID Code, LSB */ + uint8_t reg_id_lo; + /* 66 Register Manufacturer ID Code, MSB */ + uint8_t reg_id_hi; + /* 67 Register Revision Number */ + uint8_t reg_rev; + /* 68 Register Type */ + uint8_t reg_type; + /* 69-76 RC1,3,5..15 (MS Nib.)/RC0,2,4..14 (LS Nib.) */ + uint8_t rcw[8]; + } registered; + uint8_t uc[57]; /* 60-116 Module-Specific Section */ + } mod_section; + + /* Unique Module ID: Bytes 117-125 */ + uint8_t mmid_lsb; /* 117 Module MfgID Code LSB - JEP-106 */ + uint8_t mmid_msb; /* 118 Module MfgID Code MSB - JEP-106 */ + uint8_t mloc; /* 119 Mfg Location */ + uint8_t mdate[2]; /* 120-121 Mfg Date */ + uint8_t sernum[4]; /* 122-125 Module Serial Number */ + + /* CRC: Bytes 126-127 */ + uint8_t crc[2]; /* 126-127 SPD CRC */ + /* Other Manufacturer Fields and User Space: Bytes 128-255 */ + uint8_t mpart[18]; /* 128-145 Mfg's Module Part Number */ + uint8_t mrev[2]; /* 146-147 Module Revision Code */ + uint8_t dmid_lsb; /* 148 DRAM MfgID Code LSB - JEP-106 */ + uint8_t dmid_msb; /* 149 DRAM MfgID Code MSB - JEP-106 */ + uint8_t msd[26]; /* 150-175 Mfg's Specific Data */ + uint8_t cust[80]; /* 176-255 Open for Customer Use */ }; +extern uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd); extern uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd); /* * Byte 2 Fundamental Memory Types. */ #define SPD_MEMTYPE_DDR2 (0x08) +#define SPD_MEMTYPE_DDR3 (0x0B) /* DIMM Type for DDR2 SPD (according to v1.3) */ #define DDR2_SPD_DIMMTYPE_RDIMM (0x01) @@ -132,4 +245,7 @@ extern uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd); #define DDR2_SPD_DIMMTYPE_MINI_RDIMM (0x10) #define DDR2_SPD_DIMMTYPE_MINI_UDIMM (0x20) +/* Byte 3 Key Byte / Module Type for DDR3 SPD */ +#define DDR3_SPD_MODULETYPE_MASK (0x0F) +#define DDR3_SPD_MODULETYPE_UDIMM (0x02) #endif /* _DDR_SPD_H_ */ -- cgit v1.2.3 From cbeded2bad56b51a2aa25151931c0de346c00707 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:10:00 +0000 Subject: ppc: mpc8xxx: add DDR3 support Add DDR3 support into the MPC8xxx DDR driver. To avoid confusion, the function set_ddr_sdram_mode is renamed set_ddr2_sdram_mode. Checking for errors is simplified in the DDR2 DIMM parameters computation to be consistent with DDR3. This code is derived from the files found in directory drivers/ddr/fsl from U-Boot version git-be937b5. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/ddr-8xxx/Makefile | 4 +- arch/ppc/ddr-8xxx/common_timing_params.h | 2 + arch/ppc/ddr-8xxx/ctrl_regs.c | 429 ++++++++++++++++++++++++++--- arch/ppc/ddr-8xxx/ddr.h | 15 +- arch/ppc/ddr-8xxx/ddr2_dimm_params.c | 9 +- arch/ppc/ddr-8xxx/ddr2_setctrl.c | 58 ---- arch/ppc/ddr-8xxx/ddr3_dimm_params.c | 193 +++++++++++++ arch/ppc/ddr-8xxx/ddr_setctrl.c | 90 ++++++ arch/ppc/ddr-8xxx/lc_common_dimm_params.c | 103 ++++--- arch/ppc/ddr-8xxx/main.c | 12 +- arch/ppc/ddr-8xxx/options.c | 58 +++- arch/ppc/include/asm/fsl_ddr_dimm_params.h | 9 + arch/ppc/include/asm/fsl_ddr_sdram.h | 33 ++- 13 files changed, 863 insertions(+), 152 deletions(-) delete mode 100644 arch/ppc/ddr-8xxx/ddr2_setctrl.c create mode 100644 arch/ppc/ddr-8xxx/ddr3_dimm_params.c create mode 100644 arch/ppc/ddr-8xxx/ddr_setctrl.c diff --git a/arch/ppc/ddr-8xxx/Makefile b/arch/ppc/ddr-8xxx/Makefile index 54cb7ce512..43ae3a41df 100644 --- a/arch/ppc/ddr-8xxx/Makefile +++ b/arch/ppc/ddr-8xxx/Makefile @@ -1,2 +1,4 @@ obj-y += main.o util.o ctrl_regs.o options.o lc_common_dimm_params.o -obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o ddr2_setctrl.o +obj-y += ddr_setctrl.o +obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o +obj-$(CONFIG_FSL_DDR3) += ddr3_dimm_params.o diff --git a/arch/ppc/ddr-8xxx/common_timing_params.h b/arch/ppc/ddr-8xxx/common_timing_params.h index b2621937ea..85a1e2868f 100644 --- a/arch/ppc/ddr-8xxx/common_timing_params.h +++ b/arch/ppc/ddr-8xxx/common_timing_params.h @@ -23,6 +23,7 @@ struct common_timing_params_s { uint32_t tRRD_ps; /* maximum = 63750 ps */ uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ uint32_t refresh_rate_ps; + uint32_t extended_op_srt; uint32_t tIS_ps; /* byte 32, spd->ca_setup */ uint32_t tIH_ps; /* byte 33, spd->ca_hold */ uint32_t tDS_ps; /* byte 34, spd->data_setup */ @@ -36,6 +37,7 @@ struct common_timing_params_s { uint32_t additive_latency; uint32_t all_DIMMs_burst_lengths_bitmask; uint32_t all_DIMMs_registered; + uint32_t all_DIMMs_unbuffered; uint32_t all_DIMMs_ECC_capable; uint64_t total_mem; uint64_t base_address; diff --git a/arch/ppc/ddr-8xxx/ctrl_regs.c b/arch/ppc/ddr-8xxx/ctrl_regs.c index 1abc826fb8..e3d43ab09e 100644 --- a/arch/ppc/ddr-8xxx/ctrl_regs.c +++ b/arch/ppc/ddr-8xxx/ctrl_regs.c @@ -8,7 +8,7 @@ */ /* - * Generic driver for Freescale DDR2 memory controller. + * Generic driver for Freescale DDR2/DDR3 memory controller. * Based on code from spd_sdram.c * Author: James Yang [at freescale.com] */ @@ -17,6 +17,33 @@ #include #include "ddr.h" +static uint32_t compute_cas_write_latency(void) +{ + uint32_t cwl; + const uint32_t mclk_ps = get_memory_clk_period_ps(); + + if (mclk_ps >= 2500) + cwl = 5; + else if (mclk_ps >= 1875) + cwl = 6; + else if (mclk_ps >= 1500) + cwl = 7; + else if (mclk_ps >= 1250) + cwl = 8; + else if (mclk_ps >= 1070) + cwl = 9; + else if (mclk_ps >= 935) + cwl = 10; + else if (mclk_ps >= 833) + cwl = 11; + else if (mclk_ps >= 750) + cwl = 12; + else + cwl = 12; + + return cwl; +} + static void set_csn_config(int dimm_number, int i, struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, @@ -81,40 +108,91 @@ static void set_csn_config(int dimm_number, int i, } static void set_timing_cfg_0(struct fsl_ddr_cfg_regs_s *ddr, - const struct memctl_options_s *popts) + const struct memctl_options_s *popts, + const struct dimm_params_s *dimm) { - uint32_t trwt_mclk = 0; - - if (popts->trwt_override) - trwt_mclk = popts->trwt; + uint32_t trwt_mclk = 0, twrt_mclk = 0, act_pd_exit_mclk, + pre_pd_exit_mclk, taxpd_mclk, tmrd_mclk, txp, + data_rate = fsl_get_ddr_freq(0); + + if (popts->sdram_type == SDRAM_TYPE_DDR2) { + act_pd_exit_mclk = popts->txard; + pre_pd_exit_mclk = popts->txp; + taxpd_mclk = popts->taxpd; + tmrd_mclk = popts->tmrd; + } else { + /* + * tXARD is not part of the DDR3 specification, use the + * parameter txp instead of it. That is: + * txp=max(3nCK, 7.5ns). As well, use tAXPD=1. + */ + txp = max_t(uint32_t, (get_memory_clk_period_ps() * 3), 7500); + data_rate = fsl_get_ddr_freq(0); + tmrd_mclk = 4; + + /* for faster clock, need more time for data setup */ + if (popts->trwt_override) + trwt_mclk = popts->trwt; + else if (data_rate / 1000000 > 1800) + trwt_mclk = 2; + else + trwt_mclk = 0; + + if (data_rate / 1000000 > 1150) + twrt_mclk = 1; + else + twrt_mclk = 0; + + taxpd_mclk = 1; + if (popts->dynamic_power == 0) { + act_pd_exit_mclk = 1; + pre_pd_exit_mclk = 1; + } else { + /* act_pd_exit_mclk = tXARD, see above */ + act_pd_exit_mclk = picos_to_mclk(txp); + /* Mode register MR0[A12] is '1' - fast exit */ + pre_pd_exit_mclk = act_pd_exit_mclk; + } + } ddr->timing_cfg_0 = (((trwt_mclk & 0x3) << 30) - | ((popts->txard & 0x7) << 20) - | ((popts->txp & 0xF) << 16) - | ((popts->taxpd & 0xf) << 8) - | ((popts->tmrd & 0xf) << 0)); + | ((twrt_mclk & 0x3) << 28) + | ((act_pd_exit_mclk & 0xf) << 20) + | ((pre_pd_exit_mclk & 0xf) << 16) + | ((taxpd_mclk & 0xf) << 8) + | ((tmrd_mclk & 0x1f) << 0) + ); } static void set_timing_cfg_3(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, - uint32_t cas_latency) + uint32_t cas_latency, uint32_t additive_latency) { - uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec; + uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec, ext_wrrec; ext_pretoact = picos_to_mclk(dimm->tRP_ps) >> 4; ext_acttopre = picos_to_mclk(dimm->tRAS_ps) >> 4; ext_acttorw = picos_to_mclk(dimm->tRCD_ps) >> 4; cas_latency = ((cas_latency << 1) - 1) >> 4; + additive_latency = additive_latency >> 4; ext_refrec = (picos_to_mclk(dimm->tRFC_ps) - 8) >> 4; + /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ + ext_wrrec = (picos_to_mclk(dimm->tWR_ps) + + (popts->otf_burst_chop_en ? 2 : 0)) >> 4; ddr->timing_cfg_3 = (((ext_pretoact & 0x1) << 28) - | ((ext_acttopre & 0x2) << 24) + | ((ext_acttopre & 0x3) << 24) | ((ext_acttorw & 0x1) << 22) | ((ext_refrec & 0x1F) << 16) - | ((cas_latency & 0x3) << 12)); + | ((cas_latency & 0x3) << 12) + | ((additive_latency & 0x1) << 10) + | ((ext_wrrec & 0x1) << 8) + ); } static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency) { @@ -152,10 +230,19 @@ static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr, wrrec_mclk = picos_to_mclk(dimm->tWR_ps); if (wrrec_mclk <= 16) wrrec_mclk = wrrec_table[wrrec_mclk - 1]; + if (popts->otf_burst_chop_en) + wrrec_mclk += 2; wrtord_mclk = picos_to_mclk(dimm->tWTR_ps); - if (wrtord_mclk < 2) - wrtord_mclk = 2; + if (popts->sdram_type == SDRAM_TYPE_DDR2) { + wrtord_mclk = max_t(uint32_t, wrtord_mclk, 2); + } else { + wrtord_mclk = max_t(uint32_t, wrtord_mclk, 4); + acttoact_mclk = max_t(uint32_t, acttoact_mclk, 4); + } + + if (popts->otf_burst_chop_en) + wrtord_mclk += 2; ddr->timing_cfg_1 = (((pretoact_mclk & 0x0F) << 28) | ((acttopre_mclk & 0x0F) << 24) @@ -176,11 +263,16 @@ static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, cpo = popts->cpo_override; rd_to_pre = picos_to_mclk(dimm->tRTP_ps); - if (rd_to_pre < 2) - rd_to_pre = 2; + if (popts->sdram_type == SDRAM_TYPE_DDR2) { + cas_latency = cas_latency - 1; + rd_to_pre = max_t(uint32_t, rd_to_pre, 2); + } else { + cas_latency = compute_cas_write_latency(); + rd_to_pre = max_t(uint32_t, rd_to_pre, 4); + } - if (additive_latency) - rd_to_pre += additive_latency; + if (popts->otf_burst_chop_en) + rd_to_pre += 2; wr_data_delay = popts->write_data_delay; cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps); @@ -188,7 +280,7 @@ static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, ddr->timing_cfg_2 = (((additive_latency & 0xf) << 28) | ((cpo & 0x1f) << 23) - | (((cas_latency - 1) & 0xf) << 19) + | ((cas_latency & 0xf) << 19) | ((rd_to_pre & 7) << 13) | ((wr_data_delay & 7) << 10) | ((cke_pls & 0x7) << 6) @@ -199,7 +291,8 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm) { - uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse; + uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse, + threet_en, eight_be = 0; mem_en = 1; sren = popts->self_refresh_in_sleep; @@ -208,15 +301,16 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr, else ecc_en = 0; - if (popts->sdram_type) - sdram_type = popts->sdram_type; - else - sdram_type = FSL_SDRAM_TYPE; - + sdram_type = popts->sdram_type; twoT_en = popts->twoT_en; dyn_pwr = popts->dynamic_power; dbw = popts->data_bus_width; hse = popts->half_strength_driver_enable; + threet_en = popts->threet_en; + + if (sdram_type == SDRAM_TYPE_DDR3) + if ((popts->burst_length == DDR_BL8) || (dbw == 1)) + eight_be = 1; ddr->ddr_sdram_cfg = (((mem_en & 0x1) << 31) | ((sren & 0x1) << 30) @@ -224,6 +318,8 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr, | ((sdram_type & 0x7) << 24) | ((dyn_pwr & 0x1) << 21) | ((dbw & 0x3) << 19) + | ((eight_be & 0x1) << 18) + | ((threet_en & 0x1) << 16) | ((twoT_en & 0x1) << 15) | ((hse & 0x1) << 3)); } @@ -232,7 +328,8 @@ static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts) { struct ddr_board_info_s *bi = popts->board_info; - uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0; + uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0, + obc_cfg = 0, x4_en, md_en = 0, rcw_en = 0; dll_rst_dis = popts->dll_rst_dis; dqs_cfg = popts->DQS_config; @@ -256,11 +353,48 @@ static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, ddr->ddr_data_init = popts->data_init; } + if (popts->sdram_type == SDRAM_TYPE_DDR3) { + obc_cfg = popts->otf_burst_chop_en; + md_en = popts->mirrored_dimm; + } + + x4_en = popts->x4_en ? 1 : 0; + ddr->ddr_sdram_cfg_2 = (((dll_rst_dis & 0x1) << 29) | ((dqs_cfg & 0x3) << 26) | ((odt_cfg & 0x3) << 21) | ((num_pr & 0xf) << 12) - | ((d_init & 0x1) << 4)); + | (x4_en << 10) + | ((obc_cfg & 0x1) << 6) + | ((d_init & 0x1) << 4) + | ((rcw_en & 0x1) << 2) + | ((md_en & 0x1) << 0) + ); +} + +static void set_ddr_sdram_mode_2(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, + const struct common_timing_params_s *dimm) +{ + uint16_t esdmode2; + uint32_t rtt_wr, srt = 0, cwl; + + cwl = compute_cas_write_latency() - 5; + + if (popts->rtt_override) + rtt_wr = popts->rtt_wr_override_value; + else + rtt_wr = popts->cs_local_opts[0].odt_rtt_wr; + + if (dimm->extended_op_srt) + srt = dimm->extended_op_srt; + + esdmode2 = (((rtt_wr & 0x3) << 9) + | ((srt & 0x1) << 7) + | ((cwl & 0x7) << 3) + ); + + ddr->ddr_sdram_mode_2 = (esdmode2 & 0xffff) << 16; } static void @@ -277,12 +411,107 @@ set_ddr_sdram_interval(struct fsl_ddr_cfg_regs_s *ddr, ddr->ddr_sdram_interval = (((refint & 0xFFFF) << 16) | ((bstopre & 0x3FFF) << 0)); } +void set_ddr3_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, + const struct common_timing_params_s *dimm, + uint32_t cas_latency, uint32_t additive_latency) +{ + uint16_t esdmode, sdmode; + /* Mode Register - MR1 */ + uint32_t rtt, al; + /* Mode Register - MR0 */ + uint32_t dll_on, wr = 0, dll_rst, mode, caslat = 4, bt, bl, wr_mclk; + /* + * DDR_SDRAM_MODE doesn't support 9,11,13,15 + * Please refer JEDEC Standard No. 79-3E for Mode Register MR0 + * for this table + */ + static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; + uint8_t cas_latency_table[] = { /* From 5 to 16 clocks */ + 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x1, 0x3, 0x5, 0x7, 0x9, + }; + const unsigned int mclk_ps = get_memory_clk_period_ps(); + + if (popts->rtt_override) + rtt = popts->rtt_override_value; + else + rtt = popts->cs_local_opts[0].odt_rtt_norm; + + if (additive_latency == (cas_latency - 1)) + al = 1; + else if (additive_latency == (cas_latency - 2)) + al = 2; + else + al = 0; + + /* + * The esdmode value will also be used for writing + * MR1 during write leveling for DDR3, although the + * bits specifically related to the write leveling + * scheme will be handled automatically by the DDR + * controller. So wrlvl_en is set to 0 here. + */ + esdmode = (((rtt & 0x4) << 7) + | ((rtt & 0x2) << 5) + | ((al & 0x3) << 3) + | ((rtt & 0x1) << 2) + ); -static void set_ddr_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, + /* + * DLL control for precharge PD + * 0=slow exit DLL off (tXPDLL) + * 1=fast exit DLL on (tXP) + */ + dll_on = 1; + + wr_mclk = (dimm->tWR_ps + mclk_ps - 1) / mclk_ps; + if (wr_mclk <= 16) + wr = wr_table[wr_mclk - 5]; + + dll_rst = 0; /* dll no reset */ + mode = 0; /* normal mode */ + + /* look up table to get the cas latency bits */ + if (cas_latency >= 5 && cas_latency <= 16) + caslat = cas_latency_table[cas_latency - 5]; + + /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ + bt = 0; + + switch (popts->burst_length) { + case DDR_BL8: + bl = 0; + break; + case DDR_OTF: + bl = 1; + break; + case DDR_BC4: + bl = 2; + break; + default: + bl = 1; + break; + } + + sdmode = (((dll_on & 0x1) << 12) + | ((wr & 0x7) << 9) + | ((dll_rst & 0x1) << 8) + | ((mode & 0x1) << 7) + | (((caslat >> 1) & 0x7) << 4) + | ((bt & 0x1) << 3) + | ((caslat & 1) << 2) + | ((bl & 0x3) << 0) + ); + + ddr->ddr_sdram_mode = (((esdmode & 0xffff) << 16) + | ((sdmode & 0xffff) << 0) + ); +} + +void set_ddr2_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, - uint32_t cas_latency, - uint32_t additive_latency) + uint32_t cas_latency, uint32_t additive_latency) { uint16_t esdmode, sdmode; uint32_t dqs_en, rtt, al, wr, bl; @@ -342,6 +571,19 @@ static void set_ddr_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, | ((sdmode & 0xFFFF) << 0)); } +void set_ddrx_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, + const struct common_timing_params_s *dimm, + uint32_t cas_latency, uint32_t additive_latency) +{ + if (popts->sdram_type == SDRAM_TYPE_DDR2) + set_ddr2_sdram_mode(ddr, popts, dimm, cas_latency, + additive_latency); + else + set_ddr3_sdram_mode(ddr, popts, dimm, cas_latency, + additive_latency); +} + uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr) { /* @@ -355,6 +597,98 @@ uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr) return 0; } +static void set_timing_cfg_4(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts) +{ + uint32_t rrt = 0, wwt = 0, dll_lock = 1; + + if (popts->burst_length != DDR_BL8) + rrt = wwt = 2; + + ddr->timing_cfg_4 = (((rrt & 0xf) << 20) + | ((wwt & 0xf) << 16) + | (dll_lock & 0x3) + ); +} + +static void set_timing_cfg_5(struct fsl_ddr_cfg_regs_s *ddr, + const struct memctl_options_s *popts, + uint32_t cas_latency) +{ + uint32_t rodt_on, rodt_off = 4, wodt_on = 1, wodt_off = 4; + + /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ + rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1; + + ddr->timing_cfg_5 = (((rodt_on & 0x1f) << 24) + | ((rodt_off & 0x7) << 20) + | ((wodt_on & 0x1f) << 12) + | ((wodt_off & 0x7) << 8) + ); +} + +static void set_ddr_zq_cntl(struct fsl_ddr_cfg_regs_s *ddr, uint32_t zq_en) +{ + uint32_t zqinit = 0, zqoper = 0, zqcs = 0; + + if (zq_en) { + zqinit = 9; + zqoper = 8; + zqcs = 6; + } + + ddr->ddr_zq_cntl = (((zq_en & 0x1) << 31) + | ((zqinit & 0xf) << 24) + | ((zqoper & 0xf) << 16) + | ((zqcs & 0xf) << 8) + ); +} + +static void set_ddr_wrlvl_cntl(struct fsl_ddr_cfg_regs_s *ddr, + uint32_t wrlvl_en, const struct memctl_options_s *popts) +{ + uint32_t wrlvl_mrd = 0, wrlvl_odten = 0, wrlvl_dqsen = 0, + wrlvl_wlr = 0, wrlvl_start = 0, wrlvl_smpl = 0; + + /* Enable write leveling for DDR3 due to fly-by topology */ + if (wrlvl_en) { + wrlvl_mrd = 0x6; + wrlvl_odten = 0x7; + wrlvl_dqsen = 0x5; + /* + * Write leveling sample time at least need 6 clocks + * higher than tWLO to allow enough time for progagation + * delay and sampling the prime data bits. + */ + wrlvl_smpl = 0xf; + /* + * Write leveling repetition time. At least tWLO + 6 clocks + * Set it to 64 + */ + wrlvl_wlr = 0x6; + /* + * Write leveling start time + * The value use for the DQS_ADJUST for the first sample + * when write leveling is enabled. It probably needs to be + * overriden per platform. + */ + wrlvl_start = 0x8; + if (popts->wrlvl_override) { + wrlvl_smpl = popts->wrlvl_sample; + wrlvl_start = popts->wrlvl_start; + } + } + + ddr->ddr_wrlvl_cntl = (((wrlvl_en & 0x1) << 31) + | ((wrlvl_mrd & 0x7) << 24) + | ((wrlvl_odten & 0x7) << 20) + | ((wrlvl_dqsen & 0x7) << 16) + | ((wrlvl_smpl & 0xf) << 12) + | ((wrlvl_wlr & 0x7) << 8) + | ((wrlvl_start & 0x1f) << 0) + ); +} + uint32_t compute_fsl_memctl_config_regs(const struct memctl_options_s *popts, struct fsl_ddr_cfg_regs_s *ddr, @@ -364,7 +698,7 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts, { struct ddr_board_info_s *binfo = popts->board_info; uint32_t cas_latency, additive_latency, i, cs_per_dimm, - dimm_number; + dimm_number, zq_en, wrlvl_en, sr_it = 0; uint64_t ea, sa, rank_density; if (dimm == NULL) @@ -383,6 +717,9 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts, else additive_latency = dimm->additive_latency; + if (popts->auto_self_refresh_en) + sr_it = popts->sr_it; + /* Chip Select Memory Bounds (CSn_BNDS) */ for (i = 0; i < binfo->cs_per_ctrl; i++) { cs_per_dimm = binfo->cs_per_ctrl / binfo->dimm_slots_per_ctrl; @@ -405,21 +742,37 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts, sa >>= 24; ea >>= 24; - ddr->cs[i].bnds = (((sa & 0xFFF) << 16) | ((ea & 0xFFF) << 0)); + ddr->cs[i].bnds = + (((sa & 0xffff) << 16) | ((ea & 0xffff) << 0)); set_csn_config(dimm_number, i, ddr, popts, dimmp); } - set_timing_cfg_0(ddr, popts); - set_timing_cfg_3(ddr, dimm, cas_latency); - set_timing_cfg_1(ddr, dimm, cas_latency); + set_timing_cfg_0(ddr, popts, dimmp); + set_timing_cfg_3(ddr, popts, dimm, cas_latency, additive_latency); + set_timing_cfg_1(ddr, popts, dimm, cas_latency); set_timing_cfg_2(ddr, popts, dimm, cas_latency, additive_latency); + + ddr->ddr_cdr1 = popts->ddr_cdr1; + ddr->ddr_cdr1 = popts->ddr_cdr2; + set_ddr_sdram_cfg(ddr, popts, dimm); set_ddr_sdram_cfg_2(ddr, popts); - set_ddr_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency); + set_ddrx_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency); + if (popts->sdram_type == SDRAM_TYPE_DDR3) { + set_ddr_sdram_mode_2(ddr, popts, dimm); + set_timing_cfg_4(ddr, popts); + set_timing_cfg_5(ddr, popts, cas_latency); + zq_en = (popts->zq_en) ? 1 : 0; + set_ddr_zq_cntl(ddr, zq_en); + wrlvl_en = (popts->wrlvl_en) ? 1 : 0; + set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts); + } set_ddr_sdram_interval(ddr, popts, dimm); ddr->ddr_data_init = popts->data_init; ddr->ddr_sdram_clk_cntl = (popts->clk_adjust & 0xF) << 23; + ddr->ddr_sr_cntr = (sr_it & 0xf) << 16; + return check_fsl_memctl_config_regs(ddr); } diff --git a/arch/ppc/ddr-8xxx/ddr.h b/arch/ppc/ddr-8xxx/ddr.h index 6574500acc..2ef87f2776 100644 --- a/arch/ppc/ddr-8xxx/ddr.h +++ b/arch/ppc/ddr-8xxx/ddr.h @@ -47,6 +47,17 @@ struct fsl_ddr_cfg_regs_s { uint32_t ddr_sdram_clk_cntl; uint32_t ddr_init_addr; uint32_t ddr_init_ext_addr; + uint32_t timing_cfg_4; + uint32_t timing_cfg_5; + uint32_t ddr_zq_cntl; + uint32_t ddr_wrlvl_cntl; + uint32_t ddr_wrlvl_cntl_2; + uint32_t ddr_wrlvl_cntl_3; + uint32_t ddr_sr_cntr; + uint32_t ddr_sdram_rcw_1; + uint32_t ddr_sdram_rcw_2; + uint32_t ddr_cdr1; + uint32_t ddr_cdr2; uint32_t err_disable; uint32_t err_int_en; uint32_t debug[32]; @@ -82,8 +93,8 @@ uint32_t compute_fsl_memctl_config_regs( uint32_t compute_dimm_parameters( const generic_spd_eeprom_t *spdin, struct dimm_params_s *pdimm); -uint32_t compute_lowest_common_dimm_parameters( - const struct dimm_params_s *dimm_params, +void compute_lowest_common_dimm_parameters( + const struct fsl_ddr_info_s *pinfo, struct common_timing_params_s *outpdimm, uint32_t number_of_dimms); uint32_t populate_memctl_options( diff --git a/arch/ppc/ddr-8xxx/ddr2_dimm_params.c b/arch/ppc/ddr-8xxx/ddr2_dimm_params.c index b36a8887da..cc7f3fa6ba 100644 --- a/arch/ppc/ddr-8xxx/ddr2_dimm_params.c +++ b/arch/ppc/ddr-8xxx/ddr2_dimm_params.c @@ -193,17 +193,12 @@ compute_dimm_parameters(const generic_spd_eeprom_t *spdin, const struct ddr2_spd_eeprom_s *spd = spdin; uint32_t retval; - if (!spd->mem_type) { - memset(pdimm, 0, sizeof(struct dimm_params_s)); - goto error; - } - if (spd->mem_type != SPD_MEMTYPE_DDR2) goto error; retval = ddr2_spd_checksum_pass(spd); if (retval) - goto spd_err; + goto error; /* * The part name in ASCII in the SPD EEPROM is not null terminated. @@ -298,6 +293,4 @@ compute_dimm_parameters(const generic_spd_eeprom_t *spdin, return 0; error: return 1; -spd_err: - return 2; } diff --git a/arch/ppc/ddr-8xxx/ddr2_setctrl.c b/arch/ppc/ddr-8xxx/ddr2_setctrl.c deleted file mode 100644 index 14571b0489..0000000000 --- a/arch/ppc/ddr-8xxx/ddr2_setctrl.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include "ddr.h" - -int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info) -{ - uint32_t i; - void __iomem *ddr; - const struct fsl_ddr_cfg_regs_s *regs; - - regs = &info->fsl_ddr_config_reg; - ddr = info->board_info.ddr_base; - - if (in_be32(ddr + DDR_OFF(SDRAM_CFG)) & SDRAM_CFG_MEM_EN) - return 0; - - for (i = 0; i < info->board_info.cs_per_ctrl; i++) { - out_be32(ddr + DDR_OFF(CS0_BNDS) + (i << 3), regs->cs[i].bnds); - out_be32(ddr + DDR_OFF(CS0_CONFIG) + (i << 2), - regs->cs[i].config); - } - - out_be32(ddr + DDR_OFF(TIMING_CFG_3), regs->timing_cfg_3); - out_be32(ddr + DDR_OFF(TIMING_CFG_0), regs->timing_cfg_0); - out_be32(ddr + DDR_OFF(TIMING_CFG_1), regs->timing_cfg_1); - out_be32(ddr + DDR_OFF(TIMING_CFG_2), regs->timing_cfg_2); - out_be32(ddr + DDR_OFF(SDRAM_CFG_2), regs->ddr_sdram_cfg_2); - out_be32(ddr + DDR_OFF(SDRAM_MODE), regs->ddr_sdram_mode); - out_be32(ddr + DDR_OFF(SDRAM_MODE_2), regs->ddr_sdram_mode_2); - out_be32(ddr + DDR_OFF(SDRAM_MD_CNTL), regs->ddr_sdram_md_cntl); - out_be32(ddr + DDR_OFF(SDRAM_INTERVAL), regs->ddr_sdram_interval); - out_be32(ddr + DDR_OFF(SDRAM_DATA_INIT), regs->ddr_data_init); - out_be32(ddr + DDR_OFF(SDRAM_CLK_CNTL), regs->ddr_sdram_clk_cntl); - out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR), regs->ddr_init_addr); - out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR_EXT), regs->ddr_init_ext_addr); - - early_udelay(200); - asm volatile("sync;isync"); - - out_be32(ddr + DDR_OFF(SDRAM_CFG), regs->ddr_sdram_cfg); - - /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ - while (in_be32(ddr + DDR_OFF(SDRAM_CFG_2)) & SDRAM_CFG2_D_INIT) - early_udelay(10000); - - return 0; -} diff --git a/arch/ppc/ddr-8xxx/ddr3_dimm_params.c b/arch/ppc/ddr-8xxx/ddr3_dimm_params.c new file mode 100644 index 0000000000..d510c5b265 --- /dev/null +++ b/arch/ppc/ddr-8xxx/ddr3_dimm_params.c @@ -0,0 +1,193 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * Dave Liu + * + * calculate the organization and timing parameter + * from ddr3 spd, please refer to the spec + * JEDEC standard No.21-C 4_01_02_11R18.pdf + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include "ddr.h" + +/* + * Calculate the Density of each Physical Rank. + * Returned size is in bytes. + * + * each rank size = + * sdram capacity(bit) / 8 * primary bus width / sdram width + * + * where: sdram capacity = spd byte4[3:0] + * primary bus width = spd byte8[2:0] + * sdram width = spd byte7[2:0] + * + * SPD byte4 - sdram density and banks + * bit[3:0] size(bit) size(byte) + * 0000 256Mb 32MB + * 0001 512Mb 64MB + * 0010 1Gb 128MB + * 0011 2Gb 256MB + * 0100 4Gb 512MB + * 0101 8Gb 1GB + * 0110 16Gb 2GB + * + * SPD byte8 - module memory bus width + * bit[2:0] primary bus width + * 000 8bits + * 001 16bits + * 010 32bits + * 011 64bits + * + * SPD byte7 - module organiztion + * bit[2:0] sdram device width + * 000 4bits + * 001 8bits + * 010 16bits + * 011 32bits + */ +static uint64_t compute_ranksize(const struct ddr3_spd_eeprom_s *spd) +{ + uint64_t bsize; + int sdram_cap_bsize = 0, prim_bus_width = 0, sdram_width = 0; + + if ((spd->density_banks & 0xf) < 7) + sdram_cap_bsize = (spd->density_banks & 0xf) + 28; + if ((spd->bus_width & 0x7) < 4) + prim_bus_width = (spd->bus_width & 0x7) + 3; + if ((spd->organization & 0x7) < 4) + sdram_width = (spd->organization & 0x7) + 2; + + bsize = 1ULL << (sdram_cap_bsize - 3 + prim_bus_width - sdram_width); + + return bsize; +} + +/* + * compute_dimm_parameters for DDR3 SPD + * + * Compute DIMM parameters based upon the SPD information in spd. + * Writes the results to the dimm_params_s structure pointed by pdimm. + * + */ +uint32_t +compute_dimm_parameters(const generic_spd_eeprom_t *spdin, + struct dimm_params_s *pdimm) +{ + const struct ddr3_spd_eeprom_s *spd = spdin; + uint32_t retval, mtb_ps; + int ftb_tmp; + + if (spd->mem_type != SPD_MEMTYPE_DDR3) + goto error; + + retval = ddr3_spd_checksum_pass(spd); + if (retval) + goto error; + + memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); + if ((spd->info_size_crc & 0xf) > 1) + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + + /* DIMM organization parameters */ + pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; + pdimm->rank_density = compute_ranksize(spd); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + pdimm->data_width = pdimm->primary_sdram_width + pdimm->ec_sdram_width; + pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); + if ((spd->bus_width >> 3) & 0x3) + pdimm->ec_sdram_width = 8; + else + pdimm->ec_sdram_width = 0; + pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); + + /* These are the types defined by the JEDEC DDR3 SPD spec */ + pdimm->mirrored_dimm = 0; + pdimm->registered_dimm = 0; + switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) { + case DDR3_SPD_MODULETYPE_UDIMM: + /* Unbuffered DIMMs */ + if (spd->mod_section.unbuffered.addr_mapping & 0x1) + pdimm->mirrored_dimm = 1; + break; + + default: + goto error; + } + + /* SDRAM device parameters */ + pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; + pdimm->n_col_addr = (spd->addressing & 0x7) + 9; + pdimm->n_banks_per_sdram_device = + 8 << ((spd->density_banks >> 4) & 0x7); + + /* + * The SPD spec does not define an ECC bit. The DIMM is considered + * to have ECC capability if the extension bus exists. + */ + if (pdimm->ec_sdram_width) + pdimm->edc_config = 0x02; + else + pdimm->edc_config = 0x00; + + /* + * The SPD spec does not define the burst length byte. + * but the DDR3 spec defines BL8 and BC4, on bit 3 and + * bit 2. + */ + pdimm->burst_lengths_bitmask = 0x0c; + pdimm->row_density = __ilog2(pdimm->rank_density); + + mtb_ps = (spd->mtb_dividend * 1000) / spd->mtb_divisor; + pdimm->mtb_ps = mtb_ps; + + ftb_tmp = spd->ftb_div & 0xf0; + pdimm->ftb_10th_ps = ((ftb_tmp >> 4) * 10) / ftb_tmp; + + pdimm->tCKmin_X_ps = spd->tck_min * mtb_ps + + (spd->fine_tck_min * ftb_tmp) / 10; + pdimm->caslat_X = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4; + + pdimm->taa_ps = spd->taa_min * mtb_ps + + (spd->fine_taa_min * ftb_tmp) / 10; + + pdimm->tRCD_ps = spd->trcd_min * mtb_ps + + (spd->fine_trcd_min * ftb_tmp) / 10; + + pdimm->tRP_ps = spd->trp_min * mtb_ps + + (spd->fine_trp_min * ftb_tmp) / 10; + pdimm->tRAS_ps = (((spd->tras_trc_ext & 0xf) << 8) | spd->tras_min_lsb) + * mtb_ps; + pdimm->tWR_ps = spd->twr_min * mtb_ps; + pdimm->tWTR_ps = spd->twtr_min * mtb_ps; + pdimm->tRFC_ps = ((spd->trfc_min_msb << 8) | spd->trfc_min_lsb) + * mtb_ps; + pdimm->tRRD_ps = spd->trrd_min * mtb_ps; + pdimm->tRC_ps = (((spd->tras_trc_ext & 0xf0) << 4) | spd->trc_min_lsb); + pdimm->tRC_ps *= mtb_ps; + pdimm->tRC_ps += (spd->fine_trc_min * ftb_tmp) / 10; + + pdimm->tRTP_ps = spd->trtp_min * mtb_ps; + + /* + * Average periodic refresh interval + * tREFI = 7.8 us at normal temperature range + * = 3.9 us at ext temperature range + */ + pdimm->refresh_rate_ps = 7800000; + if ((spd->therm_ref_opt & 0x1) && !(spd->therm_ref_opt & 0x2)) { + pdimm->refresh_rate_ps = 3900000; + pdimm->extended_op_srt = 1; + } + + pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) + * mtb_ps; + + return 0; +error: + return 1; +} diff --git a/arch/ppc/ddr-8xxx/ddr_setctrl.c b/arch/ppc/ddr-8xxx/ddr_setctrl.c new file mode 100644 index 0000000000..115fb42070 --- /dev/null +++ b/arch/ppc/ddr-8xxx/ddr_setctrl.c @@ -0,0 +1,90 @@ +/* + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "ddr.h" + +int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info) +{ + uint32_t i, temp_sdram_cfg; + void __iomem *ddr; + const struct fsl_ddr_cfg_regs_s *regs; + + regs = &info->fsl_ddr_config_reg; + ddr = info->board_info.ddr_base; + + if (in_be32(ddr + DDR_OFF(SDRAM_CFG)) & SDRAM_CFG_MEM_EN) + return 0; + + for (i = 0; i < info->board_info.cs_per_ctrl; i++) { + out_be32(ddr + DDR_OFF(CS0_BNDS) + (i << 3), regs->cs[i].bnds); + out_be32(ddr + DDR_OFF(CS0_CONFIG) + (i << 2), + regs->cs[i].config); + if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3) + out_be32(ddr + DDR_OFF(CS0_CONFIG_2) + (i << 2), + regs->cs[i].config_2); + } + + out_be32(ddr + DDR_OFF(TIMING_CFG_3), regs->timing_cfg_3); + out_be32(ddr + DDR_OFF(TIMING_CFG_0), regs->timing_cfg_0); + out_be32(ddr + DDR_OFF(TIMING_CFG_1), regs->timing_cfg_1); + out_be32(ddr + DDR_OFF(TIMING_CFG_2), regs->timing_cfg_2); + out_be32(ddr + DDR_OFF(SDRAM_CFG_2), regs->ddr_sdram_cfg_2); + out_be32(ddr + DDR_OFF(SDRAM_MODE), regs->ddr_sdram_mode); + out_be32(ddr + DDR_OFF(SDRAM_MODE_2), regs->ddr_sdram_mode_2); + out_be32(ddr + DDR_OFF(SDRAM_MD_CNTL), regs->ddr_sdram_md_cntl); + out_be32(ddr + DDR_OFF(SDRAM_INTERVAL), regs->ddr_sdram_interval); + out_be32(ddr + DDR_OFF(SDRAM_DATA_INIT), regs->ddr_data_init); + out_be32(ddr + DDR_OFF(SDRAM_CLK_CNTL), regs->ddr_sdram_clk_cntl); + out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR), regs->ddr_init_addr); + out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR_EXT), regs->ddr_init_ext_addr); + + if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3) { + out_be32(ddr + DDR_OFF(TIMING_CFG_4), regs->timing_cfg_4); + out_be32(ddr + DDR_OFF(TIMING_CFG_5), regs->timing_cfg_5); + out_be32(ddr + DDR_OFF(ZQ_CNTL), regs->ddr_zq_cntl); + out_be32(ddr + DDR_OFF(WRLVL_CNTL), regs->ddr_wrlvl_cntl); + + if (regs->ddr_wrlvl_cntl_2) + out_be32(ddr + DDR_OFF(WRLVL_CNTL_2), + regs->ddr_wrlvl_cntl_2); + if (regs->ddr_wrlvl_cntl_3) + out_be32(ddr + DDR_OFF(WRLVL_CNTL_3), + regs->ddr_wrlvl_cntl_3); + + out_be32(ddr + DDR_OFF(SR_CNTL), regs->ddr_sr_cntr); + out_be32(ddr + DDR_OFF(SDRAM_RCW_1), regs->ddr_sdram_rcw_1); + out_be32(ddr + DDR_OFF(SDRAM_RCW_2), regs->ddr_sdram_rcw_2); + out_be32(ddr + DDR_OFF(DDRCDR1), regs->ddr_cdr1); + out_be32(ddr + DDR_OFF(DDRCDR2), regs->ddr_cdr2); + } + + out_be32(ddr + DDR_OFF(ERR_DISABLE), regs->err_disable); + out_be32(ddr + DDR_OFF(ERR_INT_EN), regs->err_int_en); + + temp_sdram_cfg = regs->ddr_sdram_cfg; + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); + out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg); + + early_udelay(500); + /* Make sure all instructions are completed before enabling memory.*/ + asm volatile("sync;isync"); + temp_sdram_cfg = in_be32(ddr + DDR_OFF(SDRAM_CFG)) & ~SDRAM_CFG_BI; + out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg | SDRAM_CFG_MEM_EN); + asm volatile("sync;isync"); + + while (in_be32(ddr + DDR_OFF(SDRAM_CFG_2)) & SDRAM_CFG2_D_INIT) + early_udelay(10000); + + return 0; +} diff --git a/arch/ppc/ddr-8xxx/lc_common_dimm_params.c b/arch/ppc/ddr-8xxx/lc_common_dimm_params.c index a1addb0696..9d90fb76db 100644 --- a/arch/ppc/ddr-8xxx/lc_common_dimm_params.c +++ b/arch/ppc/ddr-8xxx/lc_common_dimm_params.c @@ -12,6 +12,36 @@ #include "ddr.h" +static uint32_t +compute_cas_latency_ddr3(const struct dimm_params_s *dimm_params, + uint32_t number_of_dimms) +{ + uint32_t i, taamin_ps = 0, tckmin_x_ps = 0, common_caslat, + caslat_actual, retry = 16; + const uint32_t mclk_ps = get_memory_clk_period_ps(); + + /* compute the common CAS latency supported between slots */ + common_caslat = dimm_params[0].caslat_X; + for (i = 1; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) + common_caslat &= dimm_params[i].caslat_X; + } + + for (i = 0; i < number_of_dimms; i++) { + taamin_ps = max(taamin_ps, dimm_params[i].taa_ps); + tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tCKmin_X_ps); + } + + caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps; + /* check if the dimms support the CAS latency */ + while (!(common_caslat & (1 << caslat_actual)) && retry > 0) { + caslat_actual++; + retry--; + } + + return caslat_actual; +} + static unsigned int common_burst_length( const struct dimm_params_s *dimm_params, const unsigned int number_of_dimms) @@ -22,7 +52,6 @@ static unsigned int common_burst_length( for (i = 0; i < number_of_dimms; i++) if (dimm_params[i].n_ranks) temp &= dimm_params[i].burst_lengths_bitmask; - return temp; } @@ -115,16 +144,17 @@ static unsigned int compute_lowest_caslat( * whose parameters have been computed into the array pointed to * by dimm_params. */ -unsigned int -compute_lowest_common_dimm_parameters(const struct dimm_params_s *dimm, +void compute_lowest_common_dimm_parameters(const struct fsl_ddr_info_s *pinfo, struct common_timing_params_s *out, const unsigned int number_of_dimms) { - const uint32_t mclk_ps = get_memory_clk_period_ps(); uint32_t temp1, i; struct common_timing_params_s tmp = {0}; + const struct dimm_params_s *dimm = pinfo->dimm_params; + const struct memctl_options_s *popts = &pinfo->memctl_opts; tmp.tCKmax_ps = 0xFFFFFFFF; + tmp.extended_op_srt = 1; temp1 = 0; for (i = 0; i < number_of_dimms; i++) { if (dimm[i].n_ranks == 0) { @@ -157,58 +187,69 @@ compute_lowest_common_dimm_parameters(const struct dimm_params_s *dimm, tmp.tQHS_ps = max(tmp.tQHS_ps, dimm[i].tQHS_ps); tmp.refresh_rate_ps = max(tmp.refresh_rate_ps, dimm[i].refresh_rate_ps); + tmp.extended_op_srt = min(tmp.extended_op_srt, + dimm[i].extended_op_srt); /* Find maximum tDQSQ_max_ps to find slowest timing. */ tmp.tDQSQ_max_ps = max(tmp.tDQSQ_max_ps, dimm[i].tDQSQ_max_ps); } tmp.ndimms_present = number_of_dimms - temp1; if (temp1 == number_of_dimms) - return 0; + return; temp1 = common_burst_length(dimm, number_of_dimms); tmp.all_DIMMs_burst_lengths_bitmask = temp1; - tmp.all_DIMMs_registered = 0; - tmp.lowest_common_SPD_caslat = compute_lowest_caslat(dimm, - number_of_dimms); - /* - * Compute a common 'de-rated' CAS latency. - * - * The strategy here is to find the *highest* de-rated cas latency - * with the assumption that all of the DIMMs will support a de-rated - * CAS latency higher than or equal to their lowest de-rated value. - */ - temp1 = 0; - for (i = 0; i < number_of_dimms; i++) - temp1 = max(temp1, dimm[i].caslat_lowest_derated); - tmp.highest_common_derated_caslat = temp1; + /* Support only unbuffered DIMMs */ + tmp.all_DIMMs_registered = 0; + tmp.all_DIMMs_unbuffered = 1; + + if (popts->sdram_type == SDRAM_TYPE_DDR3) { + tmp.lowest_common_SPD_caslat = compute_cas_latency_ddr3(dimm, + number_of_dimms); + } else { + tmp.lowest_common_SPD_caslat = compute_lowest_caslat(dimm, + number_of_dimms); + /* + * Compute a common 'de-rated' CAS latency. + * + * The strategy here is to find the *highest* de-rated cas + * latency with the assumption that all of the DIMMs will + * support a de-rated CAS latency higher than or equal to + * their lowest de-rated value. + */ + temp1 = 0; + for (i = 0; i < number_of_dimms; i++) + temp1 = max(temp1, dimm[i].caslat_lowest_derated); + tmp.highest_common_derated_caslat = temp1; + } temp1 = 1; for (i = 0; i < number_of_dimms; i++) - if (dimm[i].n_ranks && - !(dimm[i].edc_config & EDC_ECC)) { + if (dimm[i].n_ranks && !(dimm[i].edc_config & EDC_ECC)) { temp1 = 0; break; } tmp.all_DIMMs_ECC_capable = temp1; - if (mclk_ps > tmp.tCKmax_max_ps) - return 1; - /* * AL must be less or equal to tRCD. Typically, AL would * be AL = tRCD - 1; * * When ODT read or write is enabled the sum of CAS latency + * additive latency must be at least 3 cycles. - * */ - if ((tmp.lowest_common_SPD_caslat < 4) && (picos_to_mclk(tmp.tRCD_ps) > - tmp.lowest_common_SPD_caslat)) - tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps) - - tmp.lowest_common_SPD_caslat; + tmp.additive_latency = 0; + if (popts->sdram_type == SDRAM_TYPE_DDR2) { + if ((tmp.lowest_common_SPD_caslat < 4) && + (picos_to_mclk(tmp.tRCD_ps) > + tmp.lowest_common_SPD_caslat)) + tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps) - + tmp.lowest_common_SPD_caslat; + + if (mclk_to_picos(tmp.additive_latency) > tmp.tRCD_ps) + tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps); + } memcpy(out, &tmp, sizeof(struct common_timing_params_s)); - - return 0; } diff --git a/arch/ppc/ddr-8xxx/main.c b/arch/ppc/ddr-8xxx/main.c index 6e4a02d568..99b877b5ca 100644 --- a/arch/ppc/ddr-8xxx/main.c +++ b/arch/ppc/ddr-8xxx/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "ddr.h" static int get_spd(generic_spd_eeprom_t *spd, @@ -143,6 +144,14 @@ static uint32_t compute_dimm_param(struct fsl_ddr_info_s *pinfo, uint32_t ndimm) generic_spd_eeprom_t *spd; uint32_t i, retval; + spd = &(pinfo->spd_installed_dimms[0]); + if (spd->mem_type == SPD_MEMTYPE_DDR3) + pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR3; + else if (spd->mem_type == SPD_MEMTYPE_DDR2) + pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR2; + else + return 1; + for (i = 0; i < ndimm; i++) { spd = &(pinfo->spd_installed_dimms[i]); pdimm = &(pinfo->dimm_params[i]); @@ -185,8 +194,7 @@ uint64_t fsl_ddr_compute(struct fsl_ddr_info_s *pinfo) * STEP 3: Compute a common set of timing parameters * suitable for all of the DIMMs on each memory controller */ - compute_lowest_common_dimm_parameters(pinfo->dimm_params, - timing_params, ndimm); + compute_lowest_common_dimm_parameters(pinfo, timing_params, ndimm); /* STEP 4: Gather configuration requirements from user */ populate_memctl_options(timing_params->all_DIMMs_registered, diff --git a/arch/ppc/ddr-8xxx/options.c b/arch/ppc/ddr-8xxx/options.c index 9ce2bc1b80..ccf5d5e9d8 100644 --- a/arch/ppc/ddr-8xxx/options.c +++ b/arch/ppc/ddr-8xxx/options.c @@ -46,18 +46,42 @@ uint32_t populate_memctl_options(int all_DIMMs_registered, * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit */ if (pdimm->n_ranks != 0) { - if ((pdimm->data_width >= 64) && (pdimm->data_width <= 72)) - popts->data_bus_width = 0; - else if ((pdimm->data_width >= 32) && - (pdimm->data_width <= 40)) - popts->data_bus_width = 1; - else - panic("data width %u is invalid!\n", - pdimm->data_width); + if (popts->sdram_type == SDRAM_TYPE_DDR3) { + if (pdimm[0].primary_sdram_width == 64) + popts->data_bus_width = 0; + else if (pdimm[0].primary_sdram_width == 32) + popts->data_bus_width = 1; + else if (pdimm[0].primary_sdram_width == 16) + popts->data_bus_width = 2; + else + hang(); + } else { + if ((pdimm->data_width >= 64) && + (pdimm->data_width <= 72)) + popts->data_bus_width = 0; + else if ((pdimm->data_width >= 32) && + (pdimm->data_width <= 40)) + popts->data_bus_width = 1; + else + hang(); + } + } + + if (popts->sdram_type == SDRAM_TYPE_DDR3) { + if (popts->data_bus_width == 0) { + popts->otf_burst_chop_en = 1; + popts->burst_length = DDR_OTF; + } else { + /* 32-bit or 16-bit bus */ + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + } + popts->mirrored_dimm = pdimm[0].mirrored_dimm; + } else { + /* Must be a burst length of 4 for DDR2 */ + popts->burst_length = DDR_BL4; } - /* Must be a burst length of 4 for DD2 */ - popts->burst_length = DDR_BL4; /* Decide whether to use the computed de-rated latency */ popts->use_derated_caslat = 0; @@ -70,6 +94,7 @@ uint32_t populate_memctl_options(int all_DIMMs_registered, * - how much time you want to spend playing around */ popts->twoT_en = 0; + popts->threet_en = 0; /* * Default BSTTOPRE precharge interval @@ -90,7 +115,18 @@ uint32_t populate_memctl_options(int all_DIMMs_registered, * The default value below would work for x4/x8 wide memory. * */ - popts->tFAW_window_four_activates_ps = 37500; + if (popts->sdram_type == SDRAM_TYPE_DDR2) { + popts->tFAW_window_four_activates_ps = 37500; + } else { + /* + * Due to ddr3 dimm fly-by topology, enable write leveling + * to meet the tQDSS under different loading. + */ + popts->tFAW_window_four_activates_ps = pdimm[0].tfaw_ps; + popts->wrlvl_en = 1; + popts->zq_en = 1; + popts->wrlvl_override = 0; + } /* * Default powerdown exit timings. diff --git a/arch/ppc/include/asm/fsl_ddr_dimm_params.h b/arch/ppc/include/asm/fsl_ddr_dimm_params.h index 73c239be85..9e6f6b4d34 100644 --- a/arch/ppc/include/asm/fsl_ddr_dimm_params.h +++ b/arch/ppc/include/asm/fsl_ddr_dimm_params.h @@ -21,6 +21,8 @@ struct dimm_params_s { uint32_t primary_sdram_width; uint32_t ec_sdram_width; uint32_t registered_dimm; + uint32_t device_width; + /* SDRAM device parameters */ uint32_t n_row_addr; uint32_t n_col_addr; uint32_t edc_config; /* 0 = none, 1 = parity, 2 = ECC */ @@ -28,6 +30,11 @@ struct dimm_params_s { uint32_t burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */ uint32_t row_density; uint64_t base_address; + uint32_t mirrored_dimm; + uint32_t mtb_ps; + uint32_t ftb_10th_ps; + uint32_t taa_ps; + uint32_t tfaw_ps; /* SDRAM clock periods */ uint32_t tCKmin_X_ps; uint32_t tCKmin_X_minus_1_ps; @@ -48,6 +55,7 @@ struct dimm_params_s { uint32_t tRRD_ps; /* maximum = 63750 ps */ uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ uint32_t refresh_rate_ps; + uint32_t extended_op_srt; uint32_t tIS_ps; /* byte 32, spd->ca_setup */ uint32_t tIH_ps; /* byte 33, spd->ca_hold */ uint32_t tDS_ps; /* byte 34, spd->data_setup */ @@ -55,6 +63,7 @@ struct dimm_params_s { uint32_t tRTP_ps; /* byte 38, spd->trtp */ uint32_t tDQSQ_max_ps; /* byte 44, spd->tdqsq */ uint32_t tQHS_ps; /* byte 45, spd->tqhs */ + uint32_t rcw[16]; }; #endif diff --git a/arch/ppc/include/asm/fsl_ddr_sdram.h b/arch/ppc/include/asm/fsl_ddr_sdram.h index 444bcbc497..f0f3a63355 100644 --- a/arch/ppc/include/asm/fsl_ddr_sdram.h +++ b/arch/ppc/include/asm/fsl_ddr_sdram.h @@ -19,17 +19,24 @@ #define SDRAM_TYPE_DDR3 7 #define DDR_BL4 4 +#define DDR_BC4 DDR_BL4 +#define DDR_OTF 6 #define DDR_BL8 8 #define DDR2_RTT_OFF 0 #define DDR2_RTT_75_OHM 1 #define DDR2_RTT_150_OHM 2 #define DDR2_RTT_50_OHM 3 +#define DDR3_RTT_OFF 0 +#define DDR3_RTT_40_OHM 3 -#if defined(CONFIG_FSL_DDR2) #define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) +#if defined(CONFIG_FSL_DDR2) typedef struct ddr2_spd_eeprom_s generic_spd_eeprom_t; #define FSL_SDRAM_TYPE SDRAM_TYPE_DDR2 +#elif defined(CONFIG_FSL_DDR3) +typedef struct ddr3_spd_eeprom_s generic_spd_eeprom_t; +#define FSL_SDRAM_TYPE SDRAM_TYPE_DDR3 #endif #define FSL_DDR_ODT_NEVER 0x0 @@ -121,6 +128,10 @@ struct memctl_options_s { uint32_t dynamic_power; uint32_t data_bus_width; uint32_t burst_length; + uint32_t otf_burst_chop_en; + uint32_t mirrored_dimm; + uint32_t ap_en; + uint32_t x4_en; /* Global Timing Parameters */ uint32_t cas_latency_override; uint32_t cas_latency_override_value; @@ -130,16 +141,36 @@ struct memctl_options_s { uint32_t clk_adjust; uint32_t cpo_override; uint32_t write_data_delay; + /* Write leveling */ + uint32_t wrlvl_override; + uint32_t wrlvl_sample; + uint32_t wrlvl_start; + uint32_t wrlvl_ctl_2; + uint32_t wrlvl_ctl_3; uint32_t half_strength_driver_enable; uint32_t twoT_en; + uint32_t threet_en; uint32_t bstopre; uint32_t tCKE_clock_pulse_width_ps; uint32_t tFAW_window_four_activates_ps; /* Rtt impedance */ uint32_t rtt_override; uint32_t rtt_override_value; + uint32_t rtt_wr_override_value; /* Automatic self refresh */ uint32_t auto_self_refresh_en; + uint32_t sr_it; + /* ZQ calibration */ + uint32_t zq_en; + /* Write leveling */ + uint32_t wrlvl_en; + /* RCW override for RDIMM */ + uint32_t rcw_override; + uint32_t rcw_1; + uint32_t rcw_2; + /* control register 1 */ + uint32_t ddr_cdr1; + uint32_t ddr_cdr2; /* read-to-write turnaround */ uint32_t trwt_override; uint32_t trwt; -- cgit v1.2.3 From e172c508c62542e85843f64f91b339d555cbf2e4 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:10:01 +0000 Subject: ppc: add Freescale P1022DS board support Add support for the Freescale P1022DS. Driver support is limited to: - I2C - Ethernet - Serial - NOR flash - PIXIS FPGA System clock configuration is read from the FPGA but has only been tested using a 133MHz system clock and 100MHz DDR clock. Boot arguments are defined in the environment to boot over NFS with a console configured at 115200 bauds. Enabling branch prediction is moved from board support to the platform support for all boards as it is a CPU feature. Some the code is from U-Boot version git-be937b5. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/boards/freescale-p1022ds/Makefile | 5 + arch/ppc/boards/freescale-p1022ds/config.h | 55 ++++++++ arch/ppc/boards/freescale-p1022ds/ddr.c | 126 +++++++++++++++++ arch/ppc/boards/freescale-p1022ds/env/bin/init | 2 + arch/ppc/boards/freescale-p1022ds/env/config | 2 + arch/ppc/boards/freescale-p1022ds/ics307_clk.c | 46 +++++++ arch/ppc/boards/freescale-p1022ds/law.c | 27 ++++ arch/ppc/boards/freescale-p1022ds/p1022ds.c | 181 +++++++++++++++++++++++++ arch/ppc/boards/freescale-p1022ds/p1022ds.h | 14 ++ arch/ppc/boards/freescale-p1022ds/tlb.c | 59 ++++++++ arch/ppc/boards/freescale-p2020rdb/config.h | 2 - arch/ppc/boards/geip-da923rc/config.h | 1 - arch/ppc/configs/p1022ds_defconfig | 53 ++++++++ arch/ppc/cpu-85xx/start.S | 2 +- arch/ppc/mach-mpc85xx/Kconfig | 4 + 15 files changed, 575 insertions(+), 4 deletions(-) create mode 100644 arch/ppc/boards/freescale-p1022ds/Makefile create mode 100644 arch/ppc/boards/freescale-p1022ds/config.h create mode 100644 arch/ppc/boards/freescale-p1022ds/ddr.c create mode 100644 arch/ppc/boards/freescale-p1022ds/env/bin/init create mode 100644 arch/ppc/boards/freescale-p1022ds/env/config create mode 100644 arch/ppc/boards/freescale-p1022ds/ics307_clk.c create mode 100644 arch/ppc/boards/freescale-p1022ds/law.c create mode 100644 arch/ppc/boards/freescale-p1022ds/p1022ds.c create mode 100644 arch/ppc/boards/freescale-p1022ds/p1022ds.h create mode 100644 arch/ppc/boards/freescale-p1022ds/tlb.c create mode 100644 arch/ppc/configs/p1022ds_defconfig diff --git a/arch/ppc/boards/freescale-p1022ds/Makefile b/arch/ppc/boards/freescale-p1022ds/Makefile new file mode 100644 index 0000000000..e9b59d5ccb --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/Makefile @@ -0,0 +1,5 @@ +obj-y += p1022ds.o +obj-y += law.o +obj-y += tlb.o +obj-y += ddr.o +obj-y += ics307_clk.o diff --git a/arch/ppc/boards/freescale-p1022ds/config.h b/arch/ppc/boards/freescale-p1022ds/config.h new file mode 100644 index 0000000000..666b9ff987 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/config.h @@ -0,0 +1,55 @@ +/* + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * 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. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#ifndef __ASSEMBLY__ +extern unsigned long ics307_clk_freq(unsigned int reg); +#endif +#define CFG_SYS_CLK_FREQ ics307_clk_freq(25) +#define CFG_DDR_CLK_FREQ ics307_clk_freq(28) + +#define CFG_CHIP_SELECTS_PER_CTRL 2 + +/* + * Memory map + * + * 0x0000_0000 0x7fff_ffff DDR 2G cacheable + * + * Localbus non-cacheable + * 0xe800_0000 0xefff_ffff FLASH 128M non-cacheable + * 0xffdf_0000 0xffdf_0fff PIXIS 4K Cacheable + * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0 + */ +#define CFG_SDRAM_BASE 0x00000000 + +#define CFG_CCSRBAR_DEFAULT 0xff700000 +#define CFG_CCSRBAR 0xffe00000 +#define CFG_CCSRBAR_PHYS CFG_CCSRBAR +#define CFG_IMMR CFG_CCSRBAR + +#define CFG_INIT_RAM_ADDR 0xffd00000 +#define CFG_INIT_RAM_SIZE 0x00004000 +#define CFG_INIT_BI_SIZE 0x00000100 +#define CFG_INIT_SP_OFFSET (CFG_INIT_RAM_SIZE - CFG_INIT_BI_SIZE) + +#define CFG_BOOT_BLOCK 0xe0000000 +#define CFG_BOOT_BLOCK_PHYS CFG_BOOT_BLOCK +#define CFG_FLASH_BASE 0xe8000000 +#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE +#define CFG_PIXIS_BASE 0xffdf0000 +#define CFG_PIXIS_BASE_PHYS CFG_PIXIS_BASE + +#endif /* __CONFIG_H */ diff --git a/arch/ppc/boards/freescale-p1022ds/ddr.c b/arch/ppc/boards/freescale-p1022ds/ddr.c new file mode 100644 index 0000000000..1944518c79 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/ddr.c @@ -0,0 +1,126 @@ +/* + * Copyright 2010 Freescale Semiconductor, Inc. + * Authors: Srikanth Srinivasan + * Timur Tabi + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "p1022ds.h" + +static const u8 spd_addr = 0x51; + +int fsl_ddr_board_info(struct ddr_board_info_s *info) +{ + /* + * Early mapping is needed to access the clock + * parameters in the FPGA. + */ + p1022ds_lbc_early_init(); + + info->fsl_ddr_ver = 0; + info->ddr_base = IOMEM(MPC85xx_DDR_ADDR); + /* Actual number of chip select used */ + info->cs_per_ctrl = CFG_CHIP_SELECTS_PER_CTRL; + info->dimm_slots_per_ctrl = 1; + info->i2c_bus = 1; + info->i2c_slave = 0x7f; + info->i2c_speed = 400000; + info->i2c_base = IOMEM(I2C2_BASE_ADDR); + info->spd_i2c_addr = &spd_addr; + + return 0; +} + +struct board_specific_parameters { + u32 n_ranks; + u32 datarate_mhz_high; + u32 clk_adjust; /* Range: 0-8 */ + u32 cpo; /* Range: 2-31 */ + u32 write_data_delay; /* Range: 0-6 */ + u32 force_2t; +}; + +/* + * This table contains all valid speeds we want to override with board + * specific parameters. datarate_mhz_high values need to be in ascending order + * for each n_ranks group. + */ +static const struct board_specific_parameters dimm0[] = { + /* + * memory controller 0 + * num| hi| clk| cpo|wrdata|2T + * ranks| mhz|adjst| | delay| + */ + { 1, 549, 5, 31, 3, 0 }, + { 1, 850, 5, 31, 5, 0 }, + { 2, 549, 5, 31, 3, 0 }, + { 2, 850, 5, 31, 5, 0 }, + { } +}; + +void fsl_ddr_board_options(struct memctl_options_s *popts, + struct dimm_params_s *pdimm) +{ + const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; + unsigned long ddr_freq; + uint32_t i; + + for (i = 0; i < popts->board_info->cs_per_ctrl; i++) { + popts->cs_local_opts[i].odt_rd_cfg = 0; + popts->cs_local_opts[i].odt_wr_cfg = 1; + popts->cs_local_opts[i].odt_rtt_wr = DDR3_RTT_OFF; + } + popts->cs_local_opts[0].odt_rtt_norm = DDR3_RTT_40_OHM; + popts->cs_local_opts[1].odt_rtt_norm = DDR3_RTT_OFF; + + pbsp = dimm0; + + ddr_freq = fsl_get_ddr_freq(0) / 1000000; + /* + * To have optimal parameters specific to the board, do a fine + * adjustment of DDR parameters depending on the DDR data rate. + */ + while (pbsp->datarate_mhz_high) { + if (pbsp->n_ranks == pdimm->n_ranks) { + if (ddr_freq <= pbsp->datarate_mhz_high) { + popts->clk_adjust = pbsp->clk_adjust; + popts->cpo_override = pbsp->cpo; + popts->write_data_delay = + pbsp->write_data_delay; + popts->twoT_en = pbsp->force_2t; + goto found; + } + pbsp_highest = pbsp; + } + pbsp++; + } + + /* Use highest parameters if none were found */ + if (pbsp_highest) { + popts->clk_adjust = pbsp->clk_adjust; + popts->cpo_override = pbsp->cpo; + popts->write_data_delay = pbsp->write_data_delay; + popts->twoT_en = pbsp->force_2t; + } + +found: + popts->half_strength_driver_enable = 1; + + /* Per AN4039, enable ZQ calibration. */ + popts->zq_en = 1; + + popts->auto_self_refresh_en = 1; + popts->sr_it = 0xb; + + popts->dll_rst_dis = 1; +} diff --git a/arch/ppc/boards/freescale-p1022ds/env/bin/init b/arch/ppc/boards/freescale-p1022ds/env/bin/init new file mode 100644 index 0000000000..c0e04c1f2d --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/env/bin/init @@ -0,0 +1,2 @@ +#!/bin/sh +source /env/config diff --git a/arch/ppc/boards/freescale-p1022ds/env/config b/arch/ppc/boards/freescale-p1022ds/env/config new file mode 100644 index 0000000000..bffd86882e --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/env/config @@ -0,0 +1,2 @@ +#!/bin/sh +export bootargs="root=/dev/nfs rw ip=bootp console=ttyS0,115200" \ No newline at end of file diff --git a/arch/ppc/boards/freescale-p1022ds/ics307_clk.c b/arch/ppc/boards/freescale-p1022ds/ics307_clk.c new file mode 100644 index 0000000000..f7c5bbde99 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/ics307_clk.c @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +/* decode S[0-2] to Output Divider (OD) */ +static u8 ics307_s_to_od[] = { + 10, 2, 8, 4, 5, 7, 3, 6 +}; + +/* Calculate frequency being generated by ICS307-02 clock chip. */ +unsigned long ics307_clk_freq(unsigned int reg) +{ + const unsigned long input_freq = 33333000; + void __iomem *fpga_base = IOMEM(CFG_PIXIS_BASE); + unsigned char cw0, cw1, cw2; + unsigned long vdw, rdw, od, freq; + + cw0 = in_8(fpga_base + reg); + cw1 = in_8(fpga_base + reg + 1); + cw2 = in_8(fpga_base + reg + 2); + vdw = ((cw1 << 1) & 0x1fe) + ((cw2 >> 7) & 1); + rdw = cw2 & 0x7f; + od = ics307_s_to_od[cw0 & 0x7]; + /* + * CLK1 Freq = Input Frequency * 2 * (VDW + 8) / ((RDW + 2) * OD) + * + * cw0: C1 C0 TTL F1 F0 S2 S1 S0 + * cw1: V8 V7 V6 V5 V4 V3 V2 V1 + * cw2: V0 R6 R5 R4 R3 R2 R1 R0 + * + * R6:R0 = Reference Divider Word (RDW) + * V8:V0 = VCO Divider Word (VDW) + * S2:S0 = Output Divider Select (OD) + * F1:F0 = Function of CLK2 Output + * TTL = duty cycle + * C1:C0 = internal load capacitance for crystal + */ + freq = input_freq * 2 * (vdw + 8) / ((rdw + 2) * od); + + return freq; +} diff --git a/arch/ppc/boards/freescale-p1022ds/law.c b/arch/ppc/boards/freescale-p1022ds/law.c new file mode 100644 index 0000000000..167937a05a --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/law.c @@ -0,0 +1,27 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + */ + +#include +#include + +struct law_entry law_table[] = { + FSL_SET_LAW(CFG_BOOT_BLOCK_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC), + FSL_SET_LAW(CFG_PIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC), +}; + +int num_law_entries = ARRAY_SIZE(law_table); diff --git a/arch/ppc/boards/freescale-p1022ds/p1022ds.c b/arch/ppc/boards/freescale-p1022ds/p1022ds.c new file mode 100644 index 0000000000..c800064062 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/p1022ds.c @@ -0,0 +1,181 @@ +/* + * Copyright 2014 GE Intelligent Platforms, Inc. + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define attributes for eTSEC1 and eTSEC2 */ +static struct gfar_info_struct gfar_info[] = { + { + .phyaddr = 1, + .tbiana = 0, + .tbicr = 0, + .mdiobus_tbi = 0, + }, + { + .phyaddr = 2, + .tbiana = 0, + .tbicr = 0, + .mdiobus_tbi = 0, + }, +}; + +struct i2c_platform_data i2cplat[] = { + { .bitrate = 400000, }, + { .bitrate = 400000, }, +}; + +void p1022ds_lbc_early_init(void) +{ + void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR); + void __iomem *lbc = LBC_BASE_ADDR; + + /* Set the local bus monitor timeout value to the maximum */ + clrsetbits_be32(lbc + FSL_LBC_LBCR_OFFSET, 0xff0f, 0xf); + /* Set the pin muxing to enable ETSEC2. */ + clrbits_be32(gur + MPC85xx_GUTS_PMUXCR2_OFFSET, 0x001f8000); + /* Set pmuxcr to allow both i2c1 and i2c2 */ + setbits_be32(gur + MPC85xx_GUTS_PMUXCR_OFFSET, 0x1000); + + /* Map the boot flash and FPGA */ + fsl_set_lbc_br(0, BR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | BR_PS_16 | BR_V); + fsl_set_lbc_or(0, 0xf8000ff7); + fsl_set_lbc_br(2, BR_PHYS_ADDR(CFG_PIXIS_BASE_PHYS) | BR_PS_8 | BR_V); + fsl_set_lbc_or(2, 0xffff8ff7); +} + +static void board_eth_init(void) +{ + struct i2c_adapter *adapter; + struct i2c_client client; + char mac[6]; + int ret, ix; + + adapter = i2c_get_adapter(1); + client.addr = 0x57; + client.adapter = adapter; + + for (ix = 0; ix < 2; ix++) { + int mac_offset; + + mac_offset = 0x42 + (sizeof(mac) * ix); + ret = i2c_read_reg(&client, mac_offset, mac, sizeof(mac)); + if (ret != sizeof(mac)) + pr_err("Fail to retrieve MAC address\n"); + else + eth_register_ethaddr(ix, mac); + } + + fsl_eth_init(1, &gfar_info[0]); + fsl_eth_init(2, &gfar_info[1]); +} + +static int p1022ds_devices_init(void) +{ + add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 128 << 20, 0); + devfs_add_partition("nor0", 0x7f80000, 0x80000, DEVFS_PARTITION_FIXED, + "self0"); + devfs_add_partition("nor0", 0x7f00000, 0x10000, DEVFS_PARTITION_FIXED, + "env0"); + add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100, + IORESOURCE_MEM, &i2cplat[0]); + add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, 0x100, + IORESOURCE_MEM, &i2cplat[1]); + + board_eth_init(); + + return 0; +} + +device_initcall(p1022ds_devices_init); + +static struct NS16550_plat serial_plat = { + .clock = 0, + .shift = 0, +}; + +static int p1022ds_console_init(void) +{ + barebox_set_model("Freescale P1022DS"); + barebox_set_hostname("p1022ds"); + + serial_plat.clock = fsl_get_bus_freq(0); + add_ns16550_device(DEVICE_ID_DYNAMIC, CFG_IMMR + 0x4500, 16, + IORESOURCE_MEM_8BIT, &serial_plat); + return 0; +} + +console_initcall(p1022ds_console_init); + +static int p1022ds_mem_init(void) +{ + barebox_add_memory_bank("ram0", 0x0, fsl_get_effective_memsize()); + return 0; +} + +mem_initcall(p1022ds_mem_init); + +static int p1022ds_board_init_r(void) +{ + void __iomem *fpga = IOMEM(CFG_PIXIS_BASE); + const uint32_t flashbase = CFG_BOOT_BLOCK; + const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1); + + /* Enable SPI */ + out_8(fpga + 8, (in_8(fpga + 8) & ~(0xc0)) | (0x80)); + + /* Map the NAND flash */ + fsl_set_lbc_br(1, BR_PHYS_ADDR(0xff800000) | BR_PS_8 | + (2 << BR_DECC_SHIFT) | BR_MS_FCM | BR_V); + fsl_set_lbc_or(1, 0xffff8796); + + /* Flush d-cache and invalidate i-cache of any FLASH data */ + flush_dcache(); + invalidate_icache(); + + /* invalidate existing TLB entry for flash */ + e500_disable_tlb(flash_esel); + + /* + * Remap Boot flash region to caching-inhibited + * so that flash can be erased properly. + */ + e500_set_tlb(1, flashbase, CFG_BOOT_BLOCK_PHYS, + MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, + 0, flash_esel, BOOKE_PAGESZ_256M, 1); + + fsl_l2_cache_init(); + + return 0; +} + +core_initcall(p1022ds_board_init_r); diff --git a/arch/ppc/boards/freescale-p1022ds/p1022ds.h b/arch/ppc/boards/freescale-p1022ds/p1022ds.h new file mode 100644 index 0000000000..cbc2aca644 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/p1022ds.h @@ -0,0 +1,14 @@ +/* + * Copyright 2014 GE Intelligent Platforms, Inc. + * + * 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. + */ +void p1022ds_lbc_early_init(void); diff --git a/arch/ppc/boards/freescale-p1022ds/tlb.c b/arch/ppc/boards/freescale-p1022ds/tlb.c new file mode 100644 index 0000000000..86ab43aec0 --- /dev/null +++ b/arch/ppc/boards/freescale-p1022ds/tlb.c @@ -0,0 +1,59 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * + * 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. + * + */ + +#include +#include + +struct fsl_e_tlb_entry tlb_table[] = { + /* TLB 0 - for temp stack in cache */ + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR, + MAS3_SX | MAS3_SW | MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024), + CFG_INIT_RAM_ADDR + (4 * 1024), + MAS3_SX | MAS3_SW | MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024), + CFG_INIT_RAM_ADDR + (8 * 1024), + MAS3_SX | MAS3_SW | MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024), + CFG_INIT_RAM_ADDR + (12 * 1024), + MAS3_SX | MAS3_SW | MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + + /* TLB 1 */ + /* *I*** - Covers boot page */ + FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000, + MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, + 0, 0, BOOKE_PAGESZ_4K, 1), + + /* *I*G* - CCSRBAR */ + FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS, + MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, + 0, 1, BOOKE_PAGESZ_1M, 1), + + /* W**G* - Flash/promjet, localbus */ + /* This will be changed to *I*G* after relocation to RAM. */ + FSL_SET_TLB_ENTRY(1, CFG_BOOT_BLOCK, CFG_BOOT_BLOCK_PHYS, + MAS3_SX | MAS3_SR, MAS2_M | MAS2_W | MAS2_G, + 0, 2, BOOKE_PAGESZ_256M, 1), + + FSL_SET_TLB_ENTRY(1, CFG_PIXIS_BASE, CFG_PIXIS_BASE_PHYS, + MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, + 0, 7, BOOKE_PAGESZ_4K, 1), +}; + +int num_tlb_entries = ARRAY_SIZE(tlb_table); diff --git a/arch/ppc/boards/freescale-p2020rdb/config.h b/arch/ppc/boards/freescale-p2020rdb/config.h index c6d32161cf..e607ee7b46 100644 --- a/arch/ppc/boards/freescale-p2020rdb/config.h +++ b/arch/ppc/boards/freescale-p2020rdb/config.h @@ -30,8 +30,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #define CFG_SYS_CLK_FREQ get_board_sys_clk(0) #define CFG_DDR_CLK_FREQ 66666666 -#define CFG_BTB /* toggle branch predition */ - /* * Base addresses -- Note these are effective addresses where the * actual resources get mapped (not physical addresses) diff --git a/arch/ppc/boards/geip-da923rc/config.h b/arch/ppc/boards/geip-da923rc/config.h index 6e8684f384..3895324e95 100644 --- a/arch/ppc/boards/geip-da923rc/config.h +++ b/arch/ppc/boards/geip-da923rc/config.h @@ -18,7 +18,6 @@ #define __CONFIG_H #define CFG_SYS_CLK_FREQ 66666666 -#define CFG_BTB /* toggle branch prediction */ #define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT #define CFG_CHIP_SELECTS_PER_CTRL 1 diff --git a/arch/ppc/configs/p1022ds_defconfig b/arch/ppc/configs/p1022ds_defconfig new file mode 100644 index 0000000000..878286b287 --- /dev/null +++ b/arch/ppc/configs/p1022ds_defconfig @@ -0,0 +1,53 @@ +CONFIG_ARCH_MPC85XX=y +CONFIG_P1022DS=y +CONFIG_P1022=y +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_ZLIB=y +CONFIG_BZLIB=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=n +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/ppc/boards/freescale-p1022ds/env/" +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_SAVEENV=y +CONFIG_FSL_ELBC=y +CONFIG_DRIVER_CFI=y +CONFIG_DRIVER_CFI_AMD=y +CONFIG_DRIVER_CFI_INTEL=n +CONFIG_DRIVER_CFI_BANK_WIDTH_1=n +CONFIG_DRIVER_CFI_BANK_WIDTH_2=y +CONFIG_DRIVER_CFI_BANK_WIDTH_4=n +CONFIG_MTD=y +CONFIG_MTD_WRITE=y +CONFIG_MALLOC_SIZE=0x4000000 +CONFIG_BAUDRATE=115200 +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_RELOCATABLE=y +CONFIG_DRIVER_NET_GIANFAR=y +CONFIG_NET=y +CONFIG_NET_PING=y +CONFIG_FS_TFTP=y +CONFIG_NET_TFTP=y +CONFIG_CMD_TFTP=y +CONFIG_PING=y +CONFIG_I2C=y +CONFIG_I2C_IMX=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_EXPORT=y +CONFIG_OFTREE=y +CONFIG_CMD_OFTREE_PROBE=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MEMTEST=y diff --git a/arch/ppc/cpu-85xx/start.S b/arch/ppc/cpu-85xx/start.S index 57f007b783..514fd8c516 100644 --- a/arch/ppc/cpu-85xx/start.S +++ b/arch/ppc/cpu-85xx/start.S @@ -172,7 +172,7 @@ _start_e500: mtspr HID1,r0 /* Enable Branch Prediction */ -#if defined(CFG_BTB) +#if defined(CONFIG_BTB) lis r0,BUCSR_ENABLE@h ori r0,r0,BUCSR_ENABLE@l mtspr SPRN_BUCSR,r0 diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig index 0b76204519..2d1ca8a9b6 100644 --- a/arch/ppc/mach-mpc85xx/Kconfig +++ b/arch/ppc/mach-mpc85xx/Kconfig @@ -3,6 +3,10 @@ if ARCH_MPC85XX config MMU default y if CMD_MEMTEST +config BTB + bool + default y if P2020RDB || P1022DS || DA923RC + config TEXT_BASE hex default 0xeff80000 if P2020RDB -- cgit v1.2.3 From a6750920eda7abe33b1cbc737afbdc3e13b707a4 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:10:02 +0000 Subject: ppc: mpc85xx: add stashing support The eTSEC 2.0 devices found on the 85xx family of SoCs support stashing buffer descriptors in the L2 cache. This updates the device tree fixup for these devices to ensure that the stashing related properties used by Linux are initialised correctly. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/mach-mpc85xx/fdt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/ppc/mach-mpc85xx/fdt.c b/arch/ppc/mach-mpc85xx/fdt.c index b1da144415..1a2d780737 100644 --- a/arch/ppc/mach-mpc85xx/fdt.c +++ b/arch/ppc/mach-mpc85xx/fdt.c @@ -54,6 +54,14 @@ static void fdt_add_enet_stashing(void *fdt) of_property_write_u32(node, "rx-stash-idx", 0); node = of_find_compatible_node(node, NULL, "gianfar"); } + + node = of_find_compatible_node(fdt, NULL, "fsl,etsec2"); + while (node) { + of_set_property(node, "bd-stash", NULL, 0, 1); + of_property_write_u32(node, "rx-stash-len", 96); + of_property_write_u32(node, "rx-stash-idx", 0); + node = of_find_compatible_node(node, NULL, "fsl,etsec2"); + } } static int fdt_stdout_setup(struct device_node *blob) -- cgit v1.2.3 From 18156665c00ce14a47af1ec80a735098c98bdf4c Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Thu, 13 Mar 2014 18:10:04 +0000 Subject: ppc: P1022DS: update Kconfig and Makefile Kconfig and make files are updated to build the Freescale P1022DS image. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/Makefile | 1 + arch/ppc/mach-mpc85xx/Kconfig | 33 ++++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 87be19366b..b9b355aeee 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -13,6 +13,7 @@ endif board-$(CONFIG_MACH_PHYCORE_MPC5200B_TINY) := pcm030 board-$(CONFIG_P2020RDB) := freescale-p2020rdb +board-$(CONFIG_P1022DS) := freescale-p1022ds board-$(CONFIG_DA923RC) := geip-da923rc machine-$(CONFIG_ARCH_MPC5200) := mpc5xxx diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig index 2d1ca8a9b6..ec5f04ca30 100644 --- a/arch/ppc/mach-mpc85xx/Kconfig +++ b/arch/ppc/mach-mpc85xx/Kconfig @@ -1,7 +1,7 @@ if ARCH_MPC85XX config MMU - default y if CMD_MEMTEST + default y config BTB bool @@ -9,13 +9,13 @@ config BTB config TEXT_BASE hex - default 0xeff80000 if P2020RDB + default 0xeff80000 if P2020RDB || P1022DS default 0xfff80000 if DA923RC config RESET_VECTOR_ADDRESS hex default 0xfffffffc if DA923RC - default 0xeffffffc if P2020RDB + default 0xeffffffc if P2020RDB || P1022DS config MPC85xx bool @@ -37,6 +37,11 @@ config P2020RDB help Say Y here if you are using the Freescale P2020RDB +config P1022DS + bool "P1022DS" + help + Say Y here if you are using the Freescale P1022DS + config DA923RC bool "DA923RC" help @@ -44,24 +49,34 @@ config DA923RC endchoice endif +config FSL_ELBC + bool + default y if P2020RDB || P1022DS + +config DDR_SPD + bool + select CRC16 + default y if DA923RC || P1022DS + if P2020RDB config P2020 bool default y +endif -config FSL_ELBC +if P1022DS +config P1022 bool default y -endif -if DA923RC -config MPC8544 +config FSL_DDR3 bool default y +endif -config DDR_SPD +if DA923RC +config MPC8544 bool - select CRC16 default y config FSL_DDR2 -- cgit v1.2.3 From 3e445eb1c78a1916acd2ec5238af58cd83509e94 Mon Sep 17 00:00:00 2001 From: Renaud Barbier Date: Wed, 2 Apr 2014 15:18:41 +0100 Subject: ppc: P2020RDB: add environment partition support Add an environment partition and support commands so that the system configuration can be permanent. Signed-off-by: Renaud Barbier Signed-off-by: Sascha Hauer --- arch/ppc/boards/freescale-p2020rdb/env/bin/init | 2 ++ arch/ppc/boards/freescale-p2020rdb/env/config | 2 ++ arch/ppc/boards/freescale-p2020rdb/p2020rdb.c | 9 +++++---- arch/ppc/configs/p2020rdb_defconfig | 21 ++++++++++++++++++++- 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 arch/ppc/boards/freescale-p2020rdb/env/bin/init create mode 100644 arch/ppc/boards/freescale-p2020rdb/env/config diff --git a/arch/ppc/boards/freescale-p2020rdb/env/bin/init b/arch/ppc/boards/freescale-p2020rdb/env/bin/init new file mode 100644 index 0000000000..4d7b03e26d --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/env/bin/init @@ -0,0 +1,2 @@ +#!/bin/sh +source /env/config \ No newline at end of file diff --git a/arch/ppc/boards/freescale-p2020rdb/env/config b/arch/ppc/boards/freescale-p2020rdb/env/config new file mode 100644 index 0000000000..23e0ba2a5d --- /dev/null +++ b/arch/ppc/boards/freescale-p2020rdb/env/config @@ -0,0 +1,2 @@ +#!/bin/sh +export bootargs="root=/dev/nfs rw ip=bootp" \ No newline at end of file diff --git a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c index 4d2ff222c2..229ae41f08 100644 --- a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c +++ b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c @@ -83,7 +83,10 @@ struct i2c_platform_data i2cplat = { static int devices_init(void) { add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 16 << 20, 0); - + devfs_add_partition("nor0", 0xf60000, 0x8000, DEVFS_PARTITION_FIXED, + "env0"); + devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED, + "self0"); add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100, IORESOURCE_MEM, &i2cplat); add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, @@ -92,8 +95,6 @@ static int devices_init(void) fsl_eth_init(2, &gfar_info[0]); fsl_eth_init(3, &gfar_info[1]); - devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED, - "self0"); return 0; } @@ -106,7 +107,7 @@ static struct NS16550_plat serial_plat = { static int p2020_console_init(void) { - barebox_set_model("Freescale P2020 RDB"); + barebox_set_model("Freescale P2020RDB"); barebox_set_hostname("p2020rdb"); serial_plat.clock = fsl_get_bus_freq(0); diff --git a/arch/ppc/configs/p2020rdb_defconfig b/arch/ppc/configs/p2020rdb_defconfig index 868c060fc7..c34e48d972 100644 --- a/arch/ppc/configs/p2020rdb_defconfig +++ b/arch/ppc/configs/p2020rdb_defconfig @@ -6,10 +6,25 @@ CONFIG_GLOB=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_CMD_SLEEP=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_ZLIB=y +CONFIG_BZLIB=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_EXPORT=y CONFIG_CMD_FLASH=y CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=n +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/ppc/boards/freescale-p2020rdb/env/" +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_READLINK=y CONFIG_FSL_ELBC=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_DRIVER_CFI=y CONFIG_DRIVER_CFI_AMD=y CONFIG_DRIVER_CFI_INTEL=n @@ -17,7 +32,7 @@ CONFIG_DRIVER_CFI_BANK_WIDTH_1=n CONFIG_DRIVER_CFI_BANK_WIDTH_2=y CONFIG_DRIVER_CFI_BANK_WIDTH_4=n CONFIG_MTD=y -CONFIG_MALLOC_SIZE=0x200000 +CONFIG_MALLOC_SIZE=0x2800000 CONFIG_BAUDRATE=115200 CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_RELOCATABLE=y @@ -34,3 +49,7 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MIITOOL=y CONFIG_CMD_MEMTEST=y CONFIG_CMD_IOMEM=y +CONFIG_CMD_VERSION=n +CONFIG_OFTREE=y +CONFIG_CMD_OFTREE_PROBE=y +CONFIG_CMD_OFTREE=y \ No newline at end of file -- cgit v1.2.3