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
aspeed_sdhci_probe(struct udevice * dev)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 unsigned long f_max;
39 struct clk clk;
40 int ret;
41 #ifndef CONFIG_SPL_BUILD
42 int node = dev_of_offset(dev);
43 #endif
44
45 ret = clk_get_by_index(dev, 0, &clk);
46 if (ret < 0) {
47 pr_debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
48 ret);
49 }
50
51 clock = clk_get_rate(&clk);
52 if (IS_ERR_VALUE(clock)) {
53 dev_err(dev, "failed to get clock\n");
54 return ret;
55 }
56
57 debug("%s: CLK %ld\n", __func__, clock);
58
59 #ifndef CONFIG_SPL_BUILD
60 //1: sd card pwr, 0: no pwr
61 gpio_request_by_name_nodev(offset_to_ofnode(node), "pwr-gpios", 0,
62 &host->pwr_gpio, GPIOD_IS_OUT);
63 if (dm_gpio_is_valid(&host->pwr_gpio)) {
64 printf("\n");
65 dm_gpio_set_value(&host->pwr_gpio, 1);
66 if (ret) {
67 debug("MMC not configured\n");
68 return ret;
69 }
70 }
71
72 //1: 3.3v, 0: 1.8v
73 gpio_request_by_name_nodev(offset_to_ofnode(node), "pwr-sw-gpios", 0,
74 &host->pwr_sw_gpio, GPIOD_IS_OUT);
75
76 if (dm_gpio_is_valid(&host->pwr_sw_gpio)) {
77 dm_gpio_set_value(&host->pwr_sw_gpio, 1);
78 if (ret) {
79 debug("MMC not configured\n");
80 return ret;
81 }
82 }
83 #endif
84 // host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
85 host->max_clk = clock;
86 f_max = dev_read_u32_default(dev, "max-frequency", clock);
87
88 host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
89
90 if (host->bus_width == 8)
91 host->host_caps |= MMC_MODE_8BIT;
92
93 ret = sdhci_setup_cfg(&plat->cfg, host, f_max, EMMC_MIN_FREQ);
94
95 host->mmc = &plat->mmc;
96 if (ret)
97 return ret;
98
99 host->mmc->drv_type = dev_read_u32_default(dev, "sdhci-drive-type", 0);
100 host->mmc->priv = host;
101 host->mmc->dev = dev;
102 upriv->mmc = host->mmc;
103
104 return sdhci_probe(dev);
105 }
106
aspeed_sdhci_ofdata_to_platdata(struct udevice * dev)107 static int aspeed_sdhci_ofdata_to_platdata(struct udevice *dev)
108 {
109 struct aspeed_sdhci_priv *priv = dev_get_priv(dev);
110
111 priv->host = calloc(1, sizeof(struct sdhci_host));
112 if (!priv->host)
113 return -1;
114
115 priv->host->name = dev->name;
116 priv->host->ioaddr = (void *)dev_read_addr(dev);
117
118 return 0;
119 }
120
aspeed_sdhci_bind(struct udevice * dev)121 static int aspeed_sdhci_bind(struct udevice *dev)
122 {
123 struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
124
125 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
126 }
127
128 static const struct udevice_id aspeed_sdhci_ids[] = {
129 { .compatible = "aspeed,sdhci-ast2500" },
130 { .compatible = "aspeed,sdhci-ast2600" },
131 { .compatible = "aspeed,emmc-ast2600" },
132 { }
133 };
134
135 U_BOOT_DRIVER(aspeed_sdhci_drv) = {
136 .name = "aspeed_sdhci",
137 .id = UCLASS_MMC,
138 .of_match = aspeed_sdhci_ids,
139 .ofdata_to_platdata = aspeed_sdhci_ofdata_to_platdata,
140 .ops = &sdhci_ops,
141 .bind = aspeed_sdhci_bind,
142 .probe = aspeed_sdhci_probe,
143 .priv_auto_alloc_size = sizeof(struct aspeed_sdhci_priv),
144 .platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat),
145 };
146