diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 87be19366..b9b355aee 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/boards/freescale-p1022ds/Makefile b/arch/ppc/boards/freescale-p1022ds/Makefile new file mode 100644 index 000000000..e9b59d5cc --- /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 000000000..666b9ff98 --- /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 000000000..1944518c7 --- /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 000000000..c0e04c1f2 --- /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 000000000..bffd86882 --- /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 000000000..f7c5bbde9 --- /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 000000000..167937a05 --- /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 000000000..c80006406 --- /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 000000000..cbc2aca64 --- /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 000000000..86ab43aec --- /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 c6d32161c..e607ee7b4 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/freescale-p2020rdb/env/bin/init b/arch/ppc/boards/freescale-p2020rdb/env/bin/init new file mode 100644 index 000000000..4d7b03e26 --- /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 000000000..23e0ba2a5 --- /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 4d2ff222c..229ae41f0 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/boards/geip-da923rc/config.h b/arch/ppc/boards/geip-da923rc/config.h index 6e8684f38..3895324e9 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 000000000..878286b28 --- /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/configs/p2020rdb_defconfig b/arch/ppc/configs/p2020rdb_defconfig index 868c060fc..c34e48d97 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 diff --git a/arch/ppc/cpu-85xx/start.S b/arch/ppc/cpu-85xx/start.S index 57f007b78..514fd8c51 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/ddr-8xxx/Makefile b/arch/ppc/ddr-8xxx/Makefile index 54cb7ce51..43ae3a41d 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 b2621937e..85a1e2868 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 1abc826fb..e3d43ab09 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; + 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->trwt_override) - trwt_mclk = popts->trwt; + 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)); } - -static void set_ddr_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, +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) + 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) + ); + + /* + * 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) { 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 6574500ac..2ef87f277 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 b36a8887d..cc7f3fa6b 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/ddr3_dimm_params.c b/arch/ppc/ddr-8xxx/ddr3_dimm_params.c new file mode 100644 index 000000000..d510c5b26 --- /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/ddr2_setctrl.c b/arch/ppc/ddr-8xxx/ddr_setctrl.c similarity index 53% rename from arch/ppc/ddr-8xxx/ddr2_setctrl.c rename to arch/ppc/ddr-8xxx/ddr_setctrl.c index 14571b048..115fb4207 100644 --- a/arch/ppc/ddr-8xxx/ddr2_setctrl.c +++ b/arch/ppc/ddr-8xxx/ddr_setctrl.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Freescale Semiconductor, Inc. + * 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 @@ -10,12 +10,13 @@ #include #include #include +#include #include #include "ddr.h" int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info) { - uint32_t i; + uint32_t i, temp_sdram_cfg; void __iomem *ddr; const struct fsl_ddr_cfg_regs_s *regs; @@ -29,6 +30,9 @@ int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info) 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); @@ -45,12 +49,40 @@ int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info) 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); + 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"); - 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); diff --git a/arch/ppc/ddr-8xxx/lc_common_dimm_params.c b/arch/ppc/ddr-8xxx/lc_common_dimm_params.c index a1addb069..9d90fb76d 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 6e4a02d56..99b877b5c 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 9ce2bc1b8..ccf5d5e9d 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 73c239be8..9e6f6b4d3 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 444bcbc49..f0f3a6335 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; diff --git a/arch/ppc/include/asm/fsl_lbc.h b/arch/ppc/include/asm/fsl_lbc.h index a59725cf3..27d194ee7 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 819babb67..c9633fe50 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/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig index 74bad7666..ec5f04ca3 100644 --- a/arch/ppc/mach-mpc85xx/Kconfig +++ b/arch/ppc/mach-mpc85xx/Kconfig @@ -1,17 +1,21 @@ if ARCH_MPC85XX config MMU - default y if CMD_MEMTEST + default y + +config BTB + bool + default y if P2020RDB || P1022DS || DA923RC 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 @@ -33,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 @@ -40,12 +49,27 @@ 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 + +config FSL_DDR3 bool default y endif @@ -55,10 +79,6 @@ config MPC8544 bool default y -config DDR_SPD - bool - default y - config FSL_DDR2 bool default y diff --git a/arch/ppc/mach-mpc85xx/cpuid.c b/arch/ppc/mach-mpc85xx/cpuid.c index 809497859..21892e3ff 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/fdt.c b/arch/ppc/mach-mpc85xx/fdt.c index b1da14441..1a2d78073 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) diff --git a/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h b/arch/ppc/mach-mpc85xx/include/mach/config_mpc85xx.h index 27358e83f..f9d8299b6 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 d5a9c9704..87bc5c7c6 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 diff --git a/common/ddr_spd.c b/common/ddr_spd.c index c8b73ff56..ea0b529ee 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 c8762a28d..fc03bacc5 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_ */