blob: fcd0cef9a72fe85f24f2dece704f971cf06ead39 [file] [log] [blame]
Channagoud Kadabibb9c3e32015-02-26 16:04:39 -08001/* Copyright (c) 2013-2015, 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>
vijay kumar4f4405f2014-08-08 11:49:53 +053038#include <boot_device.h>
Sridhar Parasuramc02d1072014-11-06 12:55:42 -080039#include <dme.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070040/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -070041 * Weak function for UFS.
42 * These are needed to avoid link errors for platforms which
43 * do not support UFS. Its better to keep this inside the
44 * mmc wrapper.
45 */
46__WEAK int ufs_write(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
47{
48 return 0;
49}
50
51__WEAK int ufs_read(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
52{
53 return 0;
54}
55
56__WEAK uint32_t ufs_get_page_size(struct ufs_dev *dev)
57{
58 return 0;
59}
60
61__WEAK uint32_t ufs_get_serial_num(struct ufs_dev *dev)
62{
63 return 0;
64}
65
66__WEAK uint64_t ufs_get_dev_capacity(struct ufs_dev *dev)
67{
68 return 0;
69}
70
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -070071__WEAK uint32_t ufs_get_erase_blk_size(struct ufs_dev *dev)
72{
73 return 0;
74}
75
76__WEAK int ufs_erase(struct ufs_dev* dev, uint64_t start_lba, uint32_t num_blocks)
77{
78 return 0;
79}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -080080
81__WEAK uint8_t ufs_get_num_of_luns(struct ufs_dev* dev)
82{
83 return 0;
84}
85
Channagoud Kadabia17fc422013-09-11 12:25:34 -070086/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070087 * Function: get mmc card
88 * Arg : None
89 * Return : Pointer to mmc card structure
90 * Flow : Get the card pointer from the device structure
91 */
92static struct mmc_card *get_mmc_card()
93{
Channagoud Kadabia17fc422013-09-11 12:25:34 -070094 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070095 struct mmc_card *card;
96
97 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -070098 card = &((struct mmc_device*)dev)->card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070099
100 return card;
101}
102
103/*
104 * Function: mmc_write
105 * Arg : Data address on card, data length, i/p buffer
106 * Return : 0 on Success, non zero on failure
107 * Flow : Write the data from in to the card
108 */
109uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
110{
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700111 uint32_t val = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700112 int ret = 0;
113 uint32_t block_size = 0;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700114 uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700115 uint8_t *sptr = (uint8_t *)in;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700116 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700117
118 dev = target_mmc_device();
119
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700120 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700121
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700122 ASSERT(!(data_addr % block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700123
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700124 if (data_len % block_size)
125 data_len = ROUNDUP(data_len, block_size);
126
Channagoud Kadabidefe0982015-02-26 19:00:41 -0800127 /*
128 * Flush the cache before handing over the data to
129 * storage driver
130 */
131 arch_clean_invalidate_cache_range((addr_t)in, data_len);
132
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700133 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700134 {
135 /* TODO: This function is aware of max data that can be
136 * tranferred using sdhci adma mode, need to have a cleaner
137 * implementation to keep this function independent of sdhci
138 * limitations
139 */
140 while (data_len > write_size) {
141 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size));
142 if (val)
143 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530144 dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700145 return val;
146 }
147 sptr += write_size;
148 data_addr += write_size;
149 data_len -= write_size;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700150 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700151
152 if (data_len)
153 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
154
155 if (val)
vijay kumar4f4405f2014-08-08 11:49:53 +0530156 dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700157 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700158 else
159 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700160 ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700161
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700162 if (ret)
163 {
164 dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr);
165 val = 1;
166 }
167 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700168
169 return val;
170}
171
172/*
173 * Function: mmc_read
174 * Arg : Data address on card, o/p buffer & data length
175 * Return : 0 on Success, non zero on failure
176 * Flow : Read data from the card to out
177 */
178uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
179{
180 uint32_t ret = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700181 uint32_t block_size;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700182 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700183 void *dev;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700184 uint8_t *sptr = (uint8_t *)out;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700185
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700186 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700187 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700188
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700189 ASSERT(!(data_addr % block_size));
190 ASSERT(!(data_len % block_size));
191
192
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700193 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700194 {
195 /* TODO: This function is aware of max data that can be
196 * tranferred using sdhci adma mode, need to have a cleaner
197 * implementation to keep this function independent of sdhci
198 * limitations
199 */
200 while (data_len > read_size) {
201 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size));
202 if (ret)
203 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530204 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700205 return ret;
206 }
207 sptr += read_size;
208 data_addr += read_size;
209 data_len -= read_size;
210 }
211
212 if (data_len)
213 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
214
215 if (ret)
vijay kumar4f4405f2014-08-08 11:49:53 +0530216 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700217 }
218 else
219 {
220 ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700221 if (ret)
222 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700223 dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr);
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700224 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700225
226 arch_invalidate_cache_range((addr_t)out, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700227 }
228
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700229 return ret;
230}
231
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700232
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700233/*
Oliver Wangcee448d2013-10-22 18:40:13 +0800234 * Function: mmc get erase unit size
235 * Arg : None
236 * Return : Returns the erase unit size of the storage
237 * Flow : Get the erase unit size from the card
238 */
239
240uint32_t mmc_get_eraseunit_size()
241{
242 uint32_t erase_unit_sz = 0;
243
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700244 if (platform_boot_dev_isemmc()) {
Oliver Wangcee448d2013-10-22 18:40:13 +0800245 struct mmc_device *dev;
246 struct mmc_card *card;
247
248 dev = target_mmc_device();
249 card = &dev->card;
250 /*
251 * Calculate the erase unit size,
252 * 1. Based on emmc 4.5 spec for emmc card
253 * 2. Use SD Card Status info for SD cards
254 */
255 if (MMC_CARD_MMC(card))
256 {
257 /*
258 * Calculate the erase unit size as per the emmc specification v4.5
259 */
260 if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
261 erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
262 else
263 erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
264 }
265 else
266 erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
267 }
268
269 return erase_unit_sz;
270}
271
272/*
273 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
274 * function can be used when we want to erase the blocks not
275 * aligned with the mmc erase group.
276 * Arg : Block address & length
277 * Return : Returns 0
278 * Flow : Erase the card from specified addr
279 */
280
281static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
282{
283 uint32_t *out;
Channagoud Kadabia87af972014-03-10 15:26:48 -0700284 uint32_t block_size = mmc_get_device_blocksize();
285 uint32_t erase_size = (block_size * num_blks);
286 uint32_t scratch_size = target_get_max_flash_size();
Oliver Wangcee448d2013-10-22 18:40:13 +0800287
288 dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
Oliver Wangcee448d2013-10-22 18:40:13 +0800289
Channagoud Kadabia87af972014-03-10 15:26:48 -0700290 if (erase_size <= scratch_size)
Oliver Wangcee448d2013-10-22 18:40:13 +0800291 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700292 /* Use scratch address if the unaligned blocks */
293 out = (uint32_t *) target_get_scratch_address();
294 }
295 else
296 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530297 dprintf(CRITICAL, "Erase Fail: Erase size: %u is bigger than scratch region\n", scratch_size);
Oliver Wangcee448d2013-10-22 18:40:13 +0800298 return 1;
299 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800300
Channagoud Kadabia87af972014-03-10 15:26:48 -0700301 memset((void *)out, 0, erase_size);
302
Channagoud Kadabidefe0982015-02-26 19:00:41 -0800303 /* Flush the data to memory before writing to storage */
304 arch_clean_invalidate_cache_range((addr_t) out , erase_size);
305
Channagoud Kadabia87af972014-03-10 15:26:48 -0700306 if (mmc_sdhci_write(dev, out, blk_addr, num_blks))
Oliver Wangcee448d2013-10-22 18:40:13 +0800307 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700308 dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
309 return 1;
Oliver Wangcee448d2013-10-22 18:40:13 +0800310 }
Channagoud Kadabia87af972014-03-10 15:26:48 -0700311
Oliver Wangcee448d2013-10-22 18:40:13 +0800312 return 0;
313}
314
315/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700316 * Function: mmc erase card
317 * Arg : Block address & length
318 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700319 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700320 */
321uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
322{
Oliver Wangcee448d2013-10-22 18:40:13 +0800323 struct mmc_device *dev;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700324 uint32_t block_size;
Oliver Wangcee448d2013-10-22 18:40:13 +0800325 uint32_t unaligned_blks;
326 uint32_t head_unit;
327 uint32_t tail_unit;
328 uint32_t erase_unit_sz;
329 uint32_t blk_addr;
330 uint32_t blk_count;
331 uint64_t blks_to_erase;
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700332
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700333 block_size = mmc_get_device_blocksize();
334
335 dev = target_mmc_device();
336
337 ASSERT(!(addr % block_size));
338 ASSERT(!(len % block_size));
339
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700340 if (platform_boot_dev_isemmc())
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700341 {
Oliver Wangcee448d2013-10-22 18:40:13 +0800342 erase_unit_sz = mmc_get_eraseunit_size();
343 dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700344
Oliver Wangcee448d2013-10-22 18:40:13 +0800345 blk_addr = addr / block_size;
346 blk_count = len / block_size;
347
Oliver Wangcee448d2013-10-22 18:40:13 +0800348 dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
349
350 head_unit = blk_addr / erase_unit_sz;
351 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
352
353 if (tail_unit - head_unit <= 1)
354 {
355 dprintf(INFO, "SDHCI unit erase not required\n");
356 return mmc_zero_out(dev, blk_addr, blk_count);
357 }
358
359 unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
360
361 if (unaligned_blks < erase_unit_sz)
362 {
363 dprintf(SPEW, "Handling unaligned head blocks\n");
364 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
365 return 1;
366
367 blk_addr += unaligned_blks;
368 blk_count -= unaligned_blks;
vijay kumar08bde372014-09-22 16:17:59 +0530369
370 head_unit = blk_addr / erase_unit_sz;
371 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
372
373 if (tail_unit - head_unit <= 1)
374 {
375 dprintf(INFO, "SDHCI unit erase not required\n");
376 return mmc_zero_out(dev, blk_addr, blk_count);
377 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800378 }
379
380 unaligned_blks = blk_count % erase_unit_sz;
381 blks_to_erase = blk_count - unaligned_blks;
382
vijay kumar4f4405f2014-08-08 11:49:53 +0530383 dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr,(unsigned int)blks_to_erase);
Oliver Wangcee448d2013-10-22 18:40:13 +0800384 if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700385 {
386 dprintf(CRITICAL, "MMC erase failed\n");
387 return 1;
388 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800389
390 blk_addr += blks_to_erase;
391
392 if (unaligned_blks)
393 {
394 dprintf(SPEW, "Handling unaligned tail blocks\n");
395 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
396 return 1;
397 }
398
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700399 }
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700400 else
401 {
402 if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
403 {
404 dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
405 return 1;
406 }
407 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700408
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700409 return 0;
410}
411
412/*
413 * Function: mmc get psn
414 * Arg : None
415 * Return : Returns the product serial number
416 * Flow : Get the PSN from card
417 */
418uint32_t mmc_get_psn(void)
419{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700420 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700421 {
422 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700423
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700424 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700425
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700426 return card->cid.psn;
427 }
428 else
429 {
430 void *dev;
431
432 dev = target_mmc_device();
433
434 return ufs_get_serial_num((struct ufs_dev *)dev);
435 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700436}
437
438/*
439 * Function: mmc get capacity
440 * Arg : None
441 * Return : Returns the density of the emmc card
442 * Flow : Get the density from card
443 */
444uint64_t mmc_get_device_capacity()
445{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700446 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700447 {
448 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700449
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700450 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700451
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700452 return card->capacity;
453 }
454 else
455 {
456 void *dev;
457
458 dev = target_mmc_device();
459
460 return ufs_get_dev_capacity((struct ufs_dev *)dev);
461 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700462}
463
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700464/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700465 * Function: mmc get blocksize
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700466 * Arg : None
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700467 * Return : Returns the block size of the storage
468 * Flow : Get the block size form the card
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700469 */
470uint32_t mmc_get_device_blocksize()
471{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700472 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700473 {
474 struct mmc_card *card;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700475
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700476 card = get_mmc_card();
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700477
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700478 return card->block_size;
479 }
480 else
481 {
482 void *dev;
483
484 dev = target_mmc_device();
485
486 return ufs_get_page_size((struct ufs_dev *)dev);
487 }
488}
489
490/*
491 * Function: storage page size
492 * Arg : None
493 * Return : Returns the page size for the card
494 * Flow : Get the page size for storage
495 */
496uint32_t mmc_page_size()
497{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700498 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700499 {
500 return BOARD_KERNEL_PAGESIZE;
501 }
502 else
503 {
504 void *dev;
505
506 dev = target_mmc_device();
507
508 return ufs_get_page_size((struct ufs_dev *)dev);
509 }
510}
511
512/*
513 * Function: mmc device sleep
514 * Arg : None
515 * Return : Clean up function for storage
516 * Flow : Put the mmc card to sleep
517 */
518void mmc_device_sleep()
519{
520 void *dev;
521 dev = target_mmc_device();
522
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700523 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700524 {
525 mmc_put_card_to_sleep((struct mmc_device *)dev);
526 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700527}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800528
529/*
530 * Function : mmc set LUN for ufs
531 * Arg : LUN number
532 * Return type : void
533 */
534void mmc_set_lun(uint8_t lun)
535{
536 void *dev;
537 dev = target_mmc_device();
538
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700539 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800540 {
541 ((struct ufs_dev*)dev)->current_lun = lun;
542 }
543}
544
545/*
546 * Function : mmc get LUN from ufs
547 * Arg : LUN number
548 * Return type : lun number for UFS and 0 for emmc
549 */
550uint8_t mmc_get_lun(void)
551{
552 void *dev;
553 uint8_t lun=0;
554
555 dev = target_mmc_device();
556
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700557 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800558 {
559 lun = ((struct ufs_dev*)dev)->current_lun;
560 }
561
562 return lun;
563}
564
565void mmc_read_partition_table(uint8_t arg)
566{
567 void *dev;
568 uint8_t lun = 0;
569 uint8_t max_luns;
570
571 dev = target_mmc_device();
572
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700573 if(!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800574 {
575 max_luns = ufs_get_num_of_luns((struct ufs_dev*)dev);
576
577 ASSERT(max_luns);
578
579 for(lun = arg; lun < max_luns; lun++)
580 {
581 mmc_set_lun(lun);
582
583 if(partition_read_table())
584 {
585 dprintf(CRITICAL, "Error reading the partition table info for lun %d\n", lun);
586 }
587 }
Sridhar Parasuram176c2222014-09-16 16:34:01 -0700588 mmc_set_lun(0);
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800589 }
590 else
591 {
592 if(partition_read_table())
593 {
594 dprintf(CRITICAL, "Error reading the partition table info\n");
595 }
596 }
597}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700598
599uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
600{
601 void *dev = NULL;
602 struct mmc_card *card = NULL;
603 uint32_t block_size;
604 unsigned long long ptn = 0;
605 uint64_t size;
606 int index = -1;
607 int ret = 0;
608
609 dev = target_mmc_device();
610 block_size = mmc_get_device_blocksize();
611
612 if (platform_boot_dev_isemmc())
613 {
614 card = &((struct mmc_device *)dev)->card;
615
616 index = partition_get_index(ptn_name);
617
618 ptn = partition_get_offset(index);
619 if(!ptn)
620 {
621 return 1;
622 }
623
Channagoud Kadabibb9c3e32015-02-26 16:04:39 -0800624 /* Convert the size to blocks */
625 size = partition_get_size(index) / block_size;
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700626
627 /*
628 * For read only partitions the minimum size allocated on the disk is
629 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
630 * protect atleast one WP group.
631 */
632 if (partition_read_only(index) && size < card->wp_grp_size)
633 {
Channagoud Kadabibb9c3e32015-02-26 16:04:39 -0800634 /* Write protect api takes the size in bytes, convert size to bytes */
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700635 size = card->wp_grp_size * block_size;
636 }
637 /* Set the power on WP bit */
638 return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
639 }
640 else
641 {
642 /* Enable the power on WP fo all LUNs which have WP bit is enabled */
643 ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
644 if (ret < 0)
645 {
646 dprintf(CRITICAL, "Failure to WP UFS partition\n");
647 return 1;
648 }
649 }
650
651 return 0;
652}