blob: 0a7d5b4cd487d1fbcad388b5492777751eeab26d [file] [log] [blame]
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -08001/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <stdint.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070031#include <mmc_wrapper.h>
Channagoud Kadabia17fc422013-09-11 12:25:34 -070032#include <mmc_sdhci.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070033#include <sdhci.h>
Channagoud Kadabia17fc422013-09-11 12:25:34 -070034#include <ufs.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070035#include <target.h>
Oliver Wangcee448d2013-10-22 18:40:13 +080036#include <string.h>
Channagoud Kadabifaf20f62014-10-21 22:22:37 -070037#include <partition_parser.h>
Sridhar Parasuramc02d1072014-11-06 12:55:42 -080038#include <dme.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070039/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -070040 * Weak function for UFS.
41 * These are needed to avoid link errors for platforms which
42 * do not support UFS. Its better to keep this inside the
43 * mmc wrapper.
44 */
45__WEAK int ufs_write(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
46{
47 return 0;
48}
49
50__WEAK int ufs_read(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
51{
52 return 0;
53}
54
55__WEAK uint32_t ufs_get_page_size(struct ufs_dev *dev)
56{
57 return 0;
58}
59
60__WEAK uint32_t ufs_get_serial_num(struct ufs_dev *dev)
61{
62 return 0;
63}
64
65__WEAK uint64_t ufs_get_dev_capacity(struct ufs_dev *dev)
66{
67 return 0;
68}
69
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -070070__WEAK uint32_t ufs_get_erase_blk_size(struct ufs_dev *dev)
71{
72 return 0;
73}
74
75__WEAK int ufs_erase(struct ufs_dev* dev, uint64_t start_lba, uint32_t num_blocks)
76{
77 return 0;
78}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -080079
80__WEAK uint8_t ufs_get_num_of_luns(struct ufs_dev* dev)
81{
82 return 0;
83}
84
Channagoud Kadabia17fc422013-09-11 12:25:34 -070085/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070086 * Function: get mmc card
87 * Arg : None
88 * Return : Pointer to mmc card structure
89 * Flow : Get the card pointer from the device structure
90 */
91static struct mmc_card *get_mmc_card()
92{
Channagoud Kadabia17fc422013-09-11 12:25:34 -070093 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070094 struct mmc_card *card;
95
96 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -070097 card = &((struct mmc_device*)dev)->card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070098
99 return card;
100}
101
102/*
103 * Function: mmc_write
104 * Arg : Data address on card, data length, i/p buffer
105 * Return : 0 on Success, non zero on failure
106 * Flow : Write the data from in to the card
107 */
108uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
109{
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700110 uint32_t val = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700111 int ret = 0;
112 uint32_t block_size = 0;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700113 uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700114 uint8_t *sptr = (uint8_t *)in;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700115 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700116
117 dev = target_mmc_device();
118
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700119 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700120
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700121 ASSERT(!(data_addr % block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700122
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700123 if (data_len % block_size)
124 data_len = ROUNDUP(data_len, block_size);
125
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700126 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700127 {
128 /* TODO: This function is aware of max data that can be
129 * tranferred using sdhci adma mode, need to have a cleaner
130 * implementation to keep this function independent of sdhci
131 * limitations
132 */
133 while (data_len > write_size) {
134 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size));
135 if (val)
136 {
137 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / block_size));
138 return val;
139 }
140 sptr += write_size;
141 data_addr += write_size;
142 data_len -= write_size;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700143 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700144
145 if (data_len)
146 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
147
148 if (val)
149 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700150 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700151 else
152 {
153 arch_clean_invalidate_cache_range((addr_t)in, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700154
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700155 ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700156
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700157 if (ret)
158 {
159 dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr);
160 val = 1;
161 }
162 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700163
164 return val;
165}
166
167/*
168 * Function: mmc_read
169 * Arg : Data address on card, o/p buffer & data length
170 * Return : 0 on Success, non zero on failure
171 * Flow : Read data from the card to out
172 */
173uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
174{
175 uint32_t ret = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700176 uint32_t block_size;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700177 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700178 void *dev;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700179 uint8_t *sptr = (uint8_t *)out;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700180
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700181 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700182 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700183
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700184 ASSERT(!(data_addr % block_size));
185 ASSERT(!(data_len % block_size));
186
187
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700188 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700189 {
190 /* TODO: This function is aware of max data that can be
191 * tranferred using sdhci adma mode, need to have a cleaner
192 * implementation to keep this function independent of sdhci
193 * limitations
194 */
195 while (data_len > read_size) {
196 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size));
197 if (ret)
198 {
199 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / block_size));
200 return ret;
201 }
202 sptr += read_size;
203 data_addr += read_size;
204 data_len -= read_size;
205 }
206
207 if (data_len)
208 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
209
210 if (ret)
211 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / block_size));
212 }
213 else
214 {
215 ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700216 if (ret)
217 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700218 dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr);
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700219 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700220
221 arch_invalidate_cache_range((addr_t)out, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700222 }
223
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700224 return ret;
225}
226
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700227
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700228/*
Oliver Wangcee448d2013-10-22 18:40:13 +0800229 * Function: mmc get erase unit size
230 * Arg : None
231 * Return : Returns the erase unit size of the storage
232 * Flow : Get the erase unit size from the card
233 */
234
235uint32_t mmc_get_eraseunit_size()
236{
237 uint32_t erase_unit_sz = 0;
238
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700239 if (platform_boot_dev_isemmc()) {
Oliver Wangcee448d2013-10-22 18:40:13 +0800240 struct mmc_device *dev;
241 struct mmc_card *card;
242
243 dev = target_mmc_device();
244 card = &dev->card;
245 /*
246 * Calculate the erase unit size,
247 * 1. Based on emmc 4.5 spec for emmc card
248 * 2. Use SD Card Status info for SD cards
249 */
250 if (MMC_CARD_MMC(card))
251 {
252 /*
253 * Calculate the erase unit size as per the emmc specification v4.5
254 */
255 if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
256 erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
257 else
258 erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
259 }
260 else
261 erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
262 }
263
264 return erase_unit_sz;
265}
266
267/*
268 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
269 * function can be used when we want to erase the blocks not
270 * aligned with the mmc erase group.
271 * Arg : Block address & length
272 * Return : Returns 0
273 * Flow : Erase the card from specified addr
274 */
275
276static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
277{
278 uint32_t *out;
Channagoud Kadabia87af972014-03-10 15:26:48 -0700279 uint32_t block_size = mmc_get_device_blocksize();
280 uint32_t erase_size = (block_size * num_blks);
281 uint32_t scratch_size = target_get_max_flash_size();
Oliver Wangcee448d2013-10-22 18:40:13 +0800282
283 dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
Oliver Wangcee448d2013-10-22 18:40:13 +0800284
Channagoud Kadabia87af972014-03-10 15:26:48 -0700285 if (erase_size <= scratch_size)
Oliver Wangcee448d2013-10-22 18:40:13 +0800286 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700287 /* Use scratch address if the unaligned blocks */
288 out = (uint32_t *) target_get_scratch_address();
289 }
290 else
291 {
292 dprintf(CRITICAL, "Erase Fail: Erase size: %u is bigger than scratch region:%u\n", scratch_size);
Oliver Wangcee448d2013-10-22 18:40:13 +0800293 return 1;
294 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800295
Channagoud Kadabia87af972014-03-10 15:26:48 -0700296 memset((void *)out, 0, erase_size);
297
298 if (mmc_sdhci_write(dev, out, blk_addr, num_blks))
Oliver Wangcee448d2013-10-22 18:40:13 +0800299 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700300 dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
301 return 1;
Oliver Wangcee448d2013-10-22 18:40:13 +0800302 }
Channagoud Kadabia87af972014-03-10 15:26:48 -0700303
Oliver Wangcee448d2013-10-22 18:40:13 +0800304 return 0;
305}
306
307/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700308 * Function: mmc erase card
309 * Arg : Block address & length
310 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700311 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700312 */
313uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
314{
Oliver Wangcee448d2013-10-22 18:40:13 +0800315 struct mmc_device *dev;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700316 uint32_t block_size;
Oliver Wangcee448d2013-10-22 18:40:13 +0800317 uint32_t unaligned_blks;
318 uint32_t head_unit;
319 uint32_t tail_unit;
320 uint32_t erase_unit_sz;
321 uint32_t blk_addr;
322 uint32_t blk_count;
323 uint64_t blks_to_erase;
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700324
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700325 block_size = mmc_get_device_blocksize();
326
327 dev = target_mmc_device();
328
329 ASSERT(!(addr % block_size));
330 ASSERT(!(len % block_size));
331
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700332 if (platform_boot_dev_isemmc())
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700333 {
Oliver Wangcee448d2013-10-22 18:40:13 +0800334 erase_unit_sz = mmc_get_eraseunit_size();
335 dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700336
Oliver Wangcee448d2013-10-22 18:40:13 +0800337 blk_addr = addr / block_size;
338 blk_count = len / block_size;
339
Oliver Wangcee448d2013-10-22 18:40:13 +0800340 dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
341
342 head_unit = blk_addr / erase_unit_sz;
343 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
344
345 if (tail_unit - head_unit <= 1)
346 {
347 dprintf(INFO, "SDHCI unit erase not required\n");
348 return mmc_zero_out(dev, blk_addr, blk_count);
349 }
350
351 unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
352
353 if (unaligned_blks < erase_unit_sz)
354 {
355 dprintf(SPEW, "Handling unaligned head blocks\n");
356 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
357 return 1;
358
359 blk_addr += unaligned_blks;
360 blk_count -= unaligned_blks;
vijay kumar08bde372014-09-22 16:17:59 +0530361
362 head_unit = blk_addr / erase_unit_sz;
363 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
364
365 if (tail_unit - head_unit <= 1)
366 {
367 dprintf(INFO, "SDHCI unit erase not required\n");
368 return mmc_zero_out(dev, blk_addr, blk_count);
369 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800370 }
371
372 unaligned_blks = blk_count % erase_unit_sz;
373 blks_to_erase = blk_count - unaligned_blks;
374
375 dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr, blks_to_erase);
376 if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700377 {
378 dprintf(CRITICAL, "MMC erase failed\n");
379 return 1;
380 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800381
382 blk_addr += blks_to_erase;
383
384 if (unaligned_blks)
385 {
386 dprintf(SPEW, "Handling unaligned tail blocks\n");
387 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
388 return 1;
389 }
390
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700391 }
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700392 else
393 {
394 if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
395 {
396 dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
397 return 1;
398 }
399 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700400
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700401 return 0;
402}
403
404/*
405 * Function: mmc get psn
406 * Arg : None
407 * Return : Returns the product serial number
408 * Flow : Get the PSN from card
409 */
410uint32_t mmc_get_psn(void)
411{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700412 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700413 {
414 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700415
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700416 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700417
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700418 return card->cid.psn;
419 }
420 else
421 {
422 void *dev;
423
424 dev = target_mmc_device();
425
426 return ufs_get_serial_num((struct ufs_dev *)dev);
427 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700428}
429
430/*
431 * Function: mmc get capacity
432 * Arg : None
433 * Return : Returns the density of the emmc card
434 * Flow : Get the density from card
435 */
436uint64_t mmc_get_device_capacity()
437{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700438 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700439 {
440 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700441
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700442 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700443
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700444 return card->capacity;
445 }
446 else
447 {
448 void *dev;
449
450 dev = target_mmc_device();
451
452 return ufs_get_dev_capacity((struct ufs_dev *)dev);
453 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700454}
455
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700456/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700457 * Function: mmc get blocksize
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700458 * Arg : None
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700459 * Return : Returns the block size of the storage
460 * Flow : Get the block size form the card
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700461 */
462uint32_t mmc_get_device_blocksize()
463{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700464 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700465 {
466 struct mmc_card *card;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700467
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700468 card = get_mmc_card();
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700469
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700470 return card->block_size;
471 }
472 else
473 {
474 void *dev;
475
476 dev = target_mmc_device();
477
478 return ufs_get_page_size((struct ufs_dev *)dev);
479 }
480}
481
482/*
483 * Function: storage page size
484 * Arg : None
485 * Return : Returns the page size for the card
486 * Flow : Get the page size for storage
487 */
488uint32_t mmc_page_size()
489{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700490 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700491 {
492 return BOARD_KERNEL_PAGESIZE;
493 }
494 else
495 {
496 void *dev;
497
498 dev = target_mmc_device();
499
500 return ufs_get_page_size((struct ufs_dev *)dev);
501 }
502}
503
504/*
505 * Function: mmc device sleep
506 * Arg : None
507 * Return : Clean up function for storage
508 * Flow : Put the mmc card to sleep
509 */
510void mmc_device_sleep()
511{
512 void *dev;
513 dev = target_mmc_device();
514
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700515 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700516 {
517 mmc_put_card_to_sleep((struct mmc_device *)dev);
518 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700519}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800520
521/*
522 * Function : mmc set LUN for ufs
523 * Arg : LUN number
524 * Return type : void
525 */
526void mmc_set_lun(uint8_t lun)
527{
528 void *dev;
529 dev = target_mmc_device();
530
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700531 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800532 {
533 ((struct ufs_dev*)dev)->current_lun = lun;
534 }
535}
536
537/*
538 * Function : mmc get LUN from ufs
539 * Arg : LUN number
540 * Return type : lun number for UFS and 0 for emmc
541 */
542uint8_t mmc_get_lun(void)
543{
544 void *dev;
545 uint8_t lun=0;
546
547 dev = target_mmc_device();
548
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700549 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800550 {
551 lun = ((struct ufs_dev*)dev)->current_lun;
552 }
553
554 return lun;
555}
556
557void mmc_read_partition_table(uint8_t arg)
558{
559 void *dev;
560 uint8_t lun = 0;
561 uint8_t max_luns;
562
563 dev = target_mmc_device();
564
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700565 if(!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800566 {
567 max_luns = ufs_get_num_of_luns((struct ufs_dev*)dev);
568
569 ASSERT(max_luns);
570
571 for(lun = arg; lun < max_luns; lun++)
572 {
573 mmc_set_lun(lun);
574
575 if(partition_read_table())
576 {
577 dprintf(CRITICAL, "Error reading the partition table info for lun %d\n", lun);
578 }
579 }
Sridhar Parasuram176c2222014-09-16 16:34:01 -0700580 mmc_set_lun(0);
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800581 }
582 else
583 {
584 if(partition_read_table())
585 {
586 dprintf(CRITICAL, "Error reading the partition table info\n");
587 }
588 }
589}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700590
591uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
592{
593 void *dev = NULL;
594 struct mmc_card *card = NULL;
595 uint32_t block_size;
596 unsigned long long ptn = 0;
597 uint64_t size;
598 int index = -1;
599 int ret = 0;
600
601 dev = target_mmc_device();
602 block_size = mmc_get_device_blocksize();
603
604 if (platform_boot_dev_isemmc())
605 {
606 card = &((struct mmc_device *)dev)->card;
607
608 index = partition_get_index(ptn_name);
609
610 ptn = partition_get_offset(index);
611 if(!ptn)
612 {
613 return 1;
614 }
615
616 size = partition_get_size(index);
617
618 /*
619 * For read only partitions the minimum size allocated on the disk is
620 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
621 * protect atleast one WP group.
622 */
623 if (partition_read_only(index) && size < card->wp_grp_size)
624 {
625 size = card->wp_grp_size * block_size;
626 }
627 /* Set the power on WP bit */
628 return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
629 }
630 else
631 {
632 /* Enable the power on WP fo all LUNs which have WP bit is enabled */
633 ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
634 if (ret < 0)
635 {
636 dprintf(CRITICAL, "Failure to WP UFS partition\n");
637 return 1;
638 }
639 }
640
641 return 0;
642}