2 * ARM PrimeCell MultiMedia Card Interface - PL180
4 * Copyright (C) ST-Ericsson SA 2010
6 * Author: Ulf Hansson <ulf.hansson@stericsson.com>
7 * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com>
8 * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 #include "arm_pl180_mmci.h"
35 static int wait_for_command_end(struct mmc
*dev
, struct mmc_cmd
*cmd
)
37 u32 hoststatus
, statusmask
;
38 struct pl180_mmc_host
*host
= dev
->priv
;
40 statusmask
= SDI_STA_CTIMEOUT
| SDI_STA_CCRCFAIL
;
41 if ((cmd
->resp_type
& MMC_RSP_PRESENT
))
42 statusmask
|= SDI_STA_CMDREND
;
44 statusmask
|= SDI_STA_CMDSENT
;
47 hoststatus
= readl(&host
->base
->status
) & statusmask
;
50 writel(statusmask
, &host
->base
->status_clear
);
51 if (hoststatus
& SDI_STA_CTIMEOUT
) {
52 debug("CMD%d time out\n", cmd
->cmdidx
);
54 } else if ((hoststatus
& SDI_STA_CCRCFAIL
) &&
55 (cmd
->resp_type
& MMC_RSP_CRC
)) {
56 printf("CMD%d CRC error\n", cmd
->cmdidx
);
60 if (cmd
->resp_type
& MMC_RSP_PRESENT
) {
61 cmd
->response
[0] = readl(&host
->base
->response0
);
62 cmd
->response
[1] = readl(&host
->base
->response1
);
63 cmd
->response
[2] = readl(&host
->base
->response2
);
64 cmd
->response
[3] = readl(&host
->base
->response3
);
65 debug("CMD%d response[0]:0x%08X, response[1]:0x%08X, "
66 "response[2]:0x%08X, response[3]:0x%08X\n",
67 cmd
->cmdidx
, cmd
->response
[0], cmd
->response
[1],
68 cmd
->response
[2], cmd
->response
[3]);
74 /* send command to the mmc card and wait for results */
75 static int do_command(struct mmc
*dev
, struct mmc_cmd
*cmd
)
79 struct pl180_mmc_host
*host
= dev
->priv
;
81 sdi_cmd
= ((cmd
->cmdidx
& SDI_CMD_CMDINDEX_MASK
) | SDI_CMD_CPSMEN
);
84 sdi_cmd
|= SDI_CMD_WAITRESP
;
85 if (cmd
->resp_type
& MMC_RSP_136
)
86 sdi_cmd
|= SDI_CMD_LONGRESP
;
89 writel((u32
)cmd
->cmdarg
, &host
->base
->argument
);
90 udelay(COMMAND_REG_DELAY
);
91 writel(sdi_cmd
, &host
->base
->command
);
92 result
= wait_for_command_end(dev
, cmd
);
94 /* After CMD2 set RCA to a none zero value. */
95 if ((result
== 0) && (cmd
->cmdidx
== MMC_CMD_ALL_SEND_CID
))
98 /* After CMD3 open drain is switched off and push pull is used. */
99 if ((result
== 0) && (cmd
->cmdidx
== MMC_CMD_SET_RELATIVE_ADDR
)) {
100 u32 sdi_pwr
= readl(&host
->base
->power
) & ~SDI_PWR_OPD
;
101 writel(sdi_pwr
, &host
->base
->power
);
107 static int read_bytes(struct mmc
*dev
, u32
*dest
, u32 blkcount
, u32 blksize
)
109 u32
*tempbuff
= dest
;
110 u64 xfercount
= blkcount
* blksize
;
111 struct pl180_mmc_host
*host
= dev
->priv
;
112 u32 status
, status_err
;
114 debug("read_bytes: blkcount=%u blksize=%u\n", blkcount
, blksize
);
116 status
= readl(&host
->base
->status
);
117 status_err
= status
& (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
|
119 while ((!status_err
) && (xfercount
>= sizeof(u32
))) {
120 if (status
& SDI_STA_RXDAVL
) {
121 *(tempbuff
) = readl(&host
->base
->fifo
);
123 xfercount
-= sizeof(u32
);
125 status
= readl(&host
->base
->status
);
126 status_err
= status
& (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
|
130 status_err
= status
&
131 (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
| SDI_STA_DBCKEND
|
133 while (!status_err
) {
134 status
= readl(&host
->base
->status
);
135 status_err
= status
&
136 (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
| SDI_STA_DBCKEND
|
140 if (status
& SDI_STA_DTIMEOUT
) {
141 printf("Read data timed out, xfercount: %llu, status: 0x%08X\n",
144 } else if (status
& SDI_STA_DCRCFAIL
) {
145 printf("Read data bytes CRC error: 0x%x\n", status
);
147 } else if (status
& SDI_STA_RXOVERR
) {
148 printf("Read data RX overflow error\n");
152 writel(SDI_ICR_MASK
, &host
->base
->status_clear
);
155 printf("Read data error, xfercount: %llu\n", xfercount
);
162 static int write_bytes(struct mmc
*dev
, u32
*src
, u32 blkcount
, u32 blksize
)
166 u64 xfercount
= blkcount
* blksize
;
167 struct pl180_mmc_host
*host
= dev
->priv
;
168 u32 status
, status_err
;
170 debug("write_bytes: blkcount=%u blksize=%u\n", blkcount
, blksize
);
172 status
= readl(&host
->base
->status
);
173 status_err
= status
& (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
);
174 while (!status_err
&& xfercount
) {
175 if (status
& SDI_STA_TXFIFOBW
) {
176 if (xfercount
>= SDI_FIFO_BURST_SIZE
* sizeof(u32
)) {
177 for (i
= 0; i
< SDI_FIFO_BURST_SIZE
; i
++)
178 writel(*(tempbuff
+ i
),
180 tempbuff
+= SDI_FIFO_BURST_SIZE
;
181 xfercount
-= SDI_FIFO_BURST_SIZE
* sizeof(u32
);
183 while (xfercount
>= sizeof(u32
)) {
184 writel(*(tempbuff
), &host
->base
->fifo
);
186 xfercount
-= sizeof(u32
);
190 status
= readl(&host
->base
->status
);
191 status_err
= status
& (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
);
194 status_err
= status
&
195 (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
| SDI_STA_DBCKEND
);
196 while (!status_err
) {
197 status
= readl(&host
->base
->status
);
198 status_err
= status
&
199 (SDI_STA_DCRCFAIL
| SDI_STA_DTIMEOUT
| SDI_STA_DBCKEND
);
202 if (status
& SDI_STA_DTIMEOUT
) {
203 printf("Write data timed out, xfercount:%llu,status:0x%08X\n",
206 } else if (status
& SDI_STA_DCRCFAIL
) {
207 printf("Write data CRC error\n");
211 writel(SDI_ICR_MASK
, &host
->base
->status_clear
);
214 printf("Write data error, xfercount:%llu", xfercount
);
221 static int do_data_transfer(struct mmc
*dev
,
223 struct mmc_data
*data
)
225 int error
= -ETIMEDOUT
;
226 struct pl180_mmc_host
*host
= dev
->priv
;
229 u32 data_len
= (u32
) (data
->blocks
* data
->blocksize
);
231 if (!host
->version2
) {
232 blksz
= (ffs(data
->blocksize
) - 1);
233 data_ctrl
|= ((blksz
<< 4) & SDI_DCTRL_DBLKSIZE_MASK
);
235 blksz
= data
->blocksize
;
236 data_ctrl
|= (blksz
<< SDI_DCTRL_DBLOCKSIZE_V2_SHIFT
);
238 data_ctrl
|= SDI_DCTRL_DTEN
| SDI_DCTRL_BUSYMODE
;
240 writel(SDI_DTIMER_DEFAULT
, &host
->base
->datatimer
);
241 writel(data_len
, &host
->base
->datalength
);
242 udelay(DATA_REG_DELAY
);
244 if (data
->flags
& MMC_DATA_READ
) {
245 data_ctrl
|= SDI_DCTRL_DTDIR_IN
;
246 writel(data_ctrl
, &host
->base
->datactrl
);
248 error
= do_command(dev
, cmd
);
252 error
= read_bytes(dev
, (u32
*)data
->dest
, (u32
)data
->blocks
,
253 (u32
)data
->blocksize
);
254 } else if (data
->flags
& MMC_DATA_WRITE
) {
255 error
= do_command(dev
, cmd
);
259 writel(data_ctrl
, &host
->base
->datactrl
);
260 error
= write_bytes(dev
, (u32
*)data
->src
, (u32
)data
->blocks
,
261 (u32
)data
->blocksize
);
267 static int host_request(struct mmc
*dev
,
269 struct mmc_data
*data
)
274 result
= do_data_transfer(dev
, cmd
, data
);
276 result
= do_command(dev
, cmd
);
281 /* MMC uses open drain drivers in the enumeration phase */
282 static int mmc_host_reset(struct mmc
*dev
)
284 struct pl180_mmc_host
*host
= dev
->priv
;
286 writel(host
->pwr_init
, &host
->base
->power
);
291 static void host_set_ios(struct mmc
*dev
)
293 struct pl180_mmc_host
*host
= dev
->priv
;
296 sdi_clkcr
= readl(&host
->base
->clock
);
298 /* Ramp up the clock rate */
303 if (dev
->clock
>= dev
->f_max
) {
305 dev
->clock
= dev
->f_max
;
307 clkdiv
= (host
->clock_in
/ dev
->clock
) - 2;
310 tmp_clock
= host
->clock_in
/ (clkdiv
+ 2);
311 while (tmp_clock
> dev
->clock
) {
313 tmp_clock
= host
->clock_in
/ (clkdiv
+ 2);
316 if (clkdiv
> SDI_CLKCR_CLKDIV_MASK
)
317 clkdiv
= SDI_CLKCR_CLKDIV_MASK
;
319 tmp_clock
= host
->clock_in
/ (clkdiv
+ 2);
320 dev
->clock
= tmp_clock
;
321 sdi_clkcr
&= ~(SDI_CLKCR_CLKDIV_MASK
);
325 /* Set the bus width */
326 if (dev
->bus_width
) {
329 switch (dev
->bus_width
) {
331 buswidth
|= SDI_CLKCR_WIDBUS_1
;
334 buswidth
|= SDI_CLKCR_WIDBUS_4
;
337 buswidth
|= SDI_CLKCR_WIDBUS_8
;
340 printf("Invalid bus width: %d\n", dev
->bus_width
);
343 sdi_clkcr
&= ~(SDI_CLKCR_WIDBUS_MASK
);
344 sdi_clkcr
|= buswidth
;
347 writel(sdi_clkcr
, &host
->base
->clock
);
348 udelay(CLK_CHANGE_DELAY
);
352 * mmc_host_init - initialize the mmc controller.
353 * Set initial clock and power for mmc slot.
354 * Initialize mmc struct and register with mmc framework.
356 int arm_pl180_mmci_init(struct pl180_mmc_host
*host
)
361 dev
= malloc(sizeof(struct mmc
));
365 memset(dev
, 0, sizeof(struct mmc
));
368 writel(host
->pwr_init
, &host
->base
->power
);
369 writel(host
->clkdiv_init
, &host
->base
->clock
);
370 udelay(CLK_CHANGE_DELAY
);
372 /* Disable mmc interrupts */
373 sdi_u32
= readl(&host
->base
->mask0
) & ~SDI_MASK0_MASK
;
374 writel(sdi_u32
, &host
->base
->mask0
);
375 strncpy(dev
->name
, host
->name
, sizeof(dev
->name
));
376 dev
->send_cmd
= host_request
;
377 dev
->set_ios
= host_set_ios
;
378 dev
->init
= mmc_host_reset
;
381 dev
->host_caps
= host
->caps
;
382 dev
->voltages
= host
->voltages
;
383 dev
->f_min
= host
->clock_min
;
384 dev
->f_max
= host
->clock_max
;
385 dev
->b_max
= host
->b_max
;
387 debug("registered mmc interface number is:%d\n", dev
->block_dev
.dev
);