/**
 * \file   reset_sdc.c
 * \author Cesar Fuguet
 * \date   July 23, 2014
 *
 * \brief  Wrapper for the SD card and SPI drivers
 */
#include <reset_sdc.h>
#include <reset_tty.h>
#include <reset_utils.h>
#include <defs.h>
#include <sdcard.h>
#include <spi.h>

#ifndef SEG_IOC_BASE
#   error "SEG_IOC_BASE constant must be defined in the hard_config.h file"
#endif

static struct sdcard_dev     _sdcard_device;
static struct spi_dev *const _spi_device = (struct spi_dev*)SEG_IOC_BASE;

static const int sdcard_reset_retries = 4;
static const int spi_init_clkfreq     = 200000  ; /* Hz */
static const int spi_func_clkfreq     = 10000000; /* Hz */

int reset_sdc_init()
{
    unsigned char sdcard_rsp;

    reset_puts("Initializing block device\n\r");

    /**
     * Initializing the SPI controller
     */
    spi_dev_config (
      _spi_device            ,
      spi_init_clkfreq       ,
      RESET_SYSTEM_CLK * 1000,
      8                      ,
      SPI_TX_NEGEDGE         ,
      SPI_RX_POSEDGE
    );

    /**
     * Initializing the SD Card
     */
    unsigned int iter = 0;
    while(1)
    {
        reset_puts("Trying to initialize SD card... ");

        sdcard_rsp = sdcard_dev_open(&_sdcard_device, _spi_device, 0);
        if (sdcard_rsp == 0)
        {
            reset_puts("OK\n");
            break;
        }

        reset_puts("KO\n");
        reset_sleep(1000);
        if (++iter >= sdcard_reset_retries)
        {
            reset_puts("\nERROR: During SD card reset to IDLE state\n"
                      "/ card response = ");
            reset_putx(sdcard_rsp);
            reset_puts("\n");
            reset_exit();
        }
    }

    /**
     * Set the block length of the SD Card
     */
    sdcard_rsp = sdcard_dev_set_blocklen(&_sdcard_device, 512);
    if (sdcard_rsp)
    {
        reset_puts("ERROR: During SD card blocklen initialization\n");
        reset_exit();
    }

    /**
     * Incrementing SDCARD clock frequency for normal function
     */
    spi_dev_config (
        _spi_device            ,
        spi_func_clkfreq       ,
        RESET_SYSTEM_CLK * 1000,
        -1                     ,
        -1                     ,
        -1
    );

    reset_puts("Finish block device initialization\n\r");

    return 0;
} /* end reset_spi_init() */

int reset_sdc_read( unsigned int lba, void* buffer, unsigned int count )
{
    unsigned int sdcard_rsp;
    unsigned int i;

    sdcard_dev_lseek(&_sdcard_device, lba);
    for(i = 0; i < count; i++)
    {
        unsigned char* buf = (unsigned char *) buffer + (512 * i);
        if (( sdcard_rsp = sdcard_dev_read ( &_sdcard_device, buf, 512 ) ))
        {
            reset_puts("ERROR during read on the SDCARD device. Code: ");
            reset_putx(sdcard_rsp);
            reset_puts("\n");
            return 1;
        }
    }
    return 0;
}

/*
 * vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
 */
