xref: /rk3399_rockchip-uboot/drivers/mmc/rockchip_sdhci.c (revision 7c1937d6d1c7daf8e59b4760f8adc7ee42bd7bea)
1 /*
2  * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * Rockchip SD Host Controller Interface
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  */
8 
9 #include <asm/arch/hardware.h>
10 #include <common.h>
11 #include <dm.h>
12 #include <dt-structs.h>
13 #include <libfdt.h>
14 #include <malloc.h>
15 #include <mapmem.h>
16 #include <sdhci.h>
17 #include <clk.h>
18 #include <syscon.h>
19 #include <dm/ofnode.h>
20 #include <asm/arch/clock.h>
21 
22 DECLARE_GLOBAL_DATA_PTR;
23 /* 400KHz is max freq for card ID etc. Use that as min */
24 #define EMMC_MIN_FREQ	400000
25 
26 struct rockchip_sdhc_plat {
27 #if CONFIG_IS_ENABLED(OF_PLATDATA)
28 	struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
29 #endif
30 	struct mmc_config cfg;
31 	struct mmc mmc;
32 };
33 
34 struct rockchip_emmc_phy {
35 	u32 emmcphy_con[7];
36 	u32 reserved;
37 	u32 emmcphy_status;
38 };
39 
40 struct rockchip_sdhc {
41 	struct sdhci_host host;
42 	void *base;
43 	struct rockchip_emmc_phy *phy;
44 	struct clk emmc_clk;
45 };
46 
47 #define PHYCTRL_CALDONE_MASK		0x1
48 #define PHYCTRL_CALDONE_SHIFT		0x6
49 #define PHYCTRL_CALDONE_DONE		0x1
50 
51 #define PHYCTRL_DLLRDY_MASK		0x1
52 #define PHYCTRL_DLLRDY_SHIFT		0x5
53 #define PHYCTRL_DLLRDY_DONE		0x1
54 
55 #define PHYCTRL_FREQSEL_200M            0x0
56 #define PHYCTRL_FREQSEL_50M             0x1
57 #define PHYCTRL_FREQSEL_100M            0x2
58 #define PHYCTRL_FREQSEL_150M            0x3
59 
60 #define KHz	(1000)
61 #define MHz	(1000 * KHz)
62 
63 static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
64 {
65 	u32 caldone, dllrdy, freqsel;
66 	uint start;
67 
68 	writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]);
69 	writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]);
70 	writel(RK_CLRSETBITS(0xf << 7, 6 << 7), &phy->emmcphy_con[0]);
71 
72 	/*
73 	 * According to the user manual, calpad calibration
74 	 * cycle takes more than 2us without the minimal recommended
75 	 * value, so we may need a little margin here
76 	 */
77 	udelay(3);
78 	writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]);
79 
80 	/*
81 	 * According to the user manual, it asks driver to
82 	 * wait 5us for calpad busy trimming
83 	 */
84 	udelay(5);
85 	caldone = readl(&phy->emmcphy_status);
86 	caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
87 	if (caldone != PHYCTRL_CALDONE_DONE) {
88 		debug("%s: caldone timeout.\n", __func__);
89 		return;
90 	}
91 
92 	/* Set the frequency of the DLL operation */
93 	if (clock < 75 * MHz)
94 		freqsel = PHYCTRL_FREQSEL_50M;
95 	else if (clock < 125 * MHz)
96 		freqsel = PHYCTRL_FREQSEL_100M;
97 	else if (clock < 175 * MHz)
98 		freqsel = PHYCTRL_FREQSEL_150M;
99 	else
100 		freqsel = PHYCTRL_FREQSEL_200M;
101 
102 	/* Set the frequency of the DLL operation */
103 	writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]);
104 	writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]);
105 
106 	start = get_timer(0);
107 
108 	do {
109 		udelay(1);
110 		dllrdy = readl(&phy->emmcphy_status);
111 		dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
112 		if (dllrdy == PHYCTRL_DLLRDY_DONE)
113 			break;
114 	} while (get_timer(start) < 50000);
115 
116 	if (dllrdy != PHYCTRL_DLLRDY_DONE)
117 		debug("%s: dllrdy timeout.\n", __func__);
118 }
119 
120 static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy)
121 {
122 	writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]);
123 	writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]);
124 }
125 
126 static int rk3399_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
127 {
128 	unsigned int div, clk = 0, timeout;
129 	unsigned int input_clk;
130 	struct rockchip_sdhc *priv =
131 			container_of(host, struct rockchip_sdhc, host);
132 
133 	/* Wait max 20 ms */
134 	timeout = 200;
135 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) &
136 			   (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) {
137 		if (timeout == 0) {
138 			printf("%s: Timeout to wait cmd & data inhibit\n",
139 			       __func__);
140 			return -EBUSY;
141 		}
142 
143 		timeout--;
144 		udelay(100);
145 	}
146 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
147 
148 	if (clock == 0)
149 		return 0;
150 
151 	input_clk = clk_set_rate(&priv->emmc_clk, clock);
152 	if (IS_ERR_VALUE(input_clk))
153 		input_clk = host->max_clk;
154 
155 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
156 		/*
157 		 * Check if the Host Controller supports Programmable Clock
158 		 * Mode.
159 		 */
160 		if (host->clk_mul) {
161 			for (div = 1; div <= 1024; div++) {
162 				if ((input_clk / div) <= clock)
163 					break;
164 			}
165 
166 			/*
167 			 * Set Programmable Clock Mode in the Clock
168 			 * Control register.
169 			 */
170 			clk = SDHCI_PROG_CLOCK_MODE;
171 			div--;
172 		} else {
173 			/* Version 3.00 divisors must be a multiple of 2. */
174 			if (input_clk <= clock) {
175 				div = 1;
176 			} else {
177 				for (div = 2;
178 				     div < SDHCI_MAX_DIV_SPEC_300;
179 				     div += 2) {
180 					if ((input_clk / div) <= clock)
181 						break;
182 				}
183 			}
184 			div >>= 1;
185 		}
186 	} else {
187 		/* Version 2.00 divisors must be a power of 2. */
188 		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
189 			if ((input_clk / div) <= clock)
190 				break;
191 		}
192 		div >>= 1;
193 	}
194 
195 	clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
196 	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
197 		<< SDHCI_DIVIDER_HI_SHIFT;
198 	clk |= SDHCI_CLOCK_INT_EN;
199 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
200 
201 	/* Wait max 20 ms */
202 	timeout = 20;
203 	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
204 		& SDHCI_CLOCK_INT_STABLE)) {
205 		if (timeout == 0) {
206 			printf("%s: Internal clock never stabilised.\n",
207 			       __func__);
208 			return -EBUSY;
209 		}
210 		timeout--;
211 		udelay(1000);
212 	}
213 	clk |= SDHCI_CLOCK_CARD_EN;
214 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
215 	host->clock = clock;
216 
217 	return 0;
218 }
219 
220 static int arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
221 {
222 	struct rockchip_sdhc *priv =
223 			container_of(host, struct rockchip_sdhc, host);
224 	int cycle_phy = host->clock != clock &&
225 			clock > EMMC_MIN_FREQ;
226 
227 	if (cycle_phy)
228 		rk3399_emmc_phy_power_off(priv->phy);
229 
230 	rk3399_sdhci_set_clock(host, clock);
231 
232 	if (cycle_phy)
233 		rk3399_emmc_phy_power_on(priv->phy, clock);
234 
235 	return 0;
236 }
237 
238 static struct sdhci_ops arasan_sdhci_ops = {
239 	.set_clock	= arasan_sdhci_set_clock,
240 };
241 
242 static int arasan_get_phy(struct udevice *dev)
243 {
244 	struct rockchip_sdhc *priv = dev_get_priv(dev);
245 
246 #if CONFIG_IS_ENABLED(OF_PLATDATA)
247 	priv->phy = (struct rockchip_emmc_phy *)0xff77f780;
248 #else
249 	ofnode phy_node;
250 	void *grf_base;
251 	u32 grf_phy_offset, phandle;
252 
253 	phandle = dev_read_u32_default(dev, "phys", 0);
254 	phy_node = ofnode_get_by_phandle(phandle);
255 	if (!ofnode_valid(phy_node)) {
256 		debug("Not found emmc phy device\n");
257 		return -ENODEV;
258 	}
259 
260 	grf_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
261 	if (grf_base < 0)
262 		printf("%s Get syscon grf failed", __func__);
263 	grf_phy_offset = ofnode_read_u32_default(phy_node, "reg", 0);
264 
265 	priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset);
266 #endif
267 	return 0;
268 }
269 
270 static int arasan_sdhci_probe(struct udevice *dev)
271 {
272 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
273 	struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
274 	struct rockchip_sdhc *prv = dev_get_priv(dev);
275 	struct sdhci_host *host = &prv->host;
276 	int max_frequency, ret;
277 	struct clk clk;
278 
279 #if CONFIG_IS_ENABLED(OF_PLATDATA)
280 	struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat;
281 
282 	host->name = dev->name;
283 	host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
284 	host->host_caps |= MMC_MODE_8BIT;
285 	max_frequency = dtplat->max_frequency;
286 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk);
287 #else
288 	max_frequency = dev_read_u32_default(dev, "max-frequency", 0);
289 	switch (dev_read_u32_default(dev, "bus-width", 4)) {
290 	case 8:
291 		host->host_caps |= MMC_MODE_8BIT;
292 		break;
293 	case 4:
294 		host->host_caps |= MMC_MODE_4BIT;
295 		break;
296 	case 1:
297 		break;
298 	default:
299 		printf("Invalid \"bus-width\" value\n");
300 		return -EINVAL;
301 	}
302 	ret = clk_get_by_index(dev, 0, &clk);
303 #endif
304 	if (!ret) {
305 		ret = clk_set_rate(&clk, max_frequency);
306 		if (IS_ERR_VALUE(ret))
307 			printf("%s clk set rate fail!\n", __func__);
308 	} else {
309 		printf("%s fail to get clk\n", __func__);
310 	}
311 
312 	prv->emmc_clk = clk;
313 	ret = arasan_get_phy(dev);
314 	if (ret)
315 		return ret;
316 
317 	host->ops = &arasan_sdhci_ops;
318 
319 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
320 	host->max_clk = max_frequency;
321 
322 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
323 
324 	host->mmc = &plat->mmc;
325 	if (ret)
326 		return ret;
327 	host->mmc->priv = &prv->host;
328 	host->mmc->dev = dev;
329 	upriv->mmc = host->mmc;
330 
331 	return sdhci_probe(dev);
332 }
333 
334 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
335 {
336 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
337 	struct sdhci_host *host = dev_get_priv(dev);
338 
339 	host->name = dev->name;
340 	host->ioaddr = dev_read_addr_ptr(dev);
341 #endif
342 
343 	return 0;
344 }
345 
346 static int rockchip_sdhci_bind(struct udevice *dev)
347 {
348 	struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
349 
350 	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
351 }
352 
353 static const struct udevice_id arasan_sdhci_ids[] = {
354 	{ .compatible = "arasan,sdhci-5.1" },
355 	{ }
356 };
357 
358 U_BOOT_DRIVER(arasan_sdhci_drv) = {
359 	.name		= "rockchip_rk3399_sdhci_5_1",
360 	.id		= UCLASS_MMC,
361 	.of_match	= arasan_sdhci_ids,
362 	.ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata,
363 	.ops		= &sdhci_ops,
364 	.bind		= rockchip_sdhci_bind,
365 	.probe		= arasan_sdhci_probe,
366 	.priv_auto_alloc_size = sizeof(struct rockchip_sdhc),
367 	.platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat),
368 };
369