From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Mon, 26 Dec 2011 11:32:59 -0800 Subject: [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings In-Reply-To: <1324927987-13100-1-git-send-email-sjg@chromium.org> References: <1324927987-13100-1-git-send-email-sjg@chromium.org> Message-ID: <1324927987-13100-7-git-send-email-sjg@chromium.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Jimmy Zhang Add support for setting up the memory controller parameters. Boards can call tegra_set_emc() with a table containing the required parameters. Signed-off-by: Simon Glass --- arch/arm/cpu/armv7/tegra2/Makefile | 1 + arch/arm/cpu/armv7/tegra2/emc.c | 165 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-tegra2/emc.h | 107 +++++++++++++++++++ arch/arm/include/asm/arch-tegra2/tegra2.h | 1 + 4 files changed, 274 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/armv7/tegra2/emc.c create mode 100644 arch/arm/include/asm/arch-tegra2/emc.h diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile index e9ac6c9..dcd6329 100644 --- a/arch/arm/cpu/armv7/tegra2/Makefile +++ b/arch/arm/cpu/armv7/tegra2/Makefile @@ -34,6 +34,7 @@ LIB = $(obj)lib$(SOC).o SOBJS := lowlevel_init.o COBJS-y := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o +COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o COBJS := $(COBJS-y) diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c new file mode 100644 index 0000000..563fe89 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra2/emc.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +static const struct tegra_emc_table *tegra_emc_table; +static int tegra_emc_table_size; + +static inline void emc_writel(u32 val, unsigned long addr) +{ + writel(val, TEGRA2_EMC_BASE + addr); +} + +static inline u32 emc_readl(unsigned long addr) +{ + return readl(TEGRA2_EMC_BASE + addr); +} + +/* + * This table defines the ordering of the registers provided to + * tegra_set_mmc() + * TODO: Convert to fdt version once available + */ +static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { + 0x2c, /* RC */ + 0x30, /* RFC */ + 0x34, /* RAS */ + 0x38, /* RP */ + 0x3c, /* R2W */ + 0x40, /* W2R */ + 0x44, /* R2P */ + 0x48, /* W2P */ + 0x4c, /* RD_RCD */ + 0x50, /* WR_RCD */ + 0x54, /* RRD */ + 0x58, /* REXT */ + 0x5c, /* WDV */ + 0x60, /* QUSE */ + 0x64, /* QRST */ + 0x68, /* QSAFE */ + 0x6c, /* RDV */ + 0x70, /* REFRESH */ + 0x74, /* BURST_REFRESH_NUM */ + 0x78, /* PDEX2WR */ + 0x7c, /* PDEX2RD */ + 0x80, /* PCHG2PDEN */ + 0x84, /* ACT2PDEN */ + 0x88, /* AR2PDEN */ + 0x8c, /* RW2PDEN */ + 0x90, /* TXSR */ + 0x94, /* TCKE */ + 0x98, /* TFAW */ + 0x9c, /* TRPAB */ + 0xa0, /* TCLKSTABLE */ + 0xa4, /* TCLKSTOP */ + 0xa8, /* TREFBW */ + 0xac, /* QUSE_EXTRA */ + 0x114, /* FBIO_CFG6 */ + 0xb0, /* ODT_WRITE */ + 0xb4, /* ODT_READ */ + 0x104, /* FBIO_CFG5 */ + 0x2bc, /* CFG_DIG_DLL */ + 0x2c0, /* DLL_XFORM_DQS */ + 0x2c4, /* DLL_XFORM_QUSE */ + 0x2e0, /* ZCAL_REF_CNT */ + 0x2e4, /* ZCAL_WAIT_CNT */ + 0x2a8, /* AUTO_CAL_INTERVAL */ + 0x2d0, /* CFG_CLKTRIM_0 */ + 0x2d4, /* CFG_CLKTRIM_1 */ + 0x2d8, /* CFG_CLKTRIM_2 */ +}; + +/* The EMC registers have shadow registers. When the EMC clock is updated + * in the clock controller, the shadow registers are copied to the active + * registers, allowing glitchless memory bus frequency changes. + * This function updates the shadow registers for a new clock frequency, + * and relies on the clock lock on the emc clock to avoid races between + * multiple frequency changes */ +#define EMC_SDRAM_RATE_T20 (333000 * 2 * 1000) +#define EMC_SDRAM_RATE_T25 (380000 * 2 * 1000) + +static int tegra_emc_set_rate(unsigned long rate) +{ + int i; + int j; + + if (!tegra_emc_table) + return -1; + + /* The EMC clock rate is twice the bus rate, and the bus rate is + * measured in kHz */ + rate = rate / 2 / 1000; + + for (i = 0; i < tegra_emc_table_size; i++) + if (tegra_emc_table[i].rate == rate) + break; + + if (i >= tegra_emc_table_size) + return -1; + + for (j = 0; j < TEGRA_EMC_NUM_REGS; j++) + emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]); + + /* + * trigger emc with new settings by updating clk_rst's source EMC + * Set PLLM_OUT0 (bits: 31:30= 0) and divisor bits 7:0 = 0 (ie 1) + */ + clock_ll_set_source_divisor(PERIPH_ID_EMC, 0, 0); + udelay(1); + return 0; +} + +int tegra_set_emc(const struct tegra_emc_table *table, int table_size) +{ + unsigned long rate; + + if (!table) { + tegra_emc_table = NULL; + tegra_emc_table_size = 0; + return -1; + } + + tegra_emc_table = table; + tegra_emc_table_size = table_size; + + switch (tegra_get_chip_type()) { + case TEGRA_SOC_T20: + rate = EMC_SDRAM_RATE_T20; + break; + case TEGRA_SOC_T25: + rate = EMC_SDRAM_RATE_T25; + break; + default: + /* unknown chip type, no clk change*/ + return -1; + } + + tegra_emc_set_rate(rate); + + return 0; +} diff --git a/arch/arm/include/asm/arch-tegra2/emc.h b/arch/arm/include/asm/arch-tegra2/emc.h new file mode 100644 index 0000000..a1d1e9d --- /dev/null +++ b/arch/arm/include/asm/arch-tegra2/emc.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 NVIDIA Corporation + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ARCH_EMC_H_ +#define _ARCH_EMC_H_ + +#include + +#define TEGRA_EMC_NUM_REGS 46 + +struct tegra_emc_table { + unsigned long rate; + u32 regs[TEGRA_EMC_NUM_REGS]; +}; + +/* EMC Registers */ +struct emc_ctlr { + u32 cfg; /* 0x00: EMC_CFG */ + u32 reserved0[3]; /* 0x04 ~ 0x0C */ + u32 adr_cfg; /* 0x10: EMC_ADR_CFG */ + u32 adr_cfg1; /* 0x14: EMC_ADR_CFG_1 */ + u32 reserved1[2]; /* 0x18 ~ 0x18 */ + u32 refresh_ctrl; /* 0x20: EMC_REFCTRL */ + u32 pin; /* 0x24: EMC_PIN */ + u32 timing_ctrl; /* 0x28: EMC_TIMING_CONTROL */ + u32 rc; /* 0x2C: EMC_RC */ + u32 rfc; /* 0x30: EMC_RFC */ + u32 ras; /* 0x34: EMC_RAS */ + u32 rp; /* 0x38: EMC_RP */ + u32 r2w; /* 0x3C: EMC_R2W */ + u32 w2r; /* 0x40: EMC_W2R */ + u32 r2p; /* 0x44: EMC_R2P */ + u32 w2p; /* 0x48: EMC_W2P */ + u32 rd_rcd; /* 0x4C: EMC_RD_RCD */ + u32 wd_rcd; /* 0x50: EMC_WD_RCD */ + u32 rrd; /* 0x54: EMC_RRD */ + u32 rext; /* 0x58: EMC_REXT */ + u32 wdv; /* 0x5C: EMC_WDV */ + u32 quse; /* 0x60: EMC_QUSE */ + u32 qrst; /* 0x64: EMC_QRST */ + u32 qsafe; /* 0x68: EMC_QSAFE */ + u32 rdv; /* 0x6C: EMC_RDV */ + u32 refresh; /* 0x70: EMC_REFRESH */ + u32 burst_refresh_num; /* 0x74: EMC_BURST_REFRESH_NUM */ + u32 pdex2wr; /* 0x78: EMC_PDEX2WR */ + u32 pdex2rd; /* 0x7c: EMC_PDEX2RD */ + u32 pchg2pden; /* 0x80: EMC_PCHG2PDEN */ + u32 act2pden; /* 0x84: EMC_ACT2PDEN */ + u32 ar2pden; /* 0x88: EMC_AR2PDEN */ + u32 rw2pden; /* 0x8C: EMC_RW2PDEN */ + u32 txsr; /* 0x90: EMC_TXSR */ + u32 tcke; /* 0x94: EMC_TCKE */ + u32 tfaw; /* 0x98: EMC_TFAW */ + u32 trpab; /* 0x9C: EMC_TRPAB */ + u32 tclkstable; /* 0xA0: EMC_TCLKSTABLE */ + u32 tclkstop; /* 0xA4: EMC_TCLKSTOP */ + u32 trefbw; /* 0xA8: EMC_TREFBW */ + u32 quse_extra; /* 0xAC: EMC_QUSE_EXTRA */ + u32 odt_write; /* 0xB0: EMC_ODT_WRITE */ + u32 odt_read; /* 0xB4: EMC_ODT_READ */ + u32 reserved2[5]; /* 0xB8 ~ 0xC8 */ + u32 mrs; /* 0xCC: EMC_MRS */ + u32 emrs; /* 0xD0: EMC_EMRS */ + u32 ref; /* 0xD4: EMC_REF */ + u32 pre; /* 0xD8: EMC_PRE */ + u32 nop; /* 0xDC: EMC_NOP */ + u32 self_ref; /* 0xE0: EMC_SELF_REF */ + u32 dpd; /* 0xE4: EMC_DPD */ + u32 mrw; /* 0xE8: EMC_MRW */ + u32 mrr; /* 0xEC: EMC_MRR */ + u32 reserved3; /* 0xF0: */ + u32 fbio_cfg1; /* 0xF4: EMC_FBIO_CFG1 */ + u32 fbio_dqsib_dly; /* 0xF8: EMC_FBIO_DQSIB_DLY */ + u32 fbio_dqsib_dly_msb; /* 0xFC: EMC_FBIO_DQSIB_DLY_MSG */ + u32 fbio_spare; /* 0x100: SBIO_SPARE */ + /* There are more registers ... */ +}; + +/** + * Set up the memory timings according to a provided table + * + * @param table Memory timing table + * @param table_size Number of entries in table + */ +int tegra_set_emc(const struct tegra_emc_table *table, int table_size); + +#endif diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h index f33726d..480ec0c 100644 --- a/arch/arm/include/asm/arch-tegra2/tegra2.h +++ b/arch/arm/include/asm/arch-tegra2/tegra2.h @@ -44,6 +44,7 @@ #define TEGRA2_I2C2_BASE (NV_PA_APB_MISC_BASE + 0xC400) #define TEGRA2_I2C3_BASE (NV_PA_APB_MISC_BASE + 0xC500) #define TEGRA2_DVC_BASE (NV_PA_APB_MISC_BASE + 0xD000) +#define TEGRA2_EMC_BASE (NV_PA_APB_MISC_BASE + 0xF400) #define TEGRA2_FUSE_BASE (NV_PA_APB_MISC_BASE + 0xF800) #define NV_PA_CSITE_BASE 0x70040000 #define TEGRA_USB1_BASE 0xC5000000 -- 1.7.3.1