blob: c56a61e45073eb7de099dbe4e1af9f85b9ad8a58 [file] [log] [blame]
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdint.h>
#include <mmc_sdhci.h>
#include <mmc_wrapper.h>
#include <sdhci.h>
#include <target.h>
/*
* Function: get mmc card
* Arg : None
* Return : Pointer to mmc card structure
* Flow : Get the card pointer from the device structure
*/
static struct mmc_card *get_mmc_card()
{
struct mmc_device *dev;
struct mmc_card *card;
dev = target_mmc_device();
card = &dev->card;
return card;
}
/*
* Function: mmc_write
* Arg : Data address on card, data length, i/p buffer
* Return : 0 on Success, non zero on failure
* Flow : Write the data from in to the card
*/
uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
{
int val = 0;
uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
void *sptr = in;
struct mmc_device *dev;
dev = target_mmc_device();
ASSERT(!(data_addr % MMC_BLK_SZ));
if (data_len % MMC_BLK_SZ)
data_len = ROUNDUP(data_len, MMC_BLK_SZ);
/* TODO: This function is aware of max data that can be
* tranferred using sdhci adma mode, need to have a cleaner
* implementation to keep this function independent of sdhci
* limitations
*/
while (data_len > write_size) {
val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ));
sptr += write_size;
data_addr += write_size;
data_len -= write_size;
}
if (data_len)
val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
return val;
}
/*
* Function: mmc_read
* Arg : Data address on card, o/p buffer & data length
* Return : 0 on Success, non zero on failure
* Flow : Read data from the card to out
*/
uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
{
uint32_t ret = 0;
uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
struct mmc_device *dev;
void *sptr = out;
ASSERT(!(data_addr % MMC_BLK_SZ));
ASSERT(!(data_len % MMC_BLK_SZ));
dev = target_mmc_device();
/* TODO: This function is aware of max data that can be
* tranferred using sdhci adma mode, need to have a cleaner
* implementation to keep this function independent of sdhci
* limitations
*/
while (data_len > read_size) {
ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ));
sptr += read_size;
data_addr += read_size;
data_len -= read_size;
}
if (data_len)
ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
return ret;
}
/*
* Function: mmc erase card
* Arg : Block address & length
* Return : Returns 0
* Flow : This is dummy API for backward compatibility
* erase is not supported for sdhci
*/
uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
{
/* TODO: Right now with sdhci erase function
* is not implemented, need to be added
*/
return 0;
}
/*
* Function: mmc get psn
* Arg : None
* Return : Returns the product serial number
* Flow : Get the PSN from card
*/
uint32_t mmc_get_psn(void)
{
struct mmc_card *card;
card = get_mmc_card();
return card->cid.psn;
}
/*
* Function: mmc get capacity
* Arg : None
* Return : Returns the density of the emmc card
* Flow : Get the density from card
*/
uint64_t mmc_get_device_capacity()
{
struct mmc_card *card;
card = get_mmc_card();
return card->capacity;
}