]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/mmc/host/sdhci-st.c
mmc: sdhci-st: Add macros for register offsets and bitfields for mmcss glue regs
[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
27 #include "sdhci-pltfm.h"
28
29 /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
30
31 #define ST_MMC_CCONFIG_REG_1 0x400
32 #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24)
33 #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12)
34 #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8)
35 #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0)
36 #define ST_MMC_CCONFIG_1_DEFAULT \
37 ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
38 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
39 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
40
41 #define ST_MMC_CCONFIG_REG_2 0x404
42 #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28)
43 #define ST_MMC_CCONFIG_ADMA2 BIT(24)
44 #define ST_MMC_CCONFIG_8BIT BIT(20)
45 #define ST_MMC_CCONFIG_MAX_BLK_LEN 16
46 #define MAX_BLK_LEN_1024 1
47 #define MAX_BLK_LEN_2048 2
48 #define BASE_CLK_FREQ_200 0xc8
49 #define BASE_CLK_FREQ_100 0x64
50 #define BASE_CLK_FREQ_50 0x32
51 #define ST_MMC_CCONFIG_2_DEFAULT \
52 (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
53 ST_MMC_CCONFIG_8BIT | \
54 (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
55
56 #define ST_MMC_CCONFIG_REG_3 0x408
57 #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28)
58 #define ST_MMC_CCONFIG_64BIT BIT(24)
59 #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20)
60 #define ST_MMC_CCONFIG_1P8_VOLT BIT(16)
61 #define ST_MMC_CCONFIG_3P0_VOLT BIT(12)
62 #define ST_MMC_CCONFIG_3P3_VOLT BIT(8)
63 #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4)
64 #define ST_MMC_CCONFIG_SDMA BIT(0)
65 #define ST_MMC_CCONFIG_3_DEFAULT \
66 (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \
67 ST_MMC_CCONFIG_3P3_VOLT | \
68 ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \
69 ST_MMC_CCONFIG_SDMA)
70
71 #define ST_MMC_CCONFIG_REG_4 0x40c
72 #define ST_MMC_CCONFIG_D_DRIVER BIT(20)
73 #define ST_MMC_CCONFIG_C_DRIVER BIT(16)
74 #define ST_MMC_CCONFIG_A_DRIVER BIT(12)
75 #define ST_MMC_CCONFIG_DDR50 BIT(8)
76 #define ST_MMC_CCONFIG_SDR104 BIT(4)
77 #define ST_MMC_CCONFIG_SDR50 BIT(0)
78 #define ST_MMC_CCONFIG_4_DEFAULT 0
79
80 #define ST_MMC_CCONFIG_REG_5 0x410
81 #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8)
82 #define RETUNING_TIMER_CNT_MAX 0xf
83 #define ST_MMC_CCONFIG_5_DEFAULT 0
84
85 /* I/O configuration for Arasan IP */
86 #define ST_MMC_GP_OUTPUT 0x450
87 #define ST_MMC_GP_OUTPUT_CD BIT(12)
88
89 #define ST_MMC_STATUS_R 0x460
90
91 #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8)
92
93 /* TOP config registers to manage static and dynamic delay */
94 #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8)
95 #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc)
96 /* MMC delay control register */
97 #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18)
98 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0)
99 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1)
100 #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8)
101 #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9)
102 #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10)
103 #define ST_TOP_MMC_START_DLL_LOCK BIT(11)
104
105 /* register to provide the phase-shift value for DLL */
106 #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c)
107 #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20)
108 #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24)
109
110 /* phase shift delay on the tx clk 2.188ns */
111 #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6
112
113 #define ST_TOP_MMC_DLY_MAX 0xf
114
115 #define ST_TOP_MMC_DYN_DLY_CONF \
116 (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
117 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
118 ST_TOP_MMC_START_DLL_LOCK)
119
120 static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
121 {
122 u32 ret;
123
124 switch (reg) {
125 case SDHCI_CAPABILITIES:
126 ret = readl_relaxed(host->ioaddr + reg);
127 /* Support 3.3V and 1.8V */
128 ret &= ~SDHCI_CAN_VDD_300;
129 break;
130 default:
131 ret = readl_relaxed(host->ioaddr + reg);
132 }
133 return ret;
134 }
135
136 static const struct sdhci_ops sdhci_st_ops = {
137 .get_max_clock = sdhci_pltfm_clk_get_max_clock,
138 .set_clock = sdhci_set_clock,
139 .set_bus_width = sdhci_set_bus_width,
140 .read_l = sdhci_st_readl,
141 .reset = sdhci_reset,
142 };
143
144 static const struct sdhci_pltfm_data sdhci_st_pdata = {
145 .ops = &sdhci_st_ops,
146 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
147 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
148 };
149
150
151 static int sdhci_st_probe(struct platform_device *pdev)
152 {
153 struct sdhci_host *host;
154 struct sdhci_pltfm_host *pltfm_host;
155 struct clk *clk;
156 int ret = 0;
157 u16 host_version;
158
159 clk = devm_clk_get(&pdev->dev, "mmc");
160 if (IS_ERR(clk)) {
161 dev_err(&pdev->dev, "Peripheral clk not found\n");
162 return PTR_ERR(clk);
163 }
164
165 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
166 if (IS_ERR(host)) {
167 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
168 return PTR_ERR(host);
169 }
170
171 ret = mmc_of_parse(host->mmc);
172 if (ret) {
173 dev_err(&pdev->dev, "Failed mmc_of_parse\n");
174 goto err_of;
175 }
176
177 clk_prepare_enable(clk);
178
179 pltfm_host = sdhci_priv(host);
180 pltfm_host->clk = clk;
181
182 ret = sdhci_add_host(host);
183 if (ret) {
184 dev_err(&pdev->dev, "Failed sdhci_add_host\n");
185 goto err_out;
186 }
187
188 platform_set_drvdata(pdev, host);
189
190 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
191
192 dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
193 ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
194 ((host_version & SDHCI_VENDOR_VER_MASK) >>
195 SDHCI_VENDOR_VER_SHIFT));
196
197 return 0;
198
199 err_out:
200 clk_disable_unprepare(clk);
201 err_of:
202 sdhci_pltfm_free(pdev);
203
204 return ret;
205 }
206
207 #ifdef CONFIG_PM_SLEEP
208 static int sdhci_st_suspend(struct device *dev)
209 {
210 struct sdhci_host *host = dev_get_drvdata(dev);
211 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
212 int ret = sdhci_suspend_host(host);
213
214 if (ret)
215 goto out;
216
217 clk_disable_unprepare(pltfm_host->clk);
218 out:
219 return ret;
220 }
221
222 static int sdhci_st_resume(struct device *dev)
223 {
224 struct sdhci_host *host = dev_get_drvdata(dev);
225 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
226
227 clk_prepare_enable(pltfm_host->clk);
228
229 return sdhci_resume_host(host);
230 }
231 #endif
232
233 static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
234
235 static const struct of_device_id st_sdhci_match[] = {
236 { .compatible = "st,sdhci" },
237 {},
238 };
239
240 MODULE_DEVICE_TABLE(of, st_sdhci_match);
241
242 static struct platform_driver sdhci_st_driver = {
243 .probe = sdhci_st_probe,
244 .remove = sdhci_pltfm_unregister,
245 .driver = {
246 .name = "sdhci-st",
247 .pm = &sdhci_st_pmops,
248 .of_match_table = of_match_ptr(st_sdhci_match),
249 },
250 };
251
252 module_platform_driver(sdhci_st_driver);
253
254 MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
255 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
256 MODULE_LICENSE("GPL v2");
257 MODULE_ALIAS("platform:st-sdhci");