1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include <common.h>
20 #include <malloc.h>
21 #include <sdhci.h>
22 #include "mmc_private.h"
23
24 #define MIN_FREQ 400000
25 #define NOT_FOUND (-1)
26 #define PHASE_SCALE 32
27 #define EDGE_TUNING_PHASE_STEP 4
28
29 static void hisi_enable_sample(struct sdhci_host *host);
30 static void hisi_set_drv_phase(struct sdhci_host *host, unsigned int phase);
31 static void hisi_set_sampl_phase(struct sdhci_host *host, unsigned int phase);
32 static void hisi_wait_sampl_dll_slave_ready(struct sdhci_host *host);
33 static void hisi_enable_card_clk(struct sdhci_host *host);
34 static void hisi_disable_card_clk(struct sdhci_host *host);
35 static void hisi_enable_internal_clk(struct sdhci_host *host);
36 static void hisi_disable_internal_clk(struct sdhci_host *host);
37
38 #if defined(CONFIG_TARGET_HI3556AV100) || defined(CONFIG_TARGET_HI3519AV100)
39 #include <asm/arch-hi3556av100/platform.h>
40 #include "hisi_hi3556av100.c"
41 #endif
42
43 #if defined(CONFIG_TARGET_HI3559AV100) || defined(CONFIG_TARGET_HI3569V100)
44 #include <asm/arch-hi3559av100/platform.h>
45 #include "hisi_hi3559av100.c"
46 #endif
47
48 #ifdef CONFIG_TARGET_HI3516EV200
49 #include <asm/arch-hi3516ev200/platform.h>
50 #include "hisi_hi3516ev200.c"
51 #endif
52
53 #ifdef CONFIG_TARGET_HI3516EV300
54 #include <asm/arch-hi3516ev300/platform.h>
55 #include "hisi_hi3516ev300.c"
56 #endif
57
58 #ifdef CONFIG_TARGET_HI3518EV300
59 #include <asm/arch-hi3518ev300/platform.h>
60 #include "hisi_hi3518ev300.c"
61 #endif
62
63 #ifdef CONFIG_TARGET_HI3516DV200
64 #include <asm/arch-hi3516dv200/platform.h>
65 #include "hisi_hi3516dv200.c"
66 #endif
67
68 #ifdef CONFIG_TARGET_HI3531DV200
69 #include <asm/arch-hi3531dv200/platform.h>
70 #include "hisi_hi3531dv200.c"
71 #endif
72
73 #ifdef CONFIG_TARGET_HI3535AV100
74 #include <asm/arch-hi3531dv200/platform.h>
75 #include "hisi_hi3531dv200.c"
76 #endif
77
78 #ifdef CONFIG_TARGET_HI3521DV200
79 #include <asm/arch-hi3521dv200/platform.h>
80 #include "hisi_hi3521dv200.c"
81 #endif
82
83 #ifdef CONFIG_TARGET_HI3520DV500
84 #include <asm/arch-hi3521dv200/platform.h>
85 #include "hisi_hi3521dv200.c"
86 #endif
87
hisi_enable_card_clk(struct sdhci_host * host)88 static void hisi_enable_card_clk(struct sdhci_host *host)
89 {
90 u16 clk;
91
92 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
93 clk |= SDHCI_CLOCK_CARD_EN;
94 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
95 }
96
hisi_disable_card_clk(struct sdhci_host * host)97 static void hisi_disable_card_clk(struct sdhci_host *host)
98 {
99 u16 clk;
100
101 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
102 clk &= ~SDHCI_CLOCK_CARD_EN;
103 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
104 }
105
hisi_enable_internal_clk(struct sdhci_host * host)106 static void hisi_enable_internal_clk(struct sdhci_host *host)
107 {
108 u16 clk;
109 u16 timeout = 20;
110
111 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
112 clk |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_PLL_EN;
113 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
114
115 /* Wait max 20 ms */
116 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
117 while (!(clk & SDHCI_CLOCK_INT_STABLE)) {
118 if (timeout == 0) {
119 printf("%s: Internal clock never stabilised.\n",
120 __func__);
121 return;
122 }
123 timeout--;
124 udelay(1000); /* delay 1000us */
125 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
126 }
127 }
128
hisi_disable_internal_clk(struct sdhci_host * host)129 static void __maybe_unused hisi_disable_internal_clk(struct sdhci_host *host)
130 {
131 u16 clk;
132
133 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
134 clk &= ~SDHCI_CLOCK_INT_EN;
135 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
136 }
137
hisi_set_drv_phase(struct sdhci_host * host,unsigned int phase)138 static void hisi_set_drv_phase(struct sdhci_host *host, unsigned int phase)
139 {
140 uintptr_t crg_addr;
141 unsigned int reg;
142
143 crg_addr = host->type == MMC_TYPE_MMC ?
144 REG_EMMC_DRV_DLL_CTRL : REG_SDIO0_DRV_DLL_CTRL;
145 reg = readl(crg_addr);
146 reg &= ~SDIO_DRV_PHASE_SEL_MASK;
147 reg |= sdio_drv_sel(phase);
148 writel(reg, crg_addr);
149 }
150
hisi_enable_sample(struct sdhci_host * host)151 static void hisi_enable_sample(struct sdhci_host *host)
152 {
153 unsigned int reg;
154
155 reg = sdhci_readl(host, SDHCI_AT_CTRL);
156 reg |= SDHCI_SAMPLE_EN;
157 sdhci_writel(host, reg, SDHCI_AT_CTRL);
158 }
159
hisi_set_sampl_phase(struct sdhci_host * host,unsigned int phase)160 static void hisi_set_sampl_phase(struct sdhci_host *host, unsigned int phase)
161 {
162 unsigned int reg;
163
164 reg = sdhci_readl(host, SDHCI_AT_STAT);
165 reg &= ~SDHCI_PHASE_SEL_MASK;
166 reg |= phase;
167 sdhci_writel(host, reg, SDHCI_AT_STAT);
168 }
169
hisi_wait_sampl_dll_slave_ready(struct sdhci_host * host)170 static void hisi_wait_sampl_dll_slave_ready(struct sdhci_host *host)
171 {
172 unsigned int reg;
173 unsigned int timeout = 20;
174 uintptr_t reg_addr;
175
176 reg_addr = host->type == MMC_TYPE_MMC ?
177 REG_EMMC_SAMPL_DLL_STATUS : REG_SDIO0_SAMPL_DLL_STATUS;
178 do {
179 reg = readl(reg_addr);
180 if (reg & SDIO_SAMPL_DLL_SLAVE_READY)
181 return;
182
183 udelay(1000); /* delay 1000us */
184 timeout--;
185 } while (timeout > 0);
186
187 printf("sdhci-hisi: SAMPL DLL slave not ready.\n");
188 }
189
hisi_enable_edge_tuning(struct sdhci_host * host)190 static void hisi_enable_edge_tuning(struct sdhci_host *host)
191 {
192 unsigned int reg;
193
194 reg = readl(REG_EMMC_SAMPLB_DLL_CTRL);
195 reg &= ~SDIO_SAMPLB_DLL_CLK_MASK;
196 reg |= sdio_samplb_sel(8); /* sel 8 */
197 writel(reg, REG_EMMC_SAMPLB_DLL_CTRL);
198
199 reg = sdhci_readl(host, SDHCI_MULTI_CYCLE);
200 reg |= SDHCI_EDGE_DETECT_EN;
201 sdhci_writel(host, reg, SDHCI_MULTI_CYCLE);
202 }
203
hisi_disable_edge_tuning(struct sdhci_host * host)204 static void hisi_disable_edge_tuning(struct sdhci_host *host)
205 {
206 unsigned int reg;
207
208 reg = sdhci_readl(host, SDHCI_MULTI_CYCLE);
209 reg &= ~SDHCI_EDGE_DETECT_EN;
210 sdhci_writel(host, reg, SDHCI_MULTI_CYCLE);
211 }
212
hisi_select_sampl_phase(struct sdhci_host * host,unsigned int phase)213 static void hisi_select_sampl_phase(struct sdhci_host *host, unsigned int phase)
214 {
215 hisi_disable_card_clk(host);
216 hisi_set_sampl_phase(host, phase);
217 hisi_wait_sampl_dll_slave_ready(host);
218 hisi_enable_card_clk(host);
219 udelay(1);
220 }
221
hisi_send_tuning(struct sdhci_host * host,u32 opcode,int * cmd_error)222 static int hisi_send_tuning(struct sdhci_host *host, u32 opcode, int* cmd_error)
223 {
224 int count, err;
225 const int tuning_num = 1;
226
227 count = 0;
228 do {
229 err = mmc_send_tuning(host->mmc, opcode, NULL);
230 if (err)
231 break;
232
233 count++;
234 } while (count < tuning_num);
235
236 return err;
237 }
238
hisi_mmc_exec_tuning(struct sdhci_host * host,unsigned int opcode)239 static int hisi_mmc_exec_tuning(struct sdhci_host *host, unsigned int opcode)
240 {
241 unsigned int index, val;
242 unsigned int edge_p2f, edge_f2p, start, end, phase;
243 unsigned int fall, rise, fall_updat_flag;
244 unsigned int found;
245 unsigned int prev_found = 0;
246 int err;
247 int prev_err = 0;
248 unsigned short ctrl;
249
250 hisi_wait_drv_dll_lock(host);
251 hisi_enable_sampl_dll_slave(host);
252 hisi_enable_sample(host);
253 hisi_enable_edge_tuning(host);
254 host->is_tuning = 1;
255
256 start = 0;
257 end = PHASE_SCALE / EDGE_TUNING_PHASE_STEP;
258
259 edge_p2f = start;
260 edge_f2p = end;
261 for (index = 0; index <= end; index++) {
262 hisi_select_sampl_phase(host, index * EDGE_TUNING_PHASE_STEP);
263
264 err = mmc_send_tuning(host->mmc, opcode, NULL);
265 if (!err) {
266 val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
267 found = val & SDHCI_FOUND_EDGE;
268 } else {
269 found = 1;
270 }
271
272 if (prev_found && !found)
273 edge_f2p = index;
274 else if (!prev_found && found)
275 edge_p2f = index;
276
277 if ((edge_p2f != start) && (edge_f2p != end))
278 break;
279
280 prev_found = found;
281 }
282
283 if ((edge_p2f == start) && (edge_f2p == end)) {
284 printf("sdhci-hisi: tuning failed! can not found edge!\n");
285 return -1;
286 }
287
288 hisi_disable_edge_tuning(host);
289
290 start = edge_p2f * EDGE_TUNING_PHASE_STEP;
291 end = edge_f2p * EDGE_TUNING_PHASE_STEP;
292 if (end <= start)
293 end += PHASE_SCALE;
294
295 fall = start;
296 rise = end;
297 fall_updat_flag = 0;
298 for (index = start; index <= end; index++) {
299 hisi_select_sampl_phase(host, index % PHASE_SCALE);
300
301 err = hisi_send_tuning(host, opcode, NULL);
302 if (err)
303 debug("sdhci-hisi: send tuning CMD%u fail! phase:%u err:%d\n",
304 opcode, index, err);
305
306 if (err && index == start) {
307 if (!fall_updat_flag) {
308 fall_updat_flag = 1;
309 fall = start;
310 }
311 } else {
312 if (!prev_err && err) {
313 if (!fall_updat_flag) {
314 fall_updat_flag = 1;
315 fall = index;
316 }
317 }
318 }
319
320 if (prev_err && !err)
321 rise = index;
322
323 if (err && index == end)
324 rise = end;
325
326 prev_err = err;
327 }
328
329 phase = ((fall + rise) / 2 + PHASE_SCALE / 2) % PHASE_SCALE; /* 2 for cal average */
330
331 printf("sdhci-hisi: tuning done! valid phase shift [%u, %u] Final Phase:%u\n",
332 rise % PHASE_SCALE, fall % PHASE_SCALE, phase);
333
334 host->tuning_phase = phase;
335 hisi_select_sampl_phase(host, phase);
336
337 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
338 ctrl |= SDHCI_CTRL_TUNED_CLK;
339 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
340 host->is_tuning = 0;
341
342 return 0;
343 }
344
hisi_sdhci_set_host_caps(struct sdhci_host * host)345 void hisi_sdhci_set_host_caps(struct sdhci_host *host)
346 {
347 host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz |
348 MMC_MODE_HS200 | MMC_MODE_4BIT;
349
350 #if defined(CONFIG_TARGET_HI3531DV200) || defined(CONFIG_TARGET_HI3535AV100) ||\
351 defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
352 if (get_mmc_bus_width() == MMC_BUS_WIDTH_8_BIT)
353 host->host_caps |= MMC_MODE_HS400_ES |
354 MMC_MODE_HS400 | MMC_MODE_8BIT;
355 #elif !(defined(CONFIG_TARGET_HI3516EV200) || defined(CONFIG_TARGET_HI3518EV300))
356 host->host_caps |= MMC_MODE_HS400_ES | MMC_MODE_HS400 |
357 MMC_MODE_8BIT;
358 #endif
359 }
360
hisi_sdhci_add_port(int index,uintptr_t regbase,u32 type)361 int hisi_sdhci_add_port(int index, uintptr_t regbase, u32 type)
362 {
363 struct sdhci_host *host = NULL;
364
365 if (type == MMC_TYPE_MMC)
366 emmc_hardware_init();
367 else
368 sd_hardware_init();
369
370 host = calloc(1, sizeof(struct sdhci_host));
371 if (host == NULL) {
372 puts("sdhci_host malloc fail!\n");
373 return -ENOMEM;
374 }
375
376 host->name = "hisi-sdhci";
377 host->index = index;
378 host->type = type;
379 host->ioaddr = (void *)regbase;
380 host->quirks = 0;
381 host->set_clock = hisi_mmc_set_clk;
382 host->priv_init = hisi_mmc_priv_init;
383 host->set_control_reg = hisi_mmc_set_ioconfig;
384 #ifdef MMC_SUPPORTS_TUNING
385 host->execute_tuning = hisi_mmc_exec_tuning;
386 #endif
387 hisi_sdhci_set_host_caps(host);
388 add_sdhci(host, CONFIG_HISI_SDHCI_MAX_FREQ, MIN_FREQ);
389 return 0;
390 }
391
print_mmcinfo(struct mmc * mmc)392 static void print_mmcinfo(struct mmc *mmc)
393 {
394 printf("MMC/SD Card:\n");
395 printf(" MID: 0x%x\n", mmc->cid[0] >> 24); /* bit24 - 31 */
396 printf(" Read Block: %d Bytes\n", mmc->read_bl_len);
397 printf(" Write Block: %d Bytes\n", mmc->write_bl_len);
398 printf(" Chip Size: %s Bytes (%s)\n",
399 ultohstr(mmc->capacity),
400 mmc->high_capacity ? "High Capacity" : "Low Capacity");
401 printf(" Name: \"%c%c%c%c%c\"\n",
402 mmc->cid[0] & 0xff, /* bit0 - 7 */
403 (mmc->cid[1] >> 24), /* bit24 - 32 */
404 (mmc->cid[1] >> 16) & 0xff, /* bit16 - 23 */
405 (mmc->cid[1] >> 8) & 0xff, /* bit8 - 15 */
406 mmc->cid[1] & 0xff); /* bit0 - 7 */
407
408 printf(" Chip Type: %s\n"
409 " Version: %d.%d\n",
410 IS_SD(mmc) ? "SD" : "MMC",
411 EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
412 EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
413
414 printf(" Speed: %sHz\n", ultohstr(mmc->clock));
415 printf(" Bus Width: %dbit\n", mmc->bus_width);
416 printf(" Mode: %s\n", mmc->strobe_enhanced ? "HS400ES" :
417 mmc->selected_mode == MMC_HS_400 ? "HS400" :
418 mmc->selected_mode == MMC_HS_200 ? "HS200" : "HS");
419 }
420
hisi_mmc_init(int dev_num)421 int hisi_mmc_init(int dev_num)
422 {
423 struct mmc *mmc = find_mmc_device(dev_num);
424 int ret;
425
426 if (mmc == NULL) {
427 printf("mmc device not found!!\n");
428 return -EINVAL;
429 }
430
431 #if defined(CONFIG_TARGET_HI3531DV200) || defined(CONFIG_TARGET_HI3535AV100) || \
432 defined(CONFIG_TARGET_HI3521DV200) || defined(CONFIG_TARGET_HI3520DV500)
433 mmc->dev_num = dev_num;
434 mmc->ocr_from_bootrom = dev_num == 0 ? get_ocr_from_bootrom() : 0;
435 writel(0, REG_SAVE_HCS); /* clear flag reg */
436 printf("mmc->ocr_from_bootrom 0x%08x\n", mmc->ocr_from_bootrom);
437 #endif
438 ret = mmc_init(mmc);
439 if (ret)
440 return ret;
441
442 if (!IS_SD(mmc)) {
443 print_mmcinfo(mmc);
444 return mmc_set_boot_config(mmc);
445 }
446
447 return 0;
448 }
449
printf_mmc(int dev_num)450 void printf_mmc(int dev_num)
451 {
452 struct mmc *mmc = find_mmc_device(dev_num);
453
454 if (mmc != NULL)
455 print_mmcinfo(mmc);
456 }
457