2 * Copyright 2011, Marvell Semiconductor Inc.
3 * Lei Wen <leiwen@marvell.com>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * Back ported to the 8xx platform (from the 8260 platform) by
24 * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
34 static void sdhci_reset(struct sdhci_host
*host
, u8 mask
)
36 unsigned long timeout
;
40 sdhci_writeb(host
, mask
, SDHCI_SOFTWARE_RESET
);
41 while (sdhci_readb(host
, SDHCI_SOFTWARE_RESET
) & mask
) {
43 printf("Reset 0x%x never completed.\n", (int)mask
);
51 static void sdhci_cmd_done(struct sdhci_host
*host
, struct mmc_cmd
*cmd
)
54 if (cmd
->resp_type
& MMC_RSP_136
) {
55 /* CRC is stripped so we need to do some shifting. */
56 for (i
= 0; i
< 4; i
++) {
57 cmd
->response
[i
] = sdhci_readl(host
,
58 SDHCI_RESPONSE
+ (3-i
)*4) << 8;
60 cmd
->response
[i
] |= sdhci_readb(host
,
61 SDHCI_RESPONSE
+ (3-i
)*4-1);
64 cmd
->response
[0] = sdhci_readl(host
, SDHCI_RESPONSE
);
68 static void sdhci_transfer_pio(struct sdhci_host
*host
, struct mmc_data
*data
)
72 for (i
= 0; i
< data
->blocksize
; i
+= 4) {
73 offs
= data
->dest
+ i
;
74 if (data
->flags
== MMC_DATA_READ
)
75 *(u32
*)offs
= sdhci_readl(host
, SDHCI_BUFFER
);
77 sdhci_writel(host
, *(u32
*)offs
, SDHCI_BUFFER
);
81 static int sdhci_transfer_data(struct sdhci_host
*host
, struct mmc_data
*data
,
82 unsigned int start_addr
)
84 unsigned int stat
, rdy
, mask
, timeout
, block
= 0;
87 rdy
= SDHCI_INT_SPACE_AVAIL
| SDHCI_INT_DATA_AVAIL
;
88 mask
= SDHCI_DATA_AVAILABLE
| SDHCI_SPACE_AVAILABLE
;
90 stat
= sdhci_readl(host
, SDHCI_INT_STATUS
);
91 if (stat
& SDHCI_INT_ERROR
) {
92 printf("Error detected in status(0x%X)!\n", stat
);
96 if (!(sdhci_readl(host
, SDHCI_PRESENT_STATE
) & mask
))
98 sdhci_writel(host
, rdy
, SDHCI_INT_STATUS
);
99 sdhci_transfer_pio(host
, data
);
100 data
->dest
+= data
->blocksize
;
101 if (++block
>= data
->blocks
)
104 #ifdef CONFIG_MMC_SDMA
105 if (stat
& SDHCI_INT_DMA_END
) {
106 sdhci_writel(host
, SDHCI_INT_DMA_END
, SDHCI_INT_STATUS
);
107 start_addr
&= ~(SDHCI_DEFAULT_BOUNDARY_SIZE
- 1);
108 start_addr
+= SDHCI_DEFAULT_BOUNDARY_SIZE
;
109 sdhci_writel(host
, start_addr
, SDHCI_DMA_ADDRESS
);
115 printf("Transfer data timeout\n");
118 } while (!(stat
& SDHCI_INT_DATA_END
));
122 int sdhci_send_command(struct mmc
*mmc
, struct mmc_cmd
*cmd
,
123 struct mmc_data
*data
)
125 struct sdhci_host
*host
= (struct sdhci_host
*)mmc
->priv
;
126 unsigned int stat
= 0;
128 int trans_bytes
= 0, is_aligned
= 1;
129 u32 mask
, flags
, mode
;
130 unsigned int timeout
, start_addr
= 0;
135 sdhci_writel(host
, SDHCI_INT_ALL_MASK
, SDHCI_INT_STATUS
);
136 mask
= SDHCI_CMD_INHIBIT
| SDHCI_DATA_INHIBIT
;
138 /* We shouldn't wait for data inihibit for stop commands, even
139 though they might use busy signaling */
140 if (cmd
->cmdidx
== MMC_CMD_STOP_TRANSMISSION
)
141 mask
&= ~SDHCI_DATA_INHIBIT
;
143 while (sdhci_readl(host
, SDHCI_PRESENT_STATE
) & mask
) {
145 printf("Controller never released inhibit bit(s).\n");
152 mask
= SDHCI_INT_RESPONSE
;
153 if (!(cmd
->resp_type
& MMC_RSP_PRESENT
))
154 flags
= SDHCI_CMD_RESP_NONE
;
155 else if (cmd
->resp_type
& MMC_RSP_136
)
156 flags
= SDHCI_CMD_RESP_LONG
;
157 else if (cmd
->resp_type
& MMC_RSP_BUSY
) {
158 flags
= SDHCI_CMD_RESP_SHORT_BUSY
;
159 mask
|= SDHCI_INT_DATA_END
;
161 flags
= SDHCI_CMD_RESP_SHORT
;
163 if (cmd
->resp_type
& MMC_RSP_CRC
)
164 flags
|= SDHCI_CMD_CRC
;
165 if (cmd
->resp_type
& MMC_RSP_OPCODE
)
166 flags
|= SDHCI_CMD_INDEX
;
168 flags
|= SDHCI_CMD_DATA
;
170 /*Set Transfer mode regarding to data flag*/
172 sdhci_writeb(host
, 0xe, SDHCI_TIMEOUT_CONTROL
);
173 mode
= SDHCI_TRNS_BLK_CNT_EN
;
174 trans_bytes
= data
->blocks
* data
->blocksize
;
175 if (data
->blocks
> 1)
176 mode
|= SDHCI_TRNS_MULTI
;
178 if (data
->flags
== MMC_DATA_READ
)
179 mode
|= SDHCI_TRNS_READ
;
181 #ifdef CONFIG_MMC_SDMA
182 if (data
->flags
== MMC_DATA_READ
)
183 start_addr
= (unsigned int)data
->dest
;
185 start_addr
= (unsigned int)data
->src
;
186 if ((host
->quirks
& SDHCI_QUIRK_32BIT_DMA_ADDR
) &&
187 (start_addr
& 0x7) != 0x0) {
189 start_addr
= (unsigned int)aligned_buffer
;
190 if (data
->flags
!= MMC_DATA_READ
)
191 memcpy(aligned_buffer
, data
->src
, trans_bytes
);
194 sdhci_writel(host
, start_addr
, SDHCI_DMA_ADDRESS
);
195 mode
|= SDHCI_TRNS_DMA
;
197 sdhci_writew(host
, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG
,
200 sdhci_writew(host
, data
->blocks
, SDHCI_BLOCK_COUNT
);
201 sdhci_writew(host
, mode
, SDHCI_TRANSFER_MODE
);
204 sdhci_writel(host
, cmd
->cmdarg
, SDHCI_ARGUMENT
);
205 #ifdef CONFIG_MMC_SDMA
206 flush_cache(start_addr
, trans_bytes
);
208 sdhci_writew(host
, SDHCI_MAKE_CMD(cmd
->cmdidx
, flags
), SDHCI_COMMAND
);
210 stat
= sdhci_readl(host
, SDHCI_INT_STATUS
);
211 if (stat
& SDHCI_INT_ERROR
)
213 } while ((stat
& mask
) != mask
);
215 if ((stat
& (SDHCI_INT_ERROR
| mask
)) == mask
) {
216 sdhci_cmd_done(host
, cmd
);
217 sdhci_writel(host
, mask
, SDHCI_INT_STATUS
);
222 ret
= sdhci_transfer_data(host
, data
, start_addr
);
224 stat
= sdhci_readl(host
, SDHCI_INT_STATUS
);
225 sdhci_writel(host
, SDHCI_INT_ALL_MASK
, SDHCI_INT_STATUS
);
227 if ((host
->quirks
& SDHCI_QUIRK_32BIT_DMA_ADDR
) &&
228 !is_aligned
&& (data
->flags
== MMC_DATA_READ
))
229 memcpy(data
->dest
, aligned_buffer
, trans_bytes
);
233 sdhci_reset(host
, SDHCI_RESET_CMD
);
234 sdhci_reset(host
, SDHCI_RESET_DATA
);
235 if (stat
& SDHCI_INT_TIMEOUT
)
241 static int sdhci_set_clock(struct mmc
*mmc
, unsigned int clock
)
243 struct sdhci_host
*host
= (struct sdhci_host
*)mmc
->priv
;
244 unsigned int div
, clk
, timeout
;
246 sdhci_writew(host
, 0, SDHCI_CLOCK_CONTROL
);
251 if (host
->version
>= SDHCI_SPEC_300
) {
252 /* Version 3.00 divisors must be a multiple of 2. */
253 if (mmc
->f_max
<= clock
)
256 for (div
= 2; div
< SDHCI_MAX_DIV_SPEC_300
; div
+= 2) {
257 if ((mmc
->f_max
/ div
) <= clock
)
262 /* Version 2.00 divisors must be a power of 2. */
263 for (div
= 1; div
< SDHCI_MAX_DIV_SPEC_200
; div
*= 2) {
264 if ((mmc
->f_max
/ div
) <= clock
)
270 clk
= (div
& SDHCI_DIV_MASK
) << SDHCI_DIVIDER_SHIFT
;
271 clk
|= ((div
& SDHCI_DIV_HI_MASK
) >> SDHCI_DIV_MASK_LEN
)
272 << SDHCI_DIVIDER_HI_SHIFT
;
273 clk
|= SDHCI_CLOCK_INT_EN
;
274 sdhci_writew(host
, clk
, SDHCI_CLOCK_CONTROL
);
278 while (!((clk
= sdhci_readw(host
, SDHCI_CLOCK_CONTROL
))
279 & SDHCI_CLOCK_INT_STABLE
)) {
281 printf("Internal clock never stabilised.\n");
288 clk
|= SDHCI_CLOCK_CARD_EN
;
289 sdhci_writew(host
, clk
, SDHCI_CLOCK_CONTROL
);
293 static void sdhci_set_power(struct sdhci_host
*host
, unsigned short power
)
297 if (power
!= (unsigned short)-1) {
298 switch (1 << power
) {
299 case MMC_VDD_165_195
:
300 pwr
= SDHCI_POWER_180
;
304 pwr
= SDHCI_POWER_300
;
308 pwr
= SDHCI_POWER_330
;
314 sdhci_writeb(host
, 0, SDHCI_POWER_CONTROL
);
318 pwr
|= SDHCI_POWER_ON
;
320 sdhci_writeb(host
, pwr
, SDHCI_POWER_CONTROL
);
323 void sdhci_set_ios(struct mmc
*mmc
)
326 struct sdhci_host
*host
= (struct sdhci_host
*)mmc
->priv
;
328 if (mmc
->clock
!= host
->clock
)
329 sdhci_set_clock(mmc
, mmc
->clock
);
332 ctrl
= sdhci_readb(host
, SDHCI_HOST_CONTROL
);
333 if (mmc
->bus_width
== 8) {
334 ctrl
&= ~SDHCI_CTRL_4BITBUS
;
335 if (host
->version
>= SDHCI_SPEC_300
)
336 ctrl
|= SDHCI_CTRL_8BITBUS
;
338 if (host
->version
>= SDHCI_SPEC_300
)
339 ctrl
&= ~SDHCI_CTRL_8BITBUS
;
340 if (mmc
->bus_width
== 4)
341 ctrl
|= SDHCI_CTRL_4BITBUS
;
343 ctrl
&= ~SDHCI_CTRL_4BITBUS
;
346 if (mmc
->clock
> 26000000)
347 ctrl
|= SDHCI_CTRL_HISPD
;
349 ctrl
&= ~SDHCI_CTRL_HISPD
;
351 sdhci_writeb(host
, ctrl
, SDHCI_HOST_CONTROL
);
354 int sdhci_init(struct mmc
*mmc
)
356 struct sdhci_host
*host
= (struct sdhci_host
*)mmc
->priv
;
358 if ((host
->quirks
& SDHCI_QUIRK_32BIT_DMA_ADDR
) && !aligned_buffer
) {
359 aligned_buffer
= memalign(8, 512*1024);
360 if (!aligned_buffer
) {
361 printf("Aligned buffer alloc failed!!!");
366 /* Eable all state */
367 sdhci_writel(host
, SDHCI_INT_ALL_MASK
, SDHCI_INT_ENABLE
);
368 sdhci_writel(host
, SDHCI_INT_ALL_MASK
, SDHCI_SIGNAL_ENABLE
);
370 sdhci_set_power(host
, fls(mmc
->voltages
) - 1);
375 int add_sdhci(struct sdhci_host
*host
, u32 max_clk
, u32 min_clk
)
380 mmc
= malloc(sizeof(struct mmc
));
382 printf("mmc malloc fail!\n");
389 sprintf(mmc
->name
, "%s", host
->name
);
390 mmc
->send_cmd
= sdhci_send_command
;
391 mmc
->set_ios
= sdhci_set_ios
;
392 mmc
->init
= sdhci_init
;
395 caps
= sdhci_readl(host
, SDHCI_CAPABILITIES
);
396 #ifdef CONFIG_MMC_SDMA
397 if (!(caps
& SDHCI_CAN_DO_SDMA
)) {
398 printf("Your controller don't support sdma!!\n");
404 mmc
->f_max
= max_clk
;
406 if (host
->version
>= SDHCI_SPEC_300
)
407 mmc
->f_max
= (caps
& SDHCI_CLOCK_V3_BASE_MASK
)
408 >> SDHCI_CLOCK_BASE_SHIFT
;
410 mmc
->f_max
= (caps
& SDHCI_CLOCK_BASE_MASK
)
411 >> SDHCI_CLOCK_BASE_SHIFT
;
412 mmc
->f_max
*= 1000000;
414 if (mmc
->f_max
== 0) {
415 printf("Hardware doesn't specify base clock frequency\n");
419 mmc
->f_min
= min_clk
;
421 if (host
->version
>= SDHCI_SPEC_300
)
422 mmc
->f_min
= mmc
->f_max
/ SDHCI_MAX_DIV_SPEC_300
;
424 mmc
->f_min
= mmc
->f_max
/ SDHCI_MAX_DIV_SPEC_200
;
428 if (caps
& SDHCI_CAN_VDD_330
)
429 mmc
->voltages
|= MMC_VDD_32_33
| MMC_VDD_33_34
;
430 if (caps
& SDHCI_CAN_VDD_300
)
431 mmc
->voltages
|= MMC_VDD_29_30
| MMC_VDD_30_31
;
432 if (caps
& SDHCI_CAN_VDD_180
)
433 mmc
->voltages
|= MMC_VDD_165_195
;
434 mmc
->host_caps
= MMC_MODE_HS
| MMC_MODE_HS_52MHz
| MMC_MODE_4BIT
;
435 if (caps
& SDHCI_CAN_DO_8BIT
)
436 mmc
->host_caps
|= MMC_MODE_8BIT
;
438 sdhci_reset(host
, SDHCI_RESET_ALL
);