xref: /openbmc/u-boot/drivers/mmc/aspeed_sdhci.c (revision fd0bc623)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd
4  *
5  * Rockchip SD Host Controller Interface
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <dt-structs.h>
11 #include <linux/libfdt.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <sdhci.h>
15 #include <clk.h>
16 
17 /* 400KHz is max freq for card ID etc. Use that as min */
18 #define EMMC_MIN_FREQ	400000
19 
20 struct aspeed_sdhci_plat {
21 	struct mmc_config cfg;
22 	struct mmc mmc;
23 	unsigned int f_max;
24 };
25 
26 struct aspeed_sdhci_priv {
27 	struct sdhci_host *host;
28 	struct clk clk;
29 };
30 
31 static int aspeed_sdhci_probe(struct udevice *dev)
32 {
33 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
34 	struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
35 	struct aspeed_sdhci_priv *prv = dev_get_priv(dev);
36 	struct sdhci_host *host = prv->host;
37 	unsigned long clock;
38 	struct clk clk;
39 	int ret;
40 #ifndef CONFIG_SPL_BUILD
41 	int node = dev_of_offset(dev);
42 #endif
43 
44 	ret = clk_get_by_index(dev, 0, &clk);
45 	if (ret < 0) {
46 		pr_debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
47 		      ret);
48 	}
49 
50 	clock = clk_get_rate(&clk);
51 	if (IS_ERR_VALUE(clock)) {
52 		dev_err(dev, "failed to get clock\n");
53 		return ret;
54 	}
55 
56 	debug("%s: CLK %ld\n", __func__, clock);
57 
58 #ifndef CONFIG_SPL_BUILD
59 	//1: sd card pwr, 0: no pwr
60 	gpio_request_by_name_nodev(offset_to_ofnode(node), "pwr-gpios", 0,
61 				   &host->pwr_gpio, GPIOD_IS_OUT);
62 	if (dm_gpio_is_valid(&host->pwr_gpio)) {
63 		printf("\n");
64 		dm_gpio_set_value(&host->pwr_gpio, 1);
65 		if (ret) {
66 			debug("MMC not configured\n");
67 			return ret;
68 		}
69 	}
70 
71 	//1: 3.3v, 0: 1.8v
72 	gpio_request_by_name_nodev(offset_to_ofnode(node), "pwr-sw-gpios", 0,
73 				   &host->pwr_sw_gpio, GPIOD_IS_OUT);
74 
75 	if (dm_gpio_is_valid(&host->pwr_sw_gpio)) {
76 		dm_gpio_set_value(&host->pwr_sw_gpio, 1);
77 		if (ret) {
78 			debug("MMC not configured\n");
79 			return ret;
80 		}
81 	}
82 #endif
83 //	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
84 	host->max_clk = clock;
85 
86 	host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
87 
88 	if (host->bus_width == 8)
89 		host->host_caps |= MMC_MODE_8BIT;
90 
91 	ret = sdhci_setup_cfg(&plat->cfg, host, host->max_clk, EMMC_MIN_FREQ);
92 
93 	host->mmc = &plat->mmc;
94 	if (ret)
95 		return ret;
96 
97 	host->mmc->drv_type = dev_read_u32_default(dev, "sdhci-drive-type", 0);
98 	host->mmc->priv = host;
99 	host->mmc->dev = dev;
100 	upriv->mmc = host->mmc;
101 
102 	return sdhci_probe(dev);
103 }
104 
105 static int aspeed_sdhci_ofdata_to_platdata(struct udevice *dev)
106 {
107 	struct aspeed_sdhci_priv *priv = dev_get_priv(dev);
108 
109 	priv->host = calloc(1, sizeof(struct sdhci_host));
110 	if (!priv->host)
111 			return -1;
112 
113 	priv->host->name = dev->name;
114 	priv->host->ioaddr = (void *)dev_read_addr(dev);
115 
116 	return 0;
117 }
118 
119 static int aspeed_sdhci_bind(struct udevice *dev)
120 {
121 	struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
122 
123 	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
124 }
125 
126 static const struct udevice_id aspeed_sdhci_ids[] = {
127 	{ .compatible = "aspeed,sdhci-ast2500" },
128 	{ .compatible = "aspeed,sdhci-ast2600" },
129 	{ .compatible = "aspeed,emmc-ast2600" },
130 	{ }
131 };
132 
133 U_BOOT_DRIVER(aspeed_sdhci_drv) = {
134 	.name		= "aspeed_sdhci",
135 	.id		= UCLASS_MMC,
136 	.of_match	= aspeed_sdhci_ids,
137 	.ofdata_to_platdata = aspeed_sdhci_ofdata_to_platdata,
138 	.ops		= &sdhci_ops,
139 	.bind		= aspeed_sdhci_bind,
140 	.probe		= aspeed_sdhci_probe,
141 	.priv_auto_alloc_size = sizeof(struct aspeed_sdhci_priv),
142 	.platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat),
143 };
144