///////////////////////////////////////////////////////////////////////////////////
// File     : sdc_driver.h
// Date     : 31/08/2012
// Author   : cesar fuguet
// Copyright (c) UPMC-LIP6
///////////////////////////////////////////////////////////////////////////////////

#ifndef _GIET_SDC_DRIVER_H_
#define _GIET_SDC_DRIVER_H_


#include <chdev.h>
#include <soclib_spi.h>
#include <hard_config.h>

///////////////////////////////////////////////////////////////////////////////
// SD card structure definition
///////////////////////////////////////////////////////////////////////////////
typedef struct sdcard_dev
{ 
    // SPI controller pointer 
    struct spi_dev * spi;

    // block length of the SDCARD
    unsigned int block_length;

    // access pointer representing the offset in bytes used to read or write in
    // the SDCARD. This driver is for cards SDSD, therefore this offset must be
    // multiple of the block length
    unsigned int access_pointer;

    // slave ID. This ID represents the number of the slave select signal used
    // in the hardware platform (SPI channel)
    int slave_id;

    // is the card high capacity ?
    int sdhc;
}
sdcard_dev_t;

///////////////////////////////////////////////////////////////////////////////
// This function initializes the SPI controller and call sdc_open to
// initialize  the SD card
// - channel: channel to initialize (only channel 0 supported)
// Returns 0 if success, other value if failure
///////////////////////////////////////////////////////////////////////////////
// unsigned int _sdc_init();
extern void soclib_sdc_init( chdev_t* chdev );

///////////////////////////////////////////////////////////////////////////////
// Transfer data between the block device and a memory buffer. 
// - use_irq   : not used, as DMA is not supported yet
// - to_mem    : to memory if non zero
// - lba       : first block index on the block device
// - buf_vaddr : base address of the memory buffer
// - count     : number of blocks to be transfered.
// Returns 0 if success, > 0 if error.
///////////////////////////////////////////////////////////////////////////////
extern void soclib_sdc_cmd( xptr_t thread_xp );

///////////////////////////////////////////////////////////////////////////////
// This ISR handles the IRQ generated by a SDC controler
///////////////////////////////////////////////////////////////////////////////
extern void soclib_sdc_isr( chdev_t* chdev );

///////////////////////////////////////////////////////////////////////////////
// SD card constants
///////////////////////////////////////////////////////////////////////////////

// Number of retries after an unacknowledge command
#define SDCARD_COMMAND_TIMEOUT  100

// This command is a simple SD commmand
#define SDCARD_CMD              0

// This is an application specific command
#define SDCARD_ACMD             1

// The transmition is done in the negative edge of the clock
#define SDCARD_TX_NEGEDGE       0

// The transmition is done in the positive edge of the clock
#define SDCARD_TX_POSEDGE       1

// The reception is done in the negative edge of the clock
#define SDCARD_RX_NEGEDGE       0

// The reception is done in the positive edge of the clock
#define SDCARD_RX_POSEDGE       1

///////////////////////////////////////////////////////////////////////////////
// SD card macros
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//   SDCARD_CHECK_R1_VALID()
// This macro checks if the SD card response is valid
// - x: SD card response
// Returns 1 if valid and 0 otherwise
///////////////////////////////////////////////////////////////////////////////
#define SDCARD_CHECK_R1_VALID(x)    (~x & SDCARD_R1_RSP_VALID) ? 1 : 0

///////////////////////////////////////////////////////////////////////////////
//   SDCARD_CHECK_R1_ERROR()
// This macro checks if there is an error in SD card response
// - x: SD card response
// Returns 1 if error and 0 otherwise
///////////////////////////////////////////////////////////////////////////////
#define SDCARD_CHECK_R1_ERROR(x)    ( x & 0x7E)                ? 1 : 0

// SD card response 1 (R1) format constants
#define SDCARD_R1_IN_IDLE_STATE     ( 1 << 0 ) // R1 bit 0
#define SDCARD_R1_ERASE_RESET       ( 1 << 1 ) // R1 bit 1
#define SDCARD_R1_ILLEGAL_CMD       ( 1 << 2 ) // R1 bit 2
#define SDCARD_R1_COM_CRC_ERR       ( 1 << 3 ) // R1 bit 3
#define SDCARD_R1_ERASE_SEQ_ERR     ( 1 << 4 ) // R1 bit 4
#define SDCARD_R1_ADDRESS_ERR       ( 1 << 5 ) // R1 bit 5
#define SDCARD_R1_PARAMETER_ERR     ( 1 << 6 ) // R1 bit 6
#define SDCARD_R1_RSP_VALID         ( 1 << 7 ) // R1 bit 7

#endif

// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// c-file-offsets:((innamespace . 0)(inline-open . 0))
// indent-tabs-mode: nil
// End:
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4