Commit 8809d6e036d740e6740e99bf55d34d90aa90a5b2
1 parent
dd8a14dd46
Exists in
smarc_8mq-imx_v2020.04_5.4.24_2.1.0
and in
1 other branch
MLK-24188-2 mmc: fsl_esdhc_imx: enable AHB/IPG clk
Only enable PER clk is not enough, we also need to enable AHB/IPG clk. Reviewed-by: Ye Li <ye.li@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com> (cherry picked from commit 867c5f2a706e6ee72fd263de02125c97acde89e1)
Showing 1 changed file with 20 additions and 0 deletions Inline Diff
drivers/mmc/fsl_esdhc_imx.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc | 3 | * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc |
4 | * Copyright 2019 NXP Semiconductors | 4 | * Copyright 2019 NXP Semiconductors |
5 | * Andy Fleming | 5 | * Andy Fleming |
6 | * Yangbo Lu <yangbo.lu@nxp.com> | 6 | * Yangbo Lu <yangbo.lu@nxp.com> |
7 | * | 7 | * |
8 | * Based vaguely on the pxa mmc code: | 8 | * Based vaguely on the pxa mmc code: |
9 | * (C) Copyright 2003 | 9 | * (C) Copyright 2003 |
10 | * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net | 10 | * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <config.h> | 13 | #include <config.h> |
14 | #include <common.h> | 14 | #include <common.h> |
15 | #include <command.h> | 15 | #include <command.h> |
16 | #include <clk.h> | 16 | #include <clk.h> |
17 | #include <cpu_func.h> | 17 | #include <cpu_func.h> |
18 | #include <errno.h> | 18 | #include <errno.h> |
19 | #include <hwconfig.h> | 19 | #include <hwconfig.h> |
20 | #include <mmc.h> | 20 | #include <mmc.h> |
21 | #include <part.h> | 21 | #include <part.h> |
22 | #include <dm/device_compat.h> | 22 | #include <dm/device_compat.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <power/regulator.h> | 24 | #include <power/regulator.h> |
25 | #include <malloc.h> | 25 | #include <malloc.h> |
26 | #include <fsl_esdhc_imx.h> | 26 | #include <fsl_esdhc_imx.h> |
27 | #include <fdt_support.h> | 27 | #include <fdt_support.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | #include <dm.h> | 29 | #include <dm.h> |
30 | #include <asm-generic/gpio.h> | 30 | #include <asm-generic/gpio.h> |
31 | #include <dm/pinctrl.h> | 31 | #include <dm/pinctrl.h> |
32 | #include <asm/arch/sys_proto.h> | 32 | #include <asm/arch/sys_proto.h> |
33 | 33 | ||
34 | #if !CONFIG_IS_ENABLED(BLK) | 34 | #if !CONFIG_IS_ENABLED(BLK) |
35 | #include "mmc_private.h" | 35 | #include "mmc_private.h" |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | DECLARE_GLOBAL_DATA_PTR; | 38 | DECLARE_GLOBAL_DATA_PTR; |
39 | 39 | ||
40 | #define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \ | 40 | #define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \ |
41 | IRQSTATEN_CINT | \ | 41 | IRQSTATEN_CINT | \ |
42 | IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \ | 42 | IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \ |
43 | IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \ | 43 | IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \ |
44 | IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \ | 44 | IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \ |
45 | IRQSTATEN_DINT) | 45 | IRQSTATEN_DINT) |
46 | #define MAX_TUNING_LOOP 40 | 46 | #define MAX_TUNING_LOOP 40 |
47 | #define ESDHC_DRIVER_STAGE_VALUE 0xffffffff | 47 | #define ESDHC_DRIVER_STAGE_VALUE 0xffffffff |
48 | 48 | ||
49 | struct fsl_esdhc { | 49 | struct fsl_esdhc { |
50 | uint dsaddr; /* SDMA system address register */ | 50 | uint dsaddr; /* SDMA system address register */ |
51 | uint blkattr; /* Block attributes register */ | 51 | uint blkattr; /* Block attributes register */ |
52 | uint cmdarg; /* Command argument register */ | 52 | uint cmdarg; /* Command argument register */ |
53 | uint xfertyp; /* Transfer type register */ | 53 | uint xfertyp; /* Transfer type register */ |
54 | uint cmdrsp0; /* Command response 0 register */ | 54 | uint cmdrsp0; /* Command response 0 register */ |
55 | uint cmdrsp1; /* Command response 1 register */ | 55 | uint cmdrsp1; /* Command response 1 register */ |
56 | uint cmdrsp2; /* Command response 2 register */ | 56 | uint cmdrsp2; /* Command response 2 register */ |
57 | uint cmdrsp3; /* Command response 3 register */ | 57 | uint cmdrsp3; /* Command response 3 register */ |
58 | uint datport; /* Buffer data port register */ | 58 | uint datport; /* Buffer data port register */ |
59 | uint prsstat; /* Present state register */ | 59 | uint prsstat; /* Present state register */ |
60 | uint proctl; /* Protocol control register */ | 60 | uint proctl; /* Protocol control register */ |
61 | uint sysctl; /* System Control Register */ | 61 | uint sysctl; /* System Control Register */ |
62 | uint irqstat; /* Interrupt status register */ | 62 | uint irqstat; /* Interrupt status register */ |
63 | uint irqstaten; /* Interrupt status enable register */ | 63 | uint irqstaten; /* Interrupt status enable register */ |
64 | uint irqsigen; /* Interrupt signal enable register */ | 64 | uint irqsigen; /* Interrupt signal enable register */ |
65 | uint autoc12err; /* Auto CMD error status register */ | 65 | uint autoc12err; /* Auto CMD error status register */ |
66 | uint hostcapblt; /* Host controller capabilities register */ | 66 | uint hostcapblt; /* Host controller capabilities register */ |
67 | uint wml; /* Watermark level register */ | 67 | uint wml; /* Watermark level register */ |
68 | uint mixctrl; /* For USDHC */ | 68 | uint mixctrl; /* For USDHC */ |
69 | char reserved1[4]; /* reserved */ | 69 | char reserved1[4]; /* reserved */ |
70 | uint fevt; /* Force event register */ | 70 | uint fevt; /* Force event register */ |
71 | uint admaes; /* ADMA error status register */ | 71 | uint admaes; /* ADMA error status register */ |
72 | uint adsaddr; /* ADMA system address register */ | 72 | uint adsaddr; /* ADMA system address register */ |
73 | char reserved2[4]; | 73 | char reserved2[4]; |
74 | uint dllctrl; | 74 | uint dllctrl; |
75 | uint dllstat; | 75 | uint dllstat; |
76 | uint clktunectrlstatus; | 76 | uint clktunectrlstatus; |
77 | char reserved3[4]; | 77 | char reserved3[4]; |
78 | uint strobe_dllctrl; | 78 | uint strobe_dllctrl; |
79 | uint strobe_dllstat; | 79 | uint strobe_dllstat; |
80 | char reserved4[72]; | 80 | char reserved4[72]; |
81 | uint vendorspec; | 81 | uint vendorspec; |
82 | uint mmcboot; | 82 | uint mmcboot; |
83 | uint vendorspec2; | 83 | uint vendorspec2; |
84 | uint tuning_ctrl; /* on i.MX6/7/8/RT */ | 84 | uint tuning_ctrl; /* on i.MX6/7/8/RT */ |
85 | char reserved5[44]; | 85 | char reserved5[44]; |
86 | uint hostver; /* Host controller version register */ | 86 | uint hostver; /* Host controller version register */ |
87 | char reserved6[4]; /* reserved */ | 87 | char reserved6[4]; /* reserved */ |
88 | uint dmaerraddr; /* DMA error address register */ | 88 | uint dmaerraddr; /* DMA error address register */ |
89 | char reserved7[4]; /* reserved */ | 89 | char reserved7[4]; /* reserved */ |
90 | uint dmaerrattr; /* DMA error attribute register */ | 90 | uint dmaerrattr; /* DMA error attribute register */ |
91 | char reserved8[4]; /* reserved */ | 91 | char reserved8[4]; /* reserved */ |
92 | uint hostcapblt2; /* Host controller capabilities register 2 */ | 92 | uint hostcapblt2; /* Host controller capabilities register 2 */ |
93 | char reserved9[8]; /* reserved */ | 93 | char reserved9[8]; /* reserved */ |
94 | uint tcr; /* Tuning control register */ | 94 | uint tcr; /* Tuning control register */ |
95 | char reserved10[28]; /* reserved */ | 95 | char reserved10[28]; /* reserved */ |
96 | uint sddirctl; /* SD direction control register */ | 96 | uint sddirctl; /* SD direction control register */ |
97 | char reserved11[712];/* reserved */ | 97 | char reserved11[712];/* reserved */ |
98 | uint scr; /* eSDHC control register */ | 98 | uint scr; /* eSDHC control register */ |
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct fsl_esdhc_plat { | 101 | struct fsl_esdhc_plat { |
102 | struct mmc_config cfg; | 102 | struct mmc_config cfg; |
103 | struct mmc mmc; | 103 | struct mmc mmc; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | struct esdhc_soc_data { | 106 | struct esdhc_soc_data { |
107 | u32 flags; | 107 | u32 flags; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * struct fsl_esdhc_priv | 111 | * struct fsl_esdhc_priv |
112 | * | 112 | * |
113 | * @esdhc_regs: registers of the sdhc controller | 113 | * @esdhc_regs: registers of the sdhc controller |
114 | * @sdhc_clk: Current clk of the sdhc controller | 114 | * @sdhc_clk: Current clk of the sdhc controller |
115 | * @bus_width: bus width, 1bit, 4bit or 8bit | 115 | * @bus_width: bus width, 1bit, 4bit or 8bit |
116 | * @cfg: mmc config | 116 | * @cfg: mmc config |
117 | * @mmc: mmc | 117 | * @mmc: mmc |
118 | * Following is used when Driver Model is enabled for MMC | 118 | * Following is used when Driver Model is enabled for MMC |
119 | * @dev: pointer for the device | 119 | * @dev: pointer for the device |
120 | * @non_removable: 0: removable; 1: non-removable | 120 | * @non_removable: 0: removable; 1: non-removable |
121 | * @broken_cd: 0: use GPIO for card detect; 1: Do not use GPIO for card detect | 121 | * @broken_cd: 0: use GPIO for card detect; 1: Do not use GPIO for card detect |
122 | * @wp_enable: 1: enable checking wp; 0: no check | 122 | * @wp_enable: 1: enable checking wp; 0: no check |
123 | * @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V | 123 | * @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V |
124 | * @flags: ESDHC_FLAG_xx in include/fsl_esdhc_imx.h | 124 | * @flags: ESDHC_FLAG_xx in include/fsl_esdhc_imx.h |
125 | * @caps: controller capabilities | 125 | * @caps: controller capabilities |
126 | * @tuning_step: tuning step setting in tuning_ctrl register | 126 | * @tuning_step: tuning step setting in tuning_ctrl register |
127 | * @start_tuning_tap: the start point for tuning in tuning_ctrl register | 127 | * @start_tuning_tap: the start point for tuning in tuning_ctrl register |
128 | * @strobe_dll_delay_target: settings in strobe_dllctrl | 128 | * @strobe_dll_delay_target: settings in strobe_dllctrl |
129 | * @signal_voltage: indicating the current voltage | 129 | * @signal_voltage: indicating the current voltage |
130 | * @cd_gpio: gpio for card detection | 130 | * @cd_gpio: gpio for card detection |
131 | * @wp_gpio: gpio for write protection | 131 | * @wp_gpio: gpio for write protection |
132 | */ | 132 | */ |
133 | struct fsl_esdhc_priv { | 133 | struct fsl_esdhc_priv { |
134 | struct fsl_esdhc *esdhc_regs; | 134 | struct fsl_esdhc *esdhc_regs; |
135 | unsigned int sdhc_clk; | 135 | unsigned int sdhc_clk; |
136 | struct clk per_clk; | 136 | struct clk per_clk; |
137 | struct clk ipg_clk; | ||
138 | struct clk ahb_clk; | ||
137 | unsigned int clock; | 139 | unsigned int clock; |
138 | unsigned int mode; | 140 | unsigned int mode; |
139 | unsigned int bus_width; | 141 | unsigned int bus_width; |
140 | #if !CONFIG_IS_ENABLED(BLK) | 142 | #if !CONFIG_IS_ENABLED(BLK) |
141 | struct mmc *mmc; | 143 | struct mmc *mmc; |
142 | #endif | 144 | #endif |
143 | struct udevice *dev; | 145 | struct udevice *dev; |
144 | int non_removable; | 146 | int non_removable; |
145 | int broken_cd; | 147 | int broken_cd; |
146 | int wp_enable; | 148 | int wp_enable; |
147 | int vs18_enable; | 149 | int vs18_enable; |
148 | u32 flags; | 150 | u32 flags; |
149 | u32 caps; | 151 | u32 caps; |
150 | u32 tuning_step; | 152 | u32 tuning_step; |
151 | u32 tuning_start_tap; | 153 | u32 tuning_start_tap; |
152 | u32 strobe_dll_delay_target; | 154 | u32 strobe_dll_delay_target; |
153 | u32 signal_voltage; | 155 | u32 signal_voltage; |
154 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | 156 | #if CONFIG_IS_ENABLED(DM_REGULATOR) |
155 | struct udevice *vqmmc_dev; | 157 | struct udevice *vqmmc_dev; |
156 | struct udevice *vmmc_dev; | 158 | struct udevice *vmmc_dev; |
157 | #endif | 159 | #endif |
158 | #if CONFIG_IS_ENABLED(DM_GPIO) | 160 | #if CONFIG_IS_ENABLED(DM_GPIO) |
159 | struct gpio_desc cd_gpio; | 161 | struct gpio_desc cd_gpio; |
160 | struct gpio_desc wp_gpio; | 162 | struct gpio_desc wp_gpio; |
161 | #endif | 163 | #endif |
162 | }; | 164 | }; |
163 | 165 | ||
164 | /* Return the XFERTYP flags for a given command and data packet */ | 166 | /* Return the XFERTYP flags for a given command and data packet */ |
165 | static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) | 167 | static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) |
166 | { | 168 | { |
167 | uint xfertyp = 0; | 169 | uint xfertyp = 0; |
168 | 170 | ||
169 | if (data) { | 171 | if (data) { |
170 | xfertyp |= XFERTYP_DPSEL; | 172 | xfertyp |= XFERTYP_DPSEL; |
171 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO | 173 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
172 | xfertyp |= XFERTYP_DMAEN; | 174 | xfertyp |= XFERTYP_DMAEN; |
173 | #endif | 175 | #endif |
174 | if (data->blocks > 1) { | 176 | if (data->blocks > 1) { |
175 | xfertyp |= XFERTYP_MSBSEL; | 177 | xfertyp |= XFERTYP_MSBSEL; |
176 | xfertyp |= XFERTYP_BCEN; | 178 | xfertyp |= XFERTYP_BCEN; |
177 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 | 179 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 |
178 | xfertyp |= XFERTYP_AC12EN; | 180 | xfertyp |= XFERTYP_AC12EN; |
179 | #endif | 181 | #endif |
180 | } | 182 | } |
181 | 183 | ||
182 | if (data->flags & MMC_DATA_READ) | 184 | if (data->flags & MMC_DATA_READ) |
183 | xfertyp |= XFERTYP_DTDSEL; | 185 | xfertyp |= XFERTYP_DTDSEL; |
184 | } | 186 | } |
185 | 187 | ||
186 | if (cmd->resp_type & MMC_RSP_CRC) | 188 | if (cmd->resp_type & MMC_RSP_CRC) |
187 | xfertyp |= XFERTYP_CCCEN; | 189 | xfertyp |= XFERTYP_CCCEN; |
188 | if (cmd->resp_type & MMC_RSP_OPCODE) | 190 | if (cmd->resp_type & MMC_RSP_OPCODE) |
189 | xfertyp |= XFERTYP_CICEN; | 191 | xfertyp |= XFERTYP_CICEN; |
190 | if (cmd->resp_type & MMC_RSP_136) | 192 | if (cmd->resp_type & MMC_RSP_136) |
191 | xfertyp |= XFERTYP_RSPTYP_136; | 193 | xfertyp |= XFERTYP_RSPTYP_136; |
192 | else if (cmd->resp_type & MMC_RSP_BUSY) | 194 | else if (cmd->resp_type & MMC_RSP_BUSY) |
193 | xfertyp |= XFERTYP_RSPTYP_48_BUSY; | 195 | xfertyp |= XFERTYP_RSPTYP_48_BUSY; |
194 | else if (cmd->resp_type & MMC_RSP_PRESENT) | 196 | else if (cmd->resp_type & MMC_RSP_PRESENT) |
195 | xfertyp |= XFERTYP_RSPTYP_48; | 197 | xfertyp |= XFERTYP_RSPTYP_48; |
196 | 198 | ||
197 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) | 199 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) |
198 | xfertyp |= XFERTYP_CMDTYP_ABORT; | 200 | xfertyp |= XFERTYP_CMDTYP_ABORT; |
199 | 201 | ||
200 | return XFERTYP_CMD(cmd->cmdidx) | xfertyp; | 202 | return XFERTYP_CMD(cmd->cmdidx) | xfertyp; |
201 | } | 203 | } |
202 | 204 | ||
203 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO | 205 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO |
204 | /* | 206 | /* |
205 | * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. | 207 | * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. |
206 | */ | 208 | */ |
207 | static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv, | 209 | static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv, |
208 | struct mmc_data *data) | 210 | struct mmc_data *data) |
209 | { | 211 | { |
210 | struct fsl_esdhc *regs = priv->esdhc_regs; | 212 | struct fsl_esdhc *regs = priv->esdhc_regs; |
211 | uint blocks; | 213 | uint blocks; |
212 | char *buffer; | 214 | char *buffer; |
213 | uint databuf; | 215 | uint databuf; |
214 | uint size; | 216 | uint size; |
215 | uint irqstat; | 217 | uint irqstat; |
216 | ulong start; | 218 | ulong start; |
217 | 219 | ||
218 | if (data->flags & MMC_DATA_READ) { | 220 | if (data->flags & MMC_DATA_READ) { |
219 | blocks = data->blocks; | 221 | blocks = data->blocks; |
220 | buffer = data->dest; | 222 | buffer = data->dest; |
221 | while (blocks) { | 223 | while (blocks) { |
222 | start = get_timer(0); | 224 | start = get_timer(0); |
223 | size = data->blocksize; | 225 | size = data->blocksize; |
224 | irqstat = esdhc_read32(®s->irqstat); | 226 | irqstat = esdhc_read32(®s->irqstat); |
225 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN)) { | 227 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN)) { |
226 | if (get_timer(start) > PIO_TIMEOUT) { | 228 | if (get_timer(start) > PIO_TIMEOUT) { |
227 | printf("\nData Read Failed in PIO Mode."); | 229 | printf("\nData Read Failed in PIO Mode."); |
228 | return; | 230 | return; |
229 | } | 231 | } |
230 | } | 232 | } |
231 | while (size && (!(irqstat & IRQSTAT_TC))) { | 233 | while (size && (!(irqstat & IRQSTAT_TC))) { |
232 | udelay(100); /* Wait before last byte transfer complete */ | 234 | udelay(100); /* Wait before last byte transfer complete */ |
233 | irqstat = esdhc_read32(®s->irqstat); | 235 | irqstat = esdhc_read32(®s->irqstat); |
234 | databuf = in_le32(®s->datport); | 236 | databuf = in_le32(®s->datport); |
235 | *((uint *)buffer) = databuf; | 237 | *((uint *)buffer) = databuf; |
236 | buffer += 4; | 238 | buffer += 4; |
237 | size -= 4; | 239 | size -= 4; |
238 | } | 240 | } |
239 | blocks--; | 241 | blocks--; |
240 | } | 242 | } |
241 | } else { | 243 | } else { |
242 | blocks = data->blocks; | 244 | blocks = data->blocks; |
243 | buffer = (char *)data->src; | 245 | buffer = (char *)data->src; |
244 | while (blocks) { | 246 | while (blocks) { |
245 | start = get_timer(0); | 247 | start = get_timer(0); |
246 | size = data->blocksize; | 248 | size = data->blocksize; |
247 | irqstat = esdhc_read32(®s->irqstat); | 249 | irqstat = esdhc_read32(®s->irqstat); |
248 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN)) { | 250 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN)) { |
249 | if (get_timer(start) > PIO_TIMEOUT) { | 251 | if (get_timer(start) > PIO_TIMEOUT) { |
250 | printf("\nData Write Failed in PIO Mode."); | 252 | printf("\nData Write Failed in PIO Mode."); |
251 | return; | 253 | return; |
252 | } | 254 | } |
253 | } | 255 | } |
254 | while (size && (!(irqstat & IRQSTAT_TC))) { | 256 | while (size && (!(irqstat & IRQSTAT_TC))) { |
255 | udelay(100); /* Wait before last byte transfer complete */ | 257 | udelay(100); /* Wait before last byte transfer complete */ |
256 | databuf = *((uint *)buffer); | 258 | databuf = *((uint *)buffer); |
257 | buffer += 4; | 259 | buffer += 4; |
258 | size -= 4; | 260 | size -= 4; |
259 | irqstat = esdhc_read32(®s->irqstat); | 261 | irqstat = esdhc_read32(®s->irqstat); |
260 | out_le32(®s->datport, databuf); | 262 | out_le32(®s->datport, databuf); |
261 | } | 263 | } |
262 | blocks--; | 264 | blocks--; |
263 | } | 265 | } |
264 | } | 266 | } |
265 | } | 267 | } |
266 | #endif | 268 | #endif |
267 | 269 | ||
268 | static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc, | 270 | static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc, |
269 | struct mmc_data *data) | 271 | struct mmc_data *data) |
270 | { | 272 | { |
271 | int timeout; | 273 | int timeout; |
272 | struct fsl_esdhc *regs = priv->esdhc_regs; | 274 | struct fsl_esdhc *regs = priv->esdhc_regs; |
273 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) | 275 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) |
274 | dma_addr_t addr; | 276 | dma_addr_t addr; |
275 | #endif | 277 | #endif |
276 | uint wml_value; | 278 | uint wml_value; |
277 | 279 | ||
278 | wml_value = data->blocksize/4; | 280 | wml_value = data->blocksize/4; |
279 | 281 | ||
280 | if (data->flags & MMC_DATA_READ) { | 282 | if (data->flags & MMC_DATA_READ) { |
281 | if (wml_value > WML_RD_WML_MAX) | 283 | if (wml_value > WML_RD_WML_MAX) |
282 | wml_value = WML_RD_WML_MAX_VAL; | 284 | wml_value = WML_RD_WML_MAX_VAL; |
283 | 285 | ||
284 | esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); | 286 | esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); |
285 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO | 287 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
286 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) | 288 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) |
287 | addr = virt_to_phys((void *)(data->dest)); | 289 | addr = virt_to_phys((void *)(data->dest)); |
288 | if (upper_32_bits(addr)) | 290 | if (upper_32_bits(addr)) |
289 | printf("Error found for upper 32 bits\n"); | 291 | printf("Error found for upper 32 bits\n"); |
290 | else | 292 | else |
291 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); | 293 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); |
292 | #else | 294 | #else |
293 | esdhc_write32(®s->dsaddr, (u32)data->dest); | 295 | esdhc_write32(®s->dsaddr, (u32)data->dest); |
294 | #endif | 296 | #endif |
295 | #endif | 297 | #endif |
296 | } else { | 298 | } else { |
297 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO | 299 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
298 | flush_dcache_range((ulong)data->src, | 300 | flush_dcache_range((ulong)data->src, |
299 | (ulong)data->src+data->blocks | 301 | (ulong)data->src+data->blocks |
300 | *data->blocksize); | 302 | *data->blocksize); |
301 | #endif | 303 | #endif |
302 | if (wml_value > WML_WR_WML_MAX) | 304 | if (wml_value > WML_WR_WML_MAX) |
303 | wml_value = WML_WR_WML_MAX_VAL; | 305 | wml_value = WML_WR_WML_MAX_VAL; |
304 | if (priv->wp_enable) { | 306 | if (priv->wp_enable) { |
305 | if ((esdhc_read32(®s->prsstat) & | 307 | if ((esdhc_read32(®s->prsstat) & |
306 | PRSSTAT_WPSPL) == 0) { | 308 | PRSSTAT_WPSPL) == 0) { |
307 | printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); | 309 | printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); |
308 | return -ETIMEDOUT; | 310 | return -ETIMEDOUT; |
309 | } | 311 | } |
310 | } else { | 312 | } else { |
311 | #if CONFIG_IS_ENABLED(DM_GPIO) | 313 | #if CONFIG_IS_ENABLED(DM_GPIO) |
312 | if (dm_gpio_is_valid(&priv->wp_gpio) && | 314 | if (dm_gpio_is_valid(&priv->wp_gpio) && |
313 | dm_gpio_get_value(&priv->wp_gpio)) { | 315 | dm_gpio_get_value(&priv->wp_gpio)) { |
314 | printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); | 316 | printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); |
315 | return -ETIMEDOUT; | 317 | return -ETIMEDOUT; |
316 | } | 318 | } |
317 | #endif | 319 | #endif |
318 | } | 320 | } |
319 | 321 | ||
320 | esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, | 322 | esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, |
321 | wml_value << 16); | 323 | wml_value << 16); |
322 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO | 324 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
323 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) | 325 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) |
324 | addr = virt_to_phys((void *)(data->src)); | 326 | addr = virt_to_phys((void *)(data->src)); |
325 | if (upper_32_bits(addr)) | 327 | if (upper_32_bits(addr)) |
326 | printf("Error found for upper 32 bits\n"); | 328 | printf("Error found for upper 32 bits\n"); |
327 | else | 329 | else |
328 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); | 330 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); |
329 | #else | 331 | #else |
330 | esdhc_write32(®s->dsaddr, (u32)data->src); | 332 | esdhc_write32(®s->dsaddr, (u32)data->src); |
331 | #endif | 333 | #endif |
332 | #endif | 334 | #endif |
333 | } | 335 | } |
334 | 336 | ||
335 | esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); | 337 | esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); |
336 | 338 | ||
337 | /* Calculate the timeout period for data transactions */ | 339 | /* Calculate the timeout period for data transactions */ |
338 | /* | 340 | /* |
339 | * 1)Timeout period = (2^(timeout+13)) SD Clock cycles | 341 | * 1)Timeout period = (2^(timeout+13)) SD Clock cycles |
340 | * 2)Timeout period should be minimum 0.250sec as per SD Card spec | 342 | * 2)Timeout period should be minimum 0.250sec as per SD Card spec |
341 | * So, Number of SD Clock cycles for 0.25sec should be minimum | 343 | * So, Number of SD Clock cycles for 0.25sec should be minimum |
342 | * (SD Clock/sec * 0.25 sec) SD Clock cycles | 344 | * (SD Clock/sec * 0.25 sec) SD Clock cycles |
343 | * = (mmc->clock * 1/4) SD Clock cycles | 345 | * = (mmc->clock * 1/4) SD Clock cycles |
344 | * As 1) >= 2) | 346 | * As 1) >= 2) |
345 | * => (2^(timeout+13)) >= mmc->clock * 1/4 | 347 | * => (2^(timeout+13)) >= mmc->clock * 1/4 |
346 | * Taking log2 both the sides | 348 | * Taking log2 both the sides |
347 | * => timeout + 13 >= log2(mmc->clock/4) | 349 | * => timeout + 13 >= log2(mmc->clock/4) |
348 | * Rounding up to next power of 2 | 350 | * Rounding up to next power of 2 |
349 | * => timeout + 13 = log2(mmc->clock/4) + 1 | 351 | * => timeout + 13 = log2(mmc->clock/4) + 1 |
350 | * => timeout + 13 = fls(mmc->clock/4) | 352 | * => timeout + 13 = fls(mmc->clock/4) |
351 | * | 353 | * |
352 | * However, the MMC spec "It is strongly recommended for hosts to | 354 | * However, the MMC spec "It is strongly recommended for hosts to |
353 | * implement more than 500ms timeout value even if the card | 355 | * implement more than 500ms timeout value even if the card |
354 | * indicates the 250ms maximum busy length." Even the previous | 356 | * indicates the 250ms maximum busy length." Even the previous |
355 | * value of 300ms is known to be insufficient for some cards. | 357 | * value of 300ms is known to be insufficient for some cards. |
356 | * So, we use | 358 | * So, we use |
357 | * => timeout + 13 = fls(mmc->clock/2) | 359 | * => timeout + 13 = fls(mmc->clock/2) |
358 | */ | 360 | */ |
359 | timeout = fls(mmc->clock/2); | 361 | timeout = fls(mmc->clock/2); |
360 | timeout -= 13; | 362 | timeout -= 13; |
361 | 363 | ||
362 | if (timeout > 14) | 364 | if (timeout > 14) |
363 | timeout = 14; | 365 | timeout = 14; |
364 | 366 | ||
365 | if (timeout < 0) | 367 | if (timeout < 0) |
366 | timeout = 0; | 368 | timeout = 0; |
367 | 369 | ||
368 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001 | 370 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001 |
369 | if ((timeout == 4) || (timeout == 8) || (timeout == 12)) | 371 | if ((timeout == 4) || (timeout == 8) || (timeout == 12)) |
370 | timeout++; | 372 | timeout++; |
371 | #endif | 373 | #endif |
372 | 374 | ||
373 | #ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE | 375 | #ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE |
374 | timeout = 0xE; | 376 | timeout = 0xE; |
375 | #endif | 377 | #endif |
376 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); | 378 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); |
377 | 379 | ||
378 | return 0; | 380 | return 0; |
379 | } | 381 | } |
380 | 382 | ||
381 | static void check_and_invalidate_dcache_range | 383 | static void check_and_invalidate_dcache_range |
382 | (struct mmc_cmd *cmd, | 384 | (struct mmc_cmd *cmd, |
383 | struct mmc_data *data) { | 385 | struct mmc_data *data) { |
384 | unsigned start = 0; | 386 | unsigned start = 0; |
385 | unsigned end = 0; | 387 | unsigned end = 0; |
386 | unsigned size = roundup(ARCH_DMA_MINALIGN, | 388 | unsigned size = roundup(ARCH_DMA_MINALIGN, |
387 | data->blocks*data->blocksize); | 389 | data->blocks*data->blocksize); |
388 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) | 390 | #if defined(CONFIG_S32V234) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M) |
389 | dma_addr_t addr; | 391 | dma_addr_t addr; |
390 | 392 | ||
391 | addr = virt_to_phys((void *)(data->dest)); | 393 | addr = virt_to_phys((void *)(data->dest)); |
392 | if (upper_32_bits(addr)) | 394 | if (upper_32_bits(addr)) |
393 | printf("Error found for upper 32 bits\n"); | 395 | printf("Error found for upper 32 bits\n"); |
394 | else | 396 | else |
395 | start = lower_32_bits(addr); | 397 | start = lower_32_bits(addr); |
396 | #else | 398 | #else |
397 | start = (unsigned)data->dest; | 399 | start = (unsigned)data->dest; |
398 | #endif | 400 | #endif |
399 | end = start + size; | 401 | end = start + size; |
400 | invalidate_dcache_range(start, end); | 402 | invalidate_dcache_range(start, end); |
401 | } | 403 | } |
402 | 404 | ||
403 | #ifdef CONFIG_MCF5441x | 405 | #ifdef CONFIG_MCF5441x |
404 | /* | 406 | /* |
405 | * Swaps 32-bit words to little-endian byte order. | 407 | * Swaps 32-bit words to little-endian byte order. |
406 | */ | 408 | */ |
407 | static inline void sd_swap_dma_buff(struct mmc_data *data) | 409 | static inline void sd_swap_dma_buff(struct mmc_data *data) |
408 | { | 410 | { |
409 | int i, size = data->blocksize >> 2; | 411 | int i, size = data->blocksize >> 2; |
410 | u32 *buffer = (u32 *)data->dest; | 412 | u32 *buffer = (u32 *)data->dest; |
411 | u32 sw; | 413 | u32 sw; |
412 | 414 | ||
413 | while (data->blocks--) { | 415 | while (data->blocks--) { |
414 | for (i = 0; i < size; i++) { | 416 | for (i = 0; i < size; i++) { |
415 | sw = __sw32(*buffer); | 417 | sw = __sw32(*buffer); |
416 | *buffer++ = sw; | 418 | *buffer++ = sw; |
417 | } | 419 | } |
418 | } | 420 | } |
419 | } | 421 | } |
420 | #endif | 422 | #endif |
421 | 423 | ||
422 | /* | 424 | /* |
423 | * Sends a command out on the bus. Takes the mmc pointer, | 425 | * Sends a command out on the bus. Takes the mmc pointer, |
424 | * a command pointer, and an optional data pointer. | 426 | * a command pointer, and an optional data pointer. |
425 | */ | 427 | */ |
426 | static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, | 428 | static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, |
427 | struct mmc_cmd *cmd, struct mmc_data *data) | 429 | struct mmc_cmd *cmd, struct mmc_data *data) |
428 | { | 430 | { |
429 | int err = 0; | 431 | int err = 0; |
430 | uint xfertyp; | 432 | uint xfertyp; |
431 | uint irqstat; | 433 | uint irqstat; |
432 | u32 flags = IRQSTAT_CC | IRQSTAT_CTOE; | 434 | u32 flags = IRQSTAT_CC | IRQSTAT_CTOE; |
433 | struct fsl_esdhc *regs = priv->esdhc_regs; | 435 | struct fsl_esdhc *regs = priv->esdhc_regs; |
434 | unsigned long start; | 436 | unsigned long start; |
435 | 437 | ||
436 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 | 438 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 |
437 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) | 439 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) |
438 | return 0; | 440 | return 0; |
439 | #endif | 441 | #endif |
440 | 442 | ||
441 | esdhc_write32(®s->irqstat, -1); | 443 | esdhc_write32(®s->irqstat, -1); |
442 | 444 | ||
443 | sync(); | 445 | sync(); |
444 | 446 | ||
445 | /* Wait for the bus to be idle */ | 447 | /* Wait for the bus to be idle */ |
446 | while ((esdhc_read32(®s->prsstat) & PRSSTAT_CICHB) || | 448 | while ((esdhc_read32(®s->prsstat) & PRSSTAT_CICHB) || |
447 | (esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB)) | 449 | (esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB)) |
448 | ; | 450 | ; |
449 | 451 | ||
450 | while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA) | 452 | while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA) |
451 | ; | 453 | ; |
452 | 454 | ||
453 | /* Wait at least 8 SD clock cycles before the next command */ | 455 | /* Wait at least 8 SD clock cycles before the next command */ |
454 | /* | 456 | /* |
455 | * Note: This is way more than 8 cycles, but 1ms seems to | 457 | * Note: This is way more than 8 cycles, but 1ms seems to |
456 | * resolve timing issues with some cards | 458 | * resolve timing issues with some cards |
457 | */ | 459 | */ |
458 | udelay(1000); | 460 | udelay(1000); |
459 | 461 | ||
460 | /* Set up for a data transfer if we have one */ | 462 | /* Set up for a data transfer if we have one */ |
461 | if (data) { | 463 | if (data) { |
462 | err = esdhc_setup_data(priv, mmc, data); | 464 | err = esdhc_setup_data(priv, mmc, data); |
463 | if(err) | 465 | if(err) |
464 | return err; | 466 | return err; |
465 | 467 | ||
466 | if (data->flags & MMC_DATA_READ) | 468 | if (data->flags & MMC_DATA_READ) |
467 | check_and_invalidate_dcache_range(cmd, data); | 469 | check_and_invalidate_dcache_range(cmd, data); |
468 | } | 470 | } |
469 | 471 | ||
470 | /* Figure out the transfer arguments */ | 472 | /* Figure out the transfer arguments */ |
471 | xfertyp = esdhc_xfertyp(cmd, data); | 473 | xfertyp = esdhc_xfertyp(cmd, data); |
472 | 474 | ||
473 | /* Mask all irqs */ | 475 | /* Mask all irqs */ |
474 | esdhc_write32(®s->irqsigen, 0); | 476 | esdhc_write32(®s->irqsigen, 0); |
475 | 477 | ||
476 | /* Send the command */ | 478 | /* Send the command */ |
477 | esdhc_write32(®s->cmdarg, cmd->cmdarg); | 479 | esdhc_write32(®s->cmdarg, cmd->cmdarg); |
478 | #if defined(CONFIG_FSL_USDHC) | 480 | #if defined(CONFIG_FSL_USDHC) |
479 | esdhc_write32(®s->mixctrl, | 481 | esdhc_write32(®s->mixctrl, |
480 | (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) | 482 | (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) |
481 | | (mmc->ddr_mode ? XFERTYP_DDREN : 0)); | 483 | | (mmc->ddr_mode ? XFERTYP_DDREN : 0)); |
482 | esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000); | 484 | esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000); |
483 | #else | 485 | #else |
484 | esdhc_write32(®s->xfertyp, xfertyp); | 486 | esdhc_write32(®s->xfertyp, xfertyp); |
485 | #endif | 487 | #endif |
486 | 488 | ||
487 | if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) || | 489 | if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) || |
488 | (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) | 490 | (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) |
489 | flags = IRQSTAT_BRR; | 491 | flags = IRQSTAT_BRR; |
490 | 492 | ||
491 | /* Wait for the command to complete */ | 493 | /* Wait for the command to complete */ |
492 | start = get_timer(0); | 494 | start = get_timer(0); |
493 | while (!(esdhc_read32(®s->irqstat) & flags)) { | 495 | while (!(esdhc_read32(®s->irqstat) & flags)) { |
494 | if (get_timer(start) > 1000) { | 496 | if (get_timer(start) > 1000) { |
495 | err = -ETIMEDOUT; | 497 | err = -ETIMEDOUT; |
496 | goto out; | 498 | goto out; |
497 | } | 499 | } |
498 | } | 500 | } |
499 | 501 | ||
500 | irqstat = esdhc_read32(®s->irqstat); | 502 | irqstat = esdhc_read32(®s->irqstat); |
501 | 503 | ||
502 | if (irqstat & CMD_ERR) { | 504 | if (irqstat & CMD_ERR) { |
503 | err = -ECOMM; | 505 | err = -ECOMM; |
504 | goto out; | 506 | goto out; |
505 | } | 507 | } |
506 | 508 | ||
507 | if (irqstat & IRQSTAT_CTOE) { | 509 | if (irqstat & IRQSTAT_CTOE) { |
508 | err = -ETIMEDOUT; | 510 | err = -ETIMEDOUT; |
509 | goto out; | 511 | goto out; |
510 | } | 512 | } |
511 | 513 | ||
512 | /* Switch voltage to 1.8V if CMD11 succeeded */ | 514 | /* Switch voltage to 1.8V if CMD11 succeeded */ |
513 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) { | 515 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) { |
514 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | 516 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); |
515 | 517 | ||
516 | printf("Run CMD11 1.8V switch\n"); | 518 | printf("Run CMD11 1.8V switch\n"); |
517 | /* Sleep for 5 ms - max time for card to switch to 1.8V */ | 519 | /* Sleep for 5 ms - max time for card to switch to 1.8V */ |
518 | udelay(5000); | 520 | udelay(5000); |
519 | } | 521 | } |
520 | 522 | ||
521 | /* Workaround for ESDHC errata ENGcm03648 */ | 523 | /* Workaround for ESDHC errata ENGcm03648 */ |
522 | if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { | 524 | if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { |
523 | int timeout = 50000; | 525 | int timeout = 50000; |
524 | 526 | ||
525 | /* Poll on DATA0 line for cmd with busy signal for 5000 ms */ | 527 | /* Poll on DATA0 line for cmd with busy signal for 5000 ms */ |
526 | while (timeout > 0 && !(esdhc_read32(®s->prsstat) & | 528 | while (timeout > 0 && !(esdhc_read32(®s->prsstat) & |
527 | PRSSTAT_DAT0)) { | 529 | PRSSTAT_DAT0)) { |
528 | udelay(100); | 530 | udelay(100); |
529 | timeout--; | 531 | timeout--; |
530 | } | 532 | } |
531 | 533 | ||
532 | if (timeout <= 0) { | 534 | if (timeout <= 0) { |
533 | printf("Timeout waiting for DAT0 to go high!\n"); | 535 | printf("Timeout waiting for DAT0 to go high!\n"); |
534 | err = -ETIMEDOUT; | 536 | err = -ETIMEDOUT; |
535 | goto out; | 537 | goto out; |
536 | } | 538 | } |
537 | } | 539 | } |
538 | 540 | ||
539 | /* Copy the response to the response buffer */ | 541 | /* Copy the response to the response buffer */ |
540 | if (cmd->resp_type & MMC_RSP_136) { | 542 | if (cmd->resp_type & MMC_RSP_136) { |
541 | u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; | 543 | u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; |
542 | 544 | ||
543 | cmdrsp3 = esdhc_read32(®s->cmdrsp3); | 545 | cmdrsp3 = esdhc_read32(®s->cmdrsp3); |
544 | cmdrsp2 = esdhc_read32(®s->cmdrsp2); | 546 | cmdrsp2 = esdhc_read32(®s->cmdrsp2); |
545 | cmdrsp1 = esdhc_read32(®s->cmdrsp1); | 547 | cmdrsp1 = esdhc_read32(®s->cmdrsp1); |
546 | cmdrsp0 = esdhc_read32(®s->cmdrsp0); | 548 | cmdrsp0 = esdhc_read32(®s->cmdrsp0); |
547 | cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); | 549 | cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); |
548 | cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); | 550 | cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); |
549 | cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); | 551 | cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); |
550 | cmd->response[3] = (cmdrsp0 << 8); | 552 | cmd->response[3] = (cmdrsp0 << 8); |
551 | } else | 553 | } else |
552 | cmd->response[0] = esdhc_read32(®s->cmdrsp0); | 554 | cmd->response[0] = esdhc_read32(®s->cmdrsp0); |
553 | 555 | ||
554 | /* Wait until all of the blocks are transferred */ | 556 | /* Wait until all of the blocks are transferred */ |
555 | if (data) { | 557 | if (data) { |
556 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO | 558 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO |
557 | esdhc_pio_read_write(priv, data); | 559 | esdhc_pio_read_write(priv, data); |
558 | #else | 560 | #else |
559 | flags = DATA_COMPLETE; | 561 | flags = DATA_COMPLETE; |
560 | if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) || | 562 | if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) || |
561 | (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) { | 563 | (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) { |
562 | flags = IRQSTAT_BRR; | 564 | flags = IRQSTAT_BRR; |
563 | } | 565 | } |
564 | 566 | ||
565 | do { | 567 | do { |
566 | irqstat = esdhc_read32(®s->irqstat); | 568 | irqstat = esdhc_read32(®s->irqstat); |
567 | 569 | ||
568 | if (irqstat & IRQSTAT_DTOE) { | 570 | if (irqstat & IRQSTAT_DTOE) { |
569 | err = -ETIMEDOUT; | 571 | err = -ETIMEDOUT; |
570 | goto out; | 572 | goto out; |
571 | } | 573 | } |
572 | 574 | ||
573 | if (irqstat & DATA_ERR) { | 575 | if (irqstat & DATA_ERR) { |
574 | err = -ECOMM; | 576 | err = -ECOMM; |
575 | goto out; | 577 | goto out; |
576 | } | 578 | } |
577 | } while ((irqstat & flags) != flags); | 579 | } while ((irqstat & flags) != flags); |
578 | 580 | ||
579 | /* | 581 | /* |
580 | * Need invalidate the dcache here again to avoid any | 582 | * Need invalidate the dcache here again to avoid any |
581 | * cache-fill during the DMA operations such as the | 583 | * cache-fill during the DMA operations such as the |
582 | * speculative pre-fetching etc. | 584 | * speculative pre-fetching etc. |
583 | */ | 585 | */ |
584 | if (data->flags & MMC_DATA_READ) { | 586 | if (data->flags & MMC_DATA_READ) { |
585 | check_and_invalidate_dcache_range(cmd, data); | 587 | check_and_invalidate_dcache_range(cmd, data); |
586 | #ifdef CONFIG_MCF5441x | 588 | #ifdef CONFIG_MCF5441x |
587 | sd_swap_dma_buff(data); | 589 | sd_swap_dma_buff(data); |
588 | #endif | 590 | #endif |
589 | } | 591 | } |
590 | #endif | 592 | #endif |
591 | } | 593 | } |
592 | 594 | ||
593 | out: | 595 | out: |
594 | /* Reset CMD and DATA portions on error */ | 596 | /* Reset CMD and DATA portions on error */ |
595 | if (err) { | 597 | if (err) { |
596 | esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | | 598 | esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | |
597 | SYSCTL_RSTC); | 599 | SYSCTL_RSTC); |
598 | while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) | 600 | while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) |
599 | ; | 601 | ; |
600 | 602 | ||
601 | if (data) { | 603 | if (data) { |
602 | esdhc_write32(®s->sysctl, | 604 | esdhc_write32(®s->sysctl, |
603 | esdhc_read32(®s->sysctl) | | 605 | esdhc_read32(®s->sysctl) | |
604 | SYSCTL_RSTD); | 606 | SYSCTL_RSTD); |
605 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) | 607 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) |
606 | ; | 608 | ; |
607 | } | 609 | } |
608 | 610 | ||
609 | /* If this was CMD11, then notify that power cycle is needed */ | 611 | /* If this was CMD11, then notify that power cycle is needed */ |
610 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) | 612 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) |
611 | printf("CMD11 to switch to 1.8V mode failed, card requires power cycle.\n"); | 613 | printf("CMD11 to switch to 1.8V mode failed, card requires power cycle.\n"); |
612 | } | 614 | } |
613 | 615 | ||
614 | esdhc_write32(®s->irqstat, -1); | 616 | esdhc_write32(®s->irqstat, -1); |
615 | 617 | ||
616 | return err; | 618 | return err; |
617 | } | 619 | } |
618 | 620 | ||
619 | static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) | 621 | static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) |
620 | { | 622 | { |
621 | struct fsl_esdhc *regs = priv->esdhc_regs; | 623 | struct fsl_esdhc *regs = priv->esdhc_regs; |
622 | int div = 1; | 624 | int div = 1; |
623 | #ifdef ARCH_MXC | 625 | #ifdef ARCH_MXC |
624 | #ifdef CONFIG_MX53 | 626 | #ifdef CONFIG_MX53 |
625 | /* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */ | 627 | /* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */ |
626 | int pre_div = (regs == (struct fsl_esdhc *)MMC_SDHC3_BASE_ADDR) ? 2 : 1; | 628 | int pre_div = (regs == (struct fsl_esdhc *)MMC_SDHC3_BASE_ADDR) ? 2 : 1; |
627 | #else | 629 | #else |
628 | int pre_div = 1; | 630 | int pre_div = 1; |
629 | #endif | 631 | #endif |
630 | #else | 632 | #else |
631 | int pre_div = 2; | 633 | int pre_div = 2; |
632 | #endif | 634 | #endif |
633 | int sdhc_clk = priv->sdhc_clk; | 635 | int sdhc_clk = priv->sdhc_clk; |
634 | uint clk; | 636 | uint clk; |
635 | 637 | ||
636 | /* | 638 | /* |
637 | * For ddr mode, usdhc need to enable DDR mode first, after select | 639 | * For ddr mode, usdhc need to enable DDR mode first, after select |
638 | * this DDR mode, usdhc will automatically divide the usdhc clock | 640 | * this DDR mode, usdhc will automatically divide the usdhc clock |
639 | */ | 641 | */ |
640 | if (mmc->ddr_mode) { | 642 | if (mmc->ddr_mode) { |
641 | writel(readl(®s->mixctrl) | MIX_CTRL_DDREN, ®s->mixctrl); | 643 | writel(readl(®s->mixctrl) | MIX_CTRL_DDREN, ®s->mixctrl); |
642 | sdhc_clk >>= 1; | 644 | sdhc_clk >>= 1; |
643 | } | 645 | } |
644 | 646 | ||
645 | if (sdhc_clk / 16 > clock) { | 647 | if (sdhc_clk / 16 > clock) { |
646 | for (; pre_div < 256; pre_div *= 2) | 648 | for (; pre_div < 256; pre_div *= 2) |
647 | if ((sdhc_clk / pre_div) <= (clock * 16)) | 649 | if ((sdhc_clk / pre_div) <= (clock * 16)) |
648 | break; | 650 | break; |
649 | } | 651 | } |
650 | 652 | ||
651 | for (div = 1; div <= 16; div++) | 653 | for (div = 1; div <= 16; div++) |
652 | if ((sdhc_clk / (div * pre_div)) <= clock) | 654 | if ((sdhc_clk / (div * pre_div)) <= clock) |
653 | break; | 655 | break; |
654 | 656 | ||
655 | pre_div >>= 1; | 657 | pre_div >>= 1; |
656 | div -= 1; | 658 | div -= 1; |
657 | 659 | ||
658 | clk = (pre_div << 8) | (div << 4); | 660 | clk = (pre_div << 8) | (div << 4); |
659 | 661 | ||
660 | #ifdef CONFIG_FSL_USDHC | 662 | #ifdef CONFIG_FSL_USDHC |
661 | esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); | 663 | esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); |
662 | #else | 664 | #else |
663 | esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); | 665 | esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); |
664 | #endif | 666 | #endif |
665 | 667 | ||
666 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); | 668 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); |
667 | 669 | ||
668 | udelay(10000); | 670 | udelay(10000); |
669 | 671 | ||
670 | #ifdef CONFIG_FSL_USDHC | 672 | #ifdef CONFIG_FSL_USDHC |
671 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); | 673 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); |
672 | #else | 674 | #else |
673 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); | 675 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); |
674 | #endif | 676 | #endif |
675 | 677 | ||
676 | priv->clock = clock; | 678 | priv->clock = clock; |
677 | } | 679 | } |
678 | 680 | ||
679 | #ifdef MMC_SUPPORTS_TUNING | 681 | #ifdef MMC_SUPPORTS_TUNING |
680 | static int esdhc_change_pinstate(struct udevice *dev) | 682 | static int esdhc_change_pinstate(struct udevice *dev) |
681 | { | 683 | { |
682 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 684 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
683 | int ret; | 685 | int ret; |
684 | 686 | ||
685 | switch (priv->mode) { | 687 | switch (priv->mode) { |
686 | case UHS_SDR50: | 688 | case UHS_SDR50: |
687 | case UHS_DDR50: | 689 | case UHS_DDR50: |
688 | ret = pinctrl_select_state(dev, "state_100mhz"); | 690 | ret = pinctrl_select_state(dev, "state_100mhz"); |
689 | break; | 691 | break; |
690 | case UHS_SDR104: | 692 | case UHS_SDR104: |
691 | case MMC_HS_200: | 693 | case MMC_HS_200: |
692 | case MMC_HS_400: | 694 | case MMC_HS_400: |
693 | case MMC_HS_400_ES: | 695 | case MMC_HS_400_ES: |
694 | ret = pinctrl_select_state(dev, "state_200mhz"); | 696 | ret = pinctrl_select_state(dev, "state_200mhz"); |
695 | break; | 697 | break; |
696 | default: | 698 | default: |
697 | ret = pinctrl_select_state(dev, "default"); | 699 | ret = pinctrl_select_state(dev, "default"); |
698 | break; | 700 | break; |
699 | } | 701 | } |
700 | 702 | ||
701 | if (ret) | 703 | if (ret) |
702 | printf("%s %d error\n", __func__, priv->mode); | 704 | printf("%s %d error\n", __func__, priv->mode); |
703 | 705 | ||
704 | return ret; | 706 | return ret; |
705 | } | 707 | } |
706 | 708 | ||
707 | static void esdhc_reset_tuning(struct mmc *mmc) | 709 | static void esdhc_reset_tuning(struct mmc *mmc) |
708 | { | 710 | { |
709 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); | 711 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); |
710 | struct fsl_esdhc *regs = priv->esdhc_regs; | 712 | struct fsl_esdhc *regs = priv->esdhc_regs; |
711 | 713 | ||
712 | if (priv->flags & ESDHC_FLAG_USDHC) { | 714 | if (priv->flags & ESDHC_FLAG_USDHC) { |
713 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { | 715 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { |
714 | esdhc_clrbits32(®s->autoc12err, | 716 | esdhc_clrbits32(®s->autoc12err, |
715 | MIX_CTRL_SMPCLK_SEL | | 717 | MIX_CTRL_SMPCLK_SEL | |
716 | MIX_CTRL_EXE_TUNE); | 718 | MIX_CTRL_EXE_TUNE); |
717 | } | 719 | } |
718 | } | 720 | } |
719 | } | 721 | } |
720 | 722 | ||
721 | static void esdhc_set_strobe_dll(struct mmc *mmc) | 723 | static void esdhc_set_strobe_dll(struct mmc *mmc) |
722 | { | 724 | { |
723 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); | 725 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); |
724 | struct fsl_esdhc *regs = priv->esdhc_regs; | 726 | struct fsl_esdhc *regs = priv->esdhc_regs; |
725 | u32 val; | 727 | u32 val; |
726 | 728 | ||
727 | if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) { | 729 | if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) { |
728 | writel(ESDHC_STROBE_DLL_CTRL_RESET, ®s->strobe_dllctrl); | 730 | writel(ESDHC_STROBE_DLL_CTRL_RESET, ®s->strobe_dllctrl); |
729 | 731 | ||
730 | /* | 732 | /* |
731 | * enable strobe dll ctrl and adjust the delay target | 733 | * enable strobe dll ctrl and adjust the delay target |
732 | * for the uSDHC loopback read clock | 734 | * for the uSDHC loopback read clock |
733 | */ | 735 | */ |
734 | val = ESDHC_STROBE_DLL_CTRL_ENABLE | | 736 | val = ESDHC_STROBE_DLL_CTRL_ENABLE | |
735 | (priv->strobe_dll_delay_target << | 737 | (priv->strobe_dll_delay_target << |
736 | ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); | 738 | ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); |
737 | writel(val, ®s->strobe_dllctrl); | 739 | writel(val, ®s->strobe_dllctrl); |
738 | /* wait 1us to make sure strobe dll status register stable */ | 740 | /* wait 1us to make sure strobe dll status register stable */ |
739 | mdelay(1); | 741 | mdelay(1); |
740 | val = readl(®s->strobe_dllstat); | 742 | val = readl(®s->strobe_dllstat); |
741 | if (!(val & ESDHC_STROBE_DLL_STS_REF_LOCK)) | 743 | if (!(val & ESDHC_STROBE_DLL_STS_REF_LOCK)) |
742 | pr_warn("HS400 strobe DLL status REF not lock!\n"); | 744 | pr_warn("HS400 strobe DLL status REF not lock!\n"); |
743 | if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK)) | 745 | if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK)) |
744 | pr_warn("HS400 strobe DLL status SLV not lock!\n"); | 746 | pr_warn("HS400 strobe DLL status SLV not lock!\n"); |
745 | } | 747 | } |
746 | } | 748 | } |
747 | 749 | ||
748 | static int esdhc_set_timing(struct mmc *mmc) | 750 | static int esdhc_set_timing(struct mmc *mmc) |
749 | { | 751 | { |
750 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); | 752 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); |
751 | struct fsl_esdhc *regs = priv->esdhc_regs; | 753 | struct fsl_esdhc *regs = priv->esdhc_regs; |
752 | u32 mixctrl; | 754 | u32 mixctrl; |
753 | 755 | ||
754 | mixctrl = readl(®s->mixctrl); | 756 | mixctrl = readl(®s->mixctrl); |
755 | mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN); | 757 | mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN); |
756 | 758 | ||
757 | switch (mmc->selected_mode) { | 759 | switch (mmc->selected_mode) { |
758 | case MMC_LEGACY: | 760 | case MMC_LEGACY: |
759 | esdhc_reset_tuning(mmc); | 761 | esdhc_reset_tuning(mmc); |
760 | writel(mixctrl, ®s->mixctrl); | 762 | writel(mixctrl, ®s->mixctrl); |
761 | break; | 763 | break; |
762 | case MMC_HS_400: | 764 | case MMC_HS_400: |
763 | case MMC_HS_400_ES: | 765 | case MMC_HS_400_ES: |
764 | mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN; | 766 | mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN; |
765 | writel(mixctrl, ®s->mixctrl); | 767 | writel(mixctrl, ®s->mixctrl); |
766 | esdhc_set_strobe_dll(mmc); | 768 | esdhc_set_strobe_dll(mmc); |
767 | break; | 769 | break; |
768 | case MMC_HS: | 770 | case MMC_HS: |
769 | case MMC_HS_52: | 771 | case MMC_HS_52: |
770 | case MMC_HS_200: | 772 | case MMC_HS_200: |
771 | case SD_HS: | 773 | case SD_HS: |
772 | case UHS_SDR12: | 774 | case UHS_SDR12: |
773 | case UHS_SDR25: | 775 | case UHS_SDR25: |
774 | case UHS_SDR50: | 776 | case UHS_SDR50: |
775 | case UHS_SDR104: | 777 | case UHS_SDR104: |
776 | writel(mixctrl, ®s->mixctrl); | 778 | writel(mixctrl, ®s->mixctrl); |
777 | break; | 779 | break; |
778 | case UHS_DDR50: | 780 | case UHS_DDR50: |
779 | case MMC_DDR_52: | 781 | case MMC_DDR_52: |
780 | mixctrl |= MIX_CTRL_DDREN; | 782 | mixctrl |= MIX_CTRL_DDREN; |
781 | writel(mixctrl, ®s->mixctrl); | 783 | writel(mixctrl, ®s->mixctrl); |
782 | break; | 784 | break; |
783 | default: | 785 | default: |
784 | printf("Not supported %d\n", mmc->selected_mode); | 786 | printf("Not supported %d\n", mmc->selected_mode); |
785 | return -EINVAL; | 787 | return -EINVAL; |
786 | } | 788 | } |
787 | 789 | ||
788 | priv->mode = mmc->selected_mode; | 790 | priv->mode = mmc->selected_mode; |
789 | 791 | ||
790 | return esdhc_change_pinstate(mmc->dev); | 792 | return esdhc_change_pinstate(mmc->dev); |
791 | } | 793 | } |
792 | 794 | ||
793 | static int esdhc_set_voltage(struct mmc *mmc) | 795 | static int esdhc_set_voltage(struct mmc *mmc) |
794 | { | 796 | { |
795 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); | 797 | struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); |
796 | struct fsl_esdhc *regs = priv->esdhc_regs; | 798 | struct fsl_esdhc *regs = priv->esdhc_regs; |
797 | int ret; | 799 | int ret; |
798 | 800 | ||
799 | priv->signal_voltage = mmc->signal_voltage; | 801 | priv->signal_voltage = mmc->signal_voltage; |
800 | switch (mmc->signal_voltage) { | 802 | switch (mmc->signal_voltage) { |
801 | case MMC_SIGNAL_VOLTAGE_330: | 803 | case MMC_SIGNAL_VOLTAGE_330: |
802 | if (priv->vs18_enable) | 804 | if (priv->vs18_enable) |
803 | return -EIO; | 805 | return -EIO; |
804 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | 806 | #if CONFIG_IS_ENABLED(DM_REGULATOR) |
805 | if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) { | 807 | if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) { |
806 | ret = regulator_set_value(priv->vqmmc_dev, 3300000); | 808 | ret = regulator_set_value(priv->vqmmc_dev, 3300000); |
807 | if (ret) { | 809 | if (ret) { |
808 | printf("Setting to 3.3V error"); | 810 | printf("Setting to 3.3V error"); |
809 | return -EIO; | 811 | return -EIO; |
810 | } | 812 | } |
811 | /* Wait for 5ms */ | 813 | /* Wait for 5ms */ |
812 | mdelay(5); | 814 | mdelay(5); |
813 | } | 815 | } |
814 | #endif | 816 | #endif |
815 | 817 | ||
816 | esdhc_clrbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | 818 | esdhc_clrbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); |
817 | if (!(esdhc_read32(®s->vendorspec) & | 819 | if (!(esdhc_read32(®s->vendorspec) & |
818 | ESDHC_VENDORSPEC_VSELECT)) | 820 | ESDHC_VENDORSPEC_VSELECT)) |
819 | return 0; | 821 | return 0; |
820 | 822 | ||
821 | return -EAGAIN; | 823 | return -EAGAIN; |
822 | case MMC_SIGNAL_VOLTAGE_180: | 824 | case MMC_SIGNAL_VOLTAGE_180: |
823 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | 825 | #if CONFIG_IS_ENABLED(DM_REGULATOR) |
824 | if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) { | 826 | if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) { |
825 | ret = regulator_set_value(priv->vqmmc_dev, 1800000); | 827 | ret = regulator_set_value(priv->vqmmc_dev, 1800000); |
826 | if (ret) { | 828 | if (ret) { |
827 | printf("Setting to 1.8V error"); | 829 | printf("Setting to 1.8V error"); |
828 | return -EIO; | 830 | return -EIO; |
829 | } | 831 | } |
830 | } | 832 | } |
831 | #endif | 833 | #endif |
832 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | 834 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); |
833 | if (esdhc_read32(®s->vendorspec) & ESDHC_VENDORSPEC_VSELECT) | 835 | if (esdhc_read32(®s->vendorspec) & ESDHC_VENDORSPEC_VSELECT) |
834 | return 0; | 836 | return 0; |
835 | 837 | ||
836 | return -EAGAIN; | 838 | return -EAGAIN; |
837 | case MMC_SIGNAL_VOLTAGE_120: | 839 | case MMC_SIGNAL_VOLTAGE_120: |
838 | return -ENOTSUPP; | 840 | return -ENOTSUPP; |
839 | default: | 841 | default: |
840 | return 0; | 842 | return 0; |
841 | } | 843 | } |
842 | } | 844 | } |
843 | 845 | ||
844 | static void esdhc_stop_tuning(struct mmc *mmc) | 846 | static void esdhc_stop_tuning(struct mmc *mmc) |
845 | { | 847 | { |
846 | struct mmc_cmd cmd; | 848 | struct mmc_cmd cmd; |
847 | 849 | ||
848 | cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; | 850 | cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; |
849 | cmd.cmdarg = 0; | 851 | cmd.cmdarg = 0; |
850 | cmd.resp_type = MMC_RSP_R1b; | 852 | cmd.resp_type = MMC_RSP_R1b; |
851 | 853 | ||
852 | dm_mmc_send_cmd(mmc->dev, &cmd, NULL); | 854 | dm_mmc_send_cmd(mmc->dev, &cmd, NULL); |
853 | } | 855 | } |
854 | 856 | ||
855 | static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) | 857 | static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) |
856 | { | 858 | { |
857 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); | 859 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); |
858 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 860 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
859 | struct fsl_esdhc *regs = priv->esdhc_regs; | 861 | struct fsl_esdhc *regs = priv->esdhc_regs; |
860 | struct mmc *mmc = &plat->mmc; | 862 | struct mmc *mmc = &plat->mmc; |
861 | u32 irqstaten = readl(®s->irqstaten); | 863 | u32 irqstaten = readl(®s->irqstaten); |
862 | u32 irqsigen = readl(®s->irqsigen); | 864 | u32 irqsigen = readl(®s->irqsigen); |
863 | int i, ret = -ETIMEDOUT; | 865 | int i, ret = -ETIMEDOUT; |
864 | u32 val, mixctrl; | 866 | u32 val, mixctrl; |
865 | 867 | ||
866 | /* clock tuning is not needed for upto 52MHz */ | 868 | /* clock tuning is not needed for upto 52MHz */ |
867 | if (mmc->clock <= 52000000) | 869 | if (mmc->clock <= 52000000) |
868 | return 0; | 870 | return 0; |
869 | 871 | ||
870 | /* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */ | 872 | /* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */ |
871 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { | 873 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { |
872 | val = readl(®s->autoc12err); | 874 | val = readl(®s->autoc12err); |
873 | mixctrl = readl(®s->mixctrl); | 875 | mixctrl = readl(®s->mixctrl); |
874 | val &= ~MIX_CTRL_SMPCLK_SEL; | 876 | val &= ~MIX_CTRL_SMPCLK_SEL; |
875 | mixctrl &= ~(MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN); | 877 | mixctrl &= ~(MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN); |
876 | 878 | ||
877 | val |= MIX_CTRL_EXE_TUNE; | 879 | val |= MIX_CTRL_EXE_TUNE; |
878 | mixctrl |= MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN; | 880 | mixctrl |= MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN; |
879 | 881 | ||
880 | writel(val, ®s->autoc12err); | 882 | writel(val, ®s->autoc12err); |
881 | writel(mixctrl, ®s->mixctrl); | 883 | writel(mixctrl, ®s->mixctrl); |
882 | } | 884 | } |
883 | 885 | ||
884 | /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); */ | 886 | /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); */ |
885 | mixctrl = readl(®s->mixctrl); | 887 | mixctrl = readl(®s->mixctrl); |
886 | mixctrl = MIX_CTRL_DTDSEL_READ | (mixctrl & ~MIX_CTRL_SDHCI_MASK); | 888 | mixctrl = MIX_CTRL_DTDSEL_READ | (mixctrl & ~MIX_CTRL_SDHCI_MASK); |
887 | writel(mixctrl, ®s->mixctrl); | 889 | writel(mixctrl, ®s->mixctrl); |
888 | 890 | ||
889 | writel(IRQSTATEN_BRR, ®s->irqstaten); | 891 | writel(IRQSTATEN_BRR, ®s->irqstaten); |
890 | writel(IRQSTATEN_BRR, ®s->irqsigen); | 892 | writel(IRQSTATEN_BRR, ®s->irqsigen); |
891 | 893 | ||
892 | /* | 894 | /* |
893 | * Issue opcode repeatedly till Execute Tuning is set to 0 or the number | 895 | * Issue opcode repeatedly till Execute Tuning is set to 0 or the number |
894 | * of loops reaches 40 times. | 896 | * of loops reaches 40 times. |
895 | */ | 897 | */ |
896 | for (i = 0; i < MAX_TUNING_LOOP; i++) { | 898 | for (i = 0; i < MAX_TUNING_LOOP; i++) { |
897 | u32 ctrl; | 899 | u32 ctrl; |
898 | 900 | ||
899 | if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200) { | 901 | if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200) { |
900 | if (mmc->bus_width == 8) | 902 | if (mmc->bus_width == 8) |
901 | writel(0x7080, ®s->blkattr); | 903 | writel(0x7080, ®s->blkattr); |
902 | else if (mmc->bus_width == 4) | 904 | else if (mmc->bus_width == 4) |
903 | writel(0x7040, ®s->blkattr); | 905 | writel(0x7040, ®s->blkattr); |
904 | } else { | 906 | } else { |
905 | writel(0x7040, ®s->blkattr); | 907 | writel(0x7040, ®s->blkattr); |
906 | } | 908 | } |
907 | 909 | ||
908 | /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE) */ | 910 | /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE) */ |
909 | val = readl(®s->mixctrl); | 911 | val = readl(®s->mixctrl); |
910 | val = MIX_CTRL_DTDSEL_READ | (val & ~MIX_CTRL_SDHCI_MASK); | 912 | val = MIX_CTRL_DTDSEL_READ | (val & ~MIX_CTRL_SDHCI_MASK); |
911 | writel(val, ®s->mixctrl); | 913 | writel(val, ®s->mixctrl); |
912 | 914 | ||
913 | /* We are using STD tuning, no need to check return value */ | 915 | /* We are using STD tuning, no need to check return value */ |
914 | mmc_send_tuning(mmc, opcode, NULL); | 916 | mmc_send_tuning(mmc, opcode, NULL); |
915 | 917 | ||
916 | ctrl = readl(®s->autoc12err); | 918 | ctrl = readl(®s->autoc12err); |
917 | if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && | 919 | if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && |
918 | (ctrl & MIX_CTRL_SMPCLK_SEL)) { | 920 | (ctrl & MIX_CTRL_SMPCLK_SEL)) { |
919 | /* | 921 | /* |
920 | * need to wait some time, make sure sd/mmc fininsh | 922 | * need to wait some time, make sure sd/mmc fininsh |
921 | * send out tuning data, otherwise, the sd/mmc can't | 923 | * send out tuning data, otherwise, the sd/mmc can't |
922 | * response to any command when the card still out | 924 | * response to any command when the card still out |
923 | * put the tuning data. | 925 | * put the tuning data. |
924 | */ | 926 | */ |
925 | mdelay(1); | 927 | mdelay(1); |
926 | ret = 0; | 928 | ret = 0; |
927 | break; | 929 | break; |
928 | } | 930 | } |
929 | 931 | ||
930 | /* Add 1ms delay for SD and eMMC */ | 932 | /* Add 1ms delay for SD and eMMC */ |
931 | mdelay(1); | 933 | mdelay(1); |
932 | } | 934 | } |
933 | 935 | ||
934 | writel(irqstaten, ®s->irqstaten); | 936 | writel(irqstaten, ®s->irqstaten); |
935 | writel(irqsigen, ®s->irqsigen); | 937 | writel(irqsigen, ®s->irqsigen); |
936 | 938 | ||
937 | esdhc_stop_tuning(mmc); | 939 | esdhc_stop_tuning(mmc); |
938 | 940 | ||
939 | return ret; | 941 | return ret; |
940 | } | 942 | } |
941 | #endif | 943 | #endif |
942 | 944 | ||
943 | static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | 945 | static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) |
944 | { | 946 | { |
945 | struct fsl_esdhc *regs = priv->esdhc_regs; | 947 | struct fsl_esdhc *regs = priv->esdhc_regs; |
946 | int ret __maybe_unused; | 948 | int ret __maybe_unused; |
947 | u32 clock; | 949 | u32 clock; |
948 | 950 | ||
949 | /* Set the clock speed */ | 951 | /* Set the clock speed */ |
950 | clock = mmc->clock; | 952 | clock = mmc->clock; |
951 | if (clock < mmc->cfg->f_min) | 953 | if (clock < mmc->cfg->f_min) |
952 | clock = mmc->cfg->f_min; | 954 | clock = mmc->cfg->f_min; |
953 | 955 | ||
954 | if (priv->clock != clock) | 956 | if (priv->clock != clock) |
955 | set_sysctl(priv, mmc, clock); | 957 | set_sysctl(priv, mmc, clock); |
956 | 958 | ||
957 | #ifdef MMC_SUPPORTS_TUNING | 959 | #ifdef MMC_SUPPORTS_TUNING |
958 | if (mmc->clk_disable) { | 960 | if (mmc->clk_disable) { |
959 | #ifdef CONFIG_FSL_USDHC | 961 | #ifdef CONFIG_FSL_USDHC |
960 | esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); | 962 | esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); |
961 | #else | 963 | #else |
962 | esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); | 964 | esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); |
963 | #endif | 965 | #endif |
964 | } else { | 966 | } else { |
965 | #ifdef CONFIG_FSL_USDHC | 967 | #ifdef CONFIG_FSL_USDHC |
966 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | | 968 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | |
967 | VENDORSPEC_CKEN); | 969 | VENDORSPEC_CKEN); |
968 | #else | 970 | #else |
969 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); | 971 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); |
970 | #endif | 972 | #endif |
971 | } | 973 | } |
972 | 974 | ||
973 | if (priv->mode != mmc->selected_mode) { | 975 | if (priv->mode != mmc->selected_mode) { |
974 | ret = esdhc_set_timing(mmc); | 976 | ret = esdhc_set_timing(mmc); |
975 | if (ret) { | 977 | if (ret) { |
976 | printf("esdhc_set_timing error %d\n", ret); | 978 | printf("esdhc_set_timing error %d\n", ret); |
977 | return ret; | 979 | return ret; |
978 | } | 980 | } |
979 | } | 981 | } |
980 | 982 | ||
981 | if (priv->signal_voltage != mmc->signal_voltage) { | 983 | if (priv->signal_voltage != mmc->signal_voltage) { |
982 | ret = esdhc_set_voltage(mmc); | 984 | ret = esdhc_set_voltage(mmc); |
983 | if (ret) { | 985 | if (ret) { |
984 | printf("esdhc_set_voltage error %d\n", ret); | 986 | printf("esdhc_set_voltage error %d\n", ret); |
985 | return ret; | 987 | return ret; |
986 | } | 988 | } |
987 | } | 989 | } |
988 | #endif | 990 | #endif |
989 | 991 | ||
990 | /* Set the bus width */ | 992 | /* Set the bus width */ |
991 | esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); | 993 | esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); |
992 | 994 | ||
993 | if (mmc->bus_width == 4) | 995 | if (mmc->bus_width == 4) |
994 | esdhc_setbits32(®s->proctl, PROCTL_DTW_4); | 996 | esdhc_setbits32(®s->proctl, PROCTL_DTW_4); |
995 | else if (mmc->bus_width == 8) | 997 | else if (mmc->bus_width == 8) |
996 | esdhc_setbits32(®s->proctl, PROCTL_DTW_8); | 998 | esdhc_setbits32(®s->proctl, PROCTL_DTW_8); |
997 | 999 | ||
998 | return 0; | 1000 | return 0; |
999 | } | 1001 | } |
1000 | 1002 | ||
1001 | static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | 1003 | static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) |
1002 | { | 1004 | { |
1003 | struct fsl_esdhc *regs = priv->esdhc_regs; | 1005 | struct fsl_esdhc *regs = priv->esdhc_regs; |
1004 | ulong start; | 1006 | ulong start; |
1005 | 1007 | ||
1006 | /* Reset the entire host controller */ | 1008 | /* Reset the entire host controller */ |
1007 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); | 1009 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); |
1008 | 1010 | ||
1009 | /* Wait until the controller is available */ | 1011 | /* Wait until the controller is available */ |
1010 | start = get_timer(0); | 1012 | start = get_timer(0); |
1011 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { | 1013 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { |
1012 | if (get_timer(start) > 1000) | 1014 | if (get_timer(start) > 1000) |
1013 | return -ETIMEDOUT; | 1015 | return -ETIMEDOUT; |
1014 | } | 1016 | } |
1015 | 1017 | ||
1016 | #if defined(CONFIG_FSL_USDHC) | 1018 | #if defined(CONFIG_FSL_USDHC) |
1017 | /* RSTA doesn't reset MMC_BOOT register, so manually reset it */ | 1019 | /* RSTA doesn't reset MMC_BOOT register, so manually reset it */ |
1018 | esdhc_write32(®s->mmcboot, 0x0); | 1020 | esdhc_write32(®s->mmcboot, 0x0); |
1019 | /* Reset MIX_CTRL and CLK_TUNE_CTRL_STATUS regs to 0 */ | 1021 | /* Reset MIX_CTRL and CLK_TUNE_CTRL_STATUS regs to 0 */ |
1020 | esdhc_write32(®s->mixctrl, 0x0); | 1022 | esdhc_write32(®s->mixctrl, 0x0); |
1021 | esdhc_write32(®s->clktunectrlstatus, 0x0); | 1023 | esdhc_write32(®s->clktunectrlstatus, 0x0); |
1022 | 1024 | ||
1023 | /* Put VEND_SPEC to default value */ | 1025 | /* Put VEND_SPEC to default value */ |
1024 | if (priv->vs18_enable) | 1026 | if (priv->vs18_enable) |
1025 | esdhc_write32(®s->vendorspec, (VENDORSPEC_INIT | | 1027 | esdhc_write32(®s->vendorspec, (VENDORSPEC_INIT | |
1026 | ESDHC_VENDORSPEC_VSELECT)); | 1028 | ESDHC_VENDORSPEC_VSELECT)); |
1027 | else | 1029 | else |
1028 | esdhc_write32(®s->vendorspec, VENDORSPEC_INIT); | 1030 | esdhc_write32(®s->vendorspec, VENDORSPEC_INIT); |
1029 | 1031 | ||
1030 | /* Disable DLL_CTRL delay line */ | 1032 | /* Disable DLL_CTRL delay line */ |
1031 | esdhc_write32(®s->dllctrl, 0x0); | 1033 | esdhc_write32(®s->dllctrl, 0x0); |
1032 | #endif | 1034 | #endif |
1033 | 1035 | ||
1034 | #ifndef ARCH_MXC | 1036 | #ifndef ARCH_MXC |
1035 | /* Enable cache snooping */ | 1037 | /* Enable cache snooping */ |
1036 | esdhc_write32(®s->scr, 0x00000040); | 1038 | esdhc_write32(®s->scr, 0x00000040); |
1037 | #endif | 1039 | #endif |
1038 | 1040 | ||
1039 | #ifndef CONFIG_FSL_USDHC | 1041 | #ifndef CONFIG_FSL_USDHC |
1040 | esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); | 1042 | esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); |
1041 | #else | 1043 | #else |
1042 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN); | 1044 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN); |
1043 | #endif | 1045 | #endif |
1044 | 1046 | ||
1045 | /* Set the initial clock speed */ | 1047 | /* Set the initial clock speed */ |
1046 | mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE); | 1048 | mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE); |
1047 | 1049 | ||
1048 | /* Disable the BRR and BWR bits in IRQSTAT */ | 1050 | /* Disable the BRR and BWR bits in IRQSTAT */ |
1049 | esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); | 1051 | esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); |
1050 | 1052 | ||
1051 | #ifdef CONFIG_MCF5441x | 1053 | #ifdef CONFIG_MCF5441x |
1052 | esdhc_write32(®s->proctl, PROCTL_INIT | PROCTL_D3CD); | 1054 | esdhc_write32(®s->proctl, PROCTL_INIT | PROCTL_D3CD); |
1053 | #else | 1055 | #else |
1054 | /* Put the PROCTL reg back to the default */ | 1056 | /* Put the PROCTL reg back to the default */ |
1055 | esdhc_write32(®s->proctl, PROCTL_INIT); | 1057 | esdhc_write32(®s->proctl, PROCTL_INIT); |
1056 | #endif | 1058 | #endif |
1057 | 1059 | ||
1058 | /* Set timout to the maximum value */ | 1060 | /* Set timout to the maximum value */ |
1059 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); | 1061 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); |
1060 | 1062 | ||
1061 | return 0; | 1063 | return 0; |
1062 | } | 1064 | } |
1063 | 1065 | ||
1064 | static int esdhc_getcd_common(struct fsl_esdhc_priv *priv) | 1066 | static int esdhc_getcd_common(struct fsl_esdhc_priv *priv) |
1065 | { | 1067 | { |
1066 | struct fsl_esdhc *regs = priv->esdhc_regs; | 1068 | struct fsl_esdhc *regs = priv->esdhc_regs; |
1067 | int timeout = 1000; | 1069 | int timeout = 1000; |
1068 | 1070 | ||
1069 | #ifdef CONFIG_ESDHC_DETECT_QUIRK | 1071 | #ifdef CONFIG_ESDHC_DETECT_QUIRK |
1070 | if (CONFIG_ESDHC_DETECT_QUIRK) | 1072 | if (CONFIG_ESDHC_DETECT_QUIRK) |
1071 | return 1; | 1073 | return 1; |
1072 | #endif | 1074 | #endif |
1073 | 1075 | ||
1074 | #if CONFIG_IS_ENABLED(DM_MMC) | 1076 | #if CONFIG_IS_ENABLED(DM_MMC) |
1075 | if (priv->non_removable) | 1077 | if (priv->non_removable) |
1076 | return 1; | 1078 | return 1; |
1077 | 1079 | ||
1078 | if (priv->broken_cd) | 1080 | if (priv->broken_cd) |
1079 | return 1; | 1081 | return 1; |
1080 | #if CONFIG_IS_ENABLED(DM_GPIO) | 1082 | #if CONFIG_IS_ENABLED(DM_GPIO) |
1081 | if (dm_gpio_is_valid(&priv->cd_gpio)) | 1083 | if (dm_gpio_is_valid(&priv->cd_gpio)) |
1082 | return dm_gpio_get_value(&priv->cd_gpio); | 1084 | return dm_gpio_get_value(&priv->cd_gpio); |
1083 | #endif | 1085 | #endif |
1084 | #endif | 1086 | #endif |
1085 | 1087 | ||
1086 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_CINS) && --timeout) | 1088 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_CINS) && --timeout) |
1087 | udelay(1000); | 1089 | udelay(1000); |
1088 | 1090 | ||
1089 | return timeout > 0; | 1091 | return timeout > 0; |
1090 | } | 1092 | } |
1091 | 1093 | ||
1092 | static int esdhc_reset(struct fsl_esdhc *regs) | 1094 | static int esdhc_reset(struct fsl_esdhc *regs) |
1093 | { | 1095 | { |
1094 | ulong start; | 1096 | ulong start; |
1095 | 1097 | ||
1096 | /* reset the controller */ | 1098 | /* reset the controller */ |
1097 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); | 1099 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); |
1098 | 1100 | ||
1099 | /* hardware clears the bit when it is done */ | 1101 | /* hardware clears the bit when it is done */ |
1100 | start = get_timer(0); | 1102 | start = get_timer(0); |
1101 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { | 1103 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { |
1102 | if (get_timer(start) > 100) { | 1104 | if (get_timer(start) > 100) { |
1103 | printf("MMC/SD: Reset never completed.\n"); | 1105 | printf("MMC/SD: Reset never completed.\n"); |
1104 | return -ETIMEDOUT; | 1106 | return -ETIMEDOUT; |
1105 | } | 1107 | } |
1106 | } | 1108 | } |
1107 | 1109 | ||
1108 | return 0; | 1110 | return 0; |
1109 | } | 1111 | } |
1110 | 1112 | ||
1111 | #if !CONFIG_IS_ENABLED(DM_MMC) | 1113 | #if !CONFIG_IS_ENABLED(DM_MMC) |
1112 | static int esdhc_getcd(struct mmc *mmc) | 1114 | static int esdhc_getcd(struct mmc *mmc) |
1113 | { | 1115 | { |
1114 | struct fsl_esdhc_priv *priv = mmc->priv; | 1116 | struct fsl_esdhc_priv *priv = mmc->priv; |
1115 | 1117 | ||
1116 | return esdhc_getcd_common(priv); | 1118 | return esdhc_getcd_common(priv); |
1117 | } | 1119 | } |
1118 | 1120 | ||
1119 | static int esdhc_init(struct mmc *mmc) | 1121 | static int esdhc_init(struct mmc *mmc) |
1120 | { | 1122 | { |
1121 | struct fsl_esdhc_priv *priv = mmc->priv; | 1123 | struct fsl_esdhc_priv *priv = mmc->priv; |
1122 | 1124 | ||
1123 | return esdhc_init_common(priv, mmc); | 1125 | return esdhc_init_common(priv, mmc); |
1124 | } | 1126 | } |
1125 | 1127 | ||
1126 | static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, | 1128 | static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, |
1127 | struct mmc_data *data) | 1129 | struct mmc_data *data) |
1128 | { | 1130 | { |
1129 | struct fsl_esdhc_priv *priv = mmc->priv; | 1131 | struct fsl_esdhc_priv *priv = mmc->priv; |
1130 | 1132 | ||
1131 | return esdhc_send_cmd_common(priv, mmc, cmd, data); | 1133 | return esdhc_send_cmd_common(priv, mmc, cmd, data); |
1132 | } | 1134 | } |
1133 | 1135 | ||
1134 | static int esdhc_set_ios(struct mmc *mmc) | 1136 | static int esdhc_set_ios(struct mmc *mmc) |
1135 | { | 1137 | { |
1136 | struct fsl_esdhc_priv *priv = mmc->priv; | 1138 | struct fsl_esdhc_priv *priv = mmc->priv; |
1137 | 1139 | ||
1138 | return esdhc_set_ios_common(priv, mmc); | 1140 | return esdhc_set_ios_common(priv, mmc); |
1139 | } | 1141 | } |
1140 | 1142 | ||
1141 | static const struct mmc_ops esdhc_ops = { | 1143 | static const struct mmc_ops esdhc_ops = { |
1142 | .getcd = esdhc_getcd, | 1144 | .getcd = esdhc_getcd, |
1143 | .init = esdhc_init, | 1145 | .init = esdhc_init, |
1144 | .send_cmd = esdhc_send_cmd, | 1146 | .send_cmd = esdhc_send_cmd, |
1145 | .set_ios = esdhc_set_ios, | 1147 | .set_ios = esdhc_set_ios, |
1146 | }; | 1148 | }; |
1147 | #endif | 1149 | #endif |
1148 | 1150 | ||
1149 | static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, | 1151 | static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, |
1150 | struct fsl_esdhc_plat *plat) | 1152 | struct fsl_esdhc_plat *plat) |
1151 | { | 1153 | { |
1152 | struct mmc_config *cfg; | 1154 | struct mmc_config *cfg; |
1153 | struct fsl_esdhc *regs; | 1155 | struct fsl_esdhc *regs; |
1154 | u32 caps, voltage_caps; | 1156 | u32 caps, voltage_caps; |
1155 | int ret; | 1157 | int ret; |
1156 | 1158 | ||
1157 | if (!priv) | 1159 | if (!priv) |
1158 | return -EINVAL; | 1160 | return -EINVAL; |
1159 | 1161 | ||
1160 | regs = priv->esdhc_regs; | 1162 | regs = priv->esdhc_regs; |
1161 | 1163 | ||
1162 | /* First reset the eSDHC controller */ | 1164 | /* First reset the eSDHC controller */ |
1163 | ret = esdhc_reset(regs); | 1165 | ret = esdhc_reset(regs); |
1164 | if (ret) | 1166 | if (ret) |
1165 | return ret; | 1167 | return ret; |
1166 | 1168 | ||
1167 | #ifdef CONFIG_MCF5441x | 1169 | #ifdef CONFIG_MCF5441x |
1168 | /* ColdFire, using SDHC_DATA[3] for card detection */ | 1170 | /* ColdFire, using SDHC_DATA[3] for card detection */ |
1169 | esdhc_write32(®s->proctl, PROCTL_INIT | PROCTL_D3CD); | 1171 | esdhc_write32(®s->proctl, PROCTL_INIT | PROCTL_D3CD); |
1170 | #endif | 1172 | #endif |
1171 | 1173 | ||
1172 | #ifndef CONFIG_FSL_USDHC | 1174 | #ifndef CONFIG_FSL_USDHC |
1173 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN | 1175 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN |
1174 | | SYSCTL_IPGEN | SYSCTL_CKEN); | 1176 | | SYSCTL_IPGEN | SYSCTL_CKEN); |
1175 | /* Clearing tuning bits in case ROM has set it already */ | 1177 | /* Clearing tuning bits in case ROM has set it already */ |
1176 | esdhc_write32(®s->mixctrl, 0); | 1178 | esdhc_write32(®s->mixctrl, 0); |
1177 | esdhc_write32(®s->autoc12err, 0); | 1179 | esdhc_write32(®s->autoc12err, 0); |
1178 | esdhc_write32(®s->clktunectrlstatus, 0); | 1180 | esdhc_write32(®s->clktunectrlstatus, 0); |
1179 | #else | 1181 | #else |
1180 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | | 1182 | esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | |
1181 | VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN); | 1183 | VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN); |
1182 | #endif | 1184 | #endif |
1183 | 1185 | ||
1184 | if (priv->vs18_enable) | 1186 | if (priv->vs18_enable) |
1185 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | 1187 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); |
1186 | 1188 | ||
1187 | writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); | 1189 | writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); |
1188 | cfg = &plat->cfg; | 1190 | cfg = &plat->cfg; |
1189 | #ifndef CONFIG_DM_MMC | 1191 | #ifndef CONFIG_DM_MMC |
1190 | memset(cfg, '\0', sizeof(*cfg)); | 1192 | memset(cfg, '\0', sizeof(*cfg)); |
1191 | #endif | 1193 | #endif |
1192 | 1194 | ||
1193 | voltage_caps = 0; | 1195 | voltage_caps = 0; |
1194 | caps = esdhc_read32(®s->hostcapblt); | 1196 | caps = esdhc_read32(®s->hostcapblt); |
1195 | 1197 | ||
1196 | #ifdef CONFIG_MCF5441x | 1198 | #ifdef CONFIG_MCF5441x |
1197 | /* | 1199 | /* |
1198 | * MCF5441x RM declares in more points that sdhc clock speed must | 1200 | * MCF5441x RM declares in more points that sdhc clock speed must |
1199 | * never exceed 25 Mhz. From this, the HS bit needs to be disabled | 1201 | * never exceed 25 Mhz. From this, the HS bit needs to be disabled |
1200 | * from host capabilities. | 1202 | * from host capabilities. |
1201 | */ | 1203 | */ |
1202 | caps &= ~ESDHC_HOSTCAPBLT_HSS; | 1204 | caps &= ~ESDHC_HOSTCAPBLT_HSS; |
1203 | #endif | 1205 | #endif |
1204 | 1206 | ||
1205 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135 | 1207 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135 |
1206 | caps = caps & ~(ESDHC_HOSTCAPBLT_SRS | | 1208 | caps = caps & ~(ESDHC_HOSTCAPBLT_SRS | |
1207 | ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30); | 1209 | ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30); |
1208 | #endif | 1210 | #endif |
1209 | 1211 | ||
1210 | /* T4240 host controller capabilities register should have VS33 bit */ | 1212 | /* T4240 host controller capabilities register should have VS33 bit */ |
1211 | #ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 | 1213 | #ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 |
1212 | caps = caps | ESDHC_HOSTCAPBLT_VS33; | 1214 | caps = caps | ESDHC_HOSTCAPBLT_VS33; |
1213 | #endif | 1215 | #endif |
1214 | 1216 | ||
1215 | if (caps & ESDHC_HOSTCAPBLT_VS18) | 1217 | if (caps & ESDHC_HOSTCAPBLT_VS18) |
1216 | voltage_caps |= MMC_VDD_165_195; | 1218 | voltage_caps |= MMC_VDD_165_195; |
1217 | if (caps & ESDHC_HOSTCAPBLT_VS30) | 1219 | if (caps & ESDHC_HOSTCAPBLT_VS30) |
1218 | voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31; | 1220 | voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31; |
1219 | if (caps & ESDHC_HOSTCAPBLT_VS33) | 1221 | if (caps & ESDHC_HOSTCAPBLT_VS33) |
1220 | voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34; | 1222 | voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34; |
1221 | 1223 | ||
1222 | cfg->name = "FSL_SDHC"; | 1224 | cfg->name = "FSL_SDHC"; |
1223 | #if !CONFIG_IS_ENABLED(DM_MMC) | 1225 | #if !CONFIG_IS_ENABLED(DM_MMC) |
1224 | cfg->ops = &esdhc_ops; | 1226 | cfg->ops = &esdhc_ops; |
1225 | #endif | 1227 | #endif |
1226 | #ifdef CONFIG_SYS_SD_VOLTAGE | 1228 | #ifdef CONFIG_SYS_SD_VOLTAGE |
1227 | cfg->voltages = CONFIG_SYS_SD_VOLTAGE; | 1229 | cfg->voltages = CONFIG_SYS_SD_VOLTAGE; |
1228 | #else | 1230 | #else |
1229 | cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; | 1231 | cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; |
1230 | #endif | 1232 | #endif |
1231 | if ((cfg->voltages & voltage_caps) == 0) { | 1233 | if ((cfg->voltages & voltage_caps) == 0) { |
1232 | printf("voltage not supported by controller\n"); | 1234 | printf("voltage not supported by controller\n"); |
1233 | return -1; | 1235 | return -1; |
1234 | } | 1236 | } |
1235 | 1237 | ||
1236 | if (priv->bus_width == 8) | 1238 | if (priv->bus_width == 8) |
1237 | cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; | 1239 | cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; |
1238 | else if (priv->bus_width == 4) | 1240 | else if (priv->bus_width == 4) |
1239 | cfg->host_caps = MMC_MODE_4BIT; | 1241 | cfg->host_caps = MMC_MODE_4BIT; |
1240 | 1242 | ||
1241 | cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; | 1243 | cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; |
1242 | #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE | 1244 | #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE |
1243 | cfg->host_caps |= MMC_MODE_DDR_52MHz; | 1245 | cfg->host_caps |= MMC_MODE_DDR_52MHz; |
1244 | #endif | 1246 | #endif |
1245 | 1247 | ||
1246 | if (priv->bus_width > 0) { | 1248 | if (priv->bus_width > 0) { |
1247 | if (priv->bus_width < 8) | 1249 | if (priv->bus_width < 8) |
1248 | cfg->host_caps &= ~MMC_MODE_8BIT; | 1250 | cfg->host_caps &= ~MMC_MODE_8BIT; |
1249 | if (priv->bus_width < 4) | 1251 | if (priv->bus_width < 4) |
1250 | cfg->host_caps &= ~MMC_MODE_4BIT; | 1252 | cfg->host_caps &= ~MMC_MODE_4BIT; |
1251 | } | 1253 | } |
1252 | 1254 | ||
1253 | if (caps & ESDHC_HOSTCAPBLT_HSS) | 1255 | if (caps & ESDHC_HOSTCAPBLT_HSS) |
1254 | cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; | 1256 | cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; |
1255 | 1257 | ||
1256 | #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK | 1258 | #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK |
1257 | if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK) | 1259 | if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK) |
1258 | cfg->host_caps &= ~MMC_MODE_8BIT; | 1260 | cfg->host_caps &= ~MMC_MODE_8BIT; |
1259 | #endif | 1261 | #endif |
1260 | 1262 | ||
1261 | cfg->host_caps |= priv->caps; | 1263 | cfg->host_caps |= priv->caps; |
1262 | 1264 | ||
1263 | cfg->f_min = 400000; | 1265 | cfg->f_min = 400000; |
1264 | cfg->f_max = min(priv->sdhc_clk, (u32)200000000); | 1266 | cfg->f_max = min(priv->sdhc_clk, (u32)200000000); |
1265 | 1267 | ||
1266 | cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; | 1268 | cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; |
1267 | 1269 | ||
1268 | writel(0, ®s->dllctrl); | 1270 | writel(0, ®s->dllctrl); |
1269 | if (priv->flags & ESDHC_FLAG_USDHC) { | 1271 | if (priv->flags & ESDHC_FLAG_USDHC) { |
1270 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { | 1272 | if (priv->flags & ESDHC_FLAG_STD_TUNING) { |
1271 | u32 val = readl(®s->tuning_ctrl); | 1273 | u32 val = readl(®s->tuning_ctrl); |
1272 | 1274 | ||
1273 | val |= ESDHC_STD_TUNING_EN; | 1275 | val |= ESDHC_STD_TUNING_EN; |
1274 | val &= ~ESDHC_TUNING_START_TAP_MASK; | 1276 | val &= ~ESDHC_TUNING_START_TAP_MASK; |
1275 | val |= priv->tuning_start_tap; | 1277 | val |= priv->tuning_start_tap; |
1276 | val &= ~ESDHC_TUNING_STEP_MASK; | 1278 | val &= ~ESDHC_TUNING_STEP_MASK; |
1277 | val |= (priv->tuning_step) << ESDHC_TUNING_STEP_SHIFT; | 1279 | val |= (priv->tuning_step) << ESDHC_TUNING_STEP_SHIFT; |
1278 | writel(val, ®s->tuning_ctrl); | 1280 | writel(val, ®s->tuning_ctrl); |
1279 | } | 1281 | } |
1280 | } | 1282 | } |
1281 | 1283 | ||
1282 | return 0; | 1284 | return 0; |
1283 | } | 1285 | } |
1284 | 1286 | ||
1285 | #if !CONFIG_IS_ENABLED(DM_MMC) | 1287 | #if !CONFIG_IS_ENABLED(DM_MMC) |
1286 | static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg, | 1288 | static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg, |
1287 | struct fsl_esdhc_priv *priv) | 1289 | struct fsl_esdhc_priv *priv) |
1288 | { | 1290 | { |
1289 | if (!cfg || !priv) | 1291 | if (!cfg || !priv) |
1290 | return -EINVAL; | 1292 | return -EINVAL; |
1291 | 1293 | ||
1292 | priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base); | 1294 | priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base); |
1293 | priv->bus_width = cfg->max_bus_width; | 1295 | priv->bus_width = cfg->max_bus_width; |
1294 | priv->sdhc_clk = cfg->sdhc_clk; | 1296 | priv->sdhc_clk = cfg->sdhc_clk; |
1295 | priv->wp_enable = cfg->wp_enable; | 1297 | priv->wp_enable = cfg->wp_enable; |
1296 | priv->vs18_enable = cfg->vs18_enable; | 1298 | priv->vs18_enable = cfg->vs18_enable; |
1297 | 1299 | ||
1298 | return 0; | 1300 | return 0; |
1299 | }; | 1301 | }; |
1300 | 1302 | ||
1301 | int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) | 1303 | int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) |
1302 | { | 1304 | { |
1303 | struct fsl_esdhc_plat *plat; | 1305 | struct fsl_esdhc_plat *plat; |
1304 | struct fsl_esdhc_priv *priv; | 1306 | struct fsl_esdhc_priv *priv; |
1305 | struct mmc *mmc; | 1307 | struct mmc *mmc; |
1306 | int ret; | 1308 | int ret; |
1307 | 1309 | ||
1308 | if (!cfg) | 1310 | if (!cfg) |
1309 | return -EINVAL; | 1311 | return -EINVAL; |
1310 | 1312 | ||
1311 | priv = calloc(sizeof(struct fsl_esdhc_priv), 1); | 1313 | priv = calloc(sizeof(struct fsl_esdhc_priv), 1); |
1312 | if (!priv) | 1314 | if (!priv) |
1313 | return -ENOMEM; | 1315 | return -ENOMEM; |
1314 | plat = calloc(sizeof(struct fsl_esdhc_plat), 1); | 1316 | plat = calloc(sizeof(struct fsl_esdhc_plat), 1); |
1315 | if (!plat) { | 1317 | if (!plat) { |
1316 | free(priv); | 1318 | free(priv); |
1317 | return -ENOMEM; | 1319 | return -ENOMEM; |
1318 | } | 1320 | } |
1319 | 1321 | ||
1320 | ret = fsl_esdhc_cfg_to_priv(cfg, priv); | 1322 | ret = fsl_esdhc_cfg_to_priv(cfg, priv); |
1321 | if (ret) { | 1323 | if (ret) { |
1322 | debug("%s xlate failure\n", __func__); | 1324 | debug("%s xlate failure\n", __func__); |
1323 | free(plat); | 1325 | free(plat); |
1324 | free(priv); | 1326 | free(priv); |
1325 | return ret; | 1327 | return ret; |
1326 | } | 1328 | } |
1327 | 1329 | ||
1328 | #ifdef CONFIG_MX6 | 1330 | #ifdef CONFIG_MX6 |
1329 | if (mx6_esdhc_fused(cfg->esdhc_base)) { | 1331 | if (mx6_esdhc_fused(cfg->esdhc_base)) { |
1330 | printf("ESDHC@0x%lx is fused, disable it\n", cfg->esdhc_base); | 1332 | printf("ESDHC@0x%lx is fused, disable it\n", cfg->esdhc_base); |
1331 | free(priv); | 1333 | free(priv); |
1332 | return -ENODEV; | 1334 | return -ENODEV; |
1333 | } | 1335 | } |
1334 | #endif | 1336 | #endif |
1335 | 1337 | ||
1336 | ret = fsl_esdhc_init(priv, plat); | 1338 | ret = fsl_esdhc_init(priv, plat); |
1337 | if (ret) { | 1339 | if (ret) { |
1338 | debug("%s init failure\n", __func__); | 1340 | debug("%s init failure\n", __func__); |
1339 | free(plat); | 1341 | free(plat); |
1340 | free(priv); | 1342 | free(priv); |
1341 | return ret; | 1343 | return ret; |
1342 | } | 1344 | } |
1343 | 1345 | ||
1344 | mmc = mmc_create(&plat->cfg, priv); | 1346 | mmc = mmc_create(&plat->cfg, priv); |
1345 | if (!mmc) | 1347 | if (!mmc) |
1346 | return -EIO; | 1348 | return -EIO; |
1347 | 1349 | ||
1348 | priv->mmc = mmc; | 1350 | priv->mmc = mmc; |
1349 | 1351 | ||
1350 | return 0; | 1352 | return 0; |
1351 | } | 1353 | } |
1352 | 1354 | ||
1353 | int fsl_esdhc_mmc_init(bd_t *bis) | 1355 | int fsl_esdhc_mmc_init(bd_t *bis) |
1354 | { | 1356 | { |
1355 | struct fsl_esdhc_cfg *cfg; | 1357 | struct fsl_esdhc_cfg *cfg; |
1356 | 1358 | ||
1357 | cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1); | 1359 | cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1); |
1358 | cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR; | 1360 | cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR; |
1359 | cfg->sdhc_clk = gd->arch.sdhc_clk; | 1361 | cfg->sdhc_clk = gd->arch.sdhc_clk; |
1360 | return fsl_esdhc_initialize(bis, cfg); | 1362 | return fsl_esdhc_initialize(bis, cfg); |
1361 | } | 1363 | } |
1362 | #endif | 1364 | #endif |
1363 | 1365 | ||
1364 | #ifdef CONFIG_OF_LIBFDT | 1366 | #ifdef CONFIG_OF_LIBFDT |
1365 | __weak int esdhc_status_fixup(void *blob, const char *compat) | 1367 | __weak int esdhc_status_fixup(void *blob, const char *compat) |
1366 | { | 1368 | { |
1367 | #ifdef CONFIG_FSL_ESDHC_PIN_MUX | 1369 | #ifdef CONFIG_FSL_ESDHC_PIN_MUX |
1368 | if (!hwconfig("esdhc")) { | 1370 | if (!hwconfig("esdhc")) { |
1369 | do_fixup_by_compat(blob, compat, "status", "disabled", | 1371 | do_fixup_by_compat(blob, compat, "status", "disabled", |
1370 | sizeof("disabled"), 1); | 1372 | sizeof("disabled"), 1); |
1371 | return 1; | 1373 | return 1; |
1372 | } | 1374 | } |
1373 | #endif | 1375 | #endif |
1374 | return 0; | 1376 | return 0; |
1375 | } | 1377 | } |
1376 | 1378 | ||
1377 | void fdt_fixup_esdhc(void *blob, bd_t *bd) | 1379 | void fdt_fixup_esdhc(void *blob, bd_t *bd) |
1378 | { | 1380 | { |
1379 | const char *compat = "fsl,esdhc"; | 1381 | const char *compat = "fsl,esdhc"; |
1380 | 1382 | ||
1381 | if (esdhc_status_fixup(blob, compat)) | 1383 | if (esdhc_status_fixup(blob, compat)) |
1382 | return; | 1384 | return; |
1383 | 1385 | ||
1384 | do_fixup_by_compat_u32(blob, compat, "clock-frequency", | 1386 | do_fixup_by_compat_u32(blob, compat, "clock-frequency", |
1385 | gd->arch.sdhc_clk, 1); | 1387 | gd->arch.sdhc_clk, 1); |
1386 | } | 1388 | } |
1387 | #endif | 1389 | #endif |
1388 | 1390 | ||
1389 | #if CONFIG_IS_ENABLED(DM_MMC) | 1391 | #if CONFIG_IS_ENABLED(DM_MMC) |
1390 | #include <asm/arch/clock.h> | 1392 | #include <asm/arch/clock.h> |
1391 | __weak void init_clk_usdhc(u32 index) | 1393 | __weak void init_clk_usdhc(u32 index) |
1392 | { | 1394 | { |
1393 | } | 1395 | } |
1394 | 1396 | ||
1395 | static int fsl_esdhc_probe(struct udevice *dev) | 1397 | static int fsl_esdhc_probe(struct udevice *dev) |
1396 | { | 1398 | { |
1397 | struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); | 1399 | struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); |
1398 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); | 1400 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); |
1399 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 1401 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
1400 | const void *fdt = gd->fdt_blob; | 1402 | const void *fdt = gd->fdt_blob; |
1401 | int node = dev_of_offset(dev); | 1403 | int node = dev_of_offset(dev); |
1402 | struct esdhc_soc_data *data = | 1404 | struct esdhc_soc_data *data = |
1403 | (struct esdhc_soc_data *)dev_get_driver_data(dev); | 1405 | (struct esdhc_soc_data *)dev_get_driver_data(dev); |
1404 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | 1406 | #if CONFIG_IS_ENABLED(DM_REGULATOR) |
1405 | struct udevice *vqmmc_dev; | 1407 | struct udevice *vqmmc_dev; |
1406 | #endif | 1408 | #endif |
1407 | fdt_addr_t addr; | 1409 | fdt_addr_t addr; |
1408 | unsigned int val; | 1410 | unsigned int val; |
1409 | struct mmc *mmc; | 1411 | struct mmc *mmc; |
1410 | #if !CONFIG_IS_ENABLED(BLK) | 1412 | #if !CONFIG_IS_ENABLED(BLK) |
1411 | struct blk_desc *bdesc; | 1413 | struct blk_desc *bdesc; |
1412 | #endif | 1414 | #endif |
1413 | int ret; | 1415 | int ret; |
1414 | 1416 | ||
1415 | addr = dev_read_addr(dev); | 1417 | addr = dev_read_addr(dev); |
1416 | if (addr == FDT_ADDR_T_NONE) | 1418 | if (addr == FDT_ADDR_T_NONE) |
1417 | return -EINVAL; | 1419 | return -EINVAL; |
1418 | 1420 | ||
1419 | #ifdef CONFIG_MX6 | 1421 | #ifdef CONFIG_MX6 |
1420 | if (mx6_esdhc_fused(addr)) { | 1422 | if (mx6_esdhc_fused(addr)) { |
1421 | printf("ESDHC@0x%lx is fused, disable it\n", addr); | 1423 | printf("ESDHC@0x%lx is fused, disable it\n", addr); |
1422 | return -ENODEV; | 1424 | return -ENODEV; |
1423 | } | 1425 | } |
1424 | #endif | 1426 | #endif |
1425 | 1427 | ||
1426 | priv->esdhc_regs = (struct fsl_esdhc *)addr; | 1428 | priv->esdhc_regs = (struct fsl_esdhc *)addr; |
1427 | priv->dev = dev; | 1429 | priv->dev = dev; |
1428 | priv->mode = -1; | 1430 | priv->mode = -1; |
1429 | if (data) | 1431 | if (data) |
1430 | priv->flags = data->flags; | 1432 | priv->flags = data->flags; |
1431 | 1433 | ||
1432 | val = dev_read_u32_default(dev, "bus-width", -1); | 1434 | val = dev_read_u32_default(dev, "bus-width", -1); |
1433 | if (val == 8) | 1435 | if (val == 8) |
1434 | priv->bus_width = 8; | 1436 | priv->bus_width = 8; |
1435 | else if (val == 4) | 1437 | else if (val == 4) |
1436 | priv->bus_width = 4; | 1438 | priv->bus_width = 4; |
1437 | else | 1439 | else |
1438 | priv->bus_width = 1; | 1440 | priv->bus_width = 1; |
1439 | 1441 | ||
1440 | val = fdtdec_get_int(fdt, node, "fsl,tuning-step", 1); | 1442 | val = fdtdec_get_int(fdt, node, "fsl,tuning-step", 1); |
1441 | priv->tuning_step = val; | 1443 | priv->tuning_step = val; |
1442 | val = fdtdec_get_int(fdt, node, "fsl,tuning-start-tap", | 1444 | val = fdtdec_get_int(fdt, node, "fsl,tuning-start-tap", |
1443 | ESDHC_TUNING_START_TAP_DEFAULT); | 1445 | ESDHC_TUNING_START_TAP_DEFAULT); |
1444 | priv->tuning_start_tap = val; | 1446 | priv->tuning_start_tap = val; |
1445 | val = fdtdec_get_int(fdt, node, "fsl,strobe-dll-delay-target", | 1447 | val = fdtdec_get_int(fdt, node, "fsl,strobe-dll-delay-target", |
1446 | ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT); | 1448 | ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT); |
1447 | priv->strobe_dll_delay_target = val; | 1449 | priv->strobe_dll_delay_target = val; |
1448 | 1450 | ||
1449 | if (dev_read_bool(dev, "broken-cd")) | 1451 | if (dev_read_bool(dev, "broken-cd")) |
1450 | priv->broken_cd = 1; | 1452 | priv->broken_cd = 1; |
1451 | 1453 | ||
1452 | if (dev_read_bool(dev, "non-removable")) { | 1454 | if (dev_read_bool(dev, "non-removable")) { |
1453 | priv->non_removable = 1; | 1455 | priv->non_removable = 1; |
1454 | } else { | 1456 | } else { |
1455 | priv->non_removable = 0; | 1457 | priv->non_removable = 0; |
1456 | #if CONFIG_IS_ENABLED(DM_GPIO) | 1458 | #if CONFIG_IS_ENABLED(DM_GPIO) |
1457 | gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, | 1459 | gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, |
1458 | GPIOD_IS_IN); | 1460 | GPIOD_IS_IN); |
1459 | #endif | 1461 | #endif |
1460 | } | 1462 | } |
1461 | 1463 | ||
1462 | if (dev_read_prop(dev, "fsl,wp-controller", NULL)) { | 1464 | if (dev_read_prop(dev, "fsl,wp-controller", NULL)) { |
1463 | priv->wp_enable = 1; | 1465 | priv->wp_enable = 1; |
1464 | } else { | 1466 | } else { |
1465 | priv->wp_enable = 0; | 1467 | priv->wp_enable = 0; |
1466 | #if CONFIG_IS_ENABLED(DM_GPIO) | 1468 | #if CONFIG_IS_ENABLED(DM_GPIO) |
1467 | gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, | 1469 | gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, |
1468 | GPIOD_IS_IN); | 1470 | GPIOD_IS_IN); |
1469 | #endif | 1471 | #endif |
1470 | } | 1472 | } |
1471 | 1473 | ||
1472 | priv->vs18_enable = 0; | 1474 | priv->vs18_enable = 0; |
1473 | 1475 | ||
1474 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | 1476 | #if CONFIG_IS_ENABLED(DM_REGULATOR) |
1475 | /* | 1477 | /* |
1476 | * If emmc I/O has a fixed voltage at 1.8V, this must be provided, | 1478 | * If emmc I/O has a fixed voltage at 1.8V, this must be provided, |
1477 | * otherwise, emmc will work abnormally. | 1479 | * otherwise, emmc will work abnormally. |
1478 | */ | 1480 | */ |
1479 | ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); | 1481 | ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev); |
1480 | if (ret) { | 1482 | if (ret) { |
1481 | dev_dbg(dev, "no vqmmc-supply\n"); | 1483 | dev_dbg(dev, "no vqmmc-supply\n"); |
1482 | } else { | 1484 | } else { |
1483 | ret = regulator_set_enable(vqmmc_dev, true); | 1485 | ret = regulator_set_enable(vqmmc_dev, true); |
1484 | if (ret) { | 1486 | if (ret) { |
1485 | dev_err(dev, "fail to enable vqmmc-supply\n"); | 1487 | dev_err(dev, "fail to enable vqmmc-supply\n"); |
1486 | return ret; | 1488 | return ret; |
1487 | } | 1489 | } |
1488 | 1490 | ||
1489 | if (regulator_get_value(vqmmc_dev) == 1800000) | 1491 | if (regulator_get_value(vqmmc_dev) == 1800000) |
1490 | priv->vs18_enable = 1; | 1492 | priv->vs18_enable = 1; |
1491 | } | 1493 | } |
1492 | #endif | 1494 | #endif |
1493 | 1495 | ||
1494 | /* | 1496 | /* |
1495 | * TODO: | 1497 | * TODO: |
1496 | * Because lack of clk driver, if SDHC clk is not enabled, | 1498 | * Because lack of clk driver, if SDHC clk is not enabled, |
1497 | * need to enable it first before this driver is invoked. | 1499 | * need to enable it first before this driver is invoked. |
1498 | * | 1500 | * |
1499 | * we use MXC_ESDHC_CLK to get clk freq. | 1501 | * we use MXC_ESDHC_CLK to get clk freq. |
1500 | * If one would like to make this function work, | 1502 | * If one would like to make this function work, |
1501 | * the aliases should be provided in dts as this: | 1503 | * the aliases should be provided in dts as this: |
1502 | * | 1504 | * |
1503 | * aliases { | 1505 | * aliases { |
1504 | * mmc0 = &usdhc1; | 1506 | * mmc0 = &usdhc1; |
1505 | * mmc1 = &usdhc2; | 1507 | * mmc1 = &usdhc2; |
1506 | * mmc2 = &usdhc3; | 1508 | * mmc2 = &usdhc3; |
1507 | * mmc3 = &usdhc4; | 1509 | * mmc3 = &usdhc4; |
1508 | * }; | 1510 | * }; |
1509 | * Then if your board only supports mmc2 and mmc3, but we can | 1511 | * Then if your board only supports mmc2 and mmc3, but we can |
1510 | * correctly get the seq as 2 and 3, then let mxc_get_clock | 1512 | * correctly get the seq as 2 and 3, then let mxc_get_clock |
1511 | * work as expected. | 1513 | * work as expected. |
1512 | */ | 1514 | */ |
1513 | 1515 | ||
1514 | #if CONFIG_IS_ENABLED(CLK) | 1516 | #if CONFIG_IS_ENABLED(CLK) |
1515 | /* Assigned clock already set clock */ | 1517 | /* Assigned clock already set clock */ |
1518 | ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk); | ||
1519 | if (!ret) { | ||
1520 | ret = clk_enable(&priv->ipg_clk); | ||
1521 | if (ret) { | ||
1522 | printf("Failed to enable ipg_clk\n"); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | } | ||
1526 | |||
1527 | ret = clk_get_by_name(dev, "ahb", &priv->ahb_clk); | ||
1528 | if (!ret) { | ||
1529 | ret = clk_enable(&priv->ahb_clk); | ||
1530 | if (ret) { | ||
1531 | printf("Failed to enable ahb_clk\n"); | ||
1532 | return ret; | ||
1533 | } | ||
1534 | } | ||
1535 | |||
1516 | ret = clk_get_by_name(dev, "per", &priv->per_clk); | 1536 | ret = clk_get_by_name(dev, "per", &priv->per_clk); |
1517 | if (ret) { | 1537 | if (ret) { |
1518 | printf("Failed to get per_clk\n"); | 1538 | printf("Failed to get per_clk\n"); |
1519 | return ret; | 1539 | return ret; |
1520 | } | 1540 | } |
1521 | ret = clk_enable(&priv->per_clk); | 1541 | ret = clk_enable(&priv->per_clk); |
1522 | if (ret) { | 1542 | if (ret) { |
1523 | printf("Failed to enable per_clk\n"); | 1543 | printf("Failed to enable per_clk\n"); |
1524 | return ret; | 1544 | return ret; |
1525 | } | 1545 | } |
1526 | 1546 | ||
1527 | priv->sdhc_clk = clk_get_rate(&priv->per_clk); | 1547 | priv->sdhc_clk = clk_get_rate(&priv->per_clk); |
1528 | #else | 1548 | #else |
1529 | init_clk_usdhc(dev->seq); | 1549 | init_clk_usdhc(dev->seq); |
1530 | 1550 | ||
1531 | priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); | 1551 | priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); |
1532 | if (priv->sdhc_clk <= 0) { | 1552 | if (priv->sdhc_clk <= 0) { |
1533 | dev_err(dev, "Unable to get clk for %s\n", dev->name); | 1553 | dev_err(dev, "Unable to get clk for %s\n", dev->name); |
1534 | return -EINVAL; | 1554 | return -EINVAL; |
1535 | } | 1555 | } |
1536 | #endif | 1556 | #endif |
1537 | 1557 | ||
1538 | ret = fsl_esdhc_init(priv, plat); | 1558 | ret = fsl_esdhc_init(priv, plat); |
1539 | if (ret) { | 1559 | if (ret) { |
1540 | dev_err(dev, "fsl_esdhc_init failure\n"); | 1560 | dev_err(dev, "fsl_esdhc_init failure\n"); |
1541 | return ret; | 1561 | return ret; |
1542 | } | 1562 | } |
1543 | 1563 | ||
1544 | ret = mmc_of_parse(dev, &plat->cfg); | 1564 | ret = mmc_of_parse(dev, &plat->cfg); |
1545 | if (ret) | 1565 | if (ret) |
1546 | return ret; | 1566 | return ret; |
1547 | 1567 | ||
1548 | mmc = &plat->mmc; | 1568 | mmc = &plat->mmc; |
1549 | mmc->cfg = &plat->cfg; | 1569 | mmc->cfg = &plat->cfg; |
1550 | mmc->dev = dev; | 1570 | mmc->dev = dev; |
1551 | #if !CONFIG_IS_ENABLED(BLK) | 1571 | #if !CONFIG_IS_ENABLED(BLK) |
1552 | mmc->priv = priv; | 1572 | mmc->priv = priv; |
1553 | 1573 | ||
1554 | /* Setup dsr related values */ | 1574 | /* Setup dsr related values */ |
1555 | mmc->dsr_imp = 0; | 1575 | mmc->dsr_imp = 0; |
1556 | mmc->dsr = ESDHC_DRIVER_STAGE_VALUE; | 1576 | mmc->dsr = ESDHC_DRIVER_STAGE_VALUE; |
1557 | /* Setup the universal parts of the block interface just once */ | 1577 | /* Setup the universal parts of the block interface just once */ |
1558 | bdesc = mmc_get_blk_desc(mmc); | 1578 | bdesc = mmc_get_blk_desc(mmc); |
1559 | bdesc->if_type = IF_TYPE_MMC; | 1579 | bdesc->if_type = IF_TYPE_MMC; |
1560 | bdesc->removable = 1; | 1580 | bdesc->removable = 1; |
1561 | bdesc->devnum = mmc_get_next_devnum(); | 1581 | bdesc->devnum = mmc_get_next_devnum(); |
1562 | bdesc->block_read = mmc_bread; | 1582 | bdesc->block_read = mmc_bread; |
1563 | bdesc->block_write = mmc_bwrite; | 1583 | bdesc->block_write = mmc_bwrite; |
1564 | bdesc->block_erase = mmc_berase; | 1584 | bdesc->block_erase = mmc_berase; |
1565 | 1585 | ||
1566 | /* setup initial part type */ | 1586 | /* setup initial part type */ |
1567 | bdesc->part_type = mmc->cfg->part_type; | 1587 | bdesc->part_type = mmc->cfg->part_type; |
1568 | mmc_list_add(mmc); | 1588 | mmc_list_add(mmc); |
1569 | #endif | 1589 | #endif |
1570 | 1590 | ||
1571 | upriv->mmc = mmc; | 1591 | upriv->mmc = mmc; |
1572 | 1592 | ||
1573 | return esdhc_init_common(priv, mmc); | 1593 | return esdhc_init_common(priv, mmc); |
1574 | } | 1594 | } |
1575 | 1595 | ||
1576 | #if CONFIG_IS_ENABLED(DM_MMC) | 1596 | #if CONFIG_IS_ENABLED(DM_MMC) |
1577 | static int fsl_esdhc_get_cd(struct udevice *dev) | 1597 | static int fsl_esdhc_get_cd(struct udevice *dev) |
1578 | { | 1598 | { |
1579 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 1599 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
1580 | 1600 | ||
1581 | return esdhc_getcd_common(priv); | 1601 | return esdhc_getcd_common(priv); |
1582 | } | 1602 | } |
1583 | 1603 | ||
1584 | static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, | 1604 | static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, |
1585 | struct mmc_data *data) | 1605 | struct mmc_data *data) |
1586 | { | 1606 | { |
1587 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); | 1607 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); |
1588 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 1608 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
1589 | 1609 | ||
1590 | return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data); | 1610 | return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data); |
1591 | } | 1611 | } |
1592 | 1612 | ||
1593 | static int fsl_esdhc_set_ios(struct udevice *dev) | 1613 | static int fsl_esdhc_set_ios(struct udevice *dev) |
1594 | { | 1614 | { |
1595 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); | 1615 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); |
1596 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 1616 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
1597 | 1617 | ||
1598 | return esdhc_set_ios_common(priv, &plat->mmc); | 1618 | return esdhc_set_ios_common(priv, &plat->mmc); |
1599 | } | 1619 | } |
1600 | 1620 | ||
1601 | #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) | 1621 | #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) |
1602 | static int fsl_esdhc_set_enhanced_strobe(struct udevice *dev) | 1622 | static int fsl_esdhc_set_enhanced_strobe(struct udevice *dev) |
1603 | { | 1623 | { |
1604 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); | 1624 | struct fsl_esdhc_priv *priv = dev_get_priv(dev); |
1605 | struct fsl_esdhc *regs = priv->esdhc_regs; | 1625 | struct fsl_esdhc *regs = priv->esdhc_regs; |
1606 | u32 m; | 1626 | u32 m; |
1607 | 1627 | ||
1608 | m = readl(®s->mixctrl); | 1628 | m = readl(®s->mixctrl); |
1609 | m |= MIX_CTRL_HS400_ES; | 1629 | m |= MIX_CTRL_HS400_ES; |
1610 | writel(m, ®s->mixctrl); | 1630 | writel(m, ®s->mixctrl); |
1611 | 1631 | ||
1612 | return 0; | 1632 | return 0; |
1613 | } | 1633 | } |
1614 | #endif | 1634 | #endif |
1615 | 1635 | ||
1616 | static const struct dm_mmc_ops fsl_esdhc_ops = { | 1636 | static const struct dm_mmc_ops fsl_esdhc_ops = { |
1617 | .get_cd = fsl_esdhc_get_cd, | 1637 | .get_cd = fsl_esdhc_get_cd, |
1618 | .send_cmd = fsl_esdhc_send_cmd, | 1638 | .send_cmd = fsl_esdhc_send_cmd, |
1619 | .set_ios = fsl_esdhc_set_ios, | 1639 | .set_ios = fsl_esdhc_set_ios, |
1620 | #ifdef MMC_SUPPORTS_TUNING | 1640 | #ifdef MMC_SUPPORTS_TUNING |
1621 | .execute_tuning = fsl_esdhc_execute_tuning, | 1641 | .execute_tuning = fsl_esdhc_execute_tuning, |
1622 | #endif | 1642 | #endif |
1623 | #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) | 1643 | #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) |
1624 | .set_enhanced_strobe = fsl_esdhc_set_enhanced_strobe, | 1644 | .set_enhanced_strobe = fsl_esdhc_set_enhanced_strobe, |
1625 | #endif | 1645 | #endif |
1626 | }; | 1646 | }; |
1627 | #endif | 1647 | #endif |
1628 | 1648 | ||
1629 | static struct esdhc_soc_data usdhc_imx7d_data = { | 1649 | static struct esdhc_soc_data usdhc_imx7d_data = { |
1630 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | 1650 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
1631 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | 1651 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
1632 | | ESDHC_FLAG_HS400, | 1652 | | ESDHC_FLAG_HS400, |
1633 | }; | 1653 | }; |
1634 | 1654 | ||
1635 | static struct esdhc_soc_data usdhc_imx8qm_data = { | 1655 | static struct esdhc_soc_data usdhc_imx8qm_data = { |
1636 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | | 1656 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | |
1637 | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | | 1657 | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | |
1638 | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES, | 1658 | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES, |
1639 | }; | 1659 | }; |
1640 | 1660 | ||
1641 | static const struct udevice_id fsl_esdhc_ids[] = { | 1661 | static const struct udevice_id fsl_esdhc_ids[] = { |
1642 | { .compatible = "fsl,imx53-esdhc", }, | 1662 | { .compatible = "fsl,imx53-esdhc", }, |
1643 | { .compatible = "fsl,imx6ul-usdhc", }, | 1663 | { .compatible = "fsl,imx6ul-usdhc", }, |
1644 | { .compatible = "fsl,imx6sx-usdhc", }, | 1664 | { .compatible = "fsl,imx6sx-usdhc", }, |
1645 | { .compatible = "fsl,imx6sl-usdhc", }, | 1665 | { .compatible = "fsl,imx6sl-usdhc", }, |
1646 | { .compatible = "fsl,imx6q-usdhc", }, | 1666 | { .compatible = "fsl,imx6q-usdhc", }, |
1647 | { .compatible = "fsl,imx7d-usdhc", .data = (ulong)&usdhc_imx7d_data,}, | 1667 | { .compatible = "fsl,imx7d-usdhc", .data = (ulong)&usdhc_imx7d_data,}, |
1648 | { .compatible = "fsl,imx7ulp-usdhc", }, | 1668 | { .compatible = "fsl,imx7ulp-usdhc", }, |
1649 | { .compatible = "fsl,imx8qm-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, | 1669 | { .compatible = "fsl,imx8qm-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, |
1650 | { .compatible = "fsl,imx8mm-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, | 1670 | { .compatible = "fsl,imx8mm-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, |
1651 | { .compatible = "fsl,imx8mn-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, | 1671 | { .compatible = "fsl,imx8mn-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, |
1652 | { .compatible = "fsl,imx8mq-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, | 1672 | { .compatible = "fsl,imx8mq-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, |
1653 | { .compatible = "fsl,imxrt-usdhc", }, | 1673 | { .compatible = "fsl,imxrt-usdhc", }, |
1654 | { .compatible = "fsl,esdhc", }, | 1674 | { .compatible = "fsl,esdhc", }, |
1655 | { /* sentinel */ } | 1675 | { /* sentinel */ } |
1656 | }; | 1676 | }; |
1657 | 1677 | ||
1658 | #if CONFIG_IS_ENABLED(BLK) | 1678 | #if CONFIG_IS_ENABLED(BLK) |
1659 | static int fsl_esdhc_bind(struct udevice *dev) | 1679 | static int fsl_esdhc_bind(struct udevice *dev) |
1660 | { | 1680 | { |
1661 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); | 1681 | struct fsl_esdhc_plat *plat = dev_get_platdata(dev); |
1662 | 1682 | ||
1663 | return mmc_bind(dev, &plat->mmc, &plat->cfg); | 1683 | return mmc_bind(dev, &plat->mmc, &plat->cfg); |
1664 | } | 1684 | } |
1665 | #endif | 1685 | #endif |
1666 | 1686 | ||
1667 | U_BOOT_DRIVER(fsl_esdhc) = { | 1687 | U_BOOT_DRIVER(fsl_esdhc) = { |
1668 | .name = "fsl-esdhc-mmc", | 1688 | .name = "fsl-esdhc-mmc", |
1669 | .id = UCLASS_MMC, | 1689 | .id = UCLASS_MMC, |
1670 | .of_match = fsl_esdhc_ids, | 1690 | .of_match = fsl_esdhc_ids, |
1671 | .ops = &fsl_esdhc_ops, | 1691 | .ops = &fsl_esdhc_ops, |
1672 | #if CONFIG_IS_ENABLED(BLK) | 1692 | #if CONFIG_IS_ENABLED(BLK) |
1673 | .bind = fsl_esdhc_bind, | 1693 | .bind = fsl_esdhc_bind, |
1674 | #endif | 1694 | #endif |
1675 | .probe = fsl_esdhc_probe, | 1695 | .probe = fsl_esdhc_probe, |
1676 | .platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat), | 1696 | .platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat), |
1677 | .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv), | 1697 | .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv), |
1678 | }; | 1698 | }; |
1679 | #endif | 1699 | #endif |
1680 | 1700 |