2 * (C) Copyright 2012 SAMSUNG Electronics
3 * Jaehoon Chung <jh80.chung@samsung.com>
4 * Rajeshawari Shinde <rajeshwari.s@samsung.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <asm/arch/clk.h>
27 #include <asm-generic/errno.h>
29 #define PAGE_SIZE 4096
31 static int dwmci_wait_reset(struct dwmci_host
*host
, u32 value
)
33 unsigned long timeout
= 1000;
36 dwmci_writel(host
, DWMCI_CTRL
, value
);
39 ctrl
= dwmci_readl(host
, DWMCI_CTRL
);
40 if (!(ctrl
& DWMCI_RESET_ALL
))
46 static void dwmci_set_idma_desc(struct dwmci_idmac
*idmac
,
47 u32 desc0
, u32 desc1
, u32 desc2
)
49 struct dwmci_idmac
*desc
= idmac
;
54 desc
->next_addr
= (unsigned int)desc
+ sizeof(struct dwmci_idmac
);
57 static void dwmci_prepare_data(struct dwmci_host
*host
,
58 struct mmc_data
*data
)
61 unsigned int i
= 0, flags
, cnt
, blk_cnt
;
62 ulong data_start
, data_end
, start_addr
;
63 ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac
, cur_idmac
, data
->blocks
);
66 blk_cnt
= data
->blocks
;
68 dwmci_wait_reset(host
, DWMCI_CTRL_FIFO_RESET
);
70 data_start
= (ulong
)cur_idmac
;
71 dwmci_writel(host
, DWMCI_DBADDR
, (unsigned int)cur_idmac
);
73 if (data
->flags
== MMC_DATA_READ
)
74 start_addr
= (unsigned int)data
->dest
;
76 start_addr
= (unsigned int)data
->src
;
79 flags
= DWMCI_IDMAC_OWN
| DWMCI_IDMAC_CH
;
80 flags
|= (i
== 0) ? DWMCI_IDMAC_FS
: 0;
82 flags
|= DWMCI_IDMAC_LD
;
83 cnt
= data
->blocksize
* blk_cnt
;
85 cnt
= data
->blocksize
* 8;
87 dwmci_set_idma_desc(cur_idmac
, flags
, cnt
,
88 start_addr
+ (i
* PAGE_SIZE
));
97 data_end
= (ulong
)cur_idmac
;
98 flush_dcache_range(data_start
, data_end
+ ARCH_DMA_MINALIGN
);
100 ctrl
= dwmci_readl(host
, DWMCI_CTRL
);
101 ctrl
|= DWMCI_IDMAC_EN
| DWMCI_DMA_EN
;
102 dwmci_writel(host
, DWMCI_CTRL
, ctrl
);
104 ctrl
= dwmci_readl(host
, DWMCI_BMOD
);
105 ctrl
|= DWMCI_BMOD_IDMAC_FB
| DWMCI_BMOD_IDMAC_EN
;
106 dwmci_writel(host
, DWMCI_BMOD
, ctrl
);
108 dwmci_writel(host
, DWMCI_BLKSIZ
, data
->blocksize
);
109 dwmci_writel(host
, DWMCI_BYTCNT
, data
->blocksize
* data
->blocks
);
112 static int dwmci_set_transfer_mode(struct dwmci_host
*host
,
113 struct mmc_data
*data
)
117 mode
= DWMCI_CMD_DATA_EXP
;
118 if (data
->flags
& MMC_DATA_WRITE
)
119 mode
|= DWMCI_CMD_RW
;
124 static int dwmci_send_cmd(struct mmc
*mmc
, struct mmc_cmd
*cmd
,
125 struct mmc_data
*data
)
127 struct dwmci_host
*host
= (struct dwmci_host
*)mmc
->priv
;
129 unsigned int timeout
= 100000;
133 while (dwmci_readl(host
, DWMCI_STATUS
) & DWMCI_BUSY
) {
135 printf("Timeout on data busy\n");
141 dwmci_writel(host
, DWMCI_RINTSTS
, DWMCI_INTMSK_ALL
);
144 dwmci_prepare_data(host
, data
);
147 dwmci_writel(host
, DWMCI_CMDARG
, cmd
->cmdarg
);
150 flags
= dwmci_set_transfer_mode(host
, data
);
152 if ((cmd
->resp_type
& MMC_RSP_136
) && (cmd
->resp_type
& MMC_RSP_BUSY
))
155 if (cmd
->cmdidx
== MMC_CMD_STOP_TRANSMISSION
)
156 flags
|= DWMCI_CMD_ABORT_STOP
;
158 flags
|= DWMCI_CMD_PRV_DAT_WAIT
;
160 if (cmd
->resp_type
& MMC_RSP_PRESENT
) {
161 flags
|= DWMCI_CMD_RESP_EXP
;
162 if (cmd
->resp_type
& MMC_RSP_136
)
163 flags
|= DWMCI_CMD_RESP_LENGTH
;
166 if (cmd
->resp_type
& MMC_RSP_CRC
)
167 flags
|= DWMCI_CMD_CHECK_CRC
;
169 flags
|= (cmd
->cmdidx
| DWMCI_CMD_START
| DWMCI_CMD_USE_HOLD_REG
);
171 debug("Sending CMD%d\n",cmd
->cmdidx
);
173 dwmci_writel(host
, DWMCI_CMD
, flags
);
175 for (i
= 0; i
< retry
; i
++) {
176 mask
= dwmci_readl(host
, DWMCI_RINTSTS
);
177 if (mask
& DWMCI_INTMSK_CDONE
) {
179 dwmci_writel(host
, DWMCI_RINTSTS
, mask
);
187 if (mask
& DWMCI_INTMSK_RTO
) {
188 debug("Response Timeout..\n");
190 } else if (mask
& DWMCI_INTMSK_RE
) {
191 debug("Response Error..\n");
196 if (cmd
->resp_type
& MMC_RSP_PRESENT
) {
197 if (cmd
->resp_type
& MMC_RSP_136
) {
198 cmd
->response
[0] = dwmci_readl(host
, DWMCI_RESP3
);
199 cmd
->response
[1] = dwmci_readl(host
, DWMCI_RESP2
);
200 cmd
->response
[2] = dwmci_readl(host
, DWMCI_RESP1
);
201 cmd
->response
[3] = dwmci_readl(host
, DWMCI_RESP0
);
203 cmd
->response
[0] = dwmci_readl(host
, DWMCI_RESP0
);
209 mask
= dwmci_readl(host
, DWMCI_RINTSTS
);
210 if (mask
& (DWMCI_DATA_ERR
| DWMCI_DATA_TOUT
)) {
211 debug("DATA ERROR!\n");
214 } while (!(mask
& DWMCI_INTMSK_DTO
));
216 dwmci_writel(host
, DWMCI_RINTSTS
, mask
);
218 ctrl
= dwmci_readl(host
, DWMCI_CTRL
);
219 ctrl
&= ~(DWMCI_DMA_EN
);
220 dwmci_writel(host
, DWMCI_CTRL
, ctrl
);
228 static int dwmci_setup_bus(struct dwmci_host
*host
, u32 freq
)
234 if (freq
== host
->clock
)
238 * If host->mmc_clk didn't define,
239 * then assume that host->bus_hz is source clock value.
240 * host->bus_hz should be set from user.
243 sclk
= host
->mmc_clk(host
->dev_index
);
244 else if (host
->bus_hz
)
247 printf("Didn't get source clock value..\n");
251 div
= DIV_ROUND_UP(sclk
, 2 * freq
);
253 dwmci_writel(host
, DWMCI_CLKENA
, 0);
254 dwmci_writel(host
, DWMCI_CLKSRC
, 0);
256 dwmci_writel(host
, DWMCI_CLKDIV
, div
);
257 dwmci_writel(host
, DWMCI_CMD
, DWMCI_CMD_PRV_DAT_WAIT
|
258 DWMCI_CMD_UPD_CLK
| DWMCI_CMD_START
);
261 status
= dwmci_readl(host
, DWMCI_CMD
);
263 printf("TIMEOUT error!!\n");
266 } while (status
& DWMCI_CMD_START
);
268 dwmci_writel(host
, DWMCI_CLKENA
, DWMCI_CLKEN_ENABLE
|
269 DWMCI_CLKEN_LOW_PWR
);
271 dwmci_writel(host
, DWMCI_CMD
, DWMCI_CMD_PRV_DAT_WAIT
|
272 DWMCI_CMD_UPD_CLK
| DWMCI_CMD_START
);
276 status
= dwmci_readl(host
, DWMCI_CMD
);
278 printf("TIMEOUT error!!\n");
281 } while (status
& DWMCI_CMD_START
);
288 static void dwmci_set_ios(struct mmc
*mmc
)
290 struct dwmci_host
*host
= (struct dwmci_host
*)mmc
->priv
;
293 debug("Buswidth = %d, clock: %d\n",mmc
->bus_width
, mmc
->clock
);
295 dwmci_setup_bus(host
, mmc
->clock
);
296 switch (mmc
->bus_width
) {
298 ctype
= DWMCI_CTYPE_8BIT
;
301 ctype
= DWMCI_CTYPE_4BIT
;
304 ctype
= DWMCI_CTYPE_1BIT
;
308 dwmci_writel(host
, DWMCI_CTYPE
, ctype
);
314 static int dwmci_init(struct mmc
*mmc
)
316 struct dwmci_host
*host
= (struct dwmci_host
*)mmc
->priv
;
317 u32 fifo_size
, fifoth_val
;
319 dwmci_writel(host
, DWMCI_PWREN
, 1);
321 if (!dwmci_wait_reset(host
, DWMCI_RESET_ALL
)) {
322 debug("%s[%d] Fail-reset!!\n",__func__
,__LINE__
);
326 dwmci_writel(host
, DWMCI_RINTSTS
, 0xFFFFFFFF);
327 dwmci_writel(host
, DWMCI_INTMASK
, 0);
329 dwmci_writel(host
, DWMCI_TMOUT
, 0xFFFFFFFF);
331 dwmci_writel(host
, DWMCI_IDINTEN
, 0);
332 dwmci_writel(host
, DWMCI_BMOD
, 1);
334 fifo_size
= dwmci_readl(host
, DWMCI_FIFOTH
);
335 if (host
->fifoth_val
)
336 fifoth_val
= host
->fifoth_val
;
338 fifoth_val
= MSIZE(0x2) | RX_WMARK(fifo_size
/2 -1) |
339 TX_WMARK(fifo_size
/2);
340 dwmci_writel(host
, DWMCI_FIFOTH
, fifoth_val
);
342 dwmci_writel(host
, DWMCI_CLKENA
, 0);
343 dwmci_writel(host
, DWMCI_CLKSRC
, 0);
348 int add_dwmci(struct dwmci_host
*host
, u32 max_clk
, u32 min_clk
)
353 mmc
= malloc(sizeof(struct mmc
));
355 printf("mmc malloc fail!\n");
362 sprintf(mmc
->name
, "%s", host
->name
);
363 mmc
->send_cmd
= dwmci_send_cmd
;
364 mmc
->set_ios
= dwmci_set_ios
;
365 mmc
->init
= dwmci_init
;
366 mmc
->f_min
= min_clk
;
367 mmc
->f_max
= max_clk
;
369 mmc
->voltages
= MMC_VDD_32_33
| MMC_VDD_33_34
| MMC_VDD_165_195
;
371 mmc
->host_caps
= host
->caps
;
373 if (host
->buswidth
== 8) {
374 mmc
->host_caps
|= MMC_MODE_8BIT
;
375 mmc
->host_caps
&= ~MMC_MODE_4BIT
;
377 mmc
->host_caps
|= MMC_MODE_4BIT
;
378 mmc
->host_caps
&= ~MMC_MODE_8BIT
;
380 mmc
->host_caps
|= MMC_MODE_HS
| MMC_MODE_HS_52MHz
| MMC_MODE_HC
;
382 err
= mmc_register(mmc
);