blob: dce416a755928373936d282adc68fe77c27742eb [file] [log] [blame]
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
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>
31#include <mmc_sdhci.h>
32#include <mmc_wrapper.h>
33#include <sdhci.h>
34#include <target.h>
35
36/*
37 * Function: get mmc card
38 * Arg : None
39 * Return : Pointer to mmc card structure
40 * Flow : Get the card pointer from the device structure
41 */
42static struct mmc_card *get_mmc_card()
43{
44 struct mmc_device *dev;
45 struct mmc_card *card;
46
47 dev = target_mmc_device();
48 card = &dev->card;
49
50 return card;
51}
52
53/*
54 * Function: mmc_write
55 * Arg : Data address on card, data length, i/p buffer
56 * Return : 0 on Success, non zero on failure
57 * Flow : Write the data from in to the card
58 */
59uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
60{
61 int val = 0;
62 uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
63 void *sptr = in;
64 struct mmc_device *dev;
65
66 dev = target_mmc_device();
67
68 ASSERT(!(data_addr % MMC_BLK_SZ));
69
70 if (data_len % MMC_BLK_SZ)
71 data_len = ROUNDUP(data_len, MMC_BLK_SZ);
72
73 /* TODO: This function is aware of max data that can be
74 * tranferred using sdhci adma mode, need to have a cleaner
75 * implementation to keep this function independent of sdhci
76 * limitations
77 */
78 while (data_len > write_size) {
79 val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ));
80 sptr += write_size;
81 data_addr += write_size;
82 data_len -= write_size;
83 }
84
85 if (data_len)
86 val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
87
88 return val;
89}
90
91/*
92 * Function: mmc_read
93 * Arg : Data address on card, o/p buffer & data length
94 * Return : 0 on Success, non zero on failure
95 * Flow : Read data from the card to out
96 */
97uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
98{
99 uint32_t ret = 0;
100 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
101 struct mmc_device *dev;
102 void *sptr = out;
103
104 ASSERT(!(data_addr % MMC_BLK_SZ));
105 ASSERT(!(data_len % MMC_BLK_SZ));
106
107 dev = target_mmc_device();
108
109 /* TODO: This function is aware of max data that can be
110 * tranferred using sdhci adma mode, need to have a cleaner
111 * implementation to keep this function independent of sdhci
112 * limitations
113 */
114 while (data_len > read_size) {
115 ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ));
116 sptr += read_size;
117 data_addr += read_size;
118 data_len -= read_size;
119 }
120
121 if (data_len)
122 ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
123
124 return ret;
125}
126
127/*
128 * Function: mmc erase card
129 * Arg : Block address & length
130 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700131 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700132 */
133uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
134{
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700135 struct mmc_device *dev;
136
137 dev = target_mmc_device();
138
139 ASSERT(!(addr % MMC_BLK_SZ));
140 ASSERT(!(len % MMC_BLK_SZ));
141
142 if (mmc_sdhci_erase(dev, (addr / MMC_BLK_SZ), len))
143 {
144 dprintf(CRITICAL, "MMC erase failed\n");
145 return 1;
146 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700147 return 0;
148}
149
150/*
151 * Function: mmc get psn
152 * Arg : None
153 * Return : Returns the product serial number
154 * Flow : Get the PSN from card
155 */
156uint32_t mmc_get_psn(void)
157{
158 struct mmc_card *card;
159
160 card = get_mmc_card();
161
162 return card->cid.psn;
163}
164
165/*
166 * Function: mmc get capacity
167 * Arg : None
168 * Return : Returns the density of the emmc card
169 * Flow : Get the density from card
170 */
171uint64_t mmc_get_device_capacity()
172{
173 struct mmc_card *card;
174
175 card = get_mmc_card();
176
177 return card->capacity;
178}
179