uboot/arch/arm/cpu/armv7/exynos/dmc_common.c
<<
>>
Prefs
   1/*
   2 * Mem setup common file for different types of DDR present on Exynos boards.
   3 *
   4 * Copyright (C) 2012 Samsung Electronics
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <asm/arch/spl.h>
  11
  12#include "clock_init.h"
  13#include "common_setup.h"
  14#include "exynos5_setup.h"
  15
  16#define ZQ_INIT_TIMEOUT 10000
  17
  18int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16,
  19                        uint32_t *phy1_con16, uint32_t *phy0_con17,
  20                        uint32_t *phy1_con17)
  21{
  22        unsigned long val = 0;
  23        int i;
  24
  25        /*
  26         * ZQ Calibration:
  27         * Select Driver Strength,
  28         * long calibration for manual calibration
  29         */
  30        val = PHY_CON16_RESET_VAL;
  31        val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
  32        val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
  33        val |= ZQ_CLK_DIV_EN;
  34        writel(val, phy0_con16);
  35        writel(val, phy1_con16);
  36
  37        /* Disable termination */
  38        if (mem->zq_mode_noterm)
  39                val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
  40        writel(val, phy0_con16);
  41        writel(val, phy1_con16);
  42
  43        /* ZQ_MANUAL_START: Enable */
  44        val |= ZQ_MANUAL_STR;
  45        writel(val, phy0_con16);
  46        writel(val, phy1_con16);
  47
  48        /* ZQ_MANUAL_START: Disable */
  49        val &= ~ZQ_MANUAL_STR;
  50
  51        /*
  52         * Since we are manaully calibrating the ZQ values,
  53         * we are looping for the ZQ_init to complete.
  54         */
  55        i = ZQ_INIT_TIMEOUT;
  56        while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
  57                sdelay(100);
  58                i--;
  59        }
  60        if (!i)
  61                return -1;
  62        writel(val, phy0_con16);
  63
  64        i = ZQ_INIT_TIMEOUT;
  65        while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
  66                sdelay(100);
  67                i--;
  68        }
  69        if (!i)
  70                return -1;
  71        writel(val, phy1_con16);
  72
  73        return 0;
  74}
  75
  76void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode mode)
  77{
  78        unsigned long val;
  79
  80        if (mode == DDR_MODE_DDR3) {
  81                val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
  82                writel(val, phycontrol0);
  83        }
  84
  85        /* Update DLL Information: Force DLL Resyncronization */
  86        val = readl(phycontrol0);
  87        val |= FP_RSYNC;
  88        writel(val, phycontrol0);
  89
  90        /* Reset Force DLL Resyncronization */
  91        val = readl(phycontrol0);
  92        val &= ~FP_RSYNC;
  93        writel(val, phycontrol0);
  94}
  95
  96void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd)
  97{
  98        int channel, chip;
  99
 100        for (channel = 0; channel < mem->dmc_channels; channel++) {
 101                unsigned long mask;
 102
 103                mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
 104                for (chip = 0; chip < mem->chips_to_configure; chip++) {
 105                        int i;
 106
 107                        mask |= chip << DIRECT_CMD_CHIP_SHIFT;
 108
 109                        /* Sending NOP command */
 110                        writel(DIRECT_CMD_NOP | mask, directcmd);
 111
 112                        /*
 113                         * TODO(alim.akhtar@samsung.com): Do we need these
 114                         * delays? This one and the next were not there for
 115                         * DDR3.
 116                         */
 117                        sdelay(0x10000);
 118
 119                        /* Sending EMRS/MRS commands */
 120                        for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
 121                                writel(mem->direct_cmd_msr[i] | mask,
 122                                       directcmd);
 123                                sdelay(0x10000);
 124                        }
 125
 126                        if (mem->send_zq_init) {
 127                                /* Sending ZQINIT command */
 128                                writel(DIRECT_CMD_ZQINIT | mask,
 129                                       directcmd);
 130
 131                                sdelay(10000);
 132                        }
 133                }
 134        }
 135}
 136
 137void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd)
 138{
 139        int channel, chip;
 140
 141        for (channel = 0; channel < mem->dmc_channels; channel++) {
 142                unsigned long mask;
 143
 144                mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
 145                for (chip = 0; chip < mem->chips_per_channel; chip++) {
 146                        mask |= chip << DIRECT_CMD_CHIP_SHIFT;
 147
 148                        /* PALL (all banks precharge) CMD */
 149                        writel(DIRECT_CMD_PALL | mask, directcmd);
 150                        sdelay(0x10000);
 151                }
 152        }
 153}
 154
 155void mem_ctrl_init(int reset)
 156{
 157        struct spl_machine_param *param = spl_get_machine_params();
 158        struct mem_timings *mem;
 159        int ret;
 160
 161        mem = clock_get_mem_timings();
 162
 163        /* If there are any other memory variant, add their init call below */
 164        if (param->mem_type == DDR_MODE_DDR3) {
 165                ret = ddr3_mem_ctrl_init(mem, reset);
 166                if (ret) {
 167                        /* will hang if failed to init memory control */
 168                        while (1)
 169                                ;
 170                }
 171        } else {
 172                /* will hang if unknow memory type  */
 173                while (1)
 174                        ;
 175        }
 176}
 177