blob: 9b6ee69f4671e5beed37625fb896e46f22543be1 [file] [log] [blame]
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00001/*
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +05302 * Mem setup common file for different types of DDR present on Exynos boards.
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00003 *
4 * Copyright (C) 2012 Samsung Electronics
5 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00007 */
8
9#include <common.h>
10#include <asm/arch/spl.h>
11
12#include "clock_init.h"
Rajeshwari Shinde643be9c2013-07-04 12:29:17 +053013#include "common_setup.h"
14#include "exynos5_setup.h"
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000015
16#define ZQ_INIT_TIMEOUT 10000
17
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053018int 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)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000021{
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;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053034 writel(val, phy0_con16);
35 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000036
37 /* Disable termination */
38 if (mem->zq_mode_noterm)
39 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053040 writel(val, phy0_con16);
41 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000042
43 /* ZQ_MANUAL_START: Enable */
44 val |= ZQ_MANUAL_STR;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053045 writel(val, phy0_con16);
46 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000047
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;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053056 while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000057 sdelay(100);
58 i--;
59 }
60 if (!i)
61 return -1;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053062 writel(val, phy0_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000063
64 i = ZQ_INIT_TIMEOUT;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053065 while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000066 sdelay(100);
67 i--;
68 }
69 if (!i)
70 return -1;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053071 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000072
73 return 0;
74}
75
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053076void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode mode)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000077{
78 unsigned long val;
79
80 if (mode == DDR_MODE_DDR3) {
81 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053082 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000083 }
84
85 /* Update DLL Information: Force DLL Resyncronization */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053086 val = readl(phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000087 val |= FP_RSYNC;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053088 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000089
90 /* Reset Force DLL Resyncronization */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053091 val = readl(phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000092 val &= ~FP_RSYNC;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053093 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000094}
95
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053096void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000097{
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 */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530110 writel(DIRECT_CMD_NOP | mask, directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000111
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,
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530122 directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000123 sdelay(0x10000);
124 }
125
126 if (mem->send_zq_init) {
127 /* Sending ZQINIT command */
128 writel(DIRECT_CMD_ZQINIT | mask,
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530129 directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000130
131 sdelay(10000);
132 }
133 }
134 }
135}
136
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530137void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000138{
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 */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530149 writel(DIRECT_CMD_PALL | mask, directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000150 sdelay(0x10000);
151 }
152 }
153}
154
Rajeshwari Shinde643be9c2013-07-04 12:29:17 +0530155void mem_ctrl_init(int reset)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000156{
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) {
Akshay Saraswatcfde7582014-05-26 19:17:03 +0530165 ret = ddr3_mem_ctrl_init(mem, reset);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000166 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}