]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/exynos/dmc_common.c
53cfe6edb16510397c75abd53547c2c2fa312a74
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / exynos / dmc_common.c
1 /*
2  * Mem setup common file for different types of DDR present on SMDK5250 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
18 int dmc_config_zq(struct mem_timings *mem,
19                   struct exynos5_phy_control *phy0_ctrl,
20                   struct exynos5_phy_control *phy1_ctrl)
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_ctrl->phy_con16);
35         writel(val, &phy1_ctrl->phy_con16);
36
37         /* Disable termination */
38         if (mem->zq_mode_noterm)
39                 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
40         writel(val, &phy0_ctrl->phy_con16);
41         writel(val, &phy1_ctrl->phy_con16);
42
43         /* ZQ_MANUAL_START: Enable */
44         val |= ZQ_MANUAL_STR;
45         writel(val, &phy0_ctrl->phy_con16);
46         writel(val, &phy1_ctrl->phy_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_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
57                 sdelay(100);
58                 i--;
59         }
60         if (!i)
61                 return -1;
62         writel(val, &phy0_ctrl->phy_con16);
63
64         i = ZQ_INIT_TIMEOUT;
65         while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
66                 sdelay(100);
67                 i--;
68         }
69         if (!i)
70                 return -1;
71         writel(val, &phy1_ctrl->phy_con16);
72
73         return 0;
74 }
75
76 void update_reset_dll(struct exynos5_dmc *dmc, 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, &dmc->phycontrol0);
83         }
84
85         /* Update DLL Information: Force DLL Resyncronization */
86         val = readl(&dmc->phycontrol0);
87         val |= FP_RSYNC;
88         writel(val, &dmc->phycontrol0);
89
90         /* Reset Force DLL Resyncronization */
91         val = readl(&dmc->phycontrol0);
92         val &= ~FP_RSYNC;
93         writel(val, &dmc->phycontrol0);
94 }
95
96 void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
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, &dmc->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                                        &dmc->directcmd);
123                                 sdelay(0x10000);
124                         }
125
126                         if (mem->send_zq_init) {
127                                 /* Sending ZQINIT command */
128                                 writel(DIRECT_CMD_ZQINIT | mask,
129                                        &dmc->directcmd);
130
131                                 sdelay(10000);
132                         }
133                 }
134         }
135 }
136
137 void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
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, &dmc->directcmd);
150                         sdelay(0x10000);
151                 }
152         }
153 }
154
155 void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
156 {
157         writel(mem->memconfig, &dmc->memconfig0);
158         writel(mem->memconfig, &dmc->memconfig1);
159         writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
160         writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
161 }
162
163 void mem_ctrl_init(int reset)
164 {
165         struct spl_machine_param *param = spl_get_machine_params();
166         struct mem_timings *mem;
167         int ret;
168
169         mem = clock_get_mem_timings();
170
171         /* If there are any other memory variant, add their init call below */
172         if (param->mem_type == DDR_MODE_DDR3) {
173                 ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset);
174                 if (ret) {
175                         /* will hang if failed to init memory control */
176                         while (1)
177                                 ;
178                 }
179         } else {
180                 /* will hang if unknow memory type  */
181                 while (1)
182                         ;
183         }
184 }