blob: 2a89af4d203dc76e7f7f228e88b6785a52a30ca4 [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{
Channagoud Kadabi53f1be72013-06-05 17:56:11 -070061 uint32_t val = 0;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070062 uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -070063 uint8_t *sptr = (uint8_t *)in;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070064 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) {
Channagoud Kadabi53f1be72013-06-05 17:56:11 -070079 val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ));
80 if (val)
81 {
82 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ));
83 return val;
84 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070085 sptr += write_size;
86 data_addr += write_size;
87 data_len -= write_size;
88 }
89
90 if (data_len)
Channagoud Kadabi53f1be72013-06-05 17:56:11 -070091 val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
92
93 if (val)
94 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070095
96 return val;
97}
98
99/*
100 * Function: mmc_read
101 * Arg : Data address on card, o/p buffer & data length
102 * Return : 0 on Success, non zero on failure
103 * Flow : Read data from the card to out
104 */
105uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
106{
107 uint32_t ret = 0;
108 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
109 struct mmc_device *dev;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700110 uint8_t *sptr = (uint8_t *)out;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700111
112 ASSERT(!(data_addr % MMC_BLK_SZ));
113 ASSERT(!(data_len % MMC_BLK_SZ));
114
115 dev = target_mmc_device();
116
117 /* TODO: This function is aware of max data that can be
118 * tranferred using sdhci adma mode, need to have a cleaner
119 * implementation to keep this function independent of sdhci
120 * limitations
121 */
122 while (data_len > read_size) {
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700123 ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ));
124 if (ret)
125 {
126 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ));
127 return ret;
128 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700129 sptr += read_size;
130 data_addr += read_size;
131 data_len -= read_size;
132 }
133
134 if (data_len)
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700135 ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
136
137 if (ret)
138 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700139
140 return ret;
141}
142
143/*
144 * Function: mmc erase card
145 * Arg : Block address & length
146 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700147 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700148 */
149uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
150{
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700151 struct mmc_device *dev;
152
153 dev = target_mmc_device();
154
155 ASSERT(!(addr % MMC_BLK_SZ));
156 ASSERT(!(len % MMC_BLK_SZ));
157
158 if (mmc_sdhci_erase(dev, (addr / MMC_BLK_SZ), len))
159 {
160 dprintf(CRITICAL, "MMC erase failed\n");
161 return 1;
162 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700163 return 0;
164}
165
166/*
167 * Function: mmc get psn
168 * Arg : None
169 * Return : Returns the product serial number
170 * Flow : Get the PSN from card
171 */
172uint32_t mmc_get_psn(void)
173{
174 struct mmc_card *card;
175
176 card = get_mmc_card();
177
178 return card->cid.psn;
179}
180
181/*
182 * Function: mmc get capacity
183 * Arg : None
184 * Return : Returns the density of the emmc card
185 * Flow : Get the density from card
186 */
187uint64_t mmc_get_device_capacity()
188{
189 struct mmc_card *card;
190
191 card = get_mmc_card();
192
193 return card->capacity;
194}
195
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700196/*
197 * Function: mmc get pagesize
198 * Arg : None
199 * Return : Returns the density of the emmc card
200 * Flow : Get the density from card
201 */
202uint32_t mmc_get_device_blocksize()
203{
204 struct mmc_card *card;
205
206 card = get_mmc_card();
207
208 return card->block_size;
209}