blob: 492bf58c398d4bdba1b44d5e54dd4a7fe041291b [file] [log] [blame]
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001/*
2 * (C) Copyright 2008
3 * Texas Instruments, <www.ti.com>
4 * Sukumar Ghorai <s-ghorai@ti.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation's version 2 of
12 * the License.
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 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <config.h>
26#include <common.h>
Simon Glass63334482019-11-14 12:57:39 -070027#include <cpu_func.h>
Simon Glass0f2af882020-05-10 11:40:05 -060028#include <log.h>
Pantelis Antoniou2c850462014-03-11 19:34:20 +020029#include <malloc.h>
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +020030#include <memalign.h>
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -070031#include <mmc.h>
32#include <part.h>
33#include <i2c.h>
Felix Brack419eed22017-10-11 17:05:28 +020034#if defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)
Nishanth Menon627612c2013-03-26 05:20:54 +000035#include <palmas.h>
Felix Brack419eed22017-10-11 17:05:28 +020036#endif
Simon Glass274e0b02020-05-10 11:39:56 -060037#include <asm/cache.h>
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -070038#include <asm/io.h>
39#include <asm/arch/mmc_host_def.h>
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +010040#ifdef CONFIG_OMAP54XX
41#include <asm/arch/mux_dra7xx.h>
42#include <asm/arch/dra7xx_iodelay.h>
43#endif
Roger Quadros44157de2015-09-19 16:26:53 +053044#if !defined(CONFIG_SOC_KEYSTONE)
45#include <asm/gpio.h>
Dirk Behme74140232011-05-15 09:04:47 +000046#include <asm/arch/sys_proto.h>
Roger Quadros44157de2015-09-19 16:26:53 +053047#endif
Tom Rinidf5338c2017-02-09 13:41:28 -050048#ifdef CONFIG_MMC_OMAP36XX_PINS
49#include <asm/arch/mux.h>
50#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +053051#include <dm.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070052#include <dm/devres.h>
53#include <linux/err.h>
Jean-Jacques Hiblot20157d42018-01-30 16:01:44 +010054#include <power/regulator.h>
Faiz Abbase4d30562019-01-30 18:08:42 +053055#include <thermal.h>
Mugunthan V Nd97631a2015-09-28 12:56:30 +053056
57DECLARE_GLOBAL_DATA_PTR;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -070058
Pantelis Antoniouc9e75912014-02-26 19:28:45 +020059/* simplify defines to OMAP_HSMMC_USE_GPIO */
60#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
61 (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
62#define OMAP_HSMMC_USE_GPIO
63#else
64#undef OMAP_HSMMC_USE_GPIO
65#endif
66
Grazvydas Ignotasddde1882012-03-19 12:12:06 +000067/* common definitions for all OMAPs */
68#define SYSCTL_SRC (1 << 25)
69#define SYSCTL_SRD (1 << 26)
70
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +010071#ifdef CONFIG_IODELAY_RECALIBRATION
72struct omap_hsmmc_pinctrl_state {
73 struct pad_conf_entry *padconf;
74 int npads;
75 struct iodelay_cfg_entry *iodelay;
76 int niodelays;
77};
78#endif
79
Nikita Kiryanov13822862012-12-03 02:19:43 +000080struct omap_hsmmc_data {
81 struct hsmmc *base_addr;
Simon Glass5f4bd8c2017-07-04 13:31:19 -060082#if !CONFIG_IS_ENABLED(DM_MMC)
Pantelis Antoniou2c850462014-03-11 19:34:20 +020083 struct mmc_config cfg;
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +010084#endif
Kishon Vijay Abraham I2e18c9b2018-01-30 16:01:31 +010085 uint bus_width;
Jean-Jacques Hiblot7fe2f192018-01-30 16:01:30 +010086 uint clock;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +010087 ushort last_cmd;
Pantelis Antoniouc9e75912014-02-26 19:28:45 +020088#ifdef OMAP_HSMMC_USE_GPIO
Simon Glass5f4bd8c2017-07-04 13:31:19 -060089#if CONFIG_IS_ENABLED(DM_MMC)
Mugunthan V Nd97631a2015-09-28 12:56:30 +053090 struct gpio_desc cd_gpio; /* Change Detect GPIO */
91 struct gpio_desc wp_gpio; /* Write Protect GPIO */
Mugunthan V Nd97631a2015-09-28 12:56:30 +053092#else
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +000093 int cd_gpio;
Nikita Kiryanov4be9dbc2012-12-03 02:19:47 +000094 int wp_gpio;
Pantelis Antoniouc9e75912014-02-26 19:28:45 +020095#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +053096#endif
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +010097#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +010098 enum bus_mode mode;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +010099#endif
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200100 u8 controller_flags;
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +0100101#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200102 struct omap_hsmmc_adma_desc *adma_desc_table;
103 uint desc_slot;
104#endif
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +0100105 const char *hw_rev;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100106 struct udevice *pbias_supply;
107 uint signal_voltage;
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100108#ifdef CONFIG_IODELAY_RECALIBRATION
109 struct omap_hsmmc_pinctrl_state *default_pinctrl_state;
110 struct omap_hsmmc_pinctrl_state *hs_pinctrl_state;
111 struct omap_hsmmc_pinctrl_state *hs200_1_8v_pinctrl_state;
112 struct omap_hsmmc_pinctrl_state *ddr_1_8v_pinctrl_state;
113 struct omap_hsmmc_pinctrl_state *sdr12_pinctrl_state;
114 struct omap_hsmmc_pinctrl_state *sdr25_pinctrl_state;
115 struct omap_hsmmc_pinctrl_state *ddr50_pinctrl_state;
116 struct omap_hsmmc_pinctrl_state *sdr50_pinctrl_state;
117 struct omap_hsmmc_pinctrl_state *sdr104_pinctrl_state;
118#endif
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200119};
120
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100121struct omap_mmc_of_data {
122 u8 controller_flags;
123};
124
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +0100125#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200126struct omap_hsmmc_adma_desc {
127 u8 attr;
128 u8 reserved;
129 u16 len;
130 u32 addr;
Nikita Kiryanov13822862012-12-03 02:19:43 +0000131};
132
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200133#define ADMA_MAX_LEN 63488
134
135/* Decriptor table defines */
136#define ADMA_DESC_ATTR_VALID BIT(0)
137#define ADMA_DESC_ATTR_END BIT(1)
138#define ADMA_DESC_ATTR_INT BIT(2)
139#define ADMA_DESC_ATTR_ACT1 BIT(4)
140#define ADMA_DESC_ATTR_ACT2 BIT(5)
141
142#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
143#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
144#endif
145
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500146/* If we fail after 1 second wait, something is really bad */
147#define MAX_RETRY_MS 1000
Jean-Jacques Hiblot192e4302018-01-30 16:01:37 +0100148#define MMC_TIMEOUT_MS 20
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500149
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200150/* DMA transfers can take a long time if a lot a data is transferred.
151 * The timeout must take in account the amount of data. Let's assume
152 * that the time will never exceed 333 ms per MB (in other word we assume
153 * that the bandwidth is always above 3MB/s).
154 */
155#define DMA_TIMEOUT_PER_MB 333
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100156#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
157#define OMAP_HSMMC_NO_1_8_V BIT(1)
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200158#define OMAP_HSMMC_USE_ADMA BIT(2)
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100159#define OMAP_HSMMC_REQUIRE_IODELAY BIT(3)
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200160
Sricharanf72611f2011-11-15 09:49:53 -0500161static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
162static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
163 unsigned int siz);
Jean-Jacques Hiblot7fe2f192018-01-30 16:01:30 +0100164static void omap_hsmmc_start_clock(struct hsmmc *mmc_base);
165static void omap_hsmmc_stop_clock(struct hsmmc *mmc_base);
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100166static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit);
Balaji T Kf843d332011-09-08 06:34:57 +0000167
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +0100168static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc)
169{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600170#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +0100171 return dev_get_priv(mmc->dev);
172#else
173 return (struct omap_hsmmc_data *)mmc->priv;
174#endif
175}
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +0100176static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc)
177{
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600178#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +0100179 struct omap_hsmmc_plat *plat = dev_get_platdata(mmc->dev);
180 return &plat->cfg;
181#else
182 return &((struct omap_hsmmc_data *)mmc->priv)->cfg;
183#endif
184}
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +0100185
Simon Glass5f4bd8c2017-07-04 13:31:19 -0600186#if defined(OMAP_HSMMC_USE_GPIO) && !CONFIG_IS_ENABLED(DM_MMC)
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000187static int omap_mmc_setup_gpio_in(int gpio, const char *label)
188{
Simon Glass1a96d7f2014-10-22 21:37:09 -0600189 int ret;
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000190
Simon Glassfa4689a2019-12-06 21:41:35 -0700191#if !CONFIG_IS_ENABLED(DM_GPIO)
Simon Glass1a96d7f2014-10-22 21:37:09 -0600192 if (!gpio_is_valid(gpio))
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000193 return -1;
Simon Glass1a96d7f2014-10-22 21:37:09 -0600194#endif
195 ret = gpio_request(gpio, label);
196 if (ret)
197 return ret;
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000198
Simon Glass1a96d7f2014-10-22 21:37:09 -0600199 ret = gpio_direction_input(gpio);
200 if (ret)
201 return ret;
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000202
203 return gpio;
204}
Nikita Kiryanov4eae05c2012-12-03 02:19:44 +0000205#endif
206
Jeroen Hofsteeaedeeaa2014-07-12 21:24:08 +0200207static unsigned char mmc_board_init(struct mmc *mmc)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700208{
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700209#if defined(CONFIG_OMAP34XX)
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +0100210 struct mmc_config *cfg = omap_hsmmc_get_cfg(mmc);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700211 t2_t *t2_base = (t2_t *)T2_BASE;
212 struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
Grazvydas Ignotasef2b7292012-03-19 03:50:53 +0000213 u32 pbias_lite;
Adam Fordef354962017-02-06 11:31:43 -0600214#ifdef CONFIG_MMC_OMAP36XX_PINS
215 u32 wkup_ctrl = readl(OMAP34XX_CTRL_WKUP_CTRL);
216#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700217
Grazvydas Ignotasef2b7292012-03-19 03:50:53 +0000218 pbias_lite = readl(&t2_base->pbias_lite);
219 pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0);
Albert ARIBAUD \(3ADEV\)6ad09812015-01-16 09:09:50 +0100220#ifdef CONFIG_TARGET_OMAP3_CAIRO
221 /* for cairo board, we need to set up 1.8 Volt bias level on MMC1 */
222 pbias_lite &= ~PBIASLITEVMODE0;
223#endif
Adam Fordf2eb4322018-09-05 04:11:08 -0500224#ifdef CONFIG_TARGET_OMAP3_LOGIC
225 /* For Logic PD board, 1.8V bias to go enable gpio127 for mmc_cd */
226 pbias_lite &= ~PBIASLITEVMODE1;
227#endif
Adam Fordef354962017-02-06 11:31:43 -0600228#ifdef CONFIG_MMC_OMAP36XX_PINS
229 if (get_cpu_family() == CPU_OMAP36XX) {
230 /* Disable extended drain IO before changing PBIAS */
231 wkup_ctrl &= ~OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ;
232 writel(wkup_ctrl, OMAP34XX_CTRL_WKUP_CTRL);
233 }
234#endif
Grazvydas Ignotasef2b7292012-03-19 03:50:53 +0000235 writel(pbias_lite, &t2_base->pbias_lite);
Paul Kocialkowski69559892014-11-08 20:55:47 +0100236
Grazvydas Ignotasef2b7292012-03-19 03:50:53 +0000237 writel(pbias_lite | PBIASLITEPWRDNZ1 |
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700238 PBIASSPEEDCTRL0 | PBIASLITEPWRDNZ0,
239 &t2_base->pbias_lite);
240
Adam Fordef354962017-02-06 11:31:43 -0600241#ifdef CONFIG_MMC_OMAP36XX_PINS
242 if (get_cpu_family() == CPU_OMAP36XX)
243 /* Enable extended drain IO after changing PBIAS */
244 writel(wkup_ctrl |
245 OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ,
246 OMAP34XX_CTRL_WKUP_CTRL);
247#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700248 writel(readl(&t2_base->devconf0) | MMCSDIO1ADPCLKISEL,
249 &t2_base->devconf0);
250
251 writel(readl(&t2_base->devconf1) | MMCSDIO2ADPCLKISEL,
252 &t2_base->devconf1);
253
Jonathan Solnita9b05562012-02-24 11:30:18 +0000254 /* Change from default of 52MHz to 26MHz if necessary */
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +0100255 if (!(cfg->host_caps & MMC_MODE_HS_52MHz))
Jonathan Solnita9b05562012-02-24 11:30:18 +0000256 writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
257 &t2_base->ctl_prog_io1);
258
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700259 writel(readl(&prcm_base->fclken1_core) |
260 EN_MMC1 | EN_MMC2 | EN_MMC3,
261 &prcm_base->fclken1_core);
262
263 writel(readl(&prcm_base->iclken1_core) |
264 EN_MMC1 | EN_MMC2 | EN_MMC3,
265 &prcm_base->iclken1_core);
266#endif
267
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100268#if (defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)) &&\
269 !CONFIG_IS_ENABLED(DM_REGULATOR)
Balaji T Kf843d332011-09-08 06:34:57 +0000270 /* PBIAS config needed for MMC1 only */
Jean-Jacques Hiblot26319b12017-03-22 16:00:32 +0100271 if (mmc_get_blk_desc(mmc)->devnum == 0)
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530272 vmmc_pbias_config(LDO_VOLT_3V3);
Balaji T Kd9cf8362012-03-12 02:25:49 +0000273#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700274
275 return 0;
276}
277
Sricharanf72611f2011-11-15 09:49:53 -0500278void mmc_init_stream(struct hsmmc *mmc_base)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700279{
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500280 ulong start;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700281
282 writel(readl(&mmc_base->con) | INIT_INITSTREAM, &mmc_base->con);
283
284 writel(MMC_CMD0, &mmc_base->cmd);
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500285 start = get_timer(0);
286 while (!(readl(&mmc_base->stat) & CC_MASK)) {
287 if (get_timer(0) - start > MAX_RETRY_MS) {
288 printf("%s: timedout waiting for cc!\n", __func__);
289 return;
290 }
291 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700292 writel(CC_MASK, &mmc_base->stat)
293 ;
294 writel(MMC_CMD0, &mmc_base->cmd)
295 ;
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500296 start = get_timer(0);
297 while (!(readl(&mmc_base->stat) & CC_MASK)) {
298 if (get_timer(0) - start > MAX_RETRY_MS) {
299 printf("%s: timedout waiting for cc2!\n", __func__);
300 return;
301 }
302 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700303 writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con);
304}
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100305
306#if CONFIG_IS_ENABLED(DM_MMC)
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100307#ifdef CONFIG_IODELAY_RECALIBRATION
308static void omap_hsmmc_io_recalibrate(struct mmc *mmc)
309{
310 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
311 struct omap_hsmmc_pinctrl_state *pinctrl_state;
312
313 switch (priv->mode) {
314 case MMC_HS_200:
315 pinctrl_state = priv->hs200_1_8v_pinctrl_state;
316 break;
317 case UHS_SDR104:
318 pinctrl_state = priv->sdr104_pinctrl_state;
319 break;
320 case UHS_SDR50:
321 pinctrl_state = priv->sdr50_pinctrl_state;
322 break;
323 case UHS_DDR50:
324 pinctrl_state = priv->ddr50_pinctrl_state;
325 break;
326 case UHS_SDR25:
327 pinctrl_state = priv->sdr25_pinctrl_state;
328 break;
329 case UHS_SDR12:
330 pinctrl_state = priv->sdr12_pinctrl_state;
331 break;
332 case SD_HS:
333 case MMC_HS:
334 case MMC_HS_52:
335 pinctrl_state = priv->hs_pinctrl_state;
336 break;
337 case MMC_DDR_52:
338 pinctrl_state = priv->ddr_1_8v_pinctrl_state;
339 default:
340 pinctrl_state = priv->default_pinctrl_state;
341 break;
342 }
343
Jean-Jacques Hiblotdae1ad42018-01-30 16:01:42 +0100344 if (!pinctrl_state)
345 pinctrl_state = priv->default_pinctrl_state;
346
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100347 if (priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY) {
348 if (pinctrl_state->iodelay)
349 late_recalibrate_iodelay(pinctrl_state->padconf,
350 pinctrl_state->npads,
351 pinctrl_state->iodelay,
352 pinctrl_state->niodelays);
353 else
354 do_set_mux32((*ctrl)->control_padconf_core_base,
355 pinctrl_state->padconf,
356 pinctrl_state->npads);
357 }
358}
359#endif
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +0100360static void omap_hsmmc_set_timing(struct mmc *mmc)
361{
362 u32 val;
363 struct hsmmc *mmc_base;
364 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
365
366 mmc_base = priv->base_addr;
367
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100368 omap_hsmmc_stop_clock(mmc_base);
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +0100369 val = readl(&mmc_base->ac12);
370 val &= ~AC12_UHSMC_MASK;
371 priv->mode = mmc->selected_mode;
372
Kishon Vijay Abraham I0c1f3d02018-01-30 16:01:34 +0100373 if (mmc_is_mode_ddr(priv->mode))
374 writel(readl(&mmc_base->con) | DDR, &mmc_base->con);
375 else
376 writel(readl(&mmc_base->con) & ~DDR, &mmc_base->con);
377
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +0100378 switch (priv->mode) {
379 case MMC_HS_200:
380 case UHS_SDR104:
381 val |= AC12_UHSMC_SDR104;
382 break;
383 case UHS_SDR50:
384 val |= AC12_UHSMC_SDR50;
385 break;
386 case MMC_DDR_52:
387 case UHS_DDR50:
388 val |= AC12_UHSMC_DDR50;
389 break;
390 case SD_HS:
391 case MMC_HS_52:
392 case UHS_SDR25:
393 val |= AC12_UHSMC_SDR25;
394 break;
395 case MMC_LEGACY:
396 case MMC_HS:
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +0100397 case UHS_SDR12:
398 val |= AC12_UHSMC_SDR12;
399 break;
400 default:
401 val |= AC12_UHSMC_RES;
402 break;
403 }
404 writel(val, &mmc_base->ac12);
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +0100405
406#ifdef CONFIG_IODELAY_RECALIBRATION
407 omap_hsmmc_io_recalibrate(mmc);
408#endif
409 omap_hsmmc_start_clock(mmc_base);
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +0100410}
411
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100412static void omap_hsmmc_conf_bus_power(struct mmc *mmc, uint signal_voltage)
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100413{
414 struct hsmmc *mmc_base;
415 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100416 u32 hctl, ac12;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100417
418 mmc_base = priv->base_addr;
419
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100420 hctl = readl(&mmc_base->hctl) & ~SDVS_MASK;
421 ac12 = readl(&mmc_base->ac12) & ~AC12_V1V8_SIGEN;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100422
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100423 switch (signal_voltage) {
424 case MMC_SIGNAL_VOLTAGE_330:
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530425 hctl |= SDVS_3V3;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100426 break;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100427 case MMC_SIGNAL_VOLTAGE_180:
428 hctl |= SDVS_1V8;
429 ac12 |= AC12_V1V8_SIGEN;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100430 break;
431 }
432
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100433 writel(hctl, &mmc_base->hctl);
434 writel(ac12, &mmc_base->ac12);
435}
436
Sam Protsenkodb174c62019-08-14 22:52:51 +0300437static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout_us)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100438{
439 int ret = -ETIMEDOUT;
440 u32 con;
441 bool dat0_high;
442 bool target_dat0_high = !!state;
443 struct omap_hsmmc_data *priv = dev_get_priv(dev);
444 struct hsmmc *mmc_base = priv->base_addr;
445
446 con = readl(&mmc_base->con);
447 writel(con | CON_CLKEXTFREE | CON_PADEN, &mmc_base->con);
448
Sam Protsenkodb174c62019-08-14 22:52:51 +0300449 timeout_us = DIV_ROUND_UP(timeout_us, 10); /* check every 10 us. */
450 while (timeout_us--) {
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100451 dat0_high = !!(readl(&mmc_base->pstate) & PSTATE_DLEV_DAT0);
452 if (dat0_high == target_dat0_high) {
453 ret = 0;
454 break;
455 }
456 udelay(10);
457 }
458 writel(con, &mmc_base->con);
459
460 return ret;
461}
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100462
463#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
464#if CONFIG_IS_ENABLED(DM_REGULATOR)
465static int omap_hsmmc_set_io_regulator(struct mmc *mmc, int mV)
466{
467 int ret = 0;
468 int uV = mV * 1000;
469
470 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
471
472 if (!mmc->vqmmc_supply)
473 return 0;
474
475 /* Disable PBIAS */
Lokesh Vutlab2691972019-01-11 15:15:52 +0530476 ret = regulator_set_enable_if_allowed(priv->pbias_supply, false);
477 if (ret)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100478 return ret;
479
480 /* Turn off IO voltage */
Lokesh Vutlab2691972019-01-11 15:15:52 +0530481 ret = regulator_set_enable_if_allowed(mmc->vqmmc_supply, false);
482 if (ret)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100483 return ret;
484 /* Program a new IO voltage value */
485 ret = regulator_set_value(mmc->vqmmc_supply, uV);
486 if (ret)
487 return ret;
488 /* Turn on IO voltage */
Lokesh Vutlab2691972019-01-11 15:15:52 +0530489 ret = regulator_set_enable_if_allowed(mmc->vqmmc_supply, true);
490 if (ret)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100491 return ret;
492
493 /* Program PBIAS voltage*/
494 ret = regulator_set_value(priv->pbias_supply, uV);
495 if (ret && ret != -ENOSYS)
496 return ret;
497 /* Enable PBIAS */
Lokesh Vutlab2691972019-01-11 15:15:52 +0530498 ret = regulator_set_enable_if_allowed(priv->pbias_supply, true);
499 if (ret)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100500 return ret;
501
502 return 0;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100503}
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100504#endif
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100505
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100506static int omap_hsmmc_set_signal_voltage(struct mmc *mmc)
507{
508 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
509 struct hsmmc *mmc_base = priv->base_addr;
510 int mv = mmc_voltage_to_mv(mmc->signal_voltage);
511 u32 capa_mask;
512 __maybe_unused u8 palmas_ldo_volt;
513 u32 val;
514
515 if (mv < 0)
516 return -EINVAL;
517
518 if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530519 mv = 3300;
520 capa_mask = VS33_3V3SUP;
521 palmas_ldo_volt = LDO_VOLT_3V3;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100522 } else if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
523 capa_mask = VS18_1V8SUP;
524 palmas_ldo_volt = LDO_VOLT_1V8;
525 } else {
526 return -EOPNOTSUPP;
527 }
528
529 val = readl(&mmc_base->capa);
530 if (!(val & capa_mask))
531 return -EOPNOTSUPP;
532
533 priv->signal_voltage = mmc->signal_voltage;
534
535 omap_hsmmc_conf_bus_power(mmc, mmc->signal_voltage);
536
537#if CONFIG_IS_ENABLED(DM_REGULATOR)
538 return omap_hsmmc_set_io_regulator(mmc, mv);
539#elif (defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)) && \
540 defined(CONFIG_PALMAS_POWER)
541 if (mmc_get_blk_desc(mmc)->devnum == 0)
542 vmmc_pbias_config(palmas_ldo_volt);
543 return 0;
544#else
545 return 0;
546#endif
547}
548#endif
549
550static uint32_t omap_hsmmc_set_capabilities(struct mmc *mmc)
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100551{
552 struct hsmmc *mmc_base;
553 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
554 u32 val;
555
556 mmc_base = priv->base_addr;
557 val = readl(&mmc_base->capa);
558
559 if (priv->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530560 val |= (VS33_3V3SUP | VS18_1V8SUP);
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100561 } else if (priv->controller_flags & OMAP_HSMMC_NO_1_8_V) {
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530562 val |= VS33_3V3SUP;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100563 val &= ~VS18_1V8SUP;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100564 } else {
565 val |= VS18_1V8SUP;
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530566 val &= ~VS33_3V3SUP;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100567 }
568
569 writel(val, &mmc_base->capa);
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100570
571 return val;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100572}
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100573
574#ifdef MMC_SUPPORTS_TUNING
575static void omap_hsmmc_disable_tuning(struct mmc *mmc)
576{
577 struct hsmmc *mmc_base;
578 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
579 u32 val;
580
581 mmc_base = priv->base_addr;
582 val = readl(&mmc_base->ac12);
583 val &= ~(AC12_SCLK_SEL);
584 writel(val, &mmc_base->ac12);
585
586 val = readl(&mmc_base->dll);
587 val &= ~(DLL_FORCE_VALUE | DLL_SWT);
588 writel(val, &mmc_base->dll);
589}
590
591static void omap_hsmmc_set_dll(struct mmc *mmc, int count)
592{
593 int i;
594 struct hsmmc *mmc_base;
595 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
596 u32 val;
597
598 mmc_base = priv->base_addr;
599 val = readl(&mmc_base->dll);
600 val |= DLL_FORCE_VALUE;
601 val &= ~(DLL_FORCE_SR_C_MASK << DLL_FORCE_SR_C_SHIFT);
602 val |= (count << DLL_FORCE_SR_C_SHIFT);
603 writel(val, &mmc_base->dll);
604
605 val |= DLL_CALIB;
606 writel(val, &mmc_base->dll);
607 for (i = 0; i < 1000; i++) {
608 if (readl(&mmc_base->dll) & DLL_CALIB)
609 break;
610 }
611 val &= ~DLL_CALIB;
612 writel(val, &mmc_base->dll);
613}
614
615static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode)
616{
617 struct omap_hsmmc_data *priv = dev_get_priv(dev);
618 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
619 struct mmc *mmc = upriv->mmc;
620 struct hsmmc *mmc_base;
621 u32 val;
622 u8 cur_match, prev_match = 0;
623 int ret;
624 u32 phase_delay = 0;
625 u32 start_window = 0, max_window = 0;
626 u32 length = 0, max_len = 0;
Faiz Abbase4d30562019-01-30 18:08:42 +0530627 bool single_point_failure = false;
628 struct udevice *thermal_dev;
629 int temperature;
630 int i;
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100631
632 mmc_base = priv->base_addr;
633 val = readl(&mmc_base->capa2);
634
635 /* clock tuning is not needed for upto 52MHz */
636 if (!((mmc->selected_mode == MMC_HS_200) ||
637 (mmc->selected_mode == UHS_SDR104) ||
638 ((mmc->selected_mode == UHS_SDR50) && (val & CAPA2_TSDR50))))
639 return 0;
640
Faiz Abbase4d30562019-01-30 18:08:42 +0530641 ret = uclass_first_device(UCLASS_THERMAL, &thermal_dev);
642 if (ret) {
643 printf("Couldn't get thermal device for tuning\n");
644 return ret;
645 }
646 ret = thermal_get_temp(thermal_dev, &temperature);
647 if (ret) {
648 printf("Couldn't get temperature for tuning\n");
649 return ret;
650 }
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100651 val = readl(&mmc_base->dll);
652 val |= DLL_SWT;
653 writel(val, &mmc_base->dll);
Faiz Abbase4d30562019-01-30 18:08:42 +0530654
655 /*
656 * Stage 1: Search for a maximum pass window ignoring any
657 * any single point failures. If the tuning value ends up
658 * near it, move away from it in stage 2 below
659 */
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100660 while (phase_delay <= MAX_PHASE_DELAY) {
661 omap_hsmmc_set_dll(mmc, phase_delay);
662
663 cur_match = !mmc_send_tuning(mmc, opcode, NULL);
664
665 if (cur_match) {
666 if (prev_match) {
667 length++;
Faiz Abbase4d30562019-01-30 18:08:42 +0530668 } else if (single_point_failure) {
669 /* ignore single point failure */
670 length++;
671 single_point_failure = false;
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100672 } else {
673 start_window = phase_delay;
674 length = 1;
675 }
Faiz Abbase4d30562019-01-30 18:08:42 +0530676 } else {
677 single_point_failure = prev_match;
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100678 }
679
680 if (length > max_len) {
681 max_window = start_window;
682 max_len = length;
683 }
684
685 prev_match = cur_match;
686 phase_delay += 4;
687 }
688
689 if (!max_len) {
690 ret = -EIO;
691 goto tuning_error;
692 }
693
694 val = readl(&mmc_base->ac12);
695 if (!(val & AC12_SCLK_SEL)) {
696 ret = -EIO;
697 goto tuning_error;
698 }
Faiz Abbase4d30562019-01-30 18:08:42 +0530699 /*
700 * Assign tuning value as a ratio of maximum pass window based
701 * on temperature
702 */
703 if (temperature < -20000)
704 phase_delay = min(max_window + 4 * max_len - 24,
705 max_window +
706 DIV_ROUND_UP(13 * max_len, 16) * 4);
707 else if (temperature < 20000)
708 phase_delay = max_window + DIV_ROUND_UP(9 * max_len, 16) * 4;
709 else if (temperature < 40000)
710 phase_delay = max_window + DIV_ROUND_UP(8 * max_len, 16) * 4;
711 else if (temperature < 70000)
712 phase_delay = max_window + DIV_ROUND_UP(7 * max_len, 16) * 4;
713 else if (temperature < 90000)
714 phase_delay = max_window + DIV_ROUND_UP(5 * max_len, 16) * 4;
715 else if (temperature < 120000)
716 phase_delay = max_window + DIV_ROUND_UP(4 * max_len, 16) * 4;
717 else
718 phase_delay = max_window + DIV_ROUND_UP(3 * max_len, 16) * 4;
719
720 /*
721 * Stage 2: Search for a single point failure near the chosen tuning
722 * value in two steps. First in the +3 to +10 range and then in the
723 * +2 to -10 range. If found, move away from it in the appropriate
724 * direction by the appropriate amount depending on the temperature.
725 */
726 for (i = 3; i <= 10; i++) {
727 omap_hsmmc_set_dll(mmc, phase_delay + i);
728 if (mmc_send_tuning(mmc, opcode, NULL)) {
729 if (temperature < 10000)
730 phase_delay += i + 6;
731 else if (temperature < 20000)
732 phase_delay += i - 12;
733 else if (temperature < 70000)
734 phase_delay += i - 8;
735 else if (temperature < 90000)
736 phase_delay += i - 6;
737 else
738 phase_delay += i - 6;
739
740 goto single_failure_found;
741 }
742 }
743
744 for (i = 2; i >= -10; i--) {
745 omap_hsmmc_set_dll(mmc, phase_delay + i);
746 if (mmc_send_tuning(mmc, opcode, NULL)) {
747 if (temperature < 10000)
748 phase_delay += i + 12;
749 else if (temperature < 20000)
750 phase_delay += i + 8;
751 else if (temperature < 70000)
752 phase_delay += i + 8;
753 else if (temperature < 90000)
754 phase_delay += i + 10;
755 else
756 phase_delay += i + 12;
757
758 goto single_failure_found;
759 }
760 }
761
762single_failure_found:
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100763
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +0100764 omap_hsmmc_set_dll(mmc, phase_delay);
765
766 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
767 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
768
769 return 0;
770
771tuning_error:
772
773 omap_hsmmc_disable_tuning(mmc);
774 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
775 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
776
777 return ret;
778}
779#endif
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100780#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700781
Jean-Jacques Hiblota420d7d2018-01-30 16:01:36 +0100782static void mmc_enable_irq(struct mmc *mmc, struct mmc_cmd *cmd)
783{
784 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
785 struct hsmmc *mmc_base = priv->base_addr;
786 u32 irq_mask = INT_EN_MASK;
787
788 /*
789 * TODO: Errata i802 indicates only DCRC interrupts can occur during
790 * tuning procedure and DCRC should be disabled. But see occurences
791 * of DEB, CIE, CEB, CCRC interupts during tuning procedure. These
792 * interrupts occur along with BRR, so the data is actually in the
793 * buffer. It has to be debugged why these interrutps occur
794 */
795 if (cmd && mmc_is_tuning_cmd(cmd->cmdidx))
796 irq_mask &= ~(IE_DEB | IE_DCRC | IE_CIE | IE_CEB | IE_CCRC);
797
798 writel(irq_mask, &mmc_base->ie);
799}
800
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200801static int omap_hsmmc_init_setup(struct mmc *mmc)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700802{
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +0100803 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Nikita Kiryanov13822862012-12-03 02:19:43 +0000804 struct hsmmc *mmc_base;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700805 unsigned int reg_val;
806 unsigned int dsor;
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500807 ulong start;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700808
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +0100809 mmc_base = priv->base_addr;
Balaji T Kf843d332011-09-08 06:34:57 +0000810 mmc_board_init(mmc);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700811
812 writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
813 &mmc_base->sysconfig);
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500814 start = get_timer(0);
815 while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
816 if (get_timer(0) - start > MAX_RETRY_MS) {
817 printf("%s: timedout waiting for cc2!\n", __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +0900818 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500819 }
820 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700821 writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl);
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500822 start = get_timer(0);
823 while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) {
824 if (get_timer(0) - start > MAX_RETRY_MS) {
825 printf("%s: timedout waiting for softresetall!\n",
826 __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +0900827 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500828 }
829 }
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +0100830#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200831 reg_val = readl(&mmc_base->hl_hwinfo);
832 if (reg_val & MADMA_EN)
833 priv->controller_flags |= OMAP_HSMMC_USE_ADMA;
834#endif
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100835
836#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100837 reg_val = omap_hsmmc_set_capabilities(mmc);
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530838 omap_hsmmc_conf_bus_power(mmc, (reg_val & VS33_3V3SUP) ?
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +0100839 MMC_SIGNAL_VOLTAGE_330 : MMC_SIGNAL_VOLTAGE_180);
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100840#else
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700841 writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
Faiz Abbasfc1ad622019-04-05 14:18:46 +0530842 writel(readl(&mmc_base->capa) | VS33_3V3SUP | VS18_1V8SUP,
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700843 &mmc_base->capa);
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +0100844#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700845
846 reg_val = readl(&mmc_base->con) & RESERVED_MASK;
847
848 writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH |
849 MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK |
850 HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con);
851
852 dsor = 240;
853 mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK),
Kishon Vijay Abraham I6e543812017-09-21 16:51:36 +0200854 (ICE_STOP | DTO_15THDTO));
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700855 mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
856 (dsor << CLKD_OFFSET) | ICE_OSCILLATE);
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500857 start = get_timer(0);
858 while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
859 if (get_timer(0) - start > MAX_RETRY_MS) {
860 printf("%s: timedout waiting for ics!\n", __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +0900861 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -0500862 }
863 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700864 writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
865
866 writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl);
867
Jean-Jacques Hiblota420d7d2018-01-30 16:01:36 +0100868 mmc_enable_irq(mmc, NULL);
Jean-Jacques Hiblot20157d42018-01-30 16:01:44 +0100869
870#if !CONFIG_IS_ENABLED(DM_MMC)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700871 mmc_init_stream(mmc_base);
Jean-Jacques Hiblot20157d42018-01-30 16:01:44 +0100872#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -0700873
874 return 0;
875}
876
Grazvydas Ignotasddde1882012-03-19 12:12:06 +0000877/*
878 * MMC controller internal finite state machine reset
879 *
880 * Used to reset command or data internal state machines, using respectively
881 * SRC or SRD bit of SYSCTL register
882 */
883static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
884{
885 ulong start;
886
887 mmc_reg_out(&mmc_base->sysctl, bit, bit);
888
Oleksandr Tyshchenko06640ca2013-08-06 13:44:16 +0300889 /*
890 * CMD(DAT) lines reset procedures are slightly different
891 * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx).
892 * According to OMAP3 TRM:
893 * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it
894 * returns to 0x0.
895 * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset
896 * procedure steps must be as follows:
897 * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in
898 * MMCHS_SYSCTL register (SD_SYSCTL for AM335x).
899 * 2. Poll the SRC(SRD) bit until it is set to 0x1.
900 * 3. Wait until the SRC (SRD) bit returns to 0x0
901 * (reset procedure is completed).
902 */
903#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
Nikita Kiryanov5ffdd852015-07-30 23:56:20 +0300904 defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX)
Oleksandr Tyshchenko06640ca2013-08-06 13:44:16 +0300905 if (!(readl(&mmc_base->sysctl) & bit)) {
906 start = get_timer(0);
907 while (!(readl(&mmc_base->sysctl) & bit)) {
Jean-Jacques Hiblot192e4302018-01-30 16:01:37 +0100908 if (get_timer(0) - start > MMC_TIMEOUT_MS)
Oleksandr Tyshchenko06640ca2013-08-06 13:44:16 +0300909 return;
910 }
911 }
912#endif
Grazvydas Ignotasddde1882012-03-19 12:12:06 +0000913 start = get_timer(0);
914 while ((readl(&mmc_base->sysctl) & bit) != 0) {
915 if (get_timer(0) - start > MAX_RETRY_MS) {
916 printf("%s: timedout waiting for sysctl %x to clear\n",
917 __func__, bit);
918 return;
919 }
920 }
921}
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200922
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +0100923#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +0200924static void omap_hsmmc_adma_desc(struct mmc *mmc, char *buf, u16 len, bool end)
925{
926 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
927 struct omap_hsmmc_adma_desc *desc;
928 u8 attr;
929
930 desc = &priv->adma_desc_table[priv->desc_slot];
931
932 attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
933 if (!end)
934 priv->desc_slot++;
935 else
936 attr |= ADMA_DESC_ATTR_END;
937
938 desc->len = len;
939 desc->addr = (u32)buf;
940 desc->reserved = 0;
941 desc->attr = attr;
942}
943
944static void omap_hsmmc_prepare_adma_table(struct mmc *mmc,
945 struct mmc_data *data)
946{
947 uint total_len = data->blocksize * data->blocks;
948 uint desc_count = DIV_ROUND_UP(total_len, ADMA_MAX_LEN);
949 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
950 int i = desc_count;
951 char *buf;
952
953 priv->desc_slot = 0;
954 priv->adma_desc_table = (struct omap_hsmmc_adma_desc *)
955 memalign(ARCH_DMA_MINALIGN, desc_count *
956 sizeof(struct omap_hsmmc_adma_desc));
957
958 if (data->flags & MMC_DATA_READ)
959 buf = data->dest;
960 else
961 buf = (char *)data->src;
962
963 while (--i) {
964 omap_hsmmc_adma_desc(mmc, buf, ADMA_MAX_LEN, false);
965 buf += ADMA_MAX_LEN;
966 total_len -= ADMA_MAX_LEN;
967 }
968
969 omap_hsmmc_adma_desc(mmc, buf, total_len, true);
970
971 flush_dcache_range((long)priv->adma_desc_table,
972 (long)priv->adma_desc_table +
973 ROUND(desc_count *
974 sizeof(struct omap_hsmmc_adma_desc),
975 ARCH_DMA_MINALIGN));
976}
977
978static void omap_hsmmc_prepare_data(struct mmc *mmc, struct mmc_data *data)
979{
980 struct hsmmc *mmc_base;
981 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
982 u32 val;
983 char *buf;
984
985 mmc_base = priv->base_addr;
986 omap_hsmmc_prepare_adma_table(mmc, data);
987
988 if (data->flags & MMC_DATA_READ)
989 buf = data->dest;
990 else
991 buf = (char *)data->src;
992
993 val = readl(&mmc_base->hctl);
994 val |= DMA_SELECT;
995 writel(val, &mmc_base->hctl);
996
997 val = readl(&mmc_base->con);
998 val |= DMA_MASTER;
999 writel(val, &mmc_base->con);
1000
1001 writel((u32)priv->adma_desc_table, &mmc_base->admasal);
1002
1003 flush_dcache_range((u32)buf,
1004 (u32)buf +
1005 ROUND(data->blocksize * data->blocks,
1006 ARCH_DMA_MINALIGN));
1007}
1008
1009static void omap_hsmmc_dma_cleanup(struct mmc *mmc)
1010{
1011 struct hsmmc *mmc_base;
1012 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
1013 u32 val;
1014
1015 mmc_base = priv->base_addr;
1016
1017 val = readl(&mmc_base->con);
1018 val &= ~DMA_MASTER;
1019 writel(val, &mmc_base->con);
1020
1021 val = readl(&mmc_base->hctl);
1022 val &= ~DMA_SELECT;
1023 writel(val, &mmc_base->hctl);
1024
1025 kfree(priv->adma_desc_table);
1026}
1027#else
1028#define omap_hsmmc_adma_desc
1029#define omap_hsmmc_prepare_adma_table
1030#define omap_hsmmc_prepare_data
1031#define omap_hsmmc_dma_cleanup
1032#endif
1033
Simon Glass5f4bd8c2017-07-04 13:31:19 -06001034#if !CONFIG_IS_ENABLED(DM_MMC)
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001035static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001036 struct mmc_data *data)
1037{
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001038 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001039#else
1040static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
1041 struct mmc_data *data)
1042{
1043 struct omap_hsmmc_data *priv = dev_get_priv(dev);
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +02001044 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
1045 struct mmc *mmc = upriv->mmc;
1046#endif
Nikita Kiryanov13822862012-12-03 02:19:43 +00001047 struct hsmmc *mmc_base;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001048 unsigned int flags, mmc_stat;
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001049 ulong start;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001050 priv->last_cmd = cmd->cmdidx;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001051
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001052 mmc_base = priv->base_addr;
Kishon Vijay Abraham I316e7ae2017-09-21 16:51:35 +02001053
1054 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
1055 return 0;
1056
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001057 start = get_timer(0);
Tom Rini32ec3252012-01-30 11:22:25 +00001058 while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001059 if (get_timer(0) - start > MAX_RETRY_MS) {
Tom Rini32ec3252012-01-30 11:22:25 +00001060 printf("%s: timedout waiting on cmd inhibit to clear\n",
1061 __func__);
Jean-Jacques Hiblota1e7a4d2019-07-02 10:53:48 +02001062 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
1063 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
Jaehoon Chung7825d202016-07-19 16:33:36 +09001064 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001065 }
1066 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001067 writel(0xFFFFFFFF, &mmc_base->stat);
Jean-Jacques Hiblota1e7a4d2019-07-02 10:53:48 +02001068 if (readl(&mmc_base->stat)) {
1069 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
1070 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001071 }
Jean-Jacques Hiblota1e7a4d2019-07-02 10:53:48 +02001072
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001073 /*
1074 * CMDREG
1075 * CMDIDX[13:8] : Command index
1076 * DATAPRNT[5] : Data Present Select
1077 * ENCMDIDX[4] : Command Index Check Enable
1078 * ENCMDCRC[3] : Command CRC Check Enable
1079 * RSPTYP[1:0]
1080 * 00 = No Response
1081 * 01 = Length 136
1082 * 10 = Length 48
1083 * 11 = Length 48 Check busy after response
1084 */
1085 /* Delay added before checking the status of frq change
1086 * retry not supported by mmc.c(core file)
1087 */
1088 if (cmd->cmdidx == SD_CMD_APP_SEND_SCR)
1089 udelay(50000); /* wait 50 ms */
1090
1091 if (!(cmd->resp_type & MMC_RSP_PRESENT))
1092 flags = 0;
1093 else if (cmd->resp_type & MMC_RSP_136)
1094 flags = RSP_TYPE_LGHT136 | CICE_NOCHECK;
1095 else if (cmd->resp_type & MMC_RSP_BUSY)
1096 flags = RSP_TYPE_LGHT48B;
1097 else
1098 flags = RSP_TYPE_LGHT48;
1099
1100 /* enable default flags */
1101 flags = flags | (CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK |
Kishon Vijay Abraham I6e543812017-09-21 16:51:36 +02001102 MSBS_SGLEBLK);
1103 flags &= ~(ACEN_ENABLE | BCE_ENABLE | DE_ENABLE);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001104
1105 if (cmd->resp_type & MMC_RSP_CRC)
1106 flags |= CCCE_CHECK;
1107 if (cmd->resp_type & MMC_RSP_OPCODE)
1108 flags |= CICE_CHECK;
1109
1110 if (data) {
1111 if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) ||
1112 (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) {
Kishon Vijay Abraham I316e7ae2017-09-21 16:51:35 +02001113 flags |= (MSBS_MULTIBLK | BCE_ENABLE | ACEN_ENABLE);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001114 data->blocksize = 512;
1115 writel(data->blocksize | (data->blocks << 16),
1116 &mmc_base->blk);
1117 } else
1118 writel(data->blocksize | NBLK_STPCNT, &mmc_base->blk);
1119
1120 if (data->flags & MMC_DATA_READ)
1121 flags |= (DP_DATA | DDIR_READ);
1122 else
1123 flags |= (DP_DATA | DDIR_WRITE);
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +02001124
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +01001125#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +02001126 if ((priv->controller_flags & OMAP_HSMMC_USE_ADMA) &&
1127 !mmc_is_tuning_cmd(cmd->cmdidx)) {
1128 omap_hsmmc_prepare_data(mmc, data);
1129 flags |= DE_ENABLE;
1130 }
1131#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001132 }
1133
Jean-Jacques Hiblota420d7d2018-01-30 16:01:36 +01001134 mmc_enable_irq(mmc, cmd);
1135
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001136 writel(cmd->cmdarg, &mmc_base->arg);
Lubomir Popov19df4122013-08-14 18:59:18 +03001137 udelay(20); /* To fix "No status update" error on eMMC */
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001138 writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
1139
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001140 start = get_timer(0);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001141 do {
1142 mmc_stat = readl(&mmc_base->stat);
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +02001143 if (get_timer(start) > MAX_RETRY_MS) {
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001144 printf("%s : timeout: No status update\n", __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +09001145 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001146 }
1147 } while (!mmc_stat);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001148
Grazvydas Ignotasddde1882012-03-19 12:12:06 +00001149 if ((mmc_stat & IE_CTO) != 0) {
1150 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
Jaehoon Chung7825d202016-07-19 16:33:36 +09001151 return -ETIMEDOUT;
Grazvydas Ignotasddde1882012-03-19 12:12:06 +00001152 } else if ((mmc_stat & ERRI_MASK) != 0)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001153 return -1;
1154
1155 if (mmc_stat & CC_MASK) {
1156 writel(CC_MASK, &mmc_base->stat);
1157 if (cmd->resp_type & MMC_RSP_PRESENT) {
1158 if (cmd->resp_type & MMC_RSP_136) {
1159 /* response type 2 */
1160 cmd->response[3] = readl(&mmc_base->rsp10);
1161 cmd->response[2] = readl(&mmc_base->rsp32);
1162 cmd->response[1] = readl(&mmc_base->rsp54);
1163 cmd->response[0] = readl(&mmc_base->rsp76);
1164 } else
1165 /* response types 1, 1b, 3, 4, 5, 6 */
1166 cmd->response[0] = readl(&mmc_base->rsp10);
1167 }
1168 }
1169
Jean-Jacques Hiblotcebf0592018-02-23 10:40:18 +01001170#ifdef CONFIG_MMC_OMAP_HS_ADMA
Kishon Vijay Abraham I826be2a2017-09-21 16:51:34 +02001171 if ((priv->controller_flags & OMAP_HSMMC_USE_ADMA) && data &&
1172 !mmc_is_tuning_cmd(cmd->cmdidx)) {
1173 u32 sz_mb, timeout;
1174
1175 if (mmc_stat & IE_ADMAE) {
1176 omap_hsmmc_dma_cleanup(mmc);
1177 return -EIO;
1178 }
1179
1180 sz_mb = DIV_ROUND_UP(data->blocksize * data->blocks, 1 << 20);
1181 timeout = sz_mb * DMA_TIMEOUT_PER_MB;
1182 if (timeout < MAX_RETRY_MS)
1183 timeout = MAX_RETRY_MS;
1184
1185 start = get_timer(0);
1186 do {
1187 mmc_stat = readl(&mmc_base->stat);
1188 if (mmc_stat & TC_MASK) {
1189 writel(readl(&mmc_base->stat) | TC_MASK,
1190 &mmc_base->stat);
1191 break;
1192 }
1193 if (get_timer(start) > timeout) {
1194 printf("%s : DMA timeout: No status update\n",
1195 __func__);
1196 return -ETIMEDOUT;
1197 }
1198 } while (1);
1199
1200 omap_hsmmc_dma_cleanup(mmc);
1201 return 0;
1202 }
1203#endif
1204
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001205 if (data && (data->flags & MMC_DATA_READ)) {
1206 mmc_read_data(mmc_base, data->dest,
1207 data->blocksize * data->blocks);
1208 } else if (data && (data->flags & MMC_DATA_WRITE)) {
1209 mmc_write_data(mmc_base, data->src,
1210 data->blocksize * data->blocks);
1211 }
1212 return 0;
1213}
1214
Sricharanf72611f2011-11-15 09:49:53 -05001215static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001216{
1217 unsigned int *output_buf = (unsigned int *)buf;
1218 unsigned int mmc_stat;
1219 unsigned int count;
1220
1221 /*
1222 * Start Polled Read
1223 */
1224 count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
1225 count /= 4;
1226
1227 while (size) {
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001228 ulong start = get_timer(0);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001229 do {
1230 mmc_stat = readl(&mmc_base->stat);
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001231 if (get_timer(0) - start > MAX_RETRY_MS) {
1232 printf("%s: timedout waiting for status!\n",
1233 __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +09001234 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001235 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001236 } while (mmc_stat == 0);
1237
Grazvydas Ignotasddde1882012-03-19 12:12:06 +00001238 if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0)
1239 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
1240
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001241 if ((mmc_stat & ERRI_MASK) != 0)
1242 return 1;
1243
1244 if (mmc_stat & BRR_MASK) {
1245 unsigned int k;
1246
1247 writel(readl(&mmc_base->stat) | BRR_MASK,
1248 &mmc_base->stat);
1249 for (k = 0; k < count; k++) {
1250 *output_buf = readl(&mmc_base->data);
1251 output_buf++;
1252 }
1253 size -= (count*4);
1254 }
1255
1256 if (mmc_stat & BWR_MASK)
1257 writel(readl(&mmc_base->stat) | BWR_MASK,
1258 &mmc_base->stat);
1259
1260 if (mmc_stat & TC_MASK) {
1261 writel(readl(&mmc_base->stat) | TC_MASK,
1262 &mmc_base->stat);
1263 break;
1264 }
1265 }
1266 return 0;
1267}
1268
Jean-Jacques Hiblot98821552018-02-23 10:40:17 +01001269#if CONFIG_IS_ENABLED(MMC_WRITE)
Sricharanf72611f2011-11-15 09:49:53 -05001270static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
Jean-Jacques Hiblot98821552018-02-23 10:40:17 +01001271 unsigned int size)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001272{
1273 unsigned int *input_buf = (unsigned int *)buf;
1274 unsigned int mmc_stat;
1275 unsigned int count;
1276
1277 /*
Lubomir Popov19df4122013-08-14 18:59:18 +03001278 * Start Polled Write
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001279 */
1280 count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
1281 count /= 4;
1282
1283 while (size) {
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001284 ulong start = get_timer(0);
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001285 do {
1286 mmc_stat = readl(&mmc_base->stat);
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001287 if (get_timer(0) - start > MAX_RETRY_MS) {
1288 printf("%s: timedout waiting for status!\n",
1289 __func__);
Jaehoon Chung7825d202016-07-19 16:33:36 +09001290 return -ETIMEDOUT;
Nishanth Menond3bfaac2010-11-19 11:18:12 -05001291 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001292 } while (mmc_stat == 0);
1293
Grazvydas Ignotasddde1882012-03-19 12:12:06 +00001294 if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0)
1295 mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
1296
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001297 if ((mmc_stat & ERRI_MASK) != 0)
1298 return 1;
1299
1300 if (mmc_stat & BWR_MASK) {
1301 unsigned int k;
1302
1303 writel(readl(&mmc_base->stat) | BWR_MASK,
1304 &mmc_base->stat);
1305 for (k = 0; k < count; k++) {
1306 writel(*input_buf, &mmc_base->data);
1307 input_buf++;
1308 }
1309 size -= (count*4);
1310 }
1311
1312 if (mmc_stat & BRR_MASK)
1313 writel(readl(&mmc_base->stat) | BRR_MASK,
1314 &mmc_base->stat);
1315
1316 if (mmc_stat & TC_MASK) {
1317 writel(readl(&mmc_base->stat) | TC_MASK,
1318 &mmc_base->stat);
1319 break;
1320 }
1321 }
1322 return 0;
1323}
Jean-Jacques Hiblot98821552018-02-23 10:40:17 +01001324#else
1325static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
1326 unsigned int size)
1327{
1328 return -ENOTSUPP;
1329}
1330#endif
Jean-Jacques Hiblot7fe2f192018-01-30 16:01:30 +01001331static void omap_hsmmc_stop_clock(struct hsmmc *mmc_base)
1332{
1333 writel(readl(&mmc_base->sysctl) & ~CEN_ENABLE, &mmc_base->sysctl);
1334}
1335
1336static void omap_hsmmc_start_clock(struct hsmmc *mmc_base)
1337{
1338 writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
1339}
1340
1341static void omap_hsmmc_set_clock(struct mmc *mmc)
1342{
1343 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
1344 struct hsmmc *mmc_base;
1345 unsigned int dsor = 0;
1346 ulong start;
1347
1348 mmc_base = priv->base_addr;
1349 omap_hsmmc_stop_clock(mmc_base);
1350
1351 /* TODO: Is setting DTO required here? */
1352 mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK),
1353 (ICE_STOP | DTO_15THDTO));
1354
1355 if (mmc->clock != 0) {
1356 dsor = DIV_ROUND_UP(MMC_CLOCK_REFERENCE * 1000000, mmc->clock);
1357 if (dsor > CLKD_MAX)
1358 dsor = CLKD_MAX;
1359 } else {
1360 dsor = CLKD_MAX;
1361 }
1362
1363 mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
1364 (dsor << CLKD_OFFSET) | ICE_OSCILLATE);
1365
1366 start = get_timer(0);
1367 while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
1368 if (get_timer(0) - start > MAX_RETRY_MS) {
1369 printf("%s: timedout waiting for ics!\n", __func__);
1370 return;
1371 }
1372 }
1373
Jean-Jacques Hiblot6ce31e42018-01-30 16:01:43 +01001374 priv->clock = MMC_CLOCK_REFERENCE * 1000000 / dsor;
1375 mmc->clock = priv->clock;
Jean-Jacques Hiblot7fe2f192018-01-30 16:01:30 +01001376 omap_hsmmc_start_clock(mmc_base);
1377}
1378
Kishon Vijay Abraham I2e18c9b2018-01-30 16:01:31 +01001379static void omap_hsmmc_set_bus_width(struct mmc *mmc)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001380{
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001381 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Nikita Kiryanov13822862012-12-03 02:19:43 +00001382 struct hsmmc *mmc_base;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001383
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001384 mmc_base = priv->base_addr;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001385 /* configue bus width */
1386 switch (mmc->bus_width) {
1387 case 8:
1388 writel(readl(&mmc_base->con) | DTW_8_BITMODE,
1389 &mmc_base->con);
1390 break;
1391
1392 case 4:
1393 writel(readl(&mmc_base->con) & ~DTW_8_BITMODE,
1394 &mmc_base->con);
1395 writel(readl(&mmc_base->hctl) | DTW_4_BITMODE,
1396 &mmc_base->hctl);
1397 break;
1398
1399 case 1:
1400 default:
1401 writel(readl(&mmc_base->con) & ~DTW_8_BITMODE,
1402 &mmc_base->con);
1403 writel(readl(&mmc_base->hctl) & ~DTW_4_BITMODE,
1404 &mmc_base->hctl);
1405 break;
1406 }
1407
Kishon Vijay Abraham I2e18c9b2018-01-30 16:01:31 +01001408 priv->bus_width = mmc->bus_width;
1409}
1410
1411#if !CONFIG_IS_ENABLED(DM_MMC)
1412static int omap_hsmmc_set_ios(struct mmc *mmc)
1413{
1414 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
1415#else
1416static int omap_hsmmc_set_ios(struct udevice *dev)
1417{
1418 struct omap_hsmmc_data *priv = dev_get_priv(dev);
1419 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
1420 struct mmc *mmc = upriv->mmc;
1421#endif
Kishon Vijay Abraham Ie1f25c02018-01-30 16:01:45 +01001422 struct hsmmc *mmc_base = priv->base_addr;
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001423 int ret = 0;
Kishon Vijay Abraham I2e18c9b2018-01-30 16:01:31 +01001424
1425 if (priv->bus_width != mmc->bus_width)
1426 omap_hsmmc_set_bus_width(mmc);
1427
Jean-Jacques Hiblot7fe2f192018-01-30 16:01:30 +01001428 if (priv->clock != mmc->clock)
1429 omap_hsmmc_set_clock(mmc);
Jaehoon Chungb6cd1d32016-12-30 15:30:16 +09001430
Kishon Vijay Abraham Ie1f25c02018-01-30 16:01:45 +01001431 if (mmc->clk_disable)
1432 omap_hsmmc_stop_clock(mmc_base);
1433 else
1434 omap_hsmmc_start_clock(mmc_base);
1435
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +01001436#if CONFIG_IS_ENABLED(DM_MMC)
1437 if (priv->mode != mmc->selected_mode)
1438 omap_hsmmc_set_timing(mmc);
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001439
1440#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
1441 if (priv->signal_voltage != mmc->signal_voltage)
1442 ret = omap_hsmmc_set_signal_voltage(mmc);
Jean-Jacques Hiblotcf38d4e2018-01-30 16:01:33 +01001443#endif
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001444#endif
1445 return ret;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001446}
1447
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001448#ifdef OMAP_HSMMC_USE_GPIO
Simon Glass5f4bd8c2017-07-04 13:31:19 -06001449#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001450static int omap_hsmmc_getcd(struct udevice *dev)
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001451{
Adam Ford6122af42018-08-21 07:16:56 -05001452 int value = -1;
1453#if CONFIG_IS_ENABLED(DM_GPIO)
Adam Fordac740ff2018-09-08 08:16:23 -05001454 struct omap_hsmmc_data *priv = dev_get_priv(dev);
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301455 value = dm_gpio_get_value(&priv->cd_gpio);
Adam Ford6122af42018-08-21 07:16:56 -05001456#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301457 /* if no CD return as 1 */
1458 if (value < 0)
1459 return 1;
1460
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301461 return value;
1462}
1463
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001464static int omap_hsmmc_getwp(struct udevice *dev)
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301465{
Adam Ford6122af42018-08-21 07:16:56 -05001466 int value = 0;
1467#if CONFIG_IS_ENABLED(DM_GPIO)
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001468 struct omap_hsmmc_data *priv = dev_get_priv(dev);
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301469 value = dm_gpio_get_value(&priv->wp_gpio);
Adam Ford6122af42018-08-21 07:16:56 -05001470#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301471 /* if no WP return as 0 */
1472 if (value < 0)
1473 return 0;
1474 return value;
1475}
1476#else
1477static int omap_hsmmc_getcd(struct mmc *mmc)
1478{
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001479 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001480 int cd_gpio;
1481
1482 /* if no CD return as 1 */
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001483 cd_gpio = priv->cd_gpio;
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001484 if (cd_gpio < 0)
1485 return 1;
1486
Igor Grinberg2f4e0952014-11-03 11:32:23 +02001487 /* NOTE: assumes card detect signal is active-low */
1488 return !gpio_get_value(cd_gpio);
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001489}
1490
1491static int omap_hsmmc_getwp(struct mmc *mmc)
1492{
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001493 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001494 int wp_gpio;
1495
1496 /* if no WP return as 0 */
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001497 wp_gpio = priv->wp_gpio;
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001498 if (wp_gpio < 0)
1499 return 0;
1500
Igor Grinberg2f4e0952014-11-03 11:32:23 +02001501 /* NOTE: assumes write protect signal is active-high */
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001502 return gpio_get_value(wp_gpio);
1503}
1504#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301505#endif
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001506
Simon Glass5f4bd8c2017-07-04 13:31:19 -06001507#if CONFIG_IS_ENABLED(DM_MMC)
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001508static const struct dm_mmc_ops omap_hsmmc_ops = {
1509 .send_cmd = omap_hsmmc_send_cmd,
1510 .set_ios = omap_hsmmc_set_ios,
1511#ifdef OMAP_HSMMC_USE_GPIO
1512 .get_cd = omap_hsmmc_getcd,
1513 .get_wp = omap_hsmmc_getwp,
1514#endif
Jean-Jacques Hiblotf0f821b2018-01-30 16:01:35 +01001515#ifdef MMC_SUPPORTS_TUNING
1516 .execute_tuning = omap_hsmmc_execute_tuning,
1517#endif
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001518 .wait_dat0 = omap_hsmmc_wait_dat0,
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001519};
1520#else
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001521static const struct mmc_ops omap_hsmmc_ops = {
1522 .send_cmd = omap_hsmmc_send_cmd,
1523 .set_ios = omap_hsmmc_set_ios,
1524 .init = omap_hsmmc_init_setup,
1525#ifdef OMAP_HSMMC_USE_GPIO
1526 .getcd = omap_hsmmc_getcd,
1527 .getwp = omap_hsmmc_getwp,
1528#endif
1529};
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02001530#endif
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001531
Simon Glass5f4bd8c2017-07-04 13:31:19 -06001532#if !CONFIG_IS_ENABLED(DM_MMC)
Nikita Kiryanov4be9dbc2012-12-03 02:19:47 +00001533int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
1534 int wp_gpio)
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001535{
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001536 struct mmc *mmc;
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001537 struct omap_hsmmc_data *priv;
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001538 struct mmc_config *cfg;
1539 uint host_caps_val;
1540
Alex Kiernan4b9cb772018-02-09 15:24:38 +00001541 priv = calloc(1, sizeof(*priv));
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001542 if (priv == NULL)
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001543 return -1;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001544
Rob Herring5fd3edd2015-03-23 17:56:59 -05001545 host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001546
1547 switch (dev_index) {
1548 case 0:
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001549 priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001550 break;
Tom Rinifd6e2942011-10-12 06:20:50 +00001551#ifdef OMAP_HSMMC2_BASE
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001552 case 1:
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001553 priv->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
Lubomir Popov19df4122013-08-14 18:59:18 +03001554#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
Nishanth Menon813fe9d2016-11-29 15:22:00 +05301555 defined(CONFIG_DRA7XX) || defined(CONFIG_AM33XX) || \
Roger Quadros44157de2015-09-19 16:26:53 +05301556 defined(CONFIG_AM43XX) || defined(CONFIG_SOC_KEYSTONE)) && \
1557 defined(CONFIG_HSMMC2_8BIT)
Lubomir Popov19df4122013-08-14 18:59:18 +03001558 /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */
1559 host_caps_val |= MMC_MODE_8BIT;
1560#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001561 break;
Tom Rinifd6e2942011-10-12 06:20:50 +00001562#endif
1563#ifdef OMAP_HSMMC3_BASE
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001564 case 2:
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001565 priv->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
Nishanth Menon813fe9d2016-11-29 15:22:00 +05301566#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT)
Lubomir Popov19df4122013-08-14 18:59:18 +03001567 /* Enable 8-bit interface for eMMC on DRA7XX */
1568 host_caps_val |= MMC_MODE_8BIT;
1569#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001570 break;
Tom Rinifd6e2942011-10-12 06:20:50 +00001571#endif
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001572 default:
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001573 priv->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001574 return 1;
1575 }
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001576#ifdef OMAP_HSMMC_USE_GPIO
1577 /* on error gpio values are set to -1, which is what we want */
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001578 priv->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
1579 priv->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
Pantelis Antoniouc9e75912014-02-26 19:28:45 +02001580#endif
Peter Korsgaard47c6b2a2013-03-21 04:00:04 +00001581
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001582 cfg = &priv->cfg;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001583
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001584 cfg->name = "OMAP SD/MMC";
1585 cfg->ops = &omap_hsmmc_ops;
1586
1587 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
1588 cfg->host_caps = host_caps_val & ~host_caps_mask;
1589
1590 cfg->f_min = 400000;
Jonathan Solnita9b05562012-02-24 11:30:18 +00001591
1592 if (f_max != 0)
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001593 cfg->f_max = f_max;
Jonathan Solnita9b05562012-02-24 11:30:18 +00001594 else {
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001595 if (cfg->host_caps & MMC_MODE_HS) {
1596 if (cfg->host_caps & MMC_MODE_HS_52MHz)
1597 cfg->f_max = 52000000;
Jonathan Solnita9b05562012-02-24 11:30:18 +00001598 else
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001599 cfg->f_max = 26000000;
Jonathan Solnita9b05562012-02-24 11:30:18 +00001600 } else
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001601 cfg->f_max = 20000000;
Jonathan Solnita9b05562012-02-24 11:30:18 +00001602 }
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001603
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001604 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
John Rigbyf2f43662011-04-18 05:50:08 +00001605
John Rigby91fcc4b2011-04-19 05:48:14 +00001606#if defined(CONFIG_OMAP34XX)
1607 /*
1608 * Silicon revs 2.1 and older do not support multiblock transfers.
1609 */
1610 if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001611 cfg->b_max = 1;
John Rigby91fcc4b2011-04-19 05:48:14 +00001612#endif
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001613
Jean-Jacques Hiblotd58ef8e2017-03-22 16:00:31 +01001614 mmc = mmc_create(cfg, priv);
Pantelis Antoniou2c850462014-03-11 19:34:20 +02001615 if (mmc == NULL)
1616 return -1;
Sukumar Ghoraic53f5e52010-09-18 20:32:33 -07001617
1618 return 0;
1619}
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301620#else
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001621
1622#ifdef CONFIG_IODELAY_RECALIBRATION
1623static struct pad_conf_entry *
1624omap_hsmmc_get_pad_conf_entry(const fdt32_t *pinctrl, int count)
1625{
1626 int index = 0;
1627 struct pad_conf_entry *padconf;
1628
1629 padconf = (struct pad_conf_entry *)malloc(sizeof(*padconf) * count);
1630 if (!padconf) {
1631 debug("failed to allocate memory\n");
1632 return 0;
1633 }
1634
1635 while (index < count) {
1636 padconf[index].offset = fdt32_to_cpu(pinctrl[2 * index]);
1637 padconf[index].val = fdt32_to_cpu(pinctrl[2 * index + 1]);
1638 index++;
1639 }
1640
1641 return padconf;
1642}
1643
1644static struct iodelay_cfg_entry *
1645omap_hsmmc_get_iodelay_cfg_entry(const fdt32_t *pinctrl, int count)
1646{
1647 int index = 0;
1648 struct iodelay_cfg_entry *iodelay;
1649
1650 iodelay = (struct iodelay_cfg_entry *)malloc(sizeof(*iodelay) * count);
1651 if (!iodelay) {
1652 debug("failed to allocate memory\n");
1653 return 0;
1654 }
1655
1656 while (index < count) {
1657 iodelay[index].offset = fdt32_to_cpu(pinctrl[3 * index]);
1658 iodelay[index].a_delay = fdt32_to_cpu(pinctrl[3 * index + 1]);
1659 iodelay[index].g_delay = fdt32_to_cpu(pinctrl[3 * index + 2]);
1660 index++;
1661 }
1662
1663 return iodelay;
1664}
1665
1666static const fdt32_t *omap_hsmmc_get_pinctrl_entry(u32 phandle,
1667 const char *name, int *len)
1668{
1669 const void *fdt = gd->fdt_blob;
1670 int offset;
1671 const fdt32_t *pinctrl;
1672
1673 offset = fdt_node_offset_by_phandle(fdt, phandle);
1674 if (offset < 0) {
1675 debug("failed to get pinctrl node %s.\n",
1676 fdt_strerror(offset));
1677 return 0;
1678 }
1679
1680 pinctrl = fdt_getprop(fdt, offset, name, len);
1681 if (!pinctrl) {
1682 debug("failed to get property %s\n", name);
1683 return 0;
1684 }
1685
1686 return pinctrl;
1687}
1688
1689static uint32_t omap_hsmmc_get_pad_conf_phandle(struct mmc *mmc,
1690 char *prop_name)
1691{
1692 const void *fdt = gd->fdt_blob;
1693 const __be32 *phandle;
1694 int node = dev_of_offset(mmc->dev);
1695
1696 phandle = fdt_getprop(fdt, node, prop_name, NULL);
1697 if (!phandle) {
1698 debug("failed to get property %s\n", prop_name);
1699 return 0;
1700 }
1701
1702 return fdt32_to_cpu(*phandle);
1703}
1704
1705static uint32_t omap_hsmmc_get_iodelay_phandle(struct mmc *mmc,
1706 char *prop_name)
1707{
1708 const void *fdt = gd->fdt_blob;
1709 const __be32 *phandle;
1710 int len;
1711 int count;
1712 int node = dev_of_offset(mmc->dev);
1713
1714 phandle = fdt_getprop(fdt, node, prop_name, &len);
1715 if (!phandle) {
1716 debug("failed to get property %s\n", prop_name);
1717 return 0;
1718 }
1719
1720 /* No manual mode iodelay values if count < 2 */
1721 count = len / sizeof(*phandle);
1722 if (count < 2)
1723 return 0;
1724
1725 return fdt32_to_cpu(*(phandle + 1));
1726}
1727
1728static struct pad_conf_entry *
1729omap_hsmmc_get_pad_conf(struct mmc *mmc, char *prop_name, int *npads)
1730{
1731 int len;
1732 int count;
1733 struct pad_conf_entry *padconf;
1734 u32 phandle;
1735 const fdt32_t *pinctrl;
1736
1737 phandle = omap_hsmmc_get_pad_conf_phandle(mmc, prop_name);
1738 if (!phandle)
1739 return ERR_PTR(-EINVAL);
1740
1741 pinctrl = omap_hsmmc_get_pinctrl_entry(phandle, "pinctrl-single,pins",
1742 &len);
1743 if (!pinctrl)
1744 return ERR_PTR(-EINVAL);
1745
1746 count = (len / sizeof(*pinctrl)) / 2;
1747 padconf = omap_hsmmc_get_pad_conf_entry(pinctrl, count);
1748 if (!padconf)
1749 return ERR_PTR(-EINVAL);
1750
1751 *npads = count;
1752
1753 return padconf;
1754}
1755
1756static struct iodelay_cfg_entry *
1757omap_hsmmc_get_iodelay(struct mmc *mmc, char *prop_name, int *niodelay)
1758{
1759 int len;
1760 int count;
1761 struct iodelay_cfg_entry *iodelay;
1762 u32 phandle;
1763 const fdt32_t *pinctrl;
1764
1765 phandle = omap_hsmmc_get_iodelay_phandle(mmc, prop_name);
1766 /* Not all modes have manual mode iodelay values. So its not fatal */
1767 if (!phandle)
1768 return 0;
1769
1770 pinctrl = omap_hsmmc_get_pinctrl_entry(phandle, "pinctrl-pin-array",
1771 &len);
1772 if (!pinctrl)
1773 return ERR_PTR(-EINVAL);
1774
1775 count = (len / sizeof(*pinctrl)) / 3;
1776 iodelay = omap_hsmmc_get_iodelay_cfg_entry(pinctrl, count);
1777 if (!iodelay)
1778 return ERR_PTR(-EINVAL);
1779
1780 *niodelay = count;
1781
1782 return iodelay;
1783}
1784
1785static struct omap_hsmmc_pinctrl_state *
1786omap_hsmmc_get_pinctrl_by_mode(struct mmc *mmc, char *mode)
1787{
1788 int index;
1789 int npads = 0;
1790 int niodelays = 0;
1791 const void *fdt = gd->fdt_blob;
1792 int node = dev_of_offset(mmc->dev);
1793 char prop_name[11];
1794 struct omap_hsmmc_pinctrl_state *pinctrl_state;
1795
1796 pinctrl_state = (struct omap_hsmmc_pinctrl_state *)
1797 malloc(sizeof(*pinctrl_state));
1798 if (!pinctrl_state) {
1799 debug("failed to allocate memory\n");
1800 return 0;
1801 }
1802
1803 index = fdt_stringlist_search(fdt, node, "pinctrl-names", mode);
1804 if (index < 0) {
1805 debug("fail to find %s mode %s\n", mode, fdt_strerror(index));
1806 goto err_pinctrl_state;
1807 }
1808
1809 sprintf(prop_name, "pinctrl-%d", index);
1810
1811 pinctrl_state->padconf = omap_hsmmc_get_pad_conf(mmc, prop_name,
1812 &npads);
1813 if (IS_ERR(pinctrl_state->padconf))
1814 goto err_pinctrl_state;
1815 pinctrl_state->npads = npads;
1816
1817 pinctrl_state->iodelay = omap_hsmmc_get_iodelay(mmc, prop_name,
1818 &niodelays);
1819 if (IS_ERR(pinctrl_state->iodelay))
1820 goto err_padconf;
1821 pinctrl_state->niodelays = niodelays;
1822
1823 return pinctrl_state;
1824
1825err_padconf:
1826 kfree(pinctrl_state->padconf);
1827
1828err_pinctrl_state:
1829 kfree(pinctrl_state);
1830 return 0;
1831}
1832
Jean-Jacques Hiblotdae1ad42018-01-30 16:01:42 +01001833#define OMAP_HSMMC_SETUP_PINCTRL(capmask, mode, optional) \
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001834 do { \
1835 struct omap_hsmmc_pinctrl_state *s = NULL; \
1836 char str[20]; \
1837 if (!(cfg->host_caps & capmask)) \
1838 break; \
1839 \
1840 if (priv->hw_rev) { \
1841 sprintf(str, "%s-%s", #mode, priv->hw_rev); \
1842 s = omap_hsmmc_get_pinctrl_by_mode(mmc, str); \
1843 } \
1844 \
1845 if (!s) \
1846 s = omap_hsmmc_get_pinctrl_by_mode(mmc, #mode); \
1847 \
Jean-Jacques Hiblotdae1ad42018-01-30 16:01:42 +01001848 if (!s && !optional) { \
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001849 debug("%s: no pinctrl for %s\n", \
1850 mmc->dev->name, #mode); \
1851 cfg->host_caps &= ~(capmask); \
1852 } else { \
1853 priv->mode##_pinctrl_state = s; \
1854 } \
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001855 } while (0)
1856
1857static int omap_hsmmc_get_pinctrl_state(struct mmc *mmc)
1858{
1859 struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
1860 struct mmc_config *cfg = omap_hsmmc_get_cfg(mmc);
1861 struct omap_hsmmc_pinctrl_state *default_pinctrl;
1862
1863 if (!(priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY))
1864 return 0;
1865
1866 default_pinctrl = omap_hsmmc_get_pinctrl_by_mode(mmc, "default");
1867 if (!default_pinctrl) {
1868 printf("no pinctrl state for default mode\n");
1869 return -EINVAL;
1870 }
1871
1872 priv->default_pinctrl_state = default_pinctrl;
1873
Jean-Jacques Hiblotdae1ad42018-01-30 16:01:42 +01001874 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR104), sdr104, false);
1875 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR50), sdr50, false);
1876 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_DDR50), ddr50, false);
1877 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR25), sdr25, false);
1878 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR12), sdr12, false);
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001879
Jean-Jacques Hiblotdae1ad42018-01-30 16:01:42 +01001880 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(MMC_HS_200), hs200_1_8v, false);
1881 OMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(MMC_DDR_52), ddr_1_8v, false);
1882 OMAP_HSMMC_SETUP_PINCTRL(MMC_MODE_HS, hs, true);
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001883
1884 return 0;
1885}
1886#endif
1887
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05301888#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001889#ifdef CONFIG_OMAP54XX
1890__weak const struct mmc_platform_fixups *platform_fixups_mmc(uint32_t addr)
1891{
1892 return NULL;
1893}
1894#endif
1895
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301896static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
1897{
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +01001898 struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001899 struct omap_mmc_of_data *of_data = (void *)dev_get_driver_data(dev);
1900
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +01001901 struct mmc_config *cfg = &plat->cfg;
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001902#ifdef CONFIG_OMAP54XX
1903 const struct mmc_platform_fixups *fixups;
1904#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301905 const void *fdt = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -07001906 int node = dev_of_offset(dev);
Kishon Vijay Abraham I569c3d52018-01-30 16:01:38 +01001907 int ret;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301908
Simon Glassba1dea42017-05-17 17:18:05 -06001909 plat->base_addr = map_physmem(devfdt_get_addr(dev),
1910 sizeof(struct hsmmc *),
Jean-Jacques Hiblot3d45bb42017-09-21 16:51:32 +02001911 MAP_NOCACHE);
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301912
Kishon Vijay Abraham I569c3d52018-01-30 16:01:38 +01001913 ret = mmc_of_parse(dev, cfg);
1914 if (ret < 0)
1915 return ret;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301916
Jean-Jacques Hiblot8e2bdbd2018-02-23 10:40:19 +01001917 if (!cfg->f_max)
1918 cfg->f_max = 52000000;
Kishon Vijay Abraham I569c3d52018-01-30 16:01:38 +01001919 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301920 cfg->f_min = 400000;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301921 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
1922 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
Kishon Vijay Abraham I73897ed2018-01-30 16:01:32 +01001923 if (fdtdec_get_bool(fdt, node, "ti,dual-volt"))
1924 plat->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
1925 if (fdtdec_get_bool(fdt, node, "no-1-8-v"))
1926 plat->controller_flags |= OMAP_HSMMC_NO_1_8_V;
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001927 if (of_data)
1928 plat->controller_flags |= of_data->controller_flags;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301929
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001930#ifdef CONFIG_OMAP54XX
1931 fixups = platform_fixups_mmc(devfdt_get_addr(dev));
1932 if (fixups) {
1933 plat->hw_rev = fixups->hw_rev;
1934 cfg->host_caps &= ~fixups->unsupported_caps;
1935 cfg->f_max = fixups->max_freq;
1936 }
1937#endif
1938
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301939 return 0;
1940}
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05301941#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301942
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01001943#ifdef CONFIG_BLK
1944
1945static int omap_hsmmc_bind(struct udevice *dev)
1946{
1947 struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
Jean-Jacques Hiblot4cb36a22018-02-23 10:40:16 +01001948 plat->mmc = calloc(1, sizeof(struct mmc));
1949 return mmc_bind(dev, plat->mmc, &plat->cfg);
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01001950}
1951#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301952static int omap_hsmmc_probe(struct udevice *dev)
1953{
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +01001954 struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301955 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
1956 struct omap_hsmmc_data *priv = dev_get_priv(dev);
Jean-Jacques Hiblotae51a662017-03-22 16:00:33 +01001957 struct mmc_config *cfg = &plat->cfg;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301958 struct mmc *mmc;
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001959#ifdef CONFIG_IODELAY_RECALIBRATION
1960 int ret;
1961#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301962
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301963 cfg->name = "OMAP SD/MMC";
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05301964 priv->base_addr = plat->base_addr;
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001965 priv->controller_flags = plat->controller_flags;
Kishon Vijay Abraham I8c2efe92018-01-30 16:01:41 +01001966 priv->hw_rev = plat->hw_rev;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301967
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01001968#ifdef CONFIG_BLK
Jean-Jacques Hiblot4cb36a22018-02-23 10:40:16 +01001969 mmc = plat->mmc;
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01001970#else
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301971 mmc = mmc_create(cfg, priv);
1972 if (mmc == NULL)
1973 return -1;
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01001974#endif
Jean-Jacques Hiblot7a41bb42018-01-30 16:01:46 +01001975#if CONFIG_IS_ENABLED(DM_REGULATOR)
1976 device_get_supply_regulator(dev, "pbias-supply",
1977 &priv->pbias_supply);
1978#endif
Adam Ford6122af42018-08-21 07:16:56 -05001979#if defined(OMAP_HSMMC_USE_GPIO)
1980#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_GPIO)
Mugunthan V Na9a0aa72016-04-04 17:28:01 +05301981 gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
1982 gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN);
1983#endif
Adam Ford6122af42018-08-21 07:16:56 -05001984#endif
Mugunthan V Na9a0aa72016-04-04 17:28:01 +05301985
Simon Glass77ca42b2016-05-01 13:52:34 -06001986 mmc->dev = dev;
Mugunthan V Nd97631a2015-09-28 12:56:30 +05301987 upriv->mmc = mmc;
1988
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01001989#ifdef CONFIG_IODELAY_RECALIBRATION
1990 ret = omap_hsmmc_get_pinctrl_state(mmc);
1991 /*
1992 * disable high speed modes for the platforms that require IO delay
1993 * and for which we don't have this information
1994 */
1995 if ((ret < 0) &&
1996 (priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY)) {
1997 priv->controller_flags &= ~OMAP_HSMMC_REQUIRE_IODELAY;
1998 cfg->host_caps &= ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_DDR_52) |
1999 UHS_CAPS);
2000 }
2001#endif
2002
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02002003 return omap_hsmmc_init_setup(mmc);
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302004}
2005
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05302006#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01002007
2008static const struct omap_mmc_of_data dra7_mmc_of_data = {
2009 .controller_flags = OMAP_HSMMC_REQUIRE_IODELAY,
2010};
2011
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302012static const struct udevice_id omap_hsmmc_ids[] = {
Jean-Jacques Hiblot3d45bb42017-09-21 16:51:32 +02002013 { .compatible = "ti,omap3-hsmmc" },
2014 { .compatible = "ti,omap4-hsmmc" },
2015 { .compatible = "ti,am33xx-hsmmc" },
Kishon Vijay Abraham Ie7da6ac2018-01-30 16:01:40 +01002016 { .compatible = "ti,dra7-hsmmc", .data = (ulong)&dra7_mmc_of_data },
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302017 { }
2018};
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05302019#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302020
2021U_BOOT_DRIVER(omap_hsmmc) = {
2022 .name = "omap_hsmmc",
2023 .id = UCLASS_MMC,
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05302024#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302025 .of_match = omap_hsmmc_ids,
2026 .ofdata_to_platdata = omap_hsmmc_ofdata_to_platdata,
Lokesh Vutla9a696fb2017-04-26 13:37:05 +05302027 .platdata_auto_alloc_size = sizeof(struct omap_hsmmc_plat),
2028#endif
Jean-Jacques Hiblota3c556c2017-03-22 16:00:34 +01002029#ifdef CONFIG_BLK
2030 .bind = omap_hsmmc_bind,
2031#endif
Jean-Jacques Hiblot8fc9d3a2017-04-14 19:50:02 +02002032 .ops = &omap_hsmmc_ops,
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302033 .probe = omap_hsmmc_probe,
2034 .priv_auto_alloc_size = sizeof(struct omap_hsmmc_data),
Bin Meng793260a2018-10-24 06:36:32 -07002035#if !CONFIG_IS_ENABLED(OF_CONTROL)
Lokesh Vutlac38e6452017-04-26 13:37:06 +05302036 .flags = DM_FLAG_PRE_RELOC,
Bin Meng793260a2018-10-24 06:36:32 -07002037#endif
Mugunthan V Nd97631a2015-09-28 12:56:30 +05302038};
2039#endif