blob: bcec0adfbc3552605e51f1458cca201dda115d8a [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>
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
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700127 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700128 {
129 /* TODO: This function is aware of max data that can be
130 * tranferred using sdhci adma mode, need to have a cleaner
131 * implementation to keep this function independent of sdhci
132 * limitations
133 */
134 while (data_len > write_size) {
135 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size));
136 if (val)
137 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530138 dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700139 return val;
140 }
141 sptr += write_size;
142 data_addr += write_size;
143 data_len -= write_size;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700144 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700145
146 if (data_len)
147 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
148
149 if (val)
vijay kumar4f4405f2014-08-08 11:49:53 +0530150 dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700151 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700152 else
153 {
154 arch_clean_invalidate_cache_range((addr_t)in, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700155
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700156 ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700157
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700158 if (ret)
159 {
160 dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr);
161 val = 1;
162 }
163 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700164
165 return val;
166}
167
168/*
169 * Function: mmc_read
170 * Arg : Data address on card, o/p buffer & data length
171 * Return : 0 on Success, non zero on failure
172 * Flow : Read data from the card to out
173 */
174uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
175{
176 uint32_t ret = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700177 uint32_t block_size;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700178 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700179 void *dev;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700180 uint8_t *sptr = (uint8_t *)out;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700181
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700182 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700183 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700184
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700185 ASSERT(!(data_addr % block_size));
186 ASSERT(!(data_len % block_size));
187
188
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700189 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700190 {
191 /* TODO: This function is aware of max data that can be
192 * tranferred using sdhci adma mode, need to have a cleaner
193 * implementation to keep this function independent of sdhci
194 * limitations
195 */
196 while (data_len > read_size) {
197 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size));
198 if (ret)
199 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530200 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700201 return ret;
202 }
203 sptr += read_size;
204 data_addr += read_size;
205 data_len -= read_size;
206 }
207
208 if (data_len)
209 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
210
211 if (ret)
vijay kumar4f4405f2014-08-08 11:49:53 +0530212 dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size));
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700213 }
214 else
215 {
216 ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700217 if (ret)
218 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700219 dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr);
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700220 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700221
222 arch_invalidate_cache_range((addr_t)out, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700223 }
224
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700225 return ret;
226}
227
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700228
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700229/*
Oliver Wangcee448d2013-10-22 18:40:13 +0800230 * Function: mmc get erase unit size
231 * Arg : None
232 * Return : Returns the erase unit size of the storage
233 * Flow : Get the erase unit size from the card
234 */
235
236uint32_t mmc_get_eraseunit_size()
237{
238 uint32_t erase_unit_sz = 0;
239
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700240 if (platform_boot_dev_isemmc()) {
Oliver Wangcee448d2013-10-22 18:40:13 +0800241 struct mmc_device *dev;
242 struct mmc_card *card;
243
244 dev = target_mmc_device();
245 card = &dev->card;
246 /*
247 * Calculate the erase unit size,
248 * 1. Based on emmc 4.5 spec for emmc card
249 * 2. Use SD Card Status info for SD cards
250 */
251 if (MMC_CARD_MMC(card))
252 {
253 /*
254 * Calculate the erase unit size as per the emmc specification v4.5
255 */
256 if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
257 erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
258 else
259 erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
260 }
261 else
262 erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
263 }
264
265 return erase_unit_sz;
266}
267
268/*
269 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
270 * function can be used when we want to erase the blocks not
271 * aligned with the mmc erase group.
272 * Arg : Block address & length
273 * Return : Returns 0
274 * Flow : Erase the card from specified addr
275 */
276
277static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
278{
279 uint32_t *out;
Channagoud Kadabia87af972014-03-10 15:26:48 -0700280 uint32_t block_size = mmc_get_device_blocksize();
281 uint32_t erase_size = (block_size * num_blks);
282 uint32_t scratch_size = target_get_max_flash_size();
Oliver Wangcee448d2013-10-22 18:40:13 +0800283
284 dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
Oliver Wangcee448d2013-10-22 18:40:13 +0800285
Channagoud Kadabia87af972014-03-10 15:26:48 -0700286 if (erase_size <= scratch_size)
Oliver Wangcee448d2013-10-22 18:40:13 +0800287 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700288 /* Use scratch address if the unaligned blocks */
289 out = (uint32_t *) target_get_scratch_address();
290 }
291 else
292 {
vijay kumar4f4405f2014-08-08 11:49:53 +0530293 dprintf(CRITICAL, "Erase Fail: Erase size: %u is bigger than scratch region\n", scratch_size);
Oliver Wangcee448d2013-10-22 18:40:13 +0800294 return 1;
295 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800296
Channagoud Kadabia87af972014-03-10 15:26:48 -0700297 memset((void *)out, 0, erase_size);
298
299 if (mmc_sdhci_write(dev, out, blk_addr, num_blks))
Oliver Wangcee448d2013-10-22 18:40:13 +0800300 {
Channagoud Kadabia87af972014-03-10 15:26:48 -0700301 dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
302 return 1;
Oliver Wangcee448d2013-10-22 18:40:13 +0800303 }
Channagoud Kadabia87af972014-03-10 15:26:48 -0700304
Oliver Wangcee448d2013-10-22 18:40:13 +0800305 return 0;
306}
307
308/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700309 * Function: mmc erase card
310 * Arg : Block address & length
311 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700312 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700313 */
314uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
315{
Oliver Wangcee448d2013-10-22 18:40:13 +0800316 struct mmc_device *dev;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700317 uint32_t block_size;
Oliver Wangcee448d2013-10-22 18:40:13 +0800318 uint32_t unaligned_blks;
319 uint32_t head_unit;
320 uint32_t tail_unit;
321 uint32_t erase_unit_sz;
322 uint32_t blk_addr;
323 uint32_t blk_count;
324 uint64_t blks_to_erase;
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700325
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700326 block_size = mmc_get_device_blocksize();
327
328 dev = target_mmc_device();
329
330 ASSERT(!(addr % block_size));
331 ASSERT(!(len % block_size));
332
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700333 if (platform_boot_dev_isemmc())
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700334 {
Oliver Wangcee448d2013-10-22 18:40:13 +0800335 erase_unit_sz = mmc_get_eraseunit_size();
336 dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700337
Oliver Wangcee448d2013-10-22 18:40:13 +0800338 blk_addr = addr / block_size;
339 blk_count = len / block_size;
340
Oliver Wangcee448d2013-10-22 18:40:13 +0800341 dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
342
343 head_unit = blk_addr / erase_unit_sz;
344 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
345
346 if (tail_unit - head_unit <= 1)
347 {
348 dprintf(INFO, "SDHCI unit erase not required\n");
349 return mmc_zero_out(dev, blk_addr, blk_count);
350 }
351
352 unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
353
354 if (unaligned_blks < erase_unit_sz)
355 {
356 dprintf(SPEW, "Handling unaligned head blocks\n");
357 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
358 return 1;
359
360 blk_addr += unaligned_blks;
361 blk_count -= unaligned_blks;
vijay kumar08bde372014-09-22 16:17:59 +0530362
363 head_unit = blk_addr / erase_unit_sz;
364 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
365
366 if (tail_unit - head_unit <= 1)
367 {
368 dprintf(INFO, "SDHCI unit erase not required\n");
369 return mmc_zero_out(dev, blk_addr, blk_count);
370 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800371 }
372
373 unaligned_blks = blk_count % erase_unit_sz;
374 blks_to_erase = blk_count - unaligned_blks;
375
vijay kumar4f4405f2014-08-08 11:49:53 +0530376 dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr,(unsigned int)blks_to_erase);
Oliver Wangcee448d2013-10-22 18:40:13 +0800377 if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700378 {
379 dprintf(CRITICAL, "MMC erase failed\n");
380 return 1;
381 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800382
383 blk_addr += blks_to_erase;
384
385 if (unaligned_blks)
386 {
387 dprintf(SPEW, "Handling unaligned tail blocks\n");
388 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
389 return 1;
390 }
391
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700392 }
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700393 else
394 {
395 if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
396 {
397 dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
398 return 1;
399 }
400 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700401
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700402 return 0;
403}
404
405/*
406 * Function: mmc get psn
407 * Arg : None
408 * Return : Returns the product serial number
409 * Flow : Get the PSN from card
410 */
411uint32_t mmc_get_psn(void)
412{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700413 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700414 {
415 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700416
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700417 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700418
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700419 return card->cid.psn;
420 }
421 else
422 {
423 void *dev;
424
425 dev = target_mmc_device();
426
427 return ufs_get_serial_num((struct ufs_dev *)dev);
428 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700429}
430
431/*
432 * Function: mmc get capacity
433 * Arg : None
434 * Return : Returns the density of the emmc card
435 * Flow : Get the density from card
436 */
437uint64_t mmc_get_device_capacity()
438{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700439 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700440 {
441 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700442
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700443 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700444
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700445 return card->capacity;
446 }
447 else
448 {
449 void *dev;
450
451 dev = target_mmc_device();
452
453 return ufs_get_dev_capacity((struct ufs_dev *)dev);
454 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700455}
456
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700457/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700458 * Function: mmc get blocksize
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700459 * Arg : None
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700460 * Return : Returns the block size of the storage
461 * Flow : Get the block size form the card
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700462 */
463uint32_t mmc_get_device_blocksize()
464{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700465 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700466 {
467 struct mmc_card *card;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700468
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700469 card = get_mmc_card();
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700470
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700471 return card->block_size;
472 }
473 else
474 {
475 void *dev;
476
477 dev = target_mmc_device();
478
479 return ufs_get_page_size((struct ufs_dev *)dev);
480 }
481}
482
483/*
484 * Function: storage page size
485 * Arg : None
486 * Return : Returns the page size for the card
487 * Flow : Get the page size for storage
488 */
489uint32_t mmc_page_size()
490{
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700491 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700492 {
493 return BOARD_KERNEL_PAGESIZE;
494 }
495 else
496 {
497 void *dev;
498
499 dev = target_mmc_device();
500
501 return ufs_get_page_size((struct ufs_dev *)dev);
502 }
503}
504
505/*
506 * Function: mmc device sleep
507 * Arg : None
508 * Return : Clean up function for storage
509 * Flow : Put the mmc card to sleep
510 */
511void mmc_device_sleep()
512{
513 void *dev;
514 dev = target_mmc_device();
515
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700516 if (platform_boot_dev_isemmc())
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700517 {
518 mmc_put_card_to_sleep((struct mmc_device *)dev);
519 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700520}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800521
522/*
523 * Function : mmc set LUN for ufs
524 * Arg : LUN number
525 * Return type : void
526 */
527void mmc_set_lun(uint8_t lun)
528{
529 void *dev;
530 dev = target_mmc_device();
531
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700532 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800533 {
534 ((struct ufs_dev*)dev)->current_lun = lun;
535 }
536}
537
538/*
539 * Function : mmc get LUN from ufs
540 * Arg : LUN number
541 * Return type : lun number for UFS and 0 for emmc
542 */
543uint8_t mmc_get_lun(void)
544{
545 void *dev;
546 uint8_t lun=0;
547
548 dev = target_mmc_device();
549
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700550 if (!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800551 {
552 lun = ((struct ufs_dev*)dev)->current_lun;
553 }
554
555 return lun;
556}
557
558void mmc_read_partition_table(uint8_t arg)
559{
560 void *dev;
561 uint8_t lun = 0;
562 uint8_t max_luns;
563
564 dev = target_mmc_device();
565
Sundarajan Srinivasan9786c452014-03-21 17:34:58 -0700566 if(!platform_boot_dev_isemmc())
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800567 {
568 max_luns = ufs_get_num_of_luns((struct ufs_dev*)dev);
569
570 ASSERT(max_luns);
571
572 for(lun = arg; lun < max_luns; lun++)
573 {
574 mmc_set_lun(lun);
575
576 if(partition_read_table())
577 {
578 dprintf(CRITICAL, "Error reading the partition table info for lun %d\n", lun);
579 }
580 }
Sridhar Parasuram176c2222014-09-16 16:34:01 -0700581 mmc_set_lun(0);
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800582 }
583 else
584 {
585 if(partition_read_table())
586 {
587 dprintf(CRITICAL, "Error reading the partition table info\n");
588 }
589 }
590}
Channagoud Kadabifaf20f62014-10-21 22:22:37 -0700591
592uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
593{
594 void *dev = NULL;
595 struct mmc_card *card = NULL;
596 uint32_t block_size;
597 unsigned long long ptn = 0;
598 uint64_t size;
599 int index = -1;
600 int ret = 0;
601
602 dev = target_mmc_device();
603 block_size = mmc_get_device_blocksize();
604
605 if (platform_boot_dev_isemmc())
606 {
607 card = &((struct mmc_device *)dev)->card;
608
609 index = partition_get_index(ptn_name);
610
611 ptn = partition_get_offset(index);
612 if(!ptn)
613 {
614 return 1;
615 }
616
617 size = partition_get_size(index);
618
619 /*
620 * For read only partitions the minimum size allocated on the disk is
621 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
622 * protect atleast one WP group.
623 */
624 if (partition_read_only(index) && size < card->wp_grp_size)
625 {
626 size = card->wp_grp_size * block_size;
627 }
628 /* Set the power on WP bit */
629 return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
630 }
631 else
632 {
633 /* Enable the power on WP fo all LUNs which have WP bit is enabled */
634 ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
635 if (ret < 0)
636 {
637 dprintf(CRITICAL, "Failure to WP UFS partition\n");
638 return 1;
639 }
640 }
641
642 return 0;
643}