blob: f25a633314858edeb4ee7f1229113d8510b5fb2b [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
Matthew Qinb675de32015-03-25 05:19:30 -0400192 /*
193 * dma onto write back memory is unsafe/nonportable,
194 * but callers to this routine normally provide
195 * write back buffers. Invalidate cache
196 * before read data from mmc.
197 */
198 arch_clean_invalidate_cache_range((addr_t)(out), data_len);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700199
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700200 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700201 {
202 /* TODO: This function is aware of max data that can be
203 * tranferred using sdhci adma mode, need to have a cleaner
204 * implementation to keep this function independent of sdhci
205 * limitations
206 */
207 while (data_len > read_size) {
208 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size));
209 if (ret)
210 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530211 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700212 return ret;
213 }
214 sptr += read_size;
215 data_addr += read_size;
216 data_len -= read_size;
217 }
218
219 if (data_len)
220 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
221
222 if (ret)
vijay kumar4f4405f2014-08-08 11:49:53 +0530223 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700224 }
225 else
226 {
227 ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700228 if (ret)
229 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700230 dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr);
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700231 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700232
233 arch_invalidate_cache_range((addr_t)out, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700234 }
235
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700236 return ret;
237}
238
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700239
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700240/*
Oliver Wangcee448d2013-10-22 18:40:13 +0800241 * Function: mmc get erase unit size
242 * Arg : None
243 * Return : Returns the erase unit size of the storage
244 * Flow : Get the erase unit size from the card
245 */
246
247uint32_t mmc_get_eraseunit_size()
248{
249 uint32_t erase_unit_sz = 0;
250
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700251 if (platform_boot_dev_isemmc()) {
Oliver Wangcee448d2013-10-22 18:40:13 +0800252 struct mmc_device *dev;
253 struct mmc_card *card;
254
255 dev = target_mmc_device();
256 card = &dev->card;
257 /*
258 * Calculate the erase unit size,
259 * 1. Based on emmc 4.5 spec for emmc card
260 * 2. Use SD Card Status info for SD cards
261 */
262 if (MMC_CARD_MMC(card))
263 {
264 /*
265 * Calculate the erase unit size as per the emmc specification v4.5
266 */
267 if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
268 erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
269 else
270 erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
271 }
272 else
273 erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
274 }
275
276 return erase_unit_sz;
277}
278
279/*
280 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
281 * function can be used when we want to erase the blocks not
282 * aligned with the mmc erase group.
283 * Arg : Block address & length
284 * Return : Returns 0
285 * Flow : Erase the card from specified addr
286 */
287
288static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
289{
290 uint32_t *out;
Channagoud Kadabia87af972014-03-10 15:26:48 -0700291 uint32_t block_size = mmc_get_device_blocksize();
292 uint32_t erase_size = (block_size * num_blks);
293 uint32_t scratch_size = target_get_max_flash_size();
Oliver Wangcee448d2013-10-22 18:40:13 +0800294
295 dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
Oliver Wangcee448d2013-10-22 18:40:13 +0800296
Channagoud Kadabia87af972014-03-10 15:26:48 -0700297 if (erase_size <= scratch_size)
Oliver Wangcee448d2013-10-22 18:40:13 +0800298 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700299 /* Use scratch address if the unaligned blocks */
300 out = (uint32_t *) target_get_scratch_address();
301 }
302 else
303 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530304 dprintf(CRITICAL, "Erase Fail: Erase size: %u is bigger than scratch region\n", scratch_size);
Oliver Wangcee448d2013-10-22 18:40:13 +0800305 return 1;
306 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800307
Channagoud Kadabia87af972014-03-10 15:26:48 -0700308 memset((void *)out, 0, erase_size);
309
Channagoud Kadabidefe0982015-02-26 19:00:41 -0800310 /* Flush the data to memory before writing to storage */
311 arch_clean_invalidate_cache_range((addr_t) out , erase_size);
312
Channagoud Kadabia87af972014-03-10 15:26:48 -0700313 if (mmc_sdhci_write(dev, out, blk_addr, num_blks))
Oliver Wangcee448d2013-10-22 18:40:13 +0800314 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700315 dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
316 return 1;
Oliver Wangcee448d2013-10-22 18:40:13 +0800317 }
Channagoud Kadabia87af972014-03-10 15:26:48 -0700318
Oliver Wangcee448d2013-10-22 18:40:13 +0800319 return 0;
320}
321
322/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700323 * Function: mmc erase card
324 * Arg : Block address & length
325 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700326 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700327 */
328uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
329{
Oliver Wangcee448d2013-10-22 18:40:13 +0800330 struct mmc_device *dev;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700331 uint32_t block_size;
Oliver Wangcee448d2013-10-22 18:40:13 +0800332 uint32_t unaligned_blks;
333 uint32_t head_unit;
334 uint32_t tail_unit;
335 uint32_t erase_unit_sz;
336 uint32_t blk_addr;
337 uint32_t blk_count;
338 uint64_t blks_to_erase;
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700339
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700340 block_size = mmc_get_device_blocksize();
341
342 dev = target_mmc_device();
343
344 ASSERT(!(addr % block_size));
345 ASSERT(!(len % block_size));
346
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700347 if (platform_boot_dev_isemmc())
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700348 {
Oliver Wangcee448d2013-10-22 18:40:13 +0800349 erase_unit_sz = mmc_get_eraseunit_size();
350 dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700351
Oliver Wangcee448d2013-10-22 18:40:13 +0800352 blk_addr = addr / block_size;
353 blk_count = len / block_size;
354
Oliver Wangcee448d2013-10-22 18:40:13 +0800355 dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
356
357 head_unit = blk_addr / erase_unit_sz;
358 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
359
360 if (tail_unit - head_unit <= 1)
361 {
362 dprintf(INFO, "SDHCI unit erase not required\n");
363 return mmc_zero_out(dev, blk_addr, blk_count);
364 }
365
366 unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
367
368 if (unaligned_blks < erase_unit_sz)
369 {
370 dprintf(SPEW, "Handling unaligned head blocks\n");
371 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
372 return 1;
373
374 blk_addr += unaligned_blks;
375 blk_count -= unaligned_blks;
vijay kumar08bde372014-09-22 16:17:59 +0530376
377 head_unit = blk_addr / erase_unit_sz;
378 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
379
380 if (tail_unit - head_unit <= 1)
381 {
382 dprintf(INFO, "SDHCI unit erase not required\n");
383 return mmc_zero_out(dev, blk_addr, blk_count);
384 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800385 }
386
387 unaligned_blks = blk_count % erase_unit_sz;
388 blks_to_erase = blk_count - unaligned_blks;
389
vijay kumar4f4405f2014-08-08 11:49:53 +0530390 dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr,(unsigned int)blks_to_erase);
Oliver Wangcee448d2013-10-22 18:40:13 +0800391 if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700392 {
393 dprintf(CRITICAL, "MMC erase failed\n");
394 return 1;
395 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800396
397 blk_addr += blks_to_erase;
398
399 if (unaligned_blks)
400 {
401 dprintf(SPEW, "Handling unaligned tail blocks\n");
402 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
403 return 1;
404 }
405
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700406 }
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700407 else
408 {
409 if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
410 {
411 dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
412 return 1;
413 }
414 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700415
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700416 return 0;
417}
418
419/*
420 * Function: mmc get psn
421 * Arg : None
422 * Return : Returns the product serial number
423 * Flow : Get the PSN from card
424 */
425uint32_t mmc_get_psn(void)
426{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700427 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700428 {
429 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700430
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700431 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700432
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700433 return card->cid.psn;
434 }
435 else
436 {
437 void *dev;
438
439 dev = target_mmc_device();
440
441 return ufs_get_serial_num((struct ufs_dev *)dev);
442 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700443}
444
445/*
446 * Function: mmc get capacity
447 * Arg : None
448 * Return : Returns the density of the emmc card
449 * Flow : Get the density from card
450 */
451uint64_t mmc_get_device_capacity()
452{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700453 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700454 {
455 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700456
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700457 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700458
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700459 return card->capacity;
460 }
461 else
462 {
463 void *dev;
464
465 dev = target_mmc_device();
466
467 return ufs_get_dev_capacity((struct ufs_dev *)dev);
468 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700469}
470
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700471/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700472 * Function: mmc get blocksize
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700473 * Arg : None
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700474 * Return : Returns the block size of the storage
475 * Flow : Get the block size form the card
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700476 */
477uint32_t mmc_get_device_blocksize()
478{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700479 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700480 {
481 struct mmc_card *card;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700482
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700483 card = get_mmc_card();
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700484
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700485 return card->block_size;
486 }
487 else
488 {
489 void *dev;
490
491 dev = target_mmc_device();
492
493 return ufs_get_page_size((struct ufs_dev *)dev);
494 }
495}
496
497/*
498 * Function: storage page size
499 * Arg : None
500 * Return : Returns the page size for the card
501 * Flow : Get the page size for storage
502 */
503uint32_t mmc_page_size()
504{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700505 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700506 {
507 return BOARD_KERNEL_PAGESIZE;
508 }
509 else
510 {
511 void *dev;
512
513 dev = target_mmc_device();
514
515 return ufs_get_page_size((struct ufs_dev *)dev);
516 }
517}
518
519/*
520 * Function: mmc device sleep
521 * Arg : None
522 * Return : Clean up function for storage
523 * Flow : Put the mmc card to sleep
524 */
525void mmc_device_sleep()
526{
527 void *dev;
528 dev = target_mmc_device();
529
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700530 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700531 {
532 mmc_put_card_to_sleep((struct mmc_device *)dev);
533 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700534}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800535
536/*
Sridhar Parasuramf2769492015-09-25 18:00:05 -0700537 * Function : ufs_get_boot_lun
538 * Arg : none
539 * Return type : current boot lun
540 */
541
542int ufs_get_boot_lun()
543{
544 int ret = 0;
545 void *dev;
546 dev = target_mmc_device();
547
548 if (!(platform_boot_dev_isemmc()))
549 ret = dme_get_bbootlunen((struct ufs_dev *)dev);
550 return ret;
551}
552
553
554/*
555 * Function : ufs_set_boot_lun
556 * Arg : boot lun id
557 * Return type : status
558 */
559
560int ufs_set_boot_lun(uint32_t boot_lun_id)
561{
562 int ret = 0;
563 void *dev;
564 dev = target_mmc_device();
565
566 if (!(platform_boot_dev_isemmc()))
567 ret = dme_set_bbootlunen((struct ufs_dev *)dev, boot_lun_id);
568 return ret;
569}
570
571/*
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800572 * Function : mmc set LUN for ufs
573 * Arg : LUN number
574 * Return type : void
575 */
576void mmc_set_lun(uint8_t lun)
577{
578 void *dev;
579 dev = target_mmc_device();
580
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700581 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800582 {
583 ((struct ufs_dev*)dev)->current_lun = lun;
584 }
585}
586
587/*
588 * Function : mmc get LUN from ufs
589 * Arg : LUN number
590 * Return type : lun number for UFS and 0 for emmc
591 */
592uint8_t mmc_get_lun(void)
593{
594 void *dev;
595 uint8_t lun=0;
596
597 dev = target_mmc_device();
598
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700599 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800600 {
601 lun = ((struct ufs_dev*)dev)->current_lun;
602 }
603
604 return lun;
605}
606
607void mmc_read_partition_table(uint8_t arg)
608{
609 void *dev;
610 uint8_t lun = 0;
611 uint8_t max_luns;
612
613 dev = target_mmc_device();
614
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700615 if(!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800616 {
617 max_luns = ufs_get_num_of_luns((struct ufs_dev*)dev);
618
619 ASSERT(max_luns);
620
621 for(lun = arg; lun < max_luns; lun++)
622 {
623 mmc_set_lun(lun);
624
625 if(partition_read_table())
626 {
627 dprintf(CRITICAL, "Error reading the partition table info for lun %d\n", lun);
628 }
629 }
Sridhar Parasuram176c2222014-09-16 16:34:01 -0700630 mmc_set_lun(0);
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800631 }
632 else
633 {
634 if(partition_read_table())
635 {
636 dprintf(CRITICAL, "Error reading the partition table info\n");
637 }
638 }
639}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700640
641uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
642{
643 void *dev = NULL;
644 struct mmc_card *card = NULL;
645 uint32_t block_size;
646 unsigned long long ptn = 0;
647 uint64_t size;
648 int index = -1;
Unnati Gandhie10b4f32015-03-05 17:27:57 +0530649#ifdef UFS_SUPPORT
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700650 int ret = 0;
Unnati Gandhie10b4f32015-03-05 17:27:57 +0530651#endif
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700652
653 dev = target_mmc_device();
654 block_size = mmc_get_device_blocksize();
655
656 if (platform_boot_dev_isemmc())
657 {
658 card = &((struct mmc_device *)dev)->card;
659
660 index = partition_get_index(ptn_name);
661
662 ptn = partition_get_offset(index);
663 if(!ptn)
664 {
665 return 1;
666 }
667
Channagoud Kadabibb9c3e32015-02-26 16:04:39 -0800668 /* Convert the size to blocks */
669 size = partition_get_size(index) / block_size;
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700670
671 /*
672 * For read only partitions the minimum size allocated on the disk is
673 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
674 * protect atleast one WP group.
675 */
676 if (partition_read_only(index) && size < card->wp_grp_size)
677 {
Mayank Grover72816a42018-04-09 15:05:34 +0530678 dprintf(CRITICAL, "WARNING: Size of partition is less than 1 Write Protect GRP size\n");
Channagoud Kadabibb9c3e32015-02-26 16:04:39 -0800679 /* Write protect api takes the size in bytes, convert size to bytes */
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700680 size = card->wp_grp_size * block_size;
681 }
Channagoud Kadabia2713fd2015-03-19 11:06:58 -0700682 else
683 {
684 size *= block_size;
685 }
686
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700687 /* Set the power on WP bit */
688 return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
689 }
690 else
691 {
Unnati Gandhie10b4f32015-03-05 17:27:57 +0530692#ifdef UFS_SUPPORT
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700693 /* Enable the power on WP fo all LUNs which have WP bit is enabled */
694 ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
695 if (ret < 0)
696 {
697 dprintf(CRITICAL, "Failure to WP UFS partition\n");
698 return 1;
699 }
Unnati Gandhie10b4f32015-03-05 17:27:57 +0530700#endif
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700701 }
702
703 return 0;
704}