]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/mmc/host/sdhci-st.c
mmc: sdhci-st: Add support for de-asserting reset signal and top regs resource
[mirror_ubuntu-bionic-kernel.git] / drivers / mmc / host / sdhci-st.c
1 /*
2 * Support for SDHCI on STMicroelectronics SoCs
3 *
4 * Copyright (C) 2014 STMicroelectronics Ltd
5 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
6 * Contributors: Peter Griffin <peter.griffin@linaro.org>
7 *
8 * Based on sdhci-cns3xxx.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21 #include <linux/io.h>
22 #include <linux/of.h>
23 #include <linux/module.h>
24 #include <linux/err.h>
25 #include <linux/mmc/host.h>
26 #include <linux/reset.h>
27 #include "sdhci-pltfm.h"
28
29 struct st_mmc_platform_data {
30 struct reset_control *rstc;
31 void __iomem *top_ioaddr;
32 };
33
34 /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
35
36 #define ST_MMC_CCONFIG_REG_1 0x400
37 #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24)
38 #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12)
39 #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8)
40 #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0)
41 #define ST_MMC_CCONFIG_1_DEFAULT \
42 ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
43 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
44 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
45
46 #define ST_MMC_CCONFIG_REG_2 0x404
47 #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28)
48 #define ST_MMC_CCONFIG_ADMA2 BIT(24)
49 #define ST_MMC_CCONFIG_8BIT BIT(20)
50 #define ST_MMC_CCONFIG_MAX_BLK_LEN 16
51 #define MAX_BLK_LEN_1024 1
52 #define MAX_BLK_LEN_2048 2
53 #define BASE_CLK_FREQ_200 0xc8
54 #define BASE_CLK_FREQ_100 0x64
55 #define BASE_CLK_FREQ_50 0x32
56 #define ST_MMC_CCONFIG_2_DEFAULT \
57 (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
58 ST_MMC_CCONFIG_8BIT | \
59 (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
60
61 #define ST_MMC_CCONFIG_REG_3 0x408
62 #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28)
63 #define ST_MMC_CCONFIG_64BIT BIT(24)
64 #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20)
65 #define ST_MMC_CCONFIG_1P8_VOLT BIT(16)
66 #define ST_MMC_CCONFIG_3P0_VOLT BIT(12)
67 #define ST_MMC_CCONFIG_3P3_VOLT BIT(8)
68 #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4)
69 #define ST_MMC_CCONFIG_SDMA BIT(0)
70 #define ST_MMC_CCONFIG_3_DEFAULT \
71 (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \
72 ST_MMC_CCONFIG_3P3_VOLT | \
73 ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \
74 ST_MMC_CCONFIG_SDMA)
75
76 #define ST_MMC_CCONFIG_REG_4 0x40c
77 #define ST_MMC_CCONFIG_D_DRIVER BIT(20)
78 #define ST_MMC_CCONFIG_C_DRIVER BIT(16)
79 #define ST_MMC_CCONFIG_A_DRIVER BIT(12)
80 #define ST_MMC_CCONFIG_DDR50 BIT(8)
81 #define ST_MMC_CCONFIG_SDR104 BIT(4)
82 #define ST_MMC_CCONFIG_SDR50 BIT(0)
83 #define ST_MMC_CCONFIG_4_DEFAULT 0
84
85 #define ST_MMC_CCONFIG_REG_5 0x410
86 #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8)
87 #define RETUNING_TIMER_CNT_MAX 0xf
88 #define ST_MMC_CCONFIG_5_DEFAULT 0
89
90 /* I/O configuration for Arasan IP */
91 #define ST_MMC_GP_OUTPUT 0x450
92 #define ST_MMC_GP_OUTPUT_CD BIT(12)
93
94 #define ST_MMC_STATUS_R 0x460
95
96 #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8)
97
98 /* TOP config registers to manage static and dynamic delay */
99 #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8)
100 #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc)
101 /* MMC delay control register */
102 #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18)
103 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0)
104 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1)
105 #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8)
106 #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9)
107 #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10)
108 #define ST_TOP_MMC_START_DLL_LOCK BIT(11)
109
110 /* register to provide the phase-shift value for DLL */
111 #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c)
112 #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20)
113 #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24)
114
115 /* phase shift delay on the tx clk 2.188ns */
116 #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6
117
118 #define ST_TOP_MMC_DLY_MAX 0xf
119
120 #define ST_TOP_MMC_DYN_DLY_CONF \
121 (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
122 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
123 ST_TOP_MMC_START_DLL_LOCK)
124
125 static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
126 {
127 u32 ret;
128
129 switch (reg) {
130 case SDHCI_CAPABILITIES:
131 ret = readl_relaxed(host->ioaddr + reg);
132 /* Support 3.3V and 1.8V */
133 ret &= ~SDHCI_CAN_VDD_300;
134 break;
135 default:
136 ret = readl_relaxed(host->ioaddr + reg);
137 }
138 return ret;
139 }
140
141 static const struct sdhci_ops sdhci_st_ops = {
142 .get_max_clock = sdhci_pltfm_clk_get_max_clock,
143 .set_clock = sdhci_set_clock,
144 .set_bus_width = sdhci_set_bus_width,
145 .read_l = sdhci_st_readl,
146 .reset = sdhci_reset,
147 };
148
149 static const struct sdhci_pltfm_data sdhci_st_pdata = {
150 .ops = &sdhci_st_ops,
151 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
152 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
153 };
154
155
156 static int sdhci_st_probe(struct platform_device *pdev)
157 {
158 struct sdhci_host *host;
159 struct st_mmc_platform_data *pdata;
160 struct sdhci_pltfm_host *pltfm_host;
161 struct clk *clk;
162 int ret = 0;
163 u16 host_version;
164 struct resource *res;
165
166 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
167 if (!pdata)
168 return -ENOMEM;
169
170 clk = devm_clk_get(&pdev->dev, "mmc");
171 if (IS_ERR(clk)) {
172 dev_err(&pdev->dev, "Peripheral clk not found\n");
173 return PTR_ERR(clk);
174 }
175
176 pdata->rstc = devm_reset_control_get(&pdev->dev, NULL);
177 if (IS_ERR(pdata->rstc))
178 pdata->rstc = NULL;
179 else
180 reset_control_deassert(pdata->rstc);
181
182 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
183 if (IS_ERR(host)) {
184 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
185 ret = PTR_ERR(host);
186 goto err_pltfm_init;
187 }
188
189 ret = mmc_of_parse(host->mmc);
190 if (ret) {
191 dev_err(&pdev->dev, "Failed mmc_of_parse\n");
192 goto err_of;
193 }
194
195 clk_prepare_enable(clk);
196
197 /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
198 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
199 "top-mmc-delay");
200 pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
201 if (IS_ERR(pdata->top_ioaddr)) {
202 dev_warn(&pdev->dev, "FlashSS Top Dly registers not available");
203 pdata->top_ioaddr = NULL;
204 }
205
206 pltfm_host = sdhci_priv(host);
207 pltfm_host->priv = pdata;
208 pltfm_host->clk = clk;
209
210 ret = sdhci_add_host(host);
211 if (ret) {
212 dev_err(&pdev->dev, "Failed sdhci_add_host\n");
213 goto err_out;
214 }
215
216 platform_set_drvdata(pdev, host);
217
218 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
219
220 dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
221 ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
222 ((host_version & SDHCI_VENDOR_VER_MASK) >>
223 SDHCI_VENDOR_VER_SHIFT));
224
225 return 0;
226
227 err_out:
228 clk_disable_unprepare(clk);
229 err_of:
230 sdhci_pltfm_free(pdev);
231 err_pltfm_init:
232 if (pdata->rstc)
233 reset_control_assert(pdata->rstc);
234
235 return ret;
236 }
237
238 static int sdhci_st_remove(struct platform_device *pdev)
239 {
240 struct sdhci_host *host = platform_get_drvdata(pdev);
241 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
242 struct st_mmc_platform_data *pdata = pltfm_host->priv;
243 int ret;
244
245 ret = sdhci_pltfm_unregister(pdev);
246
247 if (pdata->rstc)
248 reset_control_assert(pdata->rstc);
249
250 return ret;
251 }
252
253 #ifdef CONFIG_PM_SLEEP
254 static int sdhci_st_suspend(struct device *dev)
255 {
256 struct sdhci_host *host = dev_get_drvdata(dev);
257 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
258 struct st_mmc_platform_data *pdata = pltfm_host->priv;
259 int ret = sdhci_suspend_host(host);
260
261 if (ret)
262 goto out;
263
264 if (pdata->rstc)
265 reset_control_assert(pdata->rstc);
266
267 clk_disable_unprepare(pltfm_host->clk);
268 out:
269 return ret;
270 }
271
272 static int sdhci_st_resume(struct device *dev)
273 {
274 struct sdhci_host *host = dev_get_drvdata(dev);
275 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
276 struct st_mmc_platform_data *pdata = pltfm_host->priv;
277
278 clk_prepare_enable(pltfm_host->clk);
279
280 if (pdata->rstc)
281 reset_control_deassert(pdata->rstc);
282
283 return sdhci_resume_host(host);
284 }
285 #endif
286
287 static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
288
289 static const struct of_device_id st_sdhci_match[] = {
290 { .compatible = "st,sdhci" },
291 {},
292 };
293
294 MODULE_DEVICE_TABLE(of, st_sdhci_match);
295
296 static struct platform_driver sdhci_st_driver = {
297 .probe = sdhci_st_probe,
298 .remove = sdhci_st_remove,
299 .driver = {
300 .name = "sdhci-st",
301 .pm = &sdhci_st_pmops,
302 .of_match_table = of_match_ptr(st_sdhci_match),
303 },
304 };
305
306 module_platform_driver(sdhci_st_driver);
307
308 MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
309 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
310 MODULE_LICENSE("GPL v2");
311 MODULE_ALIAS("platform:st-sdhci");