From 3527b8cc2a989e51197831eab1f941429f8ffeea Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Sun, 20 Mar 2016 15:09:33 +0100 Subject: [PATCH] Add new, common setup code for QC/A WiSoC DDR controllers In old code, based on Qualcomm/Atheros (Q)SDK, most of the DDR controller related registers where setup with static values, based on selected PLL/clocks configuration or chosen board type. New setup code is universal and configures DDR controller based on real hardware state (clocks, memory type). For now, the code doesn't support SDRAM memory type, as I don't have access to any QC/A based platform with such type of memory chip. But it seems, that newer QC/A WiSoCs don't support it (excluding QCA953x v1?) anyway. New code contains also fixed DQS delay tap controller tune for AR93xx WiSoCs, which for now is used only for AR933x, as it turned out that DDR BITS is available also on AR934x. In old code, tune routine starts with some hardcoded values, which leads to an assumption that this starting value is inside working tap range. As it turned out after some tests, this assumption is wrong and on some real hardware platforms gives wrong delay tap values, outside correct/working range. New code was tested on many different QC/A platforms, but will need changes and fixes in future, mostly because of missing (at the moment) descriptions of DDR BIST registers. --- u-boot/board/ar7240/ap143/ap143.c | 146 +----- u-boot/board/ar7240/db12x/db12x.c | 81 +-- u-boot/cpu/mips/ar7240/Makefile | 2 - u-boot/cpu/mips/ar7240/ar933x_dram.c | 236 --------- u-boot/cpu/mips/ar7240/meminit.c | 225 -------- u-boot/cpu/mips/ar7240/qca_dram.c | 753 ++++++++++++++++++++++++++- u-boot/include/soc/qca_dram.h | 21 - u-boot/include/soc/qca_soc_common.h | 64 ++- 8 files changed, 824 insertions(+), 704 deletions(-) delete mode 100644 u-boot/cpu/mips/ar7240/ar933x_dram.c delete mode 100644 u-boot/cpu/mips/ar7240/meminit.c diff --git a/u-boot/board/ar7240/ap143/ap143.c b/u-boot/board/ar7240/ap143/ap143.c index a4fba51..5573738 100644 --- a/u-boot/board/ar7240/ap143/ap143.c +++ b/u-boot/board/ar7240/ap143/ap143.c @@ -1,140 +1,20 @@ +/* + * Copyright (C) 2016 Piotr Dymacz + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include #include -#include -#include #include -#include -#include -#include #include -extern int ath_ddr_initial_config(uint32_t refresh); -extern int ath_ddr_find_size(void); - -void ath_set_tuning_caps(void) -{ - typedef struct { - u_int8_t pad[0x28], - params_for_tuning_caps[2], - featureEnable; - } __attribute__((__packed__)) ar9300_eeprom_t; - - ar9300_eeprom_t *eep; - uint32_t val; - - eep = (ar9300_eeprom_t *)WLANCAL; - - val = XTAL_TCXODET_SET(0x0) | - XTAL_XTAL_CAPINDAC_SET(0x4b) | - XTAL_XTAL_CAPOUTDAC_SET(0x4b) | - XTAL_XTAL_DRVSTR_SET(0x3) | - XTAL_XTAL_SHORTXIN_SET(0x0) | - XTAL_XTAL_LOCALBIAS_SET(0x1) | - XTAL_XTAL_PWDCLKD_SET(0x0) | - XTAL_XTAL_BIAS2X_SET(0x0) | - XTAL_XTAL_LBIAS2X_SET(0x0) | - XTAL_XTAL_OSCON_SET(0x1) | - XTAL_XTAL_PWDCLKIN_SET(0x0) | - XTAL_LOCAL_XTAL_SET(0x0) | - XTAL_PWD_SWREGCLK_SET(0x0) | - XTAL_SPARE_SET(0x0); - - /* checking feature enable bit 6 and caldata is valid */ - if ((eep->featureEnable & 0x40) && (eep->pad[0x0] != 0xff)) { - val &= ~(XTAL_XTAL_CAPINDAC_MASK | XTAL_XTAL_CAPOUTDAC_MASK); - val |= XTAL_XTAL_CAPINDAC_SET(eep->params_for_tuning_caps[0]) | - XTAL_XTAL_CAPOUTDAC_SET(eep->params_for_tuning_caps[0]); - } - - ath_reg_wr(XTAL_ADDRESS, val); - ath_reg_wr(XTAL2_ADDRESS, XTAL2_DCA_BYPASS_SET(0x1) | - XTAL2_FSM_START_L_SET(0x1)); - ath_reg_wr(XTAL3_ADDRESS, XTAL3_EVAL_LENGTH_SET(0x400) | - XTAL3_HARMONIC_NUMBER_SET(0x51)); - -#define __str(x) # x -#define str(x) __str(x) - - //printf("Setting " str(XTAL_ADDRESS) " to 0x%x\n", val); - return; -} - -void ath_usb_initial_config(void) -{ -#define unset(a) (~(a)) - - if (ath_reg_rd(RST_BOOTSTRAP_ADDRESS) & RST_BOOTSTRAP_TESTROM_ENABLE_MASK) { - - ath_reg_rmw_set(RST_RESET_ADDRESS, RST_RESET_USB_HOST_RESET_SET(1)); - udelay(1000); - ath_reg_rmw_set(RST_RESET_ADDRESS, RST_RESET_USB_PHY_RESET_SET(1)); - udelay(1000); - - ath_reg_wr(PHY_CTRL5_ADDRESS, PHY_CTRL5_RESET_1); - udelay(1000); - - ath_reg_rmw_set(RST_RESET_ADDRESS, RST_RESET_USB_PHY_PLL_PWD_EXT_SET(1)); - udelay(1000); - ath_reg_rmw_set(RST_RESET_ADDRESS, RST_RESET_USB_PHY_ARESET_SET(1)); - udelay(1000); - - ath_reg_rmw_clear(RST_CLKGAT_EN_ADDRESS, RST_CLKGAT_EN_USB1_SET(1)); - - return; - } - - ath_reg_wr_nf(SWITCH_CLOCK_SPARE_ADDRESS, - ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS) | - SWITCH_CLOCK_SPARE_USB_REFCLK_FREQ_SEL_SET(2)); - udelay(1000); - - ath_reg_rmw_set(RST_RESET_ADDRESS, - RST_RESET_USB_PHY_SUSPEND_OVERRIDE_SET(1)); - udelay(1000); - ath_reg_rmw_clear(RST_RESET_ADDRESS, RST_RESET_USB_PHY_ARESET_SET(1)); - udelay(1000); - ath_reg_rmw_clear(RST_RESET_ADDRESS, RST_RESET_USB_PHY_RESET_SET(1)); - udelay(1000); - ath_reg_rmw_clear(RST_RESET_ADDRESS, RST_RESET_USB_HOST_RESET_SET(1)); - udelay(1000); - - ath_reg_rmw_clear(RST_RESET_ADDRESS, RST_RESET_USB_PHY_PLL_PWD_EXT_SET(1)); - udelay(10); -} - -int ath_mem_config(void) -{ - unsigned int type, reg32, *tap; - extern uint32_t *ath_ddr_tap_cal(void); - -#if !defined(CONFIG_ATH_EMULATION) - - type = ath_ddr_initial_config(CFG_DDR_REFRESH_VAL); - - tap = ath_ddr_tap_cal(); - //prmsg("tap = 0x%p\n", tap); - - tap = (uint32_t *)0xbd001f10; - //prmsg("Tap (low, high) = (0x%x, 0x%x)\n", tap[0], tap[1]); - - tap = (uint32_t *)TAP_CONTROL_0_ADDRESS; - //prmsg("Tap values = (0x%x, 0x%x, 0x%x, 0x%x)\n", - // tap[0], tap[2], tap[2], tap[3]); - - /* Take WMAC out of reset */ - reg32 = ath_reg_rd(RST_RESET_ADDRESS); - reg32 = reg32 & ~RST_RESET_RTC_RESET_SET(1); - ath_reg_wr_nf(RST_RESET_ADDRESS, reg32); - - ath_usb_initial_config(); - -#endif /* !defined(CONFIG_ATH_EMULATION) */ - - //ath_set_tuning_caps(); - - return ath_ddr_find_size(); -} - +/* + * DRAM init + */ long int dram_init() { - return ath_mem_config(); + qca_dram_init(); + + return (long int)qca_dram_size(); } diff --git a/u-boot/board/ar7240/db12x/db12x.c b/u-boot/board/ar7240/db12x/db12x.c index f1c71be..5573738 100644 --- a/u-boot/board/ar7240/db12x/db12x.c +++ b/u-boot/board/ar7240/db12x/db12x.c @@ -1,75 +1,20 @@ +/* + * Copyright (C) 2016 Piotr Dymacz + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include #include -#include -#include #include -#include -#include #include -#include "ar7240_soc.h" - -extern int wasp_ddr_initial_config(uint32_t refresh); - -void ath_set_tuning_caps(void) -{ - typedef struct { - u_int8_t pad[0x28]; - u_int8_t params_for_tuning_caps[2]; - u_int8_t featureEnable; - } __attribute__((__packed__)) ar9300_eeprom_t; - - ar9300_eeprom_t *eep = (ar9300_eeprom_t *)WLANCAL; - uint32_t val = 0; - - /* checking feature enable bit 6 and caldata is valid */ - if((eep->featureEnable & 0x40) && (eep->pad[0x0] != 0xff)){ - /* xtal_capin -bit 17:23 and xtag_capout -bit 24:30*/ - val = (eep->params_for_tuning_caps[0] & 0x7f) << 17; - val |= (eep->params_for_tuning_caps[0] & 0x7f) << 24; - } else { - /* default when no caldata available*/ - /* checking clock in bit 4 */ - if(ar7240_reg_rd(RST_BOOTSTRAP_ADDRESS) & 0x10){ - val = (0x1020 << 17); /*default 0x2040 for 40Mhz clock*/ - } else { - val = (0x2040 << 17); /*default 0x4080 for 25Mhz clock*/ - } - } - - val |= (ar7240_reg_rd(XTAL_ADDRESS) & (((1 << 17) - 1) | (1 << 31))); - ar7240_reg_wr(XTAL_ADDRESS, val); - - //prmsg("Setting 0xb8116290 to 0x%x\n", val); - return; -} - -int wasp_mem_config(void) -{ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT - unsigned int reg32; - - wasp_ddr_initial_config(CFG_DDR_REFRESH_VAL); - - /* Take WMAC out of reset */ - reg32 = ar7240_reg_rd(AR7240_RESET); - reg32 = reg32 & ~AR7240_RESET_WMAC; - - ar7240_reg_wr_nf(AR7240_RESET, reg32); - - /* Switching regulator settings */ - ar7240_reg_wr_nf(0x18116c40, 0x633c8176); /* AR_PHY_PMU1 */ - ar7240_reg_wr_nf(0x18116c44, 0x10380000); /* AR_PHY_PMU2 */ - - //wasp_usb_initial_config(); - - /* Needed here not to mess with Ethernet clocks */ - ath_set_tuning_caps(); - -#endif - // return memory size - return (int)qca_dram_size(); -} +/* + * DRAM init + */ long int dram_init() { - return (long int)wasp_mem_config(); + qca_dram_init(); + + return (long int)qca_dram_size(); } diff --git a/u-boot/cpu/mips/ar7240/Makefile b/u-boot/cpu/mips/ar7240/Makefile index c622068..c1e4feb 100644 --- a/u-boot/cpu/mips/ar7240/Makefile +++ b/u-boot/cpu/mips/ar7240/Makefile @@ -6,7 +6,6 @@ START = OBJS = SOBJS = -OBJS += meminit.o OBJS += qca_common.o OBJS += qca_clocks.o OBJS += qca_sf.o @@ -16,7 +15,6 @@ SOBJS += qca_gpio_init.o ifeq ($(BOARD), ap121) OBJS += qca_hs_uart.o OBJS += ag7240.o - OBJS += ar933x_dram.o SOBJS += ar933x_pll_init.o else OBJS += qca_ls_uart.o diff --git a/u-boot/cpu/mips/ar7240/ar933x_dram.c b/u-boot/cpu/mips/ar7240/ar933x_dram.c deleted file mode 100644 index 05fbc3e..0000000 --- a/u-boot/cpu/mips/ar7240/ar933x_dram.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Atheros AR933x WiSoC DRAM related functions - * - * Copyright (C) 2016 Piotr Dymacz - * Copyright (C) 2015-2016 Wills Wang - * Copyright (C) 2013 Qualcomm Atheros, Inc. - * Copyright (C) 2008-2010 Atheros Communications Inc. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include - -/* - * DQS delay tap tune - * - * This function is a modified C version of the original - * ar933x_ddr_tap_init(void) function, written in asm, - * included in Atheros SDK code - * - * Below is, slightly modified version based on: - * https://patchwork.ozlabs.org/patch/569046/ - */ - -#define DQS_DELAY_TAP_LIMIT_VAL 31 -#define DQS_DELAY_TAP_START_VAL (DQS_DELAY_TAP_LIMIT_VAL / 2) -#define DQS_DELAY_TAP_PATTERN_OFFSET 0x2000 -#define DQS_DELAY_TAP_PATTERN_SIZE 0x1000 - -/* Setup DQS_{0,1} tap setting */ -static inline void ar933x_ddr_tap_save(u32 tap) -{ - /* Awlays bypass higher 32-level delay chain (use only lower) */ - tap = tap | QCA_DDR_TAP_CTRL_TAP_H_BYPASS_MASK; - - qca_soc_reg_write(QCA_DDR_TAP_CTRL_0_REG, tap); - qca_soc_reg_write(QCA_DDR_TAP_CTRL_1_REG, tap); -} - -static void ar933x_ddr_tap_tune(void) -{ - u32 *addr, *addr_k0, *addr_k1; - u32 cnt_up, done, err, i, j; - u32 tap, tap_hi, tap_lo; - - /* Use middle value as starting point */ - ar933x_ddr_tap_save(DQS_DELAY_TAP_START_VAL); - - /* Prepare 4M (256 x 4 x 4 bytes) pattern */ - addr = (void *)KSEG0ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); - - for (i = 0; i < 256; i++) { - tap = 0; - - for (j = 0; j < 8; j++) { - if (i & (1 << j)) { - if (j % 2) - tap |= 0xFFFF0000; - else - tap |= 0x0000FFFF; - } - - if (j % 2) { - *addr++ = tap; - tap = 0; - } - } - } - - tap = DQS_DELAY_TAP_START_VAL; - - /* 1 -> incrementing, 0 -> decrementing */ - cnt_up = 1; - tap_lo = 0; - tap_hi = DQS_DELAY_TAP_LIMIT_VAL; - - addr = (void *)KSEG0ADDR(DQS_DELAY_TAP_PATTERN_OFFSET - + DQS_DELAY_TAP_PATTERN_SIZE); - - done = 0; - - while (!done) { - ar933x_ddr_tap_save(tap); - - err = 0; - - /* 2 passes per each tested tap value */ - for (i = 0; i < 2; i++) { - addr_k1 = (void *)KSEG1ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); - addr_k0 = (void *)KSEG0ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); - - while (addr_k0 < addr) { - if (*addr_k1++ != *addr_k0++) { - err = 1; - break; - } - } - - if (err) - break; - } - - if (err) { - if (cnt_up) { - /* Upper value found */ - tap--; - tap_hi = tap; - - cnt_up = 0; - tap = DQS_DELAY_TAP_START_VAL; - } else { - /* Lower value found */ - tap++; - tap_lo = tap; - done = 1; - } - } else { - if (cnt_up) { - if (tap < DQS_DELAY_TAP_LIMIT_VAL) { - tap++; - } else { - /* Reached max. possible value */ - tap_hi = tap; - - cnt_up = 0; - tap = DQS_DELAY_TAP_START_VAL; - } - } else { - if (tap == 0) { - /* Reached min. possible value */ - tap_lo = tap; - done = 1; - } else { - tap--; - } - } - } - } - - /* Use average value as target tap */ - tap = (tap_hi + tap_lo) / 2; - ar933x_ddr_tap_save(tap); -} - -/* - * Initial DRAM configuration - */ -void qca_dram_init(void) -{ - u32 mem_type = qca_dram_type(); - - /* AR933x supports only 16-bit memory */ - qca_soc_reg_write(QCA_DDR_RD_DATA_THIS_CYCLE_REG, 0xFF); - - /* DDR timings (if not defined, use values from old SDK code) */ -#ifdef CONFIG_QCA_DDR_CFG_REG_VAL - qca_soc_reg_write(QCA_DDR_CFG_REG, CONFIG_QCA_DDR_CFG_REG_VAL); -#else - /* - * tRAS = 16, tRCD = 6, tRP = 6, tRRD = 4, tRFC = 30, tMRD = 15 - * CAS = 7, page closed - */ - qca_soc_reg_write(QCA_DDR_CFG_REG, - _qca_ddr_cfg_reg_val(16, 6, 6, 4, 30, 15, 7, 1)); -#endif - -#ifdef CONFIG_QCA_DDR_CFG2_REG_VAL - qca_soc_reg_write(QCA_DDR_CFG2_REG, CONFIG_QCA_DDR_CFG2_REG_VAL); -#else - /* - * Burst length always 8, burst type: sequential, - * 3-state addr/ctrl outputs, output phase 0, CKE = 1, - * tWR = 6, tRTW = 14, tRTP = 8, tWTR = 14, - * gate open latency = 7, use low half width of DQ bus - */ - qca_soc_reg_write(QCA_DDR_CFG2_REG, - _qca_ddr_cfg2_reg_val(0, 1, 0, 1, 6, 14, 8, 14, 7, 1)); -#endif - - if (mem_type == RAM_MEMORY_TYPE_SDR) { - /* Enable SDR */ - qca_soc_reg_write(QCA_SDR_CFG_REG, 1); - } - - if (mem_type == RAM_MEMORY_TYPE_DDR2) { - /* Enable DDR2 */ - qca_soc_reg_write(QCA_DDR_DDR2_CFG_REG, - _qca_ddr_ddr2_cfg_reg_val(1, 22, 2)); - } - - /* Precharge all */ - qca_dram_force_preall(); - - if (mem_type == RAM_MEMORY_TYPE_DDR2) { - /* Setup target EMR2 (full array, no dcc, no srf) */ - qca_dram_set_emr2(_ddr_sdram_emr2_val(0, 0, 0)); - - /* Setup target EMR3 */ - qca_dram_set_emr3(_ddr_sdram_emr2_val(0, 0, 0)); - } - - /* Enable and reset DLL */ - qca_dram_set_emr(_ddr_sdram_emr_val(0, 1, 0, 0, 0, 0)); - - qca_dram_set_mr(_ddr_sdram_mr_val(0, 0, 1, 0)); - - /* Precharge all and 2x auto refresh */ - qca_dram_force_preall(); - - qca_dram_force_aref(); - qca_dram_force_aref(); - - if (mem_type == RAM_MEMORY_TYPE_DDR2) { - /* Setup target MR (burst sequential, CAS3, wr recoery 6) */ - qca_dram_set_mr(_ddr_sdram_mr_val(0, 3, 0, 6)); - - /* OCD calibration, target EMR (nDQS disable, weak strength) */ - qca_dram_set_emr( - _ddr_sdram_emr_val(0, 1, DDR_SDRAM_EMR_OCD_DEFAULT_VAL, 1, 0, 0)); - - qca_dram_set_emr( - _ddr_sdram_emr_val(0, 1, DDR_SDRAM_EMR_OCD_EXIT_VAL, 1, 0, 0)); - } else { - /* Setup target MR (burst sequential, CAS3) */ - qca_dram_set_mr(_ddr_sdram_mr_val(0, 3, 0, 0)); - } - - /* Enable DDR refresh and setup refresh period */ - qca_dram_set_en_refresh(); - - ar933x_ddr_tap_tune(); -} diff --git a/u-boot/cpu/mips/ar7240/meminit.c b/u-boot/cpu/mips/ar7240/meminit.c deleted file mode 100644 index 49a16b7..0000000 --- a/u-boot/cpu/mips/ar7240/meminit.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Memory controller config: - * Assumes that the caches are initialized. - * - * 0) Figah out the Tap controller settings. - * 1) Figure out whether the interface is 16bit or 32bit. - * 2) Size the DRAM - * - * 0) Tap controller settings - * -------------------------- - * The Table below provides all possible values of TAP controllers. We need to - * find the extreme left and extreme right of the spectrum (of max_udelay and - * min_udelay). We then program the TAP to be in the middle. - * Note for this we would need to be able to read and write memory. So, - * initially we assume that a 16bit interface, which will always work unless - * there is exactly _1_ 32 bit part...for now we assume this is not the case. - * - * The algo: - * 0) Program the controller in 16bit mode. - * 1) Start with the extreme left of the table - * 2) Write 0xa4, 0xb5, 0xc6, 0xd7 to 0, 2, 4, 6 - * 3) Read 0 - this will fetch the entire cacheline. - * 4) If the value at address 4 is good, record this table entry, goto 6 - * 5) Increment to get the next table entry. Goto 2. - * 6) Start with extreme right. Do the same as above. - * - * 1) 16bit or 32bit - * ----------------- - * 31st bit of reg 0x1800_0000 will determine the mode. By default, - * controller is set to 32-bit mode. In 32 bit mode, full data bus DQ [31:0] - * will be used to write 32 bit data. Suppose you have 16bit DDR memory - * (it will have 16bit wide data bus). If you try to write 16 bit DDR in 32 - * bit mode, you are going to miss upper 16 bits of data. Reading to that - * location will give you only lower 16 bits correctly, upper 16 bits will - * have some junk value. E.g., - * - * write to 0x0000_0000 0x12345678 - * write to 0x0000_1000 0x00000000 (just to discharge DQ[31:16] ) - * read from 0x0000_0000 - * if u see something like 0x0000_5678 (or XXXX_5678 but not equal to - * 0x12345678) - its a 16 bit interface - * - * 2) Size the DRAM - * ------------------- - * DDR wraps around. Write a pattern to 0x0000_0000. Write an address - * pattern at 4M, 8M, 16M etc. and check when 0x0000_0000 gets overwritten. - * - * - * We can use #define's for all these addresses and patterns but its easier - * to see what's going on without :) - */ -#include -#include -#include "ar7240_soc.h" - -#if defined(CONFIG_WASP) -int wasp_ddr_initial_config(uint32_t refresh){ - int ddr_config, ddr_config2, ext_mod, mod_val, mod_val_init, cycle_val, tap_val, type; - - switch(WASP_RAM_TYPE(ar7240_reg_rd(WASP_BOOTSTRAP_REG))){ - case 0: - case 1: // SDRAM - - // XXX XXX XXX XXX XXX XXX XXX XXX XXX - // Boot strap select is not working. In some boards, - // ddr2 shows up as sdram. Hence ignoring the foll. - // break statement. - // XXX XXX XXX XXX XXX XXX XXX XXX XXX - // break; - - ddr_config = CFG_934X_SDRAM_CONFIG_VAL; - ddr_config2 = CFG_934X_SDRAM_CONFIG2_VAL; - mod_val_init = CFG_934X_SDRAM_MODE_VAL_INIT; - mod_val = CFG_934X_SDRAM_MODE_VAL; - cycle_val = CFG_SDRAM_RD_DATA_THIS_CYCLE_VAL; - tap_val = CFG_934X_SDRAM_TAP_VAL; - - ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, 0x13b); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_DEBUG_RD_CNTL, 0x3000001f); - udelay(100); - - type = 0; - - break; - - case 2: // ddr2 - - ddr_config = CFG_934X_DDR2_CONFIG_VAL; - ddr_config2 = CFG_934X_DDR2_CONFIG2_VAL; - ext_mod = CFG_934X_DDR2_EXT_MODE_VAL; - mod_val_init = CFG_934X_DDR2_MODE_VAL_INIT; - mod_val = CFG_934X_DDR2_MODE_VAL; - cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL; - tap_val = CFG_934X_DDR2_TAP_VAL; - - ar7240_reg_wr_nf(AR7240_DDR_DDR2_CONFIG, CFG_934X_DDR2_EN_TWL_VAL); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x10); - udelay(10); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x20); - udelay(10); - - if(ar7240_reg_rd(AR7240_REV_ID) & 0xf){ - // NAND Clear - if(ar7240_reg_rd(WASP_BOOTSTRAP_REG) & (1 << 3)){ - ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, (1 << 6)); - cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_32; - } else { - ar7240_reg_rmw_set(AR7240_DDR_CTL_CONFIG, (1 << 6)); - cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16; - } - } else { -#if DDR2_32BIT_SUPPORT - ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, 0); -#endif - } - udelay(10); - - type = 1; - - break; - - case 3: // ddr1 - - ddr_config = CFG_934X_DDR1_CONFIG_VAL; - ddr_config2 = CFG_934X_DDR1_CONFIG2_VAL; - ext_mod = CFG_934X_DDR1_EXT_MODE_VAL; - mod_val_init = CFG_934X_DDR1_MODE_VAL_INIT; - mod_val = CFG_934X_DDR1_MODE_VAL; - cycle_val = CFG_DDR1_RD_DATA_THIS_CYCLE_VAL; - tap_val = CFG_934X_DDR1_TAP_VAL; - - type = 2; - - break; - } - - ar7240_reg_wr_nf(AR7240_DDR_CONFIG, ddr_config); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, ddr_config2 | 0x80); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); - udelay(10); - - ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val_init); - udelay(1000); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); - udelay(10); - - if(type == 1){ - //ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, CFG_934X_DDR2_EXT_MODE_VAL_INIT); - ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, CFG_934X_DDR2_MODE_VAL_INIT); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); - udelay(10); - } - - if(type != 0){ - ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, ext_mod); - } - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); - udelay(10); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); - udelay(10); - - ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); - udelay(10); - - ar7240_reg_wr_nf(AR7240_DDR_REFRESH, refresh); - udelay(100); - - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL0, tap_val); - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL1, tap_val); - - if(ar7240_reg_rd(AR7240_REV_ID) & 0xf){ - /* NAND Clear */ - if((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & (1 << 3)) && type){ - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL2, tap_val); - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL3, tap_val); - } - } else { -#if DDR2_32BIT_SUPPORT - if(type != 0){ - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL2, tap_val); - ar7240_reg_wr(AR7240_DDR_TAP_CONTROL3, tap_val); - } -#endif - } - - ar7240_reg_wr_nf(AR7240_DDR_RD_DATA_THIS_CYCLE, cycle_val); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_BURST, 0x74444444); - udelay(100); - - ar7240_reg_wr_nf(AR7240_DDR_BURST2, 0x222); - udelay(100); - - ar7240_reg_wr_nf(AR7240_AHB_MASTER_TIMEOUT, 0xfffff); - udelay(100); - -#if (CFG_PLL_FREQ == CFG_PLL_600_500_250) || \ - (CFG_PLL_FREQ == CFG_PLL_500_500_250) - // PMU2 ddr ldo tune - ar7240_reg_rmw_set(0xb8116c44, (0x3 << 19)); - udelay(100); -#endif - - return(type); -} -#endif diff --git a/u-boot/cpu/mips/ar7240/qca_dram.c b/u-boot/cpu/mips/ar7240/qca_dram.c index c7ee83d..3bca1d3 100644 --- a/u-boot/cpu/mips/ar7240/qca_dram.c +++ b/u-boot/cpu/mips/ar7240/qca_dram.c @@ -1,8 +1,15 @@ /* - * Qualcomm/Atheros WiSoCs DRAM related common functions + * Qualcomm/Atheros WiSoCs DRAM related + * functions for WiSoC families: + * - Atheros AR933x + * - Atheros AR934x + * - Qualcomm/Atheros QCA953x + * - Qualcomm/Atheros QCA955x + * - Qualcomm/Atheros QCA956x * * Copyright (C) 2016 Piotr Dymacz - * Copyright (C) 2013 Qualcomm Atheros, Inc. + * Copyright (C) 2015-2016 Wills Wang + * Copyright (C) 2014 Qualcomm Atheros, Inc. * Copyright (C) 2008-2010 Atheros Communications Inc. * * SPDX-License-Identifier: GPL-2.0 @@ -62,6 +69,7 @@ u32 qca_dram_size(void) u32 qca_dram_type(void) { #if defined(CONFIG_BOARD_DRAM_TYPE_SDR) + #error "SDRAM is not supported!" return RAM_MEMORY_TYPE_SDR; #elif defined(CONFIG_BOARD_DRAM_TYPE_DDR1) return RAM_MEMORY_TYPE_DDR1; @@ -132,3 +140,744 @@ u32 qca_dram_cas_lat(void) return CONFIG_BOARD_DRAM_CAS_LATENCY #endif } + +/* + * =============================================== + * DQS delay tap controller tune related functions + * =============================================== + */ +#define DQS_DELAY_TAP_DEFAULT_VAL 8 + +#if (SOC_TYPE & QCA_AR933X_SOC) |\ + (SOC_TYPE & QCA_AR934X_SOC) + #define DQS_DELAY_TAP_MAX_VAL 62 +#else + #define DQS_DELAY_TAP_MAX_VAL 63 +#endif + +/* + * Setup DQS_{0,1,2,3} delay tap control register/s + */ +static void qca_ddr_tap_save(u32 tap, u32 ddr_width) +{ +#if (SOC_TYPE & QCA_AR933X_SOC) |\ + (SOC_TYPE & QCA_AR934X_SOC) + u32 tap_h; + + /* It seems that AR93xx SoCs have two delay chains */ + if (tap > (DQS_DELAY_TAP_MAX_VAL / 2)) { + tap_h = tap - (DQS_DELAY_TAP_MAX_VAL / 2); + tap = tap & QCA_DDR_TAP_CTRL_TAP_L_MASK; + tap = tap | (tap_h << QCA_DDR_TAP_CTRL_TAP_H_SHIFT); + } +#endif + + qca_soc_reg_write(QCA_DDR_TAP_CTRL_0_REG, tap); + qca_soc_reg_write(QCA_DDR_TAP_CTRL_1_REG, tap); + + /* Setup DQS2 and DQS3 only for 32-bit DDR interface width */ + if (ddr_width == 32) { + qca_soc_reg_write(QCA_DDR_TAP_CTRL_2_REG, tap); + qca_soc_reg_write(QCA_DDR_TAP_CTRL_3_REG, tap); + } +} + +/* + * Only for AR933x we will use different code + * for delay tap controller tune as it seems + * that this SoC doesn't have DDR BIST. + * + * Below function is universal, so it should + * work also for other QC/A WiSoCs and give + * same (or very similar) results. The only + * difference is that the DDR BIST based + * version seems to be much faster. + */ +#if (SOC_TYPE & QCA_AR933X_SOC) + + #define DQS_DELAY_TAP_PATTERN_OFFSET 0x2000 + #define DQS_DELAY_TAP_PATTERN_SIZE 0x1000 + #define DQS_DELAY_TAP_TEST_LOOPS 2 + +/* + * Prepare pattern for further tests + */ +static inline void qca_ddr_tap_patt(void) +{ + u32 i, j, pat; + u32 *addr; + + /* Prepare 4M (256 x 4 x 4 bytes) pattern */ + addr = (void *)KSEG1ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); + + for (i = 0; i < 256; i++) { + pat = 0; + + for (j = 0; j < 8; j++) { + if (i & (1 << j)) { + if (j % 2) + pat |= 0xFFFF0000; + else + pat |= 0x0000FFFF; + } + + if (j % 2) { + *addr++ = pat; + pat = 0; + } + } + } +} + +/* + * This function is a modified C version of the original + * ar933x_ddr_tap_init() function, written in asm, + * included in Atheros (Q)SDK code. + * + * Below is a modified version, partially based on: + * https://patchwork.ozlabs.org/patch/569046/ + */ +static void qca_ddr_tap_tune(u32 ddr_width) +{ + u32 *addr, *addr_k0, *addr_k1; + u32 tap, tap_hi, tap_lo; + u32 err, got_lo, i; + + /* Pattern */ + qca_ddr_tap_patt(); + + got_lo = 0; + tap_hi = 0; + tap_lo = 0; + + addr = (void *)KSEG1ADDR(DQS_DELAY_TAP_PATTERN_OFFSET + + DQS_DELAY_TAP_PATTERN_SIZE); + + /* + * Idea here is to test all possible tap values, one by one, + * starting from the lowest. We are looking for a range within + * the written and read back data is the same. We assume here + * that the valid tap range is continuous. + * + * From hardware POV, delay tap controller is used to adjust + * the data window. + */ + for (tap = 0; tap <= DQS_DELAY_TAP_MAX_VAL; tap++) { + qca_ddr_tap_save(tap, ddr_width); + + err = 0; + + for (i = 0; i < DQS_DELAY_TAP_TEST_LOOPS; i++) { + addr_k1 = (void *)KSEG1ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); + addr_k0 = (void *)KSEG0ADDR(DQS_DELAY_TAP_PATTERN_OFFSET); + + while (addr_k1 < addr) { + if (*addr_k1++ != *addr_k0++) { + err = 1; + break; + } + } + + if (err) + break; + } + + if (err) { + if (got_lo) { + if (tap > 0) + tap_hi = tap - 1; + + break; + } + } else { + if (!got_lo) { + tap_lo = tap; + got_lo = 1; + } else { + tap_hi = tap; + } + } + } + + /* Calculate final tap value (rounded up average) */ + if (got_lo) { + tap = (tap_hi + tap_lo + 1) / 2; + } else { + tap = DQS_DELAY_TAP_DEFAULT_VAL; + } + + qca_ddr_tap_save(tap, ddr_width); +} + +#else /* SOC_TYPE & QCA_AR933X_SOC */ + + #define DQS_DELAY_TAP_TEST_LOOPS 8 + +/* + * Unknown magic values and registers from Atheros (Q)SDK. + * + * It looks like some test patterns and masks setup, + * but it's not confirmed. Used here values are + * different, but were tested on real hardware. + */ +static inline void qca_ddr_tap_bist_init(void) +{ + qca_soc_reg_write(QCA_DDR_PERF_COMP_AHB_GE0_0_REG, 0xAAAAAAAA); + qca_soc_reg_write(QCA_DDR_PERF_MASK_AHB_GE0_0_REG, 0xAAAAAAAA); + + qca_soc_reg_write(QCA_DDR_PERF_COMP_AHB_GE0_1_REG, 0x55555555); + qca_soc_reg_write(QCA_DDR_PERF_MASK_AHB_GE0_1_REG, 0x55555555); + + qca_soc_reg_write(QCA_DDR_PERF_COMP_AHB_GE1_0_REG, 0xAAAAAAAA); + qca_soc_reg_write(QCA_DDR_PERF_MASK_AHB_GE1_0_REG, 0xAAAAAAAA); + + qca_soc_reg_write(QCA_DDR_PERF_COMP_AHB_GE1_1_REG, 0x55555555); + qca_soc_reg_write(QCA_DDR_PERF_MASK_AHB_GE1_1_REG, 0x55555555); +} + +/* + * This function is a modified C version of the original + * ath_ddr_tap_cal() function, written in asm, + * included in Atheros (Q)SDK code. + * + * It seems that newer QC/A WiSoCs have some kind of + * built-in self-test (BIST) for DDR controller, but + * none of the used registers or their values are + * described in datasheets, so for now, we will just + * use them as in original code. + * + * Below is a modified version, partially based on: + * https://patchwork.ozlabs.org/patch/569047/ + */ +static void qca_ddr_tap_tune(u32 ddr_width) +{ + u32 tap, tap_hi, tap_lo; + u32 fail, got_lo, reg; + + got_lo = 0; + tap_hi = 0; + tap_lo = 0; + + /* How many test loops per tested tap value */ + qca_soc_reg_write(QCA_DDR_PERF_COMP_ADDR_1_REG, + (DQS_DELAY_TAP_TEST_LOOPS + << QCA_DDR_PERF_COMP_ADDR_1_TEST_CNT_SHIFT)); + + /* + * Unknown magic value, original comment: + * "4 Row Address Bits, 4 Column Address Bits, 2 BA bits" + */ + qca_soc_reg_write(QCA_DDR_PERF_MASK_ADDR_0_REG, 0xFA5DE83F); + + /* + * Test all possible tap values, try to find working range + * (minimum and maximum delays) and use average value + */ + for (tap = 0; tap <= DQS_DELAY_TAP_MAX_VAL; tap++) { + qca_ddr_tap_save(tap, ddr_width); + + qca_ddr_tap_bist_init(); + + /* Enable BIST test and wait for finish */ + qca_soc_reg_write(QCA_DDR_BIST_REG, QCA_DDR_BIST_TEST_EN_MASK); + + do { + reg = qca_soc_reg_read(QCA_DDR_BIST_STATUS_REG); + } while (!(reg & QCA_DDR_BIST_STATUS_DONE_MASK)); + + /* Disable BIST test */ + qca_soc_reg_write(QCA_DDR_BIST_REG, 0); + + /* Check how many tests failed */ + fail = (reg & QCA_DDR_BIST_STATUS_FAIL_CNT_MASK) + >> QCA_DDR_BIST_STATUS_FAIL_CNT_SHIFT; + + if (fail == 0) { + if (!got_lo) { + tap_lo = tap; + got_lo = 1; + } else { + tap_hi = tap; + } + } else { + if (got_lo) { + if (tap > 0) + tap_hi = tap - 1; + + break; + } + } + } + + /* Calculate final tap value (rounded up average) */ + if (got_lo) { + tap = (tap_hi + tap_lo + 1) / 2; + } else { + tap = DQS_DELAY_TAP_DEFAULT_VAL; + } + + qca_ddr_tap_save(tap, ddr_width); +} + +#endif /* SOC_TYPE & QCA_AR933X_SOC */ + +/* + * =============================================== + * DDR controller initialization related functions + * =============================================== + */ + +/* + * Below defines are "safe" DDR1/DDR2 timing parameters. + * They should work for most chips, but not for all. + * + * For different values, user can define target value + * of all memory controller related registers. + * + */ +#define DDRx_tMRD_ns 10 +#define DDRx_tRAS_ns 40 +#define DDRx_tRCD_ns 15 +#define DDRx_tRP_ns 15 +#define DDRx_tRRD_ns 10 +#define DDRx_tWR_ns 15 +#define DDRx_tWTR_ns 10 + +#define DDR1_tRFC_ns 75 +#define DDR2_tRFC_ns 120 + +#define DDR2_tFAW_ns 50 +#define DDR2_tWL_ns 5 + +#define DDR_addit_lat 0 +#define DDR_burst_len 8 + +/* All above values are safe for clocks not lower than below values */ +#define DDR1_timing_clk_max 400 +#define DDR2_timing_clk_max 533 + +/* Maximum timing values, based on register fields sizes */ +#define MAX_tFAW BITS(0, 6) +#define MAX_tMRD BITS(0, 4) +#define MAX_tRAS BITS(0, 5) +#define MAX_tRCD BITS(0, 4) +#define MAX_tRFC BITS(0, 6) +#define MAX_tRP BITS(0, 4) +#define MAX_tRRD BITS(0, 4) +#define MAX_tRTP BITS(0, 4) +#define MAX_tRTW BITS(0, 5) +#define MAX_tWL BITS(0, 4) +#define MAX_tWR BITS(0, 4) +#define MAX_tWTR BITS(0, 5) + +/* + * Setup DDR_CONFIG register + */ +static inline void qca_dram_set_ddr_cfg(u32 mem_cas, + u32 ddr_clk, + u32 mem_type) +{ +#ifndef CONFIG_QCA_DDR_CFG_REG_VAL + u32 reg = 0; + u32 tmp = 0; + + reg = qca_soc_reg_read(QCA_DDR_CFG_REG); + + /* Always use page close policy */ + reg = reg | QCA_DDR_CFG_PAGE_CLOSE_MASK; + + /* CAS should be (2 * MEM_CAS) or (2 * MEM_CAS) + 1/2/3 */ + tmp = 2 * mem_cas; + tmp = (tmp << QCA_DDR_CFG_CAS_3LSB_SHIFT) & QCA_DDR_CFG_CAS_3LSB_MASK; + if (mem_cas > 3) { + tmp = tmp | QCA_DDR_CFG_CAS_MSB_MASK; + } + + reg = reg & ~QCA_DDR_CFG_CAS_3LSB_MASK; + reg = reg | tmp; + + /* + * Calculate rest of timing related values, + * always round up to closest integer + */ + + /* tMRD */ + tmp = ((DDRx_tMRD_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tMRD) + tmp = MAX_tMRD; + + tmp = (tmp << QCA_DDR_CFG_TMRD_SHIFT) & QCA_DDR_CFG_TMRD_MASK; + reg = reg & ~QCA_DDR_CFG_TMRD_MASK; + reg = reg | tmp; + + /* tRFC */ + if (mem_type == RAM_MEMORY_TYPE_DDR2) { + tmp = ((DDR2_tRFC_ns * ddr_clk) + 500) / 1000; + } else { + tmp = ((DDR1_tRFC_ns * ddr_clk) + 500) / 1000; + } + + if (tmp > MAX_tRFC) + tmp = MAX_tRFC; + + tmp = (tmp << QCA_DDR_CFG_TRFC_SHIFT) & QCA_DDR_CFG_TRFC_MASK; + reg = reg & ~QCA_DDR_CFG_TRFC_MASK; + reg = reg | tmp; + + /* tRRD */ + tmp = ((DDRx_tRRD_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tRRD) + tmp = MAX_tRRD; + + tmp = (tmp << QCA_DDR_CFG_TRRD_SHIFT) & QCA_DDR_CFG_TRRD_MASK; + reg = reg & ~QCA_DDR_CFG_TRRD_MASK; + reg = reg | tmp; + + /* tRP */ + tmp = ((DDRx_tRP_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tRP) + tmp = MAX_tRP; + + tmp = (tmp << QCA_DDR_CFG_TRP_SHIFT) & QCA_DDR_CFG_TRP_MASK; + reg = reg & ~QCA_DDR_CFG_TRP_MASK; + reg = reg | tmp; + + /* tRCD */ + tmp = ((DDRx_tRCD_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tRCD) + tmp = MAX_tRCD; + + tmp = (tmp << QCA_DDR_CFG_TRCD_SHIFT) & QCA_DDR_CFG_TRCD_MASK; + reg = reg & ~QCA_DDR_CFG_TRCD_MASK; + reg = reg | tmp; + + /* tRAS */ + tmp = ((DDRx_tRAS_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tRAS) + tmp = MAX_tRAS; + + tmp = (tmp << QCA_DDR_CFG_TRAS_SHIFT) & QCA_DDR_CFG_TRAS_MASK; + reg = reg & ~QCA_DDR_CFG_TRAS_MASK; + reg = reg | tmp; + + qca_soc_reg_write(QCA_DDR_CFG_REG, reg); +#else + qca_soc_reg_write(QCA_DDR_CFG_REG, CONFIG_QCA_DDR_CFG_REG_VAL); +#endif +} + +/* + * Setup DDR_CONFIG2 register + */ +static inline void qca_dram_set_ddr_cfg2(u32 mem_cas, + u32 ddr_clk, + u32 mem_type, + u32 ddr_width) +{ +#ifndef CONFIG_QCA_DDR_CFG2_REG_VAL + u32 reg = 0; + u32 tmp = 0; + + reg = qca_soc_reg_read(QCA_DDR_CFG2_REG); + + /* Enable CKE */ + reg = reg | QCA_DDR_CFG2_CKE_MASK; + + /* Gate open latency = 2 * MEM_CAS */ + tmp = 2 * mem_cas; + tmp = (tmp << QCA_DDR_CFG2_GATE_OPEN_LATENCY_SHIFT) + & QCA_DDR_CFG2_GATE_OPEN_LATENCY_MASK; + reg = reg & ~QCA_DDR_CFG2_GATE_OPEN_LATENCY_MASK; + reg = reg | tmp; + + /* tWTR */ + if (mem_type == RAM_MEMORY_TYPE_DDR2) { + /* tWTR = 2 * WL + BL + 2 * max(tWTR/tCK, 2) */ + tmp = 2 * (mem_cas + DDR_addit_lat - 1) + DDR_burst_len + 4; + + if (ddr_clk >= 600) + tmp = tmp + 2; + } else { + /* tWTR = 2 + BL + (2 * tWTR/tCK) */ + tmp = 2 + DDR_burst_len + (((DDRx_tWTR_ns * ddr_clk) + 500) / 1000); + } + + if (tmp > MAX_tWTR) + tmp = MAX_tWTR; + + tmp = (tmp << QCA_DDR_CFG2_TWTR_SHIFT) & QCA_DDR_CFG2_TWTR_MASK; + reg = reg & ~QCA_DDR_CFG2_TWTR_MASK; + reg = reg | tmp; + + /* tRTP */ + if (ddr_width == 32) { + tmp = DDR_burst_len; + } else { + tmp = MAX_tRTP; + } + + tmp = (tmp << QCA_DDR_CFG2_TRTP_SHIFT) & QCA_DDR_CFG2_TRTP_MASK; + reg = reg & ~QCA_DDR_CFG2_TRTP_MASK; + reg = reg | tmp; + + /* tRTW */ + if (mem_type == RAM_MEMORY_TYPE_DDR2) { + /* tRTW = 2 * (RL + BL/2 + 1 -WL), RL = CL + AL, WL = RL - 1 */ + tmp = DDR_burst_len + 4; + } else { + /* tRTW = 2 * (CL + BL/2) */ + tmp = DDR_burst_len + (2 * mem_cas); + } + + if (tmp > MAX_tRTW) + tmp = MAX_tRTW; + + tmp = (tmp << QCA_DDR_CFG2_TRTW_SHIFT) & QCA_DDR_CFG2_TRTW_MASK; + reg = reg & ~QCA_DDR_CFG2_TRTW_MASK; + reg = reg | tmp; + + /* tWR */ + tmp = ((DDRx_tWR_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tWR) + tmp = MAX_tWR; + + tmp = (tmp << QCA_DDR_CFG2_TWR_SHIFT) & QCA_DDR_CFG2_TWR_MASK; + reg = reg & ~QCA_DDR_CFG2_TWR_MASK; + reg = reg | tmp; + + /* Always use burst length = 8 and type: sequential */ + tmp = (DDR_burst_len << QCA_DDR_CFG2_BURST_LEN_SHIFT) + & QCA_DDR_CFG2_BURST_LEN_MASK; + reg = reg & ~(QCA_DDR_CFG2_BURST_LEN_MASK + | QCA_DDR_CFG2_BURST_TYPE_MASK); + reg = reg | tmp; + + qca_soc_reg_write(QCA_DDR_CFG2_REG, reg); +#else + qca_soc_reg_write(QCA_DDR_CFG2_REG, CONFIG_QCA_DDR_CFG2_REG_VAL); +#endif +} + +/* + * Setup DDR2_CONFIG register (only for DDR2) + */ +static inline void qca_dram_set_ddr2_cfg(u32 mem_cas, + u32 ddr_clk) +{ +#ifndef CONFIG_QCA_DDR_DDR2_CFG_REG_VAL + u32 reg = 0; + u32 tmp = 0; + + reg = qca_soc_reg_read(QCA_DDR_DDR2_CFG_REG); + + /* Enable DDR2 */ + reg = reg | QCA_DDR_DDR2_CFG_DDR2_EN_MASK; + + /* tFAW */ + tmp = ((DDR2_tFAW_ns * ddr_clk) + 500) / 1000; + if (tmp > MAX_tFAW) + tmp = MAX_tFAW; + + tmp = (tmp << QCA_DDR_DDR2_CFG_DDR2_TFAW_SHIFT) + & QCA_DDR_DDR2_CFG_DDR2_TFAW_MASK; + reg = reg & ~QCA_DDR_DDR2_CFG_DDR2_TFAW_MASK; + reg = reg | tmp; + + /* tWL */ + tmp = (2 * mem_cas) - 3; + + /* For some reason, odd value doesn't work on AR933x (FIXME) */ + #if (SOC_TYPE & QCA_AR933X_SOC) + if (tmp % 2) + tmp = tmp - 1; + #endif + + tmp = (tmp << QCA_DDR_DDR2_CFG_DDR2_TWL_SHIFT) + & QCA_DDR_DDR2_CFG_DDR2_TWL_MASK; + reg = reg & ~QCA_DDR_DDR2_CFG_DDR2_TWL_MASK; + reg = reg | tmp; + + qca_soc_reg_write(QCA_DDR_DDR2_CFG_REG, reg); +#else + qca_soc_reg_write(QCA_DDR_DDR2_CFG_REG, CONFIG_QCA_DDR_DDR2_CFG_REG_VAL); +#endif +} + +/* + * Enables DDR refresh and sets + * refresh period based on XTAL + */ +static inline void qca_dram_set_en_refresh(void) +{ + /* + * Enable DDR refresh and setup refresh period: + * 1. We assume 7.8 us maximum average period refresh interval + * 2. 7.8 us ~= 0.1282 MHz + * 3. For 25 MHz XTAL: (25 / 0.1282) ~= 195 + * 4. For 40 MHz XTAL: (40 / 0.1282) ~= 312 + */ + if (qca_xtal_is_40mhz()) { + qca_soc_reg_write(QCA_DDR_REFRESH_REG, + QCA_DDR_REFRESH_EN_MASK + | (312 << QCA_DDR_REFRESH_PERIOD_SHIFT)); + } else { + qca_soc_reg_write(QCA_DDR_REFRESH_REG, + QCA_DDR_REFRESH_EN_MASK + | (195 << QCA_DDR_REFRESH_PERIOD_SHIFT)); + } +} + +/* + * Initial DRAM configuration + */ +void qca_dram_init(void) +{ + u32 ahb_clk, cpu_clk, ddr_clk, mem_type, tmp_clk; + u32 cas_lat, ddr_width, wr_recovery; + + mem_type = qca_dram_type(); + + qca_sys_clocks(&cpu_clk, &ddr_clk, &ahb_clk, NULL, NULL); + cpu_clk = cpu_clk / 1000000; + ddr_clk = ddr_clk / 1000000; + ahb_clk = ahb_clk / 1000000; + + /* Set CAS based on clock, but allow to set static value */ +#ifndef CONFIG_BOARD_DRAM_CAS_LATENCY + if (mem_type == RAM_MEMORY_TYPE_DDR1) { + if (ddr_clk <= 266) { + cas_lat = 2; + } else { + cas_lat = 3; + } + } else { + if (ddr_clk <= 400) { + cas_lat = 3; + } else if (ddr_clk <= 533) { + cas_lat = 4; + } else if (ddr_clk <= 666) { + cas_lat = 5; + } else if (ddr_clk <= 800) { + cas_lat = 6; + } else { + cas_lat = 7; + } + } +#else + cas_lat = CONFIG_BOARD_DRAM_CAS_LATENCY; +#endif + +#if (SOC_TYPE & QCA_AR933X_SOC) + /* AR933x supports only 16-bit memory */ + ddr_width = 16; + qca_soc_reg_write(QCA_DDR_RD_DATA_THIS_CYCLE_REG, 0xFF); +#else + /* For other WiSoCs we can determine DDR width, based on bootstrap */ + ddr_width = qca_dram_ddr_width(); + + if (ddr_width == 32) { + /* For 32-bit clear HALF_WIDTH and set VEC = 0xFF */ + qca_soc_reg_read_clear(QCA_DDR_CTRL_CFG_REG, + QCA_DDR_CTRL_CFG_HALF_WIDTH_MASK); + + qca_soc_reg_write(QCA_DDR_RD_DATA_THIS_CYCLE_REG, 0xFF); + } else { + qca_soc_reg_read_set(QCA_DDR_CTRL_CFG_REG, + QCA_DDR_CTRL_CFG_HALF_WIDTH_MASK); + + qca_soc_reg_write(QCA_DDR_RD_DATA_THIS_CYCLE_REG, 0xFFFF); + } + + /* If DDR_CLK < 2 * AHB_CLK, set DDR FSM wait control to 0xA24 */ + if (ddr_clk < (2 * ahb_clk)) + qca_soc_reg_write(QCA_DDR_FSM_WAIT_CTRL_REG, 0xA24); +#endif + + /* CPU/DDR sync mode */ + if (cpu_clk == ddr_clk) { +#if (SOC_TYPE & QCA_AR933X_SOC) + qca_soc_reg_read_set(QCA_DDR_TAP_CTRL_3_REG, (1 << 8)); +#else + qca_soc_reg_read_set(QCA_DDR_CTRL_CFG_REG, + QCA_DDR_CTRL_CFG_CPU_DDR_SYNC_MASK); +#endif + } else { +#if (SOC_TYPE & QCA_AR933X_SOC) + qca_soc_reg_read_clear(QCA_DDR_TAP_CTRL_3_REG, (1 << 8)); +#else + qca_soc_reg_read_clear(QCA_DDR_CTRL_CFG_REG, + QCA_DDR_CTRL_CFG_CPU_DDR_SYNC_MASK); +#endif + } + + /* Check if clock is not too low for our "safe" timing values */ + tmp_clk = ddr_clk; + if (mem_type == RAM_MEMORY_TYPE_DDR1) { + if (tmp_clk < DDR1_timing_clk_max) + tmp_clk = DDR1_timing_clk_max; + } else { + if (tmp_clk < DDR2_timing_clk_max) + tmp_clk = DDR2_timing_clk_max; + } + + /* Enable DDR2 */ + if (mem_type == RAM_MEMORY_TYPE_DDR2) { +#if (SOC_TYPE & QCA_AR933X_SOC) + qca_dram_set_ddr2_cfg(cas_lat, tmp_clk); +#else + qca_soc_reg_write(QCA_DDR_CTRL_CFG_REG, + QCA_DDR_CTRL_CFG_PAD_DDR2_SEL_MASK); + + qca_dram_set_ddr2_cfg(cas_lat, tmp_clk); +#endif + + } + + /* Setup DDR timing related registers */ + qca_dram_set_ddr_cfg(cas_lat, tmp_clk, mem_type); + qca_dram_set_ddr_cfg2(cas_lat, tmp_clk, mem_type, ddr_width); + + /* Precharge all */ + qca_dram_force_preall(); + + if (mem_type == RAM_MEMORY_TYPE_DDR2) { + /* Setup target EMR2 and EMR3 */ + qca_dram_set_emr2(_ddr_sdram_emr2_val(0, 0, 0)); + qca_dram_set_emr3(0); + } + + /* Enable and reset DLL */ + qca_dram_set_emr(_ddr_sdram_emr_val(0, 1, 0, 0, 0, 0)); + qca_dram_set_mr(_ddr_sdram_mr_val(0, 0, 1, 0)); + + /* Precharge all, 2x auto refresh */ + qca_dram_force_preall(); + + qca_dram_force_aref(); + qca_dram_force_aref(); + + if (mem_type == RAM_MEMORY_TYPE_DDR2) { + /* Setup target MR */ + wr_recovery = ((DDRx_tWR_ns * tmp_clk) + 1000) / 2000; + qca_dram_set_mr(_ddr_sdram_mr_val(0, cas_lat, 0, wr_recovery)); + + /* OCD calibration, target EMR (nDQS disable, weak strength) */ + qca_dram_set_emr( + _ddr_sdram_emr_val(0, 1, DDR_SDRAM_EMR_OCD_DEFAULT_VAL, 1, 0, 0)); + + qca_dram_set_emr( + _ddr_sdram_emr_val(0, 1, DDR_SDRAM_EMR_OCD_EXIT_VAL, 1, 0, 0)); + } else { + /* Setup target MR */ + qca_dram_set_mr(_ddr_sdram_mr_val(0, cas_lat, 0, 0)); + } + + /* Enable DDR refresh and setup refresh period */ + qca_dram_set_en_refresh(); + + /* + * At this point memory should be fully configured, + * so we can perform delay tap controller tune. + */ + qca_ddr_tap_tune(ddr_width); +} diff --git a/u-boot/include/soc/qca_dram.h b/u-boot/include/soc/qca_dram.h index d5f7229..e50471d 100644 --- a/u-boot/include/soc/qca_dram.h +++ b/u-boot/include/soc/qca_dram.h @@ -216,25 +216,4 @@ static inline void qca_dram_set_emr3(u32 value) qca_dram_force_emr3s(); } -/* Enables DDR refresh and sets refresh period based on XTAL */ -static inline void qca_dram_set_en_refresh(void) -{ - /* - * Enable DDR refresh and setup refresh period: - * 1. We assume 7.8 us maximum average period refresh interval - * 2. 7.8 us ~= 0.1282 MHz - * 3. For 25 MHz XTAL: (25 / 0.1282) ~= 195 - * 4. For 40 MHz XTAL: (40 / 0.1282) ~= 312 - */ - if (qca_xtal_is_40mhz()) { - qca_soc_reg_write(QCA_DDR_REFRESH_REG, - QCA_DDR_REFRESH_EN_MASK - | (312 << QCA_DDR_REFRESH_PERIOD_SHIFT)); - } else { - qca_soc_reg_write(QCA_DDR_REFRESH_REG, - QCA_DDR_REFRESH_EN_MASK - | (195 << QCA_DDR_REFRESH_PERIOD_SHIFT)); - } -} - #endif /* _QCA_DRAM_H_ */ diff --git a/u-boot/include/soc/qca_soc_common.h b/u-boot/include/soc/qca_soc_common.h index 1eb0a6f..1f0a24e 100644 --- a/u-boot/include/soc/qca_soc_common.h +++ b/u-boot/include/soc/qca_soc_common.h @@ -1,13 +1,14 @@ /* * Qualcomm/Atheros Wireless SOC common registers definitions * - * Copyright (C) 2014 Piotr Dymacz + * Copyright (C) 2016 Piotr Dymacz + * Copyright (C) 2014 Qualcomm Atheros, Inc. * Copyright (C) 2008-2010 Atheros Communications Inc. * * Partially based on: * Linux/arch/mips/include/asm/mach-ath79/ar71xx_regs.h * - * SPDX-License-Identifier:GPL-2.0 + * SPDX-License-Identifier: GPL-2.0 */ #ifndef _QCA_SOC_COMMON_H_ @@ -43,7 +44,7 @@ #if (SOC_TYPE & QCA_AR933X_SOC) #define QCA_SLIC_BASE_REG QCA_APB_BASE_REG + 0x00090000 -#elif (SOC_TYPE & QCA_AR934X_SOC) | \ +#elif (SOC_TYPE & QCA_AR934X_SOC) |\ (SOC_TYPE & QCA_AR955X_SOC) #define QCA_SLIC_BASE_REG QCA_APB_BASE_REG + 0x000A9000 #endif @@ -67,17 +68,6 @@ #define QCA_DDR_WB_FLUSH_GE0_REG QCA_DDR_CTRL_BASE_REG + 0x07C #define QCA_DDR_WB_FLUSH_GE1_REG QCA_DDR_CTRL_BASE_REG + 0x080 #define QCA_DDR_WB_FLUSH_USB_REG QCA_DDR_CTRL_BASE_REG + 0x084 -#else - #define QCA_DDR_WB_FLUSH_GE0_REG QCA_DDR_CTRL_BASE_REG + 0x09C - #define QCA_DDR_WB_FLUSH_GE1_REG QCA_DDR_CTRL_BASE_REG + 0x0A0 - #define QCA_DDR_WB_FLUSH_USB_REG QCA_DDR_CTRL_BASE_REG + 0x0A4 - #define QCA_DDR_WB_FLUSH_PCIE_REG QCA_DDR_CTRL_BASE_REG + 0x0A8 - #define QCA_DDR_WB_FLUSH_WMAC_REG QCA_DDR_CTRL_BASE_REG + 0x0AC - #define QCA_DDR_WB_FLUSH_SRC1_REG QCA_DDR_CTRL_BASE_REG + 0x0B0 - #define QCA_DDR_WB_FLUSH_SRC2_REG QCA_DDR_CTRL_BASE_REG + 0x0B4 -#endif - -#if (SOC_TYPE & QCA_AR933X_SOC) #define QCA_DDR_DDR2_CFG_REG QCA_DDR_CTRL_BASE_REG + 0x08C #define QCA_DDR_EMR2_REG QCA_DDR_CTRL_BASE_REG + 0x090 #define QCA_DDR_EMR3_REG QCA_DDR_CTRL_BASE_REG + 0x094 @@ -87,6 +77,13 @@ #define QCA_AHB_MASTER_TOUT_SLV_ADDR_REG QCA_DDR_CTRL_BASE_REG + 0x0A4 #define QCA_SDR_CFG_REG QCA_DDR_CTRL_BASE_REG + 0x0D8 #else + #define QCA_DDR_WB_FLUSH_GE0_REG QCA_DDR_CTRL_BASE_REG + 0x09C + #define QCA_DDR_WB_FLUSH_GE1_REG QCA_DDR_CTRL_BASE_REG + 0x0A0 + #define QCA_DDR_WB_FLUSH_USB_REG QCA_DDR_CTRL_BASE_REG + 0x0A4 + #define QCA_DDR_WB_FLUSH_PCIE_REG QCA_DDR_CTRL_BASE_REG + 0x0A8 + #define QCA_DDR_WB_FLUSH_WMAC_REG QCA_DDR_CTRL_BASE_REG + 0x0AC + #define QCA_DDR_WB_FLUSH_SRC1_REG QCA_DDR_CTRL_BASE_REG + 0x0B0 + #define QCA_DDR_WB_FLUSH_SRC2_REG QCA_DDR_CTRL_BASE_REG + 0x0B4 #define QCA_DDR_DDR2_CFG_REG QCA_DDR_CTRL_BASE_REG + 0x0B8 #define QCA_DDR_EMR2_REG QCA_DDR_CTRL_BASE_REG + 0x0BC #define QCA_DDR_EMR3_REG QCA_DDR_CTRL_BASE_REG + 0x0C0 @@ -101,6 +98,23 @@ #define QCA_DDR_SELF_REFRESH_TIMER_REG QCA_DDR_CTRL_BASE_REG + 0x114 #define QCA_DDR_WMAC_FLUSH_REG QCA_DDR_CTRL_BASE_REG + 0x128 #define QCA_DDR_CFG3_REG QCA_DDR_CTRL_BASE_REG + 0x15C + + /* + * Below register addresses and names come directly form Atheros (Q)SDK code: + * tap-955x.S/tap-953x.S/tap-956x.S, as they do not exist in any datasheet + */ + #define QCA_DDR_PERF_MASK_ADDR_0_REG QCA_DDR_CTRL_BASE_REG + 0x02C + #define QCA_DDR_PERF_MASK_AHB_GE0_0_REG QCA_DDR_CTRL_BASE_REG + 0x034 + #define QCA_DDR_PERF_COMP_AHB_GE0_0_REG QCA_DDR_CTRL_BASE_REG + 0x038 + #define QCA_DDR_PERF_MASK_AHB_GE1_0_REG QCA_DDR_CTRL_BASE_REG + 0x03C + #define QCA_DDR_PERF_COMP_AHB_GE1_0_REG QCA_DDR_CTRL_BASE_REG + 0x040 + #define QCA_DDR_PERF_COMP_ADDR_1_REG QCA_DDR_CTRL_BASE_REG + 0x068 + #define QCA_DDR_PERF_MASK_AHB_GE0_1_REG QCA_DDR_CTRL_BASE_REG + 0x06C + #define QCA_DDR_PERF_COMP_AHB_GE0_1_REG QCA_DDR_CTRL_BASE_REG + 0x070 + #define QCA_DDR_PERF_MASK_AHB_GE1_1_REG QCA_DDR_CTRL_BASE_REG + 0x074 + #define QCA_DDR_PERF_COMP_AHB_GE1_1_REG QCA_DDR_CTRL_BASE_REG + 0x078 + #define QCA_DDR_BIST_REG QCA_DDR_CTRL_BASE_REG + 0x11C + #define QCA_DDR_BIST_STATUS_REG QCA_DDR_CTRL_BASE_REG + 0x120 #endif /* @@ -186,12 +200,12 @@ #define QCA_DDR_RD_DATA_THIS_CYCLE_VEC_MASK BITS(QCA_DDR_RD_DATA_THIS_CYCLE_VEC_SHIFT, 32) /* TAP_CONTROL_X registers (DQS delay tap control for byte X) */ -#if (SOC_TYPE & QCA_AR933X_SOC) | \ +#if (SOC_TYPE & QCA_AR933X_SOC) |\ (SOC_TYPE & QCA_AR934X_SOC) #define QCA_DDR_TAP_CTRL_TAP_L_SHIFT 0 #define QCA_DDR_TAP_CTRL_TAP_L_MASK BITS(QCA_DDR_TAP_CTRL_TAP_L_SHIFT, 5) #define QCA_DDR_TAP_CTRL_TAP_H_SHIFT 8 - #define QCA_DDR_TAP_CTRL_TAP_H_MASK BITS(QCA_DDR_TAP_CTRL_TAP_H_SHIFT, 2) + #define QCA_DDR_TAP_CTRL_TAP_H_MASK BITS(QCA_DDR_TAP_CTRL_TAP_H_SHIFT, 5) #define QCA_DDR_TAP_CTRL_TAP_H_BYPASS_SHIFT 16 #define QCA_DDR_TAP_CTRL_TAP_H_BYPASS_MASK (1 << QCA_DDR_TAP_CTRL_TAP_H_BYPASS_SHIFT) #else @@ -264,6 +278,22 @@ #define QCA_DDR_CFG3_TWR_MSB_SHIFT 3 #define QCA_DDR_CFG3_TWR_MSB_MASK (1 << QCA_DDR_CFG3_TWR_MSB_SHIFT) +/* DDR_BIST (unknown, not described in datasheet, based on code only) */ +#define QCA_DDR_BIST_TEST_EN_SHIFT 0 +#define QCA_DDR_BIST_TEST_EN_MASK (1 << QCA_DDR_BIST_TEST_EN_SHIFT) + +/* DDR_BIST_STATUS (unknown, not described in datasheet, based on code only) */ +#define QCA_DDR_BIST_STATUS_DONE_SHIFT 0 +#define QCA_DDR_BIST_STATUS_DONE_MASK (1 << QCA_DDR_BIST_STATUS_DONE_SHIFT) +#define QCA_DDR_BIST_STATUS_PASS_CNT_SHIFT 1 +#define QCA_DDR_BIST_STATUS_PASS_CNT_MASK BITS(QCA_DDR_BIST_STATUS_PASS_CNT_SHIFT, 8) +#define QCA_DDR_BIST_STATUS_FAIL_CNT_SHIFT 9 +#define QCA_DDR_BIST_STATUS_FAIL_CNT_MASK BITS(QCA_DDR_BIST_STATUS_FAIL_CNT_SHIFT, 8) + +/* DDR_PERF_COMP_ADDR_1 (unknown, not described in datasheet, based on code only) */ +#define QCA_DDR_PERF_COMP_ADDR_1_TEST_CNT_SHIFT 1 +#define QCA_DDR_PERF_COMP_ADDR_1_TEST_CNT_MASK BITS(QCA_DDR_PERF_COMP_ADDR_1_TEST_CNT_SHIFT, 8) + /* * Low-Speed UART registers */ @@ -1374,7 +1404,7 @@ #define QCA_RST_RESET_EXT_RST_SHIFT 28 #define QCA_RST_RESET_EXT_RST_MASK (1 << QCA_RST_RESET_EXT_RST_SHIFT) -#if (SOC_TYPE & QCA_AR934X_SOC) | \ +#if (SOC_TYPE & QCA_AR934X_SOC) |\ (SOC_TYPE & QCA_QCA955X_SOC) #define QCA_RST_RESET_HOST_DMA_RST_SHIFT 29 #define QCA_RST_RESET_HOST_DMA_RST_MASK (1 << QCA_RST_RESET_HOST_DMA_RST_SHIFT) -- 2.25.1