| /* |
| * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <common.h> |
| #include <asm/io.h> |
| #include <asm/arch/bitfield.h> |
| #include <asm/arch/tegra2.h> |
| #include <asm/arch/sys_proto.h> |
| #include <asm/arch/clk_rst.h> |
| #include <asm/arch/clock.h> |
| #include <asm/arch/pmu.h> |
| #include <asm/arch/emc.h> |
| #include "board.h" |
| |
| 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, (NV_PA_EMC_BASE + addr)); |
| } |
| |
| static inline u32 emc_readl(unsigned long addr) |
| { |
| return readl((NV_PA_EMC_BASE + addr)); |
| } |
| |
| 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; |
| } |
| |
| static 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; |
| } |
| |
| struct tegra_board_emc_table { |
| int id; /* Boot strap ID */ |
| const struct tegra_emc_table *table; |
| const int table_size; |
| const char *name; |
| }; |
| |
| |
| static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = { |
| { |
| .rate = 166500, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000a, /* RC */ |
| 0x00000021, /* RFC */ |
| 0x00000008, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x000004df, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000a, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000006, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa04004ae, /* CFG_DIG_DLL */ |
| 0x007fd010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 333000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000014, /* RC */ |
| 0x00000041, /* RFC */ |
| 0x0000000f, /* RAS */ |
| 0x00000005, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000005, /* RD_RCD */ |
| 0x00000005, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x000009ff, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000005, /* PCHG2PDEN */ |
| 0x00000005, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000f, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000c, /* TFAW */ |
| 0x00000006, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe034048b, /* CFG_DIG_DLL */ |
| 0x007e8010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000c, /* RC */ |
| 0x00000026, /* RFC */ |
| 0x00000009, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000b, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007dc010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000017, /* RC */ |
| 0x0000004b, /* RFC */ |
| 0x00000012, /* RAS */ |
| 0x00000006, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000006, /* RD_RCD */ |
| 0x00000006, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000006, /* PCHG2PDEN */ |
| 0x00000006, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x00000011, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000007, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007d8010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| void seaboard_emc_init(void) |
| { |
| switch (tegra_get_chip_type()) { |
| case TEGRA_SOC_T20: |
| tegra_set_emc(seaboard_emc_tables_hynix_333Mhz, |
| ARRAY_SIZE(seaboard_emc_tables_hynix_333Mhz)); |
| break; |
| case TEGRA_SOC_T25: |
| tegra_set_emc(seaboard_emc_tables_hynix_380Mhz, |
| ARRAY_SIZE(seaboard_emc_tables_hynix_380Mhz)); |
| break; |
| default: |
| /* unknown chip type, no clk change*/ |
| tegra_set_emc(NULL, 0); |
| break; |
| } |
| } |
| |
| static const struct tegra_emc_table kaen_emc_tables_Nanya_380Mhz[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000b, /* RC */ |
| 0x00000019, /* RFC */ |
| 0x00000009, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000b, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000003, /* WDV */ |
| 0x00000004, /* QUSE */ |
| 0x00000003, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000c, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000a, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x00000008, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007da010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000016, /* RC */ |
| 0x00000031, /* RFC */ |
| 0x00000012, /* RAS */ |
| 0x00000005, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000b, /* W2P */ |
| 0x00000005, /* RD_RCD */ |
| 0x00000005, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000003, /* WDV */ |
| 0x00000004, /* QUSE */ |
| 0x00000003, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000c, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000005, /* PCHG2PDEN */ |
| 0x00000005, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000f, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000006, /* TRPAB */ |
| 0x00000008, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007df010, /* DLL_XFORM_DQS */ |
| 0x00064000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| static const struct tegra_emc_table kaen_emc_tables_Samsung_380Mhz[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000c, /* RC */ |
| 0x00000019, /* RFC */ |
| 0x00000009, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000b, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x00000008, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007e2010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000017, /* RC */ |
| 0x00000031, /* RFC */ |
| 0x00000012, /* RAS */ |
| 0x00000006, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000006, /* RD_RCD */ |
| 0x00000006, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000006, /* PCHG2PDEN */ |
| 0x00000006, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x00000011, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000007, /* TRPAB */ |
| 0x00000008, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007de010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| struct tegra_board_emc_table kaen_emc[] = { |
| { |
| .table = kaen_emc_tables_Samsung_380Mhz, |
| .table_size = ARRAY_SIZE(kaen_emc_tables_Samsung_380Mhz), |
| .name = "Samsung 380MHz", |
| }, |
| { |
| .table = kaen_emc_tables_Nanya_380Mhz, |
| .table_size = ARRAY_SIZE(kaen_emc_tables_Nanya_380Mhz), |
| .name = "Nanya 380MHz", |
| }, |
| { |
| .table = kaen_emc_tables_Samsung_380Mhz, |
| .table_size = ARRAY_SIZE(kaen_emc_tables_Samsung_380Mhz), |
| .name = "Samsung 380MHz", |
| }, |
| { |
| .table = kaen_emc_tables_Nanya_380Mhz, |
| .table_size = ARRAY_SIZE(kaen_emc_tables_Nanya_380Mhz), |
| .name = "Nanya 380MHz", |
| }, |
| }; |
| |
| #define STRAP_OPT 0x008 |
| #define GMI_AD0 (1 << 4) |
| #define GMI_AD1 (1 << 5) |
| #define RAM_ID_MASK (GMI_AD0 | GMI_AD1) |
| #define RAM_CODE_SHIFT 4 |
| |
| void kaen_emc_init(void) |
| { |
| u32 reg; |
| int ram_id; |
| |
| reg = readl(NV_PA_APB_MISC_BASE + STRAP_OPT); |
| ram_id = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; |
| |
| if (ram_id >= ARRAY_SIZE(kaen_emc) || !kaen_emc[ram_id].table) { |
| tegra_set_emc(NULL, 0); |
| } else { |
| tegra_set_emc(kaen_emc[ram_id].table, |
| kaen_emc[ram_id].table_size); |
| } |
| } |
| |
| static const struct tegra_emc_table aebl_emc_tables_Micron_380Mhz[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000b, /* RC */ |
| 0x00000026, /* RFC */ |
| 0x00000008, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000b, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000003, /* WDV */ |
| 0x00000004, /* QUSE */ |
| 0x00000003, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000c, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000a, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007e4010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000015, /* RC */ |
| 0x0000004c, /* RFC */ |
| 0x00000010, /* RAS */ |
| 0x00000005, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000b, /* W2P */ |
| 0x00000005, /* RD_RCD */ |
| 0x00000005, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000003, /* WDV */ |
| 0x00000004, /* QUSE */ |
| 0x00000003, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000c, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000005, /* PCHG2PDEN */ |
| 0x00000005, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000f, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000006, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007e0010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| static const struct tegra_emc_table aebl_emc_tables_Hynix_380Mhz[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000c, /* RC */ |
| 0x00000026, /* RFC */ |
| 0x00000009, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000b, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007e0010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000017, /* RC */ |
| 0x0000004b, /* RFC */ |
| 0x00000012, /* RAS */ |
| 0x00000006, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000006, /* RD_RCD */ |
| 0x00000006, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000006, /* PCHG2PDEN */ |
| 0x00000006, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x00000011, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000007, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000003, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007da010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| struct tegra_board_emc_table aebl_emc[] = { |
| { |
| .table = aebl_emc_tables_Micron_380Mhz, |
| .table_size = ARRAY_SIZE(aebl_emc_tables_Micron_380Mhz), |
| .name = "0: Micron 380MHz", |
| }, |
| { |
| .table = aebl_emc_tables_Hynix_380Mhz, |
| .table_size = ARRAY_SIZE(aebl_emc_tables_Hynix_380Mhz), |
| .name = "1: Hynix 380MHz", |
| }, |
| { |
| .table = aebl_emc_tables_Micron_380Mhz, |
| .table_size = ARRAY_SIZE(aebl_emc_tables_Micron_380Mhz), |
| .name = "2: Micron 380MHz", |
| }, |
| { |
| .table = aebl_emc_tables_Hynix_380Mhz, |
| .table_size = ARRAY_SIZE(aebl_emc_tables_Hynix_380Mhz), |
| .name = "3: Hynix 380MHz", |
| }, |
| }; |
| |
| void aebl_emc_init(void) |
| { |
| u32 reg; |
| int ram_id; |
| |
| reg = readl(NV_PA_APB_MISC_BASE + STRAP_OPT); |
| ram_id = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; |
| |
| if (ram_id >= ARRAY_SIZE(aebl_emc) || !aebl_emc[ram_id].table) { |
| tegra_set_emc(NULL, 0); |
| } else { |
| tegra_set_emc(aebl_emc[ram_id].table, |
| aebl_emc[ram_id].table_size); |
| } |
| } |
| |
| /* These values are not final, but they do work on the board */ |
| static const struct tegra_emc_table asymptote_emc_tables[] = { |
| { |
| .rate = 190000, /* SDRAM frequency */ |
| .regs = { |
| 0x0000000c, /* RC */ |
| 0x00000026, /* RFC */ |
| 0x00000009, /* RAS */ |
| 0x00000003, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000004, /* W2R */ |
| 0x00000002, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000003, /* RD_RCD */ |
| 0x00000003, /* WR_RCD */ |
| 0x00000002, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x0000059f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000003, /* PCHG2PDEN */ |
| 0x00000003, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x0000000b, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x00000007, /* TFAW */ |
| 0x00000004, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xa06204ae, /* CFG_DIG_DLL */ |
| 0x007dc010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| }, { |
| .rate = 380000, /* SDRAM frequency */ |
| .regs = { |
| 0x00000017, /* RC */ |
| 0x0000004b, /* RFC */ |
| 0x00000012, /* RAS */ |
| 0x00000006, /* RP */ |
| 0x00000004, /* R2W */ |
| 0x00000005, /* W2R */ |
| 0x00000003, /* R2P */ |
| 0x0000000c, /* W2P */ |
| 0x00000006, /* RD_RCD */ |
| 0x00000006, /* WR_RCD */ |
| 0x00000003, /* RRD */ |
| 0x00000001, /* REXT */ |
| 0x00000004, /* WDV */ |
| 0x00000005, /* QUSE */ |
| 0x00000004, /* QRST */ |
| 0x00000009, /* QSAFE */ |
| 0x0000000d, /* RDV */ |
| 0x00000b5f, /* REFRESH */ |
| 0x00000000, /* BURST_REFRESH_NUM */ |
| 0x00000003, /* PDEX2WR */ |
| 0x00000003, /* PDEX2RD */ |
| 0x00000006, /* PCHG2PDEN */ |
| 0x00000006, /* ACT2PDEN */ |
| 0x00000001, /* AR2PDEN */ |
| 0x00000011, /* RW2PDEN */ |
| 0x000000c8, /* TXSR */ |
| 0x00000003, /* TCKE */ |
| 0x0000000e, /* TFAW */ |
| 0x00000007, /* TRPAB */ |
| 0x0000000f, /* TCLKSTABLE */ |
| 0x00000002, /* TCLKSTOP */ |
| 0x00000000, /* TREFBW */ |
| 0x00000000, /* QUSE_EXTRA */ |
| 0x00000002, /* FBIO_CFG6 */ |
| 0x00000000, /* ODT_WRITE */ |
| 0x00000000, /* ODT_READ */ |
| 0x00000083, /* FBIO_CFG5 */ |
| 0xe044048b, /* CFG_DIG_DLL */ |
| 0x007d8010, /* DLL_XFORM_DQS */ |
| 0x00000000, /* DLL_XFORM_QUSE */ |
| 0x00000000, /* ZCAL_REF_CNT */ |
| 0x00000000, /* ZCAL_WAIT_CNT */ |
| 0x00000000, /* AUTO_CAL_INTERVAL */ |
| 0x00000000, /* CFG_CLKTRIM_0 */ |
| 0x00000000, /* CFG_CLKTRIM_1 */ |
| 0x00000000, /* CFG_CLKTRIM_2 */ |
| } |
| } |
| }; |
| |
| void asymptote_emc_init(void) |
| { |
| tegra_set_emc(asymptote_emc_tables, ARRAY_SIZE(asymptote_emc_tables)); |
| } |
| |
| struct emc_init { |
| unsigned int id; /* board id */ |
| void (*init)(void); |
| }; |
| |
| static struct emc_init board_table[] = { |
| { |
| .id = MACH_TYPE_AEBL, |
| .init = aebl_emc_init, |
| }, |
| { |
| .id = MACH_TYPE_HARMONY, |
| .init = NULL, |
| }, |
| { |
| .id = MACH_TYPE_KAEN, |
| .init = kaen_emc_init, |
| }, |
| { |
| .id = MACH_TYPE_SEABOARD, |
| .init = seaboard_emc_init, |
| }, |
| { |
| .id = MACH_TYPE_WARIO, |
| .init = NULL, |
| }, |
| { |
| .id = MACH_TYPE_ASYMPTOTE, |
| .init = asymptote_emc_init, |
| }, |
| }; |
| |
| int board_emc_init(void) |
| { |
| int i; |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| /* if voltage has not been set properly, return */ |
| if (!tegra2_pmu_is_voltage_nominal()) |
| return -1; |
| |
| for (i = 0; i < ARRAY_SIZE(board_table); i++) { |
| if (board_table[i].id == gd->bd->bi_arch_number) { |
| if (board_table[i].init) { |
| board_table[i].init(); |
| return 0; |
| } else |
| return -1; |
| } |
| } |
| return -1; |
| } |