Commit 41f7be3c78e793535e484e5f5010cc98410598de
Committed by
Tom Rini
1 parent
4e4ad6d140
Exists in
v2017.01-smarct4x
and in
30 other branches
driver: dwmmc: Fix pointer conversion warnings for hikey
Fix below compilation warings happening for hikey_defconfig drivers/mmc/dw_mmc.c: In function ‘dwmci_set_idma_desc’: drivers/mmc/dw_mmc.c:43:20: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac); ^ drivers/mmc/dw_mmc.c: In function ‘dwmci_prepare_data’: drivers/mmc/dw_mmc.c:61:35: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac); ^ drivers/mmc/dw_mmc.c:73:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] (u32)bounce_buffer + (i * PAGE_SIZE)); ^ CC drivers/mmc/hi6220_dw_mmc.o drivers/mmc/hi6220_dw_mmc.c: In function ‘hi6220_dwmci_add_port’: drivers/mmc/hi6220_dw_mmc.c:51:17: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] host->ioaddr = (void *)regbase; Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
Showing 2 changed files with 4 additions and 4 deletions Inline Diff
drivers/mmc/dw_mmc.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2012 SAMSUNG Electronics | 2 | * (C) Copyright 2012 SAMSUNG Electronics |
3 | * Jaehoon Chung <jh80.chung@samsung.com> | 3 | * Jaehoon Chung <jh80.chung@samsung.com> |
4 | * Rajeshawari Shinde <rajeshwari.s@samsung.com> | 4 | * Rajeshawari Shinde <rajeshwari.s@samsung.com> |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <bouncebuf.h> | 9 | #include <bouncebuf.h> |
10 | #include <common.h> | 10 | #include <common.h> |
11 | #include <errno.h> | 11 | #include <errno.h> |
12 | #include <malloc.h> | 12 | #include <malloc.h> |
13 | #include <memalign.h> | 13 | #include <memalign.h> |
14 | #include <mmc.h> | 14 | #include <mmc.h> |
15 | #include <dwmmc.h> | 15 | #include <dwmmc.h> |
16 | #include <asm-generic/errno.h> | 16 | #include <asm-generic/errno.h> |
17 | 17 | ||
18 | #define PAGE_SIZE 4096 | 18 | #define PAGE_SIZE 4096 |
19 | 19 | ||
20 | static int dwmci_wait_reset(struct dwmci_host *host, u32 value) | 20 | static int dwmci_wait_reset(struct dwmci_host *host, u32 value) |
21 | { | 21 | { |
22 | unsigned long timeout = 1000; | 22 | unsigned long timeout = 1000; |
23 | u32 ctrl; | 23 | u32 ctrl; |
24 | 24 | ||
25 | dwmci_writel(host, DWMCI_CTRL, value); | 25 | dwmci_writel(host, DWMCI_CTRL, value); |
26 | 26 | ||
27 | while (timeout--) { | 27 | while (timeout--) { |
28 | ctrl = dwmci_readl(host, DWMCI_CTRL); | 28 | ctrl = dwmci_readl(host, DWMCI_CTRL); |
29 | if (!(ctrl & DWMCI_RESET_ALL)) | 29 | if (!(ctrl & DWMCI_RESET_ALL)) |
30 | return 1; | 30 | return 1; |
31 | } | 31 | } |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | static void dwmci_set_idma_desc(struct dwmci_idmac *idmac, | 35 | static void dwmci_set_idma_desc(struct dwmci_idmac *idmac, |
36 | u32 desc0, u32 desc1, u32 desc2) | 36 | u32 desc0, u32 desc1, u32 desc2) |
37 | { | 37 | { |
38 | struct dwmci_idmac *desc = idmac; | 38 | struct dwmci_idmac *desc = idmac; |
39 | 39 | ||
40 | desc->flags = desc0; | 40 | desc->flags = desc0; |
41 | desc->cnt = desc1; | 41 | desc->cnt = desc1; |
42 | desc->addr = desc2; | 42 | desc->addr = desc2; |
43 | desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac); | 43 | desc->next_addr = (ulong)desc + sizeof(struct dwmci_idmac); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void dwmci_prepare_data(struct dwmci_host *host, | 46 | static void dwmci_prepare_data(struct dwmci_host *host, |
47 | struct mmc_data *data, | 47 | struct mmc_data *data, |
48 | struct dwmci_idmac *cur_idmac, | 48 | struct dwmci_idmac *cur_idmac, |
49 | void *bounce_buffer) | 49 | void *bounce_buffer) |
50 | { | 50 | { |
51 | unsigned long ctrl; | 51 | unsigned long ctrl; |
52 | unsigned int i = 0, flags, cnt, blk_cnt; | 52 | unsigned int i = 0, flags, cnt, blk_cnt; |
53 | ulong data_start, data_end; | 53 | ulong data_start, data_end; |
54 | 54 | ||
55 | 55 | ||
56 | blk_cnt = data->blocks; | 56 | blk_cnt = data->blocks; |
57 | 57 | ||
58 | dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET); | 58 | dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET); |
59 | 59 | ||
60 | data_start = (ulong)cur_idmac; | 60 | data_start = (ulong)cur_idmac; |
61 | dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac); | 61 | dwmci_writel(host, DWMCI_DBADDR, (ulong)cur_idmac); |
62 | 62 | ||
63 | do { | 63 | do { |
64 | flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ; | 64 | flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ; |
65 | flags |= (i == 0) ? DWMCI_IDMAC_FS : 0; | 65 | flags |= (i == 0) ? DWMCI_IDMAC_FS : 0; |
66 | if (blk_cnt <= 8) { | 66 | if (blk_cnt <= 8) { |
67 | flags |= DWMCI_IDMAC_LD; | 67 | flags |= DWMCI_IDMAC_LD; |
68 | cnt = data->blocksize * blk_cnt; | 68 | cnt = data->blocksize * blk_cnt; |
69 | } else | 69 | } else |
70 | cnt = data->blocksize * 8; | 70 | cnt = data->blocksize * 8; |
71 | 71 | ||
72 | dwmci_set_idma_desc(cur_idmac, flags, cnt, | 72 | dwmci_set_idma_desc(cur_idmac, flags, cnt, |
73 | (u32)bounce_buffer + (i * PAGE_SIZE)); | 73 | (ulong)bounce_buffer + (i * PAGE_SIZE)); |
74 | 74 | ||
75 | if (blk_cnt <= 8) | 75 | if (blk_cnt <= 8) |
76 | break; | 76 | break; |
77 | blk_cnt -= 8; | 77 | blk_cnt -= 8; |
78 | cur_idmac++; | 78 | cur_idmac++; |
79 | i++; | 79 | i++; |
80 | } while(1); | 80 | } while(1); |
81 | 81 | ||
82 | data_end = (ulong)cur_idmac; | 82 | data_end = (ulong)cur_idmac; |
83 | flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN); | 83 | flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN); |
84 | 84 | ||
85 | ctrl = dwmci_readl(host, DWMCI_CTRL); | 85 | ctrl = dwmci_readl(host, DWMCI_CTRL); |
86 | ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN; | 86 | ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN; |
87 | dwmci_writel(host, DWMCI_CTRL, ctrl); | 87 | dwmci_writel(host, DWMCI_CTRL, ctrl); |
88 | 88 | ||
89 | ctrl = dwmci_readl(host, DWMCI_BMOD); | 89 | ctrl = dwmci_readl(host, DWMCI_BMOD); |
90 | ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN; | 90 | ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN; |
91 | dwmci_writel(host, DWMCI_BMOD, ctrl); | 91 | dwmci_writel(host, DWMCI_BMOD, ctrl); |
92 | 92 | ||
93 | dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize); | 93 | dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize); |
94 | dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); | 94 | dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); |
95 | } | 95 | } |
96 | 96 | ||
97 | static int dwmci_set_transfer_mode(struct dwmci_host *host, | 97 | static int dwmci_set_transfer_mode(struct dwmci_host *host, |
98 | struct mmc_data *data) | 98 | struct mmc_data *data) |
99 | { | 99 | { |
100 | unsigned long mode; | 100 | unsigned long mode; |
101 | 101 | ||
102 | mode = DWMCI_CMD_DATA_EXP; | 102 | mode = DWMCI_CMD_DATA_EXP; |
103 | if (data->flags & MMC_DATA_WRITE) | 103 | if (data->flags & MMC_DATA_WRITE) |
104 | mode |= DWMCI_CMD_RW; | 104 | mode |= DWMCI_CMD_RW; |
105 | 105 | ||
106 | return mode; | 106 | return mode; |
107 | } | 107 | } |
108 | 108 | ||
109 | static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, | 109 | static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, |
110 | struct mmc_data *data) | 110 | struct mmc_data *data) |
111 | { | 111 | { |
112 | struct dwmci_host *host = mmc->priv; | 112 | struct dwmci_host *host = mmc->priv; |
113 | ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, | 113 | ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, |
114 | data ? DIV_ROUND_UP(data->blocks, 8) : 0); | 114 | data ? DIV_ROUND_UP(data->blocks, 8) : 0); |
115 | int ret = 0, flags = 0, i; | 115 | int ret = 0, flags = 0, i; |
116 | unsigned int timeout = 100000; | 116 | unsigned int timeout = 100000; |
117 | u32 retry = 10000; | 117 | u32 retry = 10000; |
118 | u32 mask, ctrl; | 118 | u32 mask, ctrl; |
119 | ulong start = get_timer(0); | 119 | ulong start = get_timer(0); |
120 | struct bounce_buffer bbstate; | 120 | struct bounce_buffer bbstate; |
121 | 121 | ||
122 | while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { | 122 | while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { |
123 | if (get_timer(start) > timeout) { | 123 | if (get_timer(start) > timeout) { |
124 | debug("%s: Timeout on data busy\n", __func__); | 124 | debug("%s: Timeout on data busy\n", __func__); |
125 | return TIMEOUT; | 125 | return TIMEOUT; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
129 | dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); | 129 | dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); |
130 | 130 | ||
131 | if (data) { | 131 | if (data) { |
132 | if (data->flags == MMC_DATA_READ) { | 132 | if (data->flags == MMC_DATA_READ) { |
133 | bounce_buffer_start(&bbstate, (void*)data->dest, | 133 | bounce_buffer_start(&bbstate, (void*)data->dest, |
134 | data->blocksize * | 134 | data->blocksize * |
135 | data->blocks, GEN_BB_WRITE); | 135 | data->blocks, GEN_BB_WRITE); |
136 | } else { | 136 | } else { |
137 | bounce_buffer_start(&bbstate, (void*)data->src, | 137 | bounce_buffer_start(&bbstate, (void*)data->src, |
138 | data->blocksize * | 138 | data->blocksize * |
139 | data->blocks, GEN_BB_READ); | 139 | data->blocks, GEN_BB_READ); |
140 | } | 140 | } |
141 | dwmci_prepare_data(host, data, cur_idmac, | 141 | dwmci_prepare_data(host, data, cur_idmac, |
142 | bbstate.bounce_buffer); | 142 | bbstate.bounce_buffer); |
143 | } | 143 | } |
144 | 144 | ||
145 | dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg); | 145 | dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg); |
146 | 146 | ||
147 | if (data) | 147 | if (data) |
148 | flags = dwmci_set_transfer_mode(host, data); | 148 | flags = dwmci_set_transfer_mode(host, data); |
149 | 149 | ||
150 | if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) | 150 | if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) |
151 | return -1; | 151 | return -1; |
152 | 152 | ||
153 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) | 153 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) |
154 | flags |= DWMCI_CMD_ABORT_STOP; | 154 | flags |= DWMCI_CMD_ABORT_STOP; |
155 | else | 155 | else |
156 | flags |= DWMCI_CMD_PRV_DAT_WAIT; | 156 | flags |= DWMCI_CMD_PRV_DAT_WAIT; |
157 | 157 | ||
158 | if (cmd->resp_type & MMC_RSP_PRESENT) { | 158 | if (cmd->resp_type & MMC_RSP_PRESENT) { |
159 | flags |= DWMCI_CMD_RESP_EXP; | 159 | flags |= DWMCI_CMD_RESP_EXP; |
160 | if (cmd->resp_type & MMC_RSP_136) | 160 | if (cmd->resp_type & MMC_RSP_136) |
161 | flags |= DWMCI_CMD_RESP_LENGTH; | 161 | flags |= DWMCI_CMD_RESP_LENGTH; |
162 | } | 162 | } |
163 | 163 | ||
164 | if (cmd->resp_type & MMC_RSP_CRC) | 164 | if (cmd->resp_type & MMC_RSP_CRC) |
165 | flags |= DWMCI_CMD_CHECK_CRC; | 165 | flags |= DWMCI_CMD_CHECK_CRC; |
166 | 166 | ||
167 | flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); | 167 | flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); |
168 | 168 | ||
169 | debug("Sending CMD%d\n",cmd->cmdidx); | 169 | debug("Sending CMD%d\n",cmd->cmdidx); |
170 | 170 | ||
171 | dwmci_writel(host, DWMCI_CMD, flags); | 171 | dwmci_writel(host, DWMCI_CMD, flags); |
172 | 172 | ||
173 | for (i = 0; i < retry; i++) { | 173 | for (i = 0; i < retry; i++) { |
174 | mask = dwmci_readl(host, DWMCI_RINTSTS); | 174 | mask = dwmci_readl(host, DWMCI_RINTSTS); |
175 | if (mask & DWMCI_INTMSK_CDONE) { | 175 | if (mask & DWMCI_INTMSK_CDONE) { |
176 | if (!data) | 176 | if (!data) |
177 | dwmci_writel(host, DWMCI_RINTSTS, mask); | 177 | dwmci_writel(host, DWMCI_RINTSTS, mask); |
178 | break; | 178 | break; |
179 | } | 179 | } |
180 | } | 180 | } |
181 | 181 | ||
182 | if (i == retry) { | 182 | if (i == retry) { |
183 | debug("%s: Timeout.\n", __func__); | 183 | debug("%s: Timeout.\n", __func__); |
184 | return TIMEOUT; | 184 | return TIMEOUT; |
185 | } | 185 | } |
186 | 186 | ||
187 | if (mask & DWMCI_INTMSK_RTO) { | 187 | if (mask & DWMCI_INTMSK_RTO) { |
188 | /* | 188 | /* |
189 | * Timeout here is not necessarily fatal. (e)MMC cards | 189 | * Timeout here is not necessarily fatal. (e)MMC cards |
190 | * will splat here when they receive CMD55 as they do | 190 | * will splat here when they receive CMD55 as they do |
191 | * not support this command and that is exactly the way | 191 | * not support this command and that is exactly the way |
192 | * to tell them apart from SD cards. Thus, this output | 192 | * to tell them apart from SD cards. Thus, this output |
193 | * below shall be debug(). eMMC cards also do not favor | 193 | * below shall be debug(). eMMC cards also do not favor |
194 | * CMD8, please keep that in mind. | 194 | * CMD8, please keep that in mind. |
195 | */ | 195 | */ |
196 | debug("%s: Response Timeout.\n", __func__); | 196 | debug("%s: Response Timeout.\n", __func__); |
197 | return TIMEOUT; | 197 | return TIMEOUT; |
198 | } else if (mask & DWMCI_INTMSK_RE) { | 198 | } else if (mask & DWMCI_INTMSK_RE) { |
199 | debug("%s: Response Error.\n", __func__); | 199 | debug("%s: Response Error.\n", __func__); |
200 | return -EIO; | 200 | return -EIO; |
201 | } | 201 | } |
202 | 202 | ||
203 | 203 | ||
204 | if (cmd->resp_type & MMC_RSP_PRESENT) { | 204 | if (cmd->resp_type & MMC_RSP_PRESENT) { |
205 | if (cmd->resp_type & MMC_RSP_136) { | 205 | if (cmd->resp_type & MMC_RSP_136) { |
206 | cmd->response[0] = dwmci_readl(host, DWMCI_RESP3); | 206 | cmd->response[0] = dwmci_readl(host, DWMCI_RESP3); |
207 | cmd->response[1] = dwmci_readl(host, DWMCI_RESP2); | 207 | cmd->response[1] = dwmci_readl(host, DWMCI_RESP2); |
208 | cmd->response[2] = dwmci_readl(host, DWMCI_RESP1); | 208 | cmd->response[2] = dwmci_readl(host, DWMCI_RESP1); |
209 | cmd->response[3] = dwmci_readl(host, DWMCI_RESP0); | 209 | cmd->response[3] = dwmci_readl(host, DWMCI_RESP0); |
210 | } else { | 210 | } else { |
211 | cmd->response[0] = dwmci_readl(host, DWMCI_RESP0); | 211 | cmd->response[0] = dwmci_readl(host, DWMCI_RESP0); |
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | if (data) { | 215 | if (data) { |
216 | start = get_timer(0); | 216 | start = get_timer(0); |
217 | timeout = 240000; | 217 | timeout = 240000; |
218 | for (;;) { | 218 | for (;;) { |
219 | mask = dwmci_readl(host, DWMCI_RINTSTS); | 219 | mask = dwmci_readl(host, DWMCI_RINTSTS); |
220 | /* Error during data transfer. */ | 220 | /* Error during data transfer. */ |
221 | if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { | 221 | if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { |
222 | debug("%s: DATA ERROR!\n", __func__); | 222 | debug("%s: DATA ERROR!\n", __func__); |
223 | ret = -EINVAL; | 223 | ret = -EINVAL; |
224 | break; | 224 | break; |
225 | } | 225 | } |
226 | 226 | ||
227 | /* Data arrived correctly. */ | 227 | /* Data arrived correctly. */ |
228 | if (mask & DWMCI_INTMSK_DTO) { | 228 | if (mask & DWMCI_INTMSK_DTO) { |
229 | ret = 0; | 229 | ret = 0; |
230 | break; | 230 | break; |
231 | } | 231 | } |
232 | 232 | ||
233 | /* Check for timeout. */ | 233 | /* Check for timeout. */ |
234 | if (get_timer(start) > timeout) { | 234 | if (get_timer(start) > timeout) { |
235 | debug("%s: Timeout waiting for data!\n", | 235 | debug("%s: Timeout waiting for data!\n", |
236 | __func__); | 236 | __func__); |
237 | ret = TIMEOUT; | 237 | ret = TIMEOUT; |
238 | break; | 238 | break; |
239 | } | 239 | } |
240 | } | 240 | } |
241 | 241 | ||
242 | dwmci_writel(host, DWMCI_RINTSTS, mask); | 242 | dwmci_writel(host, DWMCI_RINTSTS, mask); |
243 | 243 | ||
244 | ctrl = dwmci_readl(host, DWMCI_CTRL); | 244 | ctrl = dwmci_readl(host, DWMCI_CTRL); |
245 | ctrl &= ~(DWMCI_DMA_EN); | 245 | ctrl &= ~(DWMCI_DMA_EN); |
246 | dwmci_writel(host, DWMCI_CTRL, ctrl); | 246 | dwmci_writel(host, DWMCI_CTRL, ctrl); |
247 | 247 | ||
248 | bounce_buffer_stop(&bbstate); | 248 | bounce_buffer_stop(&bbstate); |
249 | } | 249 | } |
250 | 250 | ||
251 | udelay(100); | 251 | udelay(100); |
252 | 252 | ||
253 | return ret; | 253 | return ret; |
254 | } | 254 | } |
255 | 255 | ||
256 | static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) | 256 | static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) |
257 | { | 257 | { |
258 | u32 div, status; | 258 | u32 div, status; |
259 | int timeout = 10000; | 259 | int timeout = 10000; |
260 | unsigned long sclk; | 260 | unsigned long sclk; |
261 | 261 | ||
262 | if ((freq == host->clock) || (freq == 0)) | 262 | if ((freq == host->clock) || (freq == 0)) |
263 | return 0; | 263 | return 0; |
264 | /* | 264 | /* |
265 | * If host->get_mmc_clk isn't defined, | 265 | * If host->get_mmc_clk isn't defined, |
266 | * then assume that host->bus_hz is source clock value. | 266 | * then assume that host->bus_hz is source clock value. |
267 | * host->bus_hz should be set by user. | 267 | * host->bus_hz should be set by user. |
268 | */ | 268 | */ |
269 | if (host->get_mmc_clk) | 269 | if (host->get_mmc_clk) |
270 | sclk = host->get_mmc_clk(host, freq); | 270 | sclk = host->get_mmc_clk(host, freq); |
271 | else if (host->bus_hz) | 271 | else if (host->bus_hz) |
272 | sclk = host->bus_hz; | 272 | sclk = host->bus_hz; |
273 | else { | 273 | else { |
274 | debug("%s: Didn't get source clock value.\n", __func__); | 274 | debug("%s: Didn't get source clock value.\n", __func__); |
275 | return -EINVAL; | 275 | return -EINVAL; |
276 | } | 276 | } |
277 | 277 | ||
278 | if (sclk == freq) | 278 | if (sclk == freq) |
279 | div = 0; /* bypass mode */ | 279 | div = 0; /* bypass mode */ |
280 | else | 280 | else |
281 | div = DIV_ROUND_UP(sclk, 2 * freq); | 281 | div = DIV_ROUND_UP(sclk, 2 * freq); |
282 | 282 | ||
283 | dwmci_writel(host, DWMCI_CLKENA, 0); | 283 | dwmci_writel(host, DWMCI_CLKENA, 0); |
284 | dwmci_writel(host, DWMCI_CLKSRC, 0); | 284 | dwmci_writel(host, DWMCI_CLKSRC, 0); |
285 | 285 | ||
286 | dwmci_writel(host, DWMCI_CLKDIV, div); | 286 | dwmci_writel(host, DWMCI_CLKDIV, div); |
287 | dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | | 287 | dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | |
288 | DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); | 288 | DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); |
289 | 289 | ||
290 | do { | 290 | do { |
291 | status = dwmci_readl(host, DWMCI_CMD); | 291 | status = dwmci_readl(host, DWMCI_CMD); |
292 | if (timeout-- < 0) { | 292 | if (timeout-- < 0) { |
293 | debug("%s: Timeout!\n", __func__); | 293 | debug("%s: Timeout!\n", __func__); |
294 | return -ETIMEDOUT; | 294 | return -ETIMEDOUT; |
295 | } | 295 | } |
296 | } while (status & DWMCI_CMD_START); | 296 | } while (status & DWMCI_CMD_START); |
297 | 297 | ||
298 | dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE | | 298 | dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE | |
299 | DWMCI_CLKEN_LOW_PWR); | 299 | DWMCI_CLKEN_LOW_PWR); |
300 | 300 | ||
301 | dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | | 301 | dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | |
302 | DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); | 302 | DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); |
303 | 303 | ||
304 | timeout = 10000; | 304 | timeout = 10000; |
305 | do { | 305 | do { |
306 | status = dwmci_readl(host, DWMCI_CMD); | 306 | status = dwmci_readl(host, DWMCI_CMD); |
307 | if (timeout-- < 0) { | 307 | if (timeout-- < 0) { |
308 | debug("%s: Timeout!\n", __func__); | 308 | debug("%s: Timeout!\n", __func__); |
309 | return -ETIMEDOUT; | 309 | return -ETIMEDOUT; |
310 | } | 310 | } |
311 | } while (status & DWMCI_CMD_START); | 311 | } while (status & DWMCI_CMD_START); |
312 | 312 | ||
313 | host->clock = freq; | 313 | host->clock = freq; |
314 | 314 | ||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | static void dwmci_set_ios(struct mmc *mmc) | 318 | static void dwmci_set_ios(struct mmc *mmc) |
319 | { | 319 | { |
320 | struct dwmci_host *host = (struct dwmci_host *)mmc->priv; | 320 | struct dwmci_host *host = (struct dwmci_host *)mmc->priv; |
321 | u32 ctype, regs; | 321 | u32 ctype, regs; |
322 | 322 | ||
323 | debug("Buswidth = %d, clock: %d\n", mmc->bus_width, mmc->clock); | 323 | debug("Buswidth = %d, clock: %d\n", mmc->bus_width, mmc->clock); |
324 | 324 | ||
325 | dwmci_setup_bus(host, mmc->clock); | 325 | dwmci_setup_bus(host, mmc->clock); |
326 | switch (mmc->bus_width) { | 326 | switch (mmc->bus_width) { |
327 | case 8: | 327 | case 8: |
328 | ctype = DWMCI_CTYPE_8BIT; | 328 | ctype = DWMCI_CTYPE_8BIT; |
329 | break; | 329 | break; |
330 | case 4: | 330 | case 4: |
331 | ctype = DWMCI_CTYPE_4BIT; | 331 | ctype = DWMCI_CTYPE_4BIT; |
332 | break; | 332 | break; |
333 | default: | 333 | default: |
334 | ctype = DWMCI_CTYPE_1BIT; | 334 | ctype = DWMCI_CTYPE_1BIT; |
335 | break; | 335 | break; |
336 | } | 336 | } |
337 | 337 | ||
338 | dwmci_writel(host, DWMCI_CTYPE, ctype); | 338 | dwmci_writel(host, DWMCI_CTYPE, ctype); |
339 | 339 | ||
340 | regs = dwmci_readl(host, DWMCI_UHS_REG); | 340 | regs = dwmci_readl(host, DWMCI_UHS_REG); |
341 | if (mmc->ddr_mode) | 341 | if (mmc->ddr_mode) |
342 | regs |= DWMCI_DDR_MODE; | 342 | regs |= DWMCI_DDR_MODE; |
343 | else | 343 | else |
344 | regs &= ~DWMCI_DDR_MODE; | 344 | regs &= ~DWMCI_DDR_MODE; |
345 | 345 | ||
346 | dwmci_writel(host, DWMCI_UHS_REG, regs); | 346 | dwmci_writel(host, DWMCI_UHS_REG, regs); |
347 | 347 | ||
348 | if (host->clksel) | 348 | if (host->clksel) |
349 | host->clksel(host); | 349 | host->clksel(host); |
350 | } | 350 | } |
351 | 351 | ||
352 | static int dwmci_init(struct mmc *mmc) | 352 | static int dwmci_init(struct mmc *mmc) |
353 | { | 353 | { |
354 | struct dwmci_host *host = mmc->priv; | 354 | struct dwmci_host *host = mmc->priv; |
355 | 355 | ||
356 | if (host->board_init) | 356 | if (host->board_init) |
357 | host->board_init(host); | 357 | host->board_init(host); |
358 | 358 | ||
359 | dwmci_writel(host, DWMCI_PWREN, 1); | 359 | dwmci_writel(host, DWMCI_PWREN, 1); |
360 | 360 | ||
361 | if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { | 361 | if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { |
362 | debug("%s[%d] Fail-reset!!\n", __func__, __LINE__); | 362 | debug("%s[%d] Fail-reset!!\n", __func__, __LINE__); |
363 | return -EIO; | 363 | return -EIO; |
364 | } | 364 | } |
365 | 365 | ||
366 | /* Enumerate at 400KHz */ | 366 | /* Enumerate at 400KHz */ |
367 | dwmci_setup_bus(host, mmc->cfg->f_min); | 367 | dwmci_setup_bus(host, mmc->cfg->f_min); |
368 | 368 | ||
369 | dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF); | 369 | dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF); |
370 | dwmci_writel(host, DWMCI_INTMASK, 0); | 370 | dwmci_writel(host, DWMCI_INTMASK, 0); |
371 | 371 | ||
372 | dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF); | 372 | dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF); |
373 | 373 | ||
374 | dwmci_writel(host, DWMCI_IDINTEN, 0); | 374 | dwmci_writel(host, DWMCI_IDINTEN, 0); |
375 | dwmci_writel(host, DWMCI_BMOD, 1); | 375 | dwmci_writel(host, DWMCI_BMOD, 1); |
376 | 376 | ||
377 | if (!host->fifoth_val) { | 377 | if (!host->fifoth_val) { |
378 | uint32_t fifo_size; | 378 | uint32_t fifo_size; |
379 | 379 | ||
380 | fifo_size = dwmci_readl(host, DWMCI_FIFOTH); | 380 | fifo_size = dwmci_readl(host, DWMCI_FIFOTH); |
381 | fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1; | 381 | fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1; |
382 | host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) | | 382 | host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) | |
383 | TX_WMARK(fifo_size / 2); | 383 | TX_WMARK(fifo_size / 2); |
384 | } | 384 | } |
385 | dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); | 385 | dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); |
386 | 386 | ||
387 | dwmci_writel(host, DWMCI_CLKENA, 0); | 387 | dwmci_writel(host, DWMCI_CLKENA, 0); |
388 | dwmci_writel(host, DWMCI_CLKSRC, 0); | 388 | dwmci_writel(host, DWMCI_CLKSRC, 0); |
389 | 389 | ||
390 | return 0; | 390 | return 0; |
391 | } | 391 | } |
392 | 392 | ||
393 | static const struct mmc_ops dwmci_ops = { | 393 | static const struct mmc_ops dwmci_ops = { |
394 | .send_cmd = dwmci_send_cmd, | 394 | .send_cmd = dwmci_send_cmd, |
395 | .set_ios = dwmci_set_ios, | 395 | .set_ios = dwmci_set_ios, |
396 | .init = dwmci_init, | 396 | .init = dwmci_init, |
397 | }; | 397 | }; |
398 | 398 | ||
399 | int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) | 399 | int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) |
400 | { | 400 | { |
401 | host->cfg.name = host->name; | 401 | host->cfg.name = host->name; |
402 | host->cfg.ops = &dwmci_ops; | 402 | host->cfg.ops = &dwmci_ops; |
403 | host->cfg.f_min = min_clk; | 403 | host->cfg.f_min = min_clk; |
404 | host->cfg.f_max = max_clk; | 404 | host->cfg.f_max = max_clk; |
405 | 405 | ||
406 | host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; | 406 | host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; |
407 | 407 | ||
408 | host->cfg.host_caps = host->caps; | 408 | host->cfg.host_caps = host->caps; |
409 | 409 | ||
410 | if (host->buswidth == 8) { | 410 | if (host->buswidth == 8) { |
411 | host->cfg.host_caps |= MMC_MODE_8BIT; | 411 | host->cfg.host_caps |= MMC_MODE_8BIT; |
412 | host->cfg.host_caps &= ~MMC_MODE_4BIT; | 412 | host->cfg.host_caps &= ~MMC_MODE_4BIT; |
413 | } else { | 413 | } else { |
414 | host->cfg.host_caps |= MMC_MODE_4BIT; | 414 | host->cfg.host_caps |= MMC_MODE_4BIT; |
415 | host->cfg.host_caps &= ~MMC_MODE_8BIT; | 415 | host->cfg.host_caps &= ~MMC_MODE_8BIT; |
416 | } | 416 | } |
417 | host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; | 417 | host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; |
418 | 418 | ||
419 | host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; | 419 | host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; |
420 | 420 | ||
421 | host->mmc = mmc_create(&host->cfg, host); | 421 | host->mmc = mmc_create(&host->cfg, host); |
422 | if (host->mmc == NULL) | 422 | if (host->mmc == NULL) |
423 | return -1; | 423 | return -1; |
424 | 424 | ||
425 | return 0; | 425 | return 0; |
426 | } | 426 | } |
427 | 427 |
drivers/mmc/hi6220_dw_mmc.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2015 Linaro | 2 | * (C) Copyright 2015 Linaro |
3 | * peter.griffin <peter.griffin@linaro.org> | 3 | * peter.griffin <peter.griffin@linaro.org> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <dwmmc.h> | 9 | #include <dwmmc.h> |
10 | #include <malloc.h> | 10 | #include <malloc.h> |
11 | #include <asm-generic/errno.h> | 11 | #include <asm-generic/errno.h> |
12 | 12 | ||
13 | #define DWMMC_MAX_CH_NUM 4 | 13 | #define DWMMC_MAX_CH_NUM 4 |
14 | 14 | ||
15 | #define DWMMC_MAX_FREQ 50000000 | 15 | #define DWMMC_MAX_FREQ 50000000 |
16 | #define DWMMC_MIN_FREQ 400000 | 16 | #define DWMMC_MIN_FREQ 400000 |
17 | 17 | ||
18 | /* Source clock is configured to 100MHz by ATF bl1*/ | 18 | /* Source clock is configured to 100MHz by ATF bl1*/ |
19 | #define MMC0_DEFAULT_FREQ 100000000 | 19 | #define MMC0_DEFAULT_FREQ 100000000 |
20 | 20 | ||
21 | static int hi6220_dwmci_core_init(struct dwmci_host *host, int index) | 21 | static int hi6220_dwmci_core_init(struct dwmci_host *host, int index) |
22 | { | 22 | { |
23 | host->name = "HiKey DWMMC"; | 23 | host->name = "HiKey DWMMC"; |
24 | 24 | ||
25 | host->dev_index = index; | 25 | host->dev_index = index; |
26 | 26 | ||
27 | /* Add the mmc channel to be registered with mmc core */ | 27 | /* Add the mmc channel to be registered with mmc core */ |
28 | if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { | 28 | if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { |
29 | printf("DWMMC%d registration failed\n", index); | 29 | printf("DWMMC%d registration failed\n", index); |
30 | return -1; | 30 | return -1; |
31 | } | 31 | } |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * This function adds the mmc channel to be registered with mmc core. | 36 | * This function adds the mmc channel to be registered with mmc core. |
37 | * index - mmc channel number. | 37 | * index - mmc channel number. |
38 | * regbase - register base address of mmc channel specified in 'index'. | 38 | * regbase - register base address of mmc channel specified in 'index'. |
39 | * bus_width - operating bus width of mmc channel specified in 'index'. | 39 | * bus_width - operating bus width of mmc channel specified in 'index'. |
40 | */ | 40 | */ |
41 | int hi6220_dwmci_add_port(int index, u32 regbase, int bus_width) | 41 | int hi6220_dwmci_add_port(int index, u32 regbase, int bus_width) |
42 | { | 42 | { |
43 | struct dwmci_host *host = NULL; | 43 | struct dwmci_host *host = NULL; |
44 | 44 | ||
45 | host = calloc(1, sizeof(struct dwmci_host)); | 45 | host = calloc(1, sizeof(struct dwmci_host)); |
46 | if (!host) { | 46 | if (!host) { |
47 | error("dwmci_host calloc failed!\n"); | 47 | error("dwmci_host calloc failed!\n"); |
48 | return -ENOMEM; | 48 | return -ENOMEM; |
49 | } | 49 | } |
50 | 50 | ||
51 | host->ioaddr = (void *)regbase; | 51 | host->ioaddr = (void *)(ulong)regbase; |
52 | host->buswidth = bus_width; | 52 | host->buswidth = bus_width; |
53 | host->bus_hz = MMC0_DEFAULT_FREQ; | 53 | host->bus_hz = MMC0_DEFAULT_FREQ; |
54 | 54 | ||
55 | return hi6220_dwmci_core_init(host, index); | 55 | return hi6220_dwmci_core_init(host, index); |
56 | } | 56 | } |
57 | 57 |