/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * 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 Texas Instruments Incorporated 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE 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.
 *
 */


/****
 * \file : test_sdmmc.c
 *
 * \brief: source file to test the SD/MMC chip.
 */

#include "dm8127_types.h"
#include "sdio.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sdmmc.h"


#define HSMMC_BASE1	  (0x481D8000)//()
//#define TEST_PATTERN  (0xA5)
UINT8 writebuf[SECTOR_SIZE], readbuf[SECTOR_SIZE];
UINT8 savebuf[SECTOR_SIZE];

/****
 *\brief: SD/MMC handler function.
 *
 *\descr: This function initialize the SDIO device to detect the SD/MMC device.
 *
 *\param: VOID
 *\return:  SUCCESS on successful detection of SD/MMC card.
 *          FAILED failed to detect SD card
 *
 */
int SD_MMC_test
(
		void *testargs
)
{
	SINT32 cardtype;
	SINT32 is_highcap_card = 0;
	SINT32 retval = FAILURE;



#ifdef DEBUG
	printf ("SD_Card Tests:\n");
	printf ("*) The test verifies the command, clock and data lines of sd/mmc by writing and verifies the data written\n");
	printf ("*) Ensure that the Boot Switches are selected as specified in the README\n");
	printf ("*) Ensure that an SD card is inserted into the Base Board of your EVM\n\n");
	printf ("Running SDMMC Tests:\n");
#else
	 Uart_stringSend("\r\n==================================="
					"\r\n            SD Card Test           "
					"\r\n===================================\r\n");

	Uart_stringSend("\n\rSD_Card Tests:\n\r"
			        "The test verifies the command, clock and data lines of sd/mmc "
			        "\r\nby writing and verifies the data written, "
			        "\r\nEnsure that the Boot Switches are selected as specified\n\r"
			        "\r\nand SD card is inserted into the Base Board of your EVM\n\n\r"
			        "Running SD/MMC test \n\r");
#endif

	SDIO_DEV_init((SDIO_controller_t *) HSMMC_BASE1); /* initialization here */
	cardtype = detect_card((SDIO_controller_t *) HSMMC_BASE1, &is_highcap_card);


	switch (cardtype) {
	case MMC_CARD:
#ifdef DEBUG
		printf ("\tMMC Card Detected\n");
#else
		Uart_stringSend("\tMMC Card Detected\n");
#endif

		break;
	case SD_CARD:
		retval = SUCCESS;
#ifdef DEBUG
		printf ("\tSD Card Detected\n");
#else
		Uart_stringSend ("SD Card Detected\n");
#endif

		retval = sdmmc_rwtest((SDIO_controller_t *)HSMMC_BASE1, is_highcap_card);
		break;
	case SDIO_CARD:
		retval = SUCCESS;

#ifdef DEBUG
		printf ("\tSDIO Card Detected\n");
		printf ("Please Insert an SDIO Card and run this program again!\n");
#else
		Uart_stringSend("\tSDIO Card Detected\n"
				        "Please Insert an SDIO Card and run this program again!\n");
#endif

		break;
	case UNKNOWN_CARD:
	default:
		retval = FAILURE;

#ifdef DEBUG
		printf ("\tUnable to communicate with the card\n");
		printf ("\tEnsure that an SD card is inserted into the Base Board of your EVM\n");
#else
		Uart_stringSend("\r\nUnable to communicate with the card\n"
				        "\rEnsure that an SD card is inserted into the Base Board of your EVM\n");
#endif

		break;
	}
	
	if (retval == SUCCESS)
	{
#ifdef DEBUG
		printf ("\nSDMMC Test Passed\n");
#else
		Uart_stringSend("\n\rSDMMC Test Passed\n\r");
#endif
	}
	else
	{
#ifdef DEBUG
		printf ("\nSDMMC Test Failed\n");
#else
		Uart_stringSend("\n\rSDMMC Test Failed\n\r");
#endif
	}
	Uart_stringSend("\r\n-------------------------X-----------------------------");
	return(retval);
}

/***
 * \brief: SD/MMC read write and verify routine.
 *
 * \param: *base         base address of SDIo device
 * \n       highcap_card  block read/write card type
 *
 * \return: SUCCESS  for successful read write
 * \n       FAILURE failed to perform read or write operation
 */
SINT32 sdmmc_rwtest
(
	SDIO_controller_t *base,
	SINT32 highcap_card
)
{
//	UINT8 writebuf[SECTOR_SIZE], readbuf[SECTOR_SIZE];
//	UINT8 savebuf[SECTOR_SIZE];
	SINT32 retval;
	SINT32 block = 1;
	
	memset (writebuf, TEST_PATTERN, sizeof(writebuf));
	memset (readbuf, 0x00, sizeof(readbuf));
	
	retval = bread (base, highcap_card, block, SECTOR_SIZE, savebuf);
	if (retval < 0) {

#ifdef DEBUG
		printf ("\tUnable to Read Block data\n");
#else
		Uart_stringSend("\rUnable to Read Block data\n\r");
#endif

		return FAILURE;
	}
#ifdef DEBUG
	printf ("\tSDMMC: Writing a pattern to Block %d....", block);
#else
	platform_write("\rSDMMC: Writing a pattern to Block %d....\n\r", block);
#endif
	retval = bwrite (base, highcap_card, block, SECTOR_SIZE, writebuf);
	if (retval == SUCCESS){
#ifdef DEBUG
		printf ("Write test passed\n");
#else
		Uart_stringSend("Write test passed\n");
#endif

	}
	else {
#ifdef DEBUG
		printf ("Unable to Write Sector\n");
#else
		Uart_stringSend("\r\nUnable to Write Sector\n\r");
#endif
		return FAILURE;
	}
#ifdef DEBUG
	printf ("\tSDMMC: Reading from Block %d...", block);
#else
	platform_write ("\r\nSDMMC: Reading from Block %d...\r\n", block);
#endif

	retval = bread (base, highcap_card, block, SECTOR_SIZE, readbuf);
	if (retval == SUCCESS){
#ifdef DEBUG
		printf ("Read test passed\n");
#else
		Uart_stringSend("\rRead test passed");
#endif
	}
	else {
#ifdef DEBUG
		printf ("Unable to Read Sector\n");
#else
		Uart_stringSend("\rUnable to Read Sector\n");
#endif
		return FAILURE;
	}
	
	retval = bwrite (base, highcap_card, block, SECTOR_SIZE, savebuf);
	if (retval == FAILURE) {
#ifdef DEBUG
		printf ("\tUnable to restore the original contents of the SDMMC card\n");
#else
		Uart_stringSend ("\rUnable to restore the original contents of the SDMMC card\n");
#endif
		return FAILURE;
	}
		
	if (memcmp(writebuf, readbuf, SECTOR_SIZE) == 0)
	{
#ifdef DEBUG
		printf ("\tVerify data...Passed\n");
#else
		Uart_stringSend("\r\nVerify data...Passed\n\r");
#endif
		return SUCCESS;
	}else {
#ifdef DEBUG
		printf ("\tVerify data...Failed\n");
#else
		Uart_stringSend("\r\nVerify data...Failed\n");
#endif
		return FAILURE;
	}
}
