blob: eff134c8f578452ae36df559d5637dd8c2a282a2 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kever Yang79c83062016-07-18 17:00:58 +08002/*
3 * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd
4 *
5 * Rockchip SD Host Controller Interface
Kever Yang79c83062016-07-18 17:00:58 +08006 */
7
8#include <common.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +08009#include <clk.h>
Kever Yang79c83062016-07-18 17:00:58 +080010#include <dm.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +080011#include <dm/ofnode.h>
Kever Yangc2868212017-02-13 17:38:57 +080012#include <dt-structs.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +080013#include <linux/delay.h>
Simon Glass61b29b82020-02-03 07:36:15 -070014#include <linux/err.h>
Masahiro Yamadab08c8c42018-03-05 01:20:11 +090015#include <linux/libfdt.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +080016#include <linux/iopoll.h>
Kever Yang79c83062016-07-18 17:00:58 +080017#include <malloc.h>
Kever Yangc2868212017-02-13 17:38:57 +080018#include <mapmem.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +080019#include "mmc_private.h"
Kever Yang79c83062016-07-18 17:00:58 +080020#include <sdhci.h>
Yifeng Zhaoac804142021-06-29 16:24:41 +080021#include <syscon.h>
22#include <asm/arch-rockchip/clock.h>
23#include <asm/arch-rockchip/hardware.h>
Kever Yang79c83062016-07-18 17:00:58 +080024
25/* 400KHz is max freq for card ID etc. Use that as min */
26#define EMMC_MIN_FREQ 400000
Yifeng Zhaoac804142021-06-29 16:24:41 +080027#define KHz (1000)
28#define MHz (1000 * KHz)
29#define SDHCI_TUNING_LOOP_COUNT 40
30
31#define PHYCTRL_CALDONE_MASK 0x1
32#define PHYCTRL_CALDONE_SHIFT 0x6
33#define PHYCTRL_CALDONE_DONE 0x1
34#define PHYCTRL_DLLRDY_MASK 0x1
35#define PHYCTRL_DLLRDY_SHIFT 0x5
36#define PHYCTRL_DLLRDY_DONE 0x1
37#define PHYCTRL_FREQSEL_200M 0x0
38#define PHYCTRL_FREQSEL_50M 0x1
39#define PHYCTRL_FREQSEL_100M 0x2
40#define PHYCTRL_FREQSEL_150M 0x3
41#define PHYCTRL_DLL_LOCK_WO_TMOUT(x) \
42 ((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
43 PHYCTRL_DLLRDY_DONE)
Kever Yang79c83062016-07-18 17:00:58 +080044
45struct rockchip_sdhc_plat {
46 struct mmc_config cfg;
47 struct mmc mmc;
48};
49
Yifeng Zhaoac804142021-06-29 16:24:41 +080050struct rockchip_emmc_phy {
51 u32 emmcphy_con[7];
52 u32 reserved;
53 u32 emmcphy_status;
Kever Yang79c83062016-07-18 17:00:58 +080054};
55
Yifeng Zhaoac804142021-06-29 16:24:41 +080056struct rockchip_sdhc {
57 struct sdhci_host host;
58 struct udevice *dev;
59 void *base;
60 struct rockchip_emmc_phy *phy;
61 struct clk emmc_clk;
62};
63
64struct sdhci_data {
65 int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
66 int (*emmc_phy_init)(struct udevice *dev);
67 int (*get_phy)(struct udevice *dev);
68};
69
70static int rk3399_emmc_phy_init(struct udevice *dev)
Kever Yang79c83062016-07-18 17:00:58 +080071{
Yifeng Zhaoac804142021-06-29 16:24:41 +080072 return 0;
73}
74
75static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
76{
77 u32 caldone, dllrdy, freqsel;
78
79 writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]);
80 writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]);
81 writel(RK_CLRSETBITS(0xf << 7, 6 << 7), &phy->emmcphy_con[0]);
82
83 /*
84 * According to the user manual, calpad calibration
85 * cycle takes more than 2us without the minimal recommended
86 * value, so we may need a little margin here
87 */
88 udelay(3);
89 writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]);
90
91 /*
92 * According to the user manual, it asks driver to
93 * wait 5us for calpad busy trimming. But it seems that
94 * 5us of caldone isn't enough for all cases.
95 */
96 udelay(500);
97 caldone = readl(&phy->emmcphy_status);
98 caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
99 if (caldone != PHYCTRL_CALDONE_DONE) {
100 printf("%s: caldone timeout.\n", __func__);
101 return;
102 }
103
104 /* Set the frequency of the DLL operation */
105 if (clock < 75 * MHz)
106 freqsel = PHYCTRL_FREQSEL_50M;
107 else if (clock < 125 * MHz)
108 freqsel = PHYCTRL_FREQSEL_100M;
109 else if (clock < 175 * MHz)
110 freqsel = PHYCTRL_FREQSEL_150M;
111 else
112 freqsel = PHYCTRL_FREQSEL_200M;
113
114 /* Set the frequency of the DLL operation */
115 writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]);
116 writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]);
117
118 read_poll_timeout(readl, &phy->emmcphy_status, dllrdy,
119 PHYCTRL_DLL_LOCK_WO_TMOUT(dllrdy), 1, 5000);
120}
121
122static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy)
123{
124 writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]);
125 writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]);
126}
127
128static int rk3399_emmc_get_phy(struct udevice *dev)
129{
130 struct rockchip_sdhc *priv = dev_get_priv(dev);
131 ofnode phy_node;
132 void *grf_base;
133 u32 grf_phy_offset, phandle;
134
135 phandle = dev_read_u32_default(dev, "phys", 0);
136 phy_node = ofnode_get_by_phandle(phandle);
137 if (!ofnode_valid(phy_node)) {
138 debug("Not found emmc phy device\n");
139 return -ENODEV;
140 }
141
142 grf_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
143 if (grf_base < 0) {
144 printf("%s Get syscon grf failed", __func__);
145 return -ENODEV;
146 }
147 grf_phy_offset = ofnode_read_u32_default(phy_node, "reg", 0);
148
149 priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset);
150
151 return 0;
152}
153
154static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
155{
156 struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
157 int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ;
158
159 if (cycle_phy)
160 rk3399_emmc_phy_power_off(priv->phy);
161
162 sdhci_set_clock(host->mmc, clock);
163
164 if (cycle_phy)
165 rk3399_emmc_phy_power_on(priv->phy, clock);
166
167 return 0;
168}
169
170static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
171{
172 struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
173 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
174 struct mmc *mmc = host->mmc;
175 uint clock = mmc->tran_speed;
176 u32 reg;
177
178 if (!clock)
179 clock = mmc->clock;
180
181 if (data->emmc_set_clock)
182 data->emmc_set_clock(host, clock);
183
184 if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
185 reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
186 reg &= ~SDHCI_CTRL_UHS_MASK;
187 reg |= SDHCI_CTRL_HS400;
188 sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
189 } else {
190 sdhci_set_uhs_timing(host);
191 }
192
193 return 0;
194}
195
196static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
197{
198 struct sdhci_host *host = dev_get_priv(mmc->dev);
199 char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
200 struct mmc_cmd cmd;
201 u32 ctrl, blk_size;
202 int ret = 0;
203
204 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
205 ctrl |= SDHCI_CTRL_EXEC_TUNING;
206 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
207
208 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
209 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
210
211 blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 64);
212 if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && host->mmc->bus_width == 8)
213 blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 128);
214 sdhci_writew(host, blk_size, SDHCI_BLOCK_SIZE);
215 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
216
217 cmd.cmdidx = opcode;
218 cmd.resp_type = MMC_RSP_R1;
219 cmd.cmdarg = 0;
220
221 do {
222 if (tuning_loop_counter-- == 0)
223 break;
224
225 mmc_send_cmd(mmc, &cmd, NULL);
226
227 if (opcode == MMC_CMD_SEND_TUNING_BLOCK)
228 /*
229 * For tuning command, do not do busy loop. As tuning
230 * is happening (CLK-DATA latching for setup/hold time
231 * requirements), give time to complete
232 */
233 udelay(1);
234
235 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
236 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
237
238 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
239 printf("%s:Tuning failed\n", __func__);
240 ret = -EIO;
241 }
242
243 if (tuning_loop_counter < 0) {
244 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
245 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
246 }
247
248 /* Enable only interrupts served by the SD controller */
249 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
250 /* Mask all sdhci interrupt sources */
251 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
252
253 return ret;
254}
255
256static struct sdhci_ops rockchip_sdhci_ops = {
257 .set_ios_post = rockchip_sdhci_set_ios_post,
258 .platform_execute_tuning = &rockchip_sdhci_execute_tuning,
259};
260
261static int rockchip_sdhci_probe(struct udevice *dev)
262{
263 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(dev);
Kever Yang79c83062016-07-18 17:00:58 +0800264 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Simon Glassc69cda22020-12-03 16:55:20 -0700265 struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
Kever Yang79c83062016-07-18 17:00:58 +0800266 struct rockchip_sdhc *prv = dev_get_priv(dev);
Yifeng Zhaoac804142021-06-29 16:24:41 +0800267 struct mmc_config *cfg = &plat->cfg;
Kever Yang79c83062016-07-18 17:00:58 +0800268 struct sdhci_host *host = &prv->host;
Kever Yang39fbb562016-12-28 11:32:35 +0800269 struct clk clk;
Yifeng Zhaoac804142021-06-29 16:24:41 +0800270 int ret;
Kever Yang39fbb562016-12-28 11:32:35 +0800271
Yifeng Zhaoac804142021-06-29 16:24:41 +0800272 host->max_clk = cfg->f_max;
Kever Yang39fbb562016-12-28 11:32:35 +0800273 ret = clk_get_by_index(dev, 0, &clk);
274 if (!ret) {
Yifeng Zhaoac804142021-06-29 16:24:41 +0800275 ret = clk_set_rate(&clk, host->max_clk);
Kever Yang39fbb562016-12-28 11:32:35 +0800276 if (IS_ERR_VALUE(ret))
277 printf("%s clk set rate fail!\n", __func__);
278 } else {
279 printf("%s fail to get clk\n", __func__);
280 }
Kever Yang79c83062016-07-18 17:00:58 +0800281
Yifeng Zhaoac804142021-06-29 16:24:41 +0800282 prv->emmc_clk = clk;
283 prv->dev = dev;
284
285 if (data->get_phy) {
286 ret = data->get_phy(dev);
287 if (ret)
288 return ret;
289 }
290
291 if (data->emmc_phy_init) {
292 ret = data->emmc_phy_init(dev);
293 if (ret)
294 return ret;
295 }
296
297 host->ops = &rockchip_sdhci_ops;
Kever Yang79c83062016-07-18 17:00:58 +0800298 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
299
Kever Yang79c83062016-07-18 17:00:58 +0800300 host->mmc = &plat->mmc;
Kever Yang79c83062016-07-18 17:00:58 +0800301 host->mmc->priv = &prv->host;
302 host->mmc->dev = dev;
303 upriv->mmc = host->mmc;
304
Yifeng Zhaoac804142021-06-29 16:24:41 +0800305 ret = sdhci_setup_cfg(cfg, host, cfg->f_max, EMMC_MIN_FREQ);
Kever Yang4dcdc5c2019-07-19 18:01:11 +0800306 if (ret)
307 return ret;
308
Kever Yang79c83062016-07-18 17:00:58 +0800309 return sdhci_probe(dev);
310}
311
Yifeng Zhaoac804142021-06-29 16:24:41 +0800312static int rockchip_sdhci_of_to_plat(struct udevice *dev)
Kever Yang79c83062016-07-18 17:00:58 +0800313{
Yifeng Zhaoac804142021-06-29 16:24:41 +0800314 struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
Kever Yang79c83062016-07-18 17:00:58 +0800315 struct sdhci_host *host = dev_get_priv(dev);
Yifeng Zhaoac804142021-06-29 16:24:41 +0800316 struct mmc_config *cfg = &plat->cfg;
317 int ret;
Kever Yang79c83062016-07-18 17:00:58 +0800318
319 host->name = dev->name;
Philipp Tomsich327b2b32017-09-11 22:04:21 +0200320 host->ioaddr = dev_read_addr_ptr(dev);
Yifeng Zhaoac804142021-06-29 16:24:41 +0800321
322 ret = mmc_of_parse(dev, cfg);
323 if (ret)
324 return ret;
Kever Yang79c83062016-07-18 17:00:58 +0800325
326 return 0;
327}
328
329static int rockchip_sdhci_bind(struct udevice *dev)
330{
Simon Glassc69cda22020-12-03 16:55:20 -0700331 struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
Kever Yang79c83062016-07-18 17:00:58 +0800332
Masahiro Yamada24f5aec2016-09-06 22:17:32 +0900333 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Kever Yang79c83062016-07-18 17:00:58 +0800334}
335
Yifeng Zhaoac804142021-06-29 16:24:41 +0800336static const struct sdhci_data rk3399_data = {
337 .emmc_set_clock = rk3399_sdhci_emmc_set_clock,
338 .get_phy = rk3399_emmc_get_phy,
339 .emmc_phy_init = rk3399_emmc_phy_init,
340};
341
342static const struct udevice_id sdhci_ids[] = {
343 {
344 .compatible = "arasan,sdhci-5.1",
345 .data = (ulong)&rk3399_data,
346 },
Kever Yang79c83062016-07-18 17:00:58 +0800347 { }
348};
349
350U_BOOT_DRIVER(arasan_sdhci_drv) = {
Yifeng Zhaoac804142021-06-29 16:24:41 +0800351 .name = "rockchip_sdhci_5_1",
Kever Yang79c83062016-07-18 17:00:58 +0800352 .id = UCLASS_MMC,
Yifeng Zhaoac804142021-06-29 16:24:41 +0800353 .of_match = sdhci_ids,
354 .of_to_plat = rockchip_sdhci_of_to_plat,
Kever Yang79c83062016-07-18 17:00:58 +0800355 .ops = &sdhci_ops,
356 .bind = rockchip_sdhci_bind,
Yifeng Zhaoac804142021-06-29 16:24:41 +0800357 .probe = rockchip_sdhci_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700358 .priv_auto = sizeof(struct rockchip_sdhc),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700359 .plat_auto = sizeof(struct rockchip_sdhc_plat),
Kever Yang79c83062016-07-18 17:00:58 +0800360};