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