+/*
+ * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <config.h>
#include <common.h>
-#include <command.h>
-#include <asm/mipsregs.h>
#include <asm/addrspace.h>
-#include <config.h>
-#include <version.h>
-#include <atheros.h>
#include <soc/qca_soc_common.h>
-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();
}
+/*
+ * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <config.h>
#include <common.h>
-#include <command.h>
-#include <asm/mipsregs.h>
#include <asm/addrspace.h>
-#include <config.h>
-#include <version.h>
#include <soc/qca_soc_common.h>
-#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();
}
OBJS =
SOBJS =
-OBJS += meminit.o
OBJS += qca_common.o
OBJS += qca_clocks.o
OBJS += qca_sf.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
+++ /dev/null
-/*
- * Atheros AR933x WiSoC DRAM related functions
- *
- * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
- * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
- * Copyright (C) 2013 Qualcomm Atheros, Inc.
- * Copyright (C) 2008-2010 Atheros Communications Inc.
- *
- * SPDX-License-Identifier: GPL-2.0
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/addrspace.h>
-#include <soc/qca_soc_common.h>
-#include <soc/qca_dram.h>
-
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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 <common.h>
-#include <asm/addrspace.h>
-#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
/*
- * 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 <piotr@dymacz.pl>
- * Copyright (C) 2013 Qualcomm Atheros, Inc.
+ * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
+ * Copyright (C) 2014 Qualcomm Atheros, Inc.
* Copyright (C) 2008-2010 Atheros Communications Inc.
*
* SPDX-License-Identifier: GPL-2.0
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;
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);
+}
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_ */
/*
* Qualcomm/Atheros Wireless SOC common registers definitions
*
- * Copyright (C) 2014 Piotr Dymacz <piotr@dymacz.pl>
+ * Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>
+ * 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_
#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
#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
#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
#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
/*
#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
#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
*/
#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)