///////////////////////////////////////////////////////////////////////////////////
// File     : boot_mmc_driver.c
// Date     : 18/01/2017
// Author   : alain greiner
// Copyright (c) UPMC-LIP6
///////////////////////////////////////////////////////////////////////////////////

#include <boot_mmc_driver.h>
#include <boot_config.h>
#include <boot_utils.h>

#if !defined(SEG_MMC_BASE) 
# error: You must define SEG_MMC_BASE in the boot_config.h file
#endif

/****************************************************************************
 * This static function set a new value to a MMC register.                  *
 * @ cxy    : target cluster identifier.                                    *
 * @ func   : accessed function in MMC (should be 0 for config).            *
 * @ index  : target register index.                                        *
 * @ val    : new value to be written.                                      *
 ****************************************************************************/
static void boot_mmc_set_register( uint32_t cxy, 
                                   uint32_t func, 
                                   uint32_t index, 
                                   uint32_t value )
{
    uint32_t * ptr = (uint32_t *)SEG_MMC_BASE + MMC_REG( func , index );

    boot_remote_sw( XPTR( cxy , ptr ) , value ); 

} // end boot_mmc_set_register()


///////////////////////////////////////
int boot_mmc_inval( uint64_t buf_paddr,
                    uint32_t buf_length )
{
    if ( buf_paddr & 0x3F )
    {
        boot_printf("\n[BOOT ERROR] in boot_mmc_inval() : paddr not 64 bytes aligned\n");
        return -1;
    }

    // get cxy from paddr
    uint32_t cxy = (uint32_t)(buf_paddr>>32);

    // write MMC registers  
    boot_mmc_set_register(cxy, MEMC_CONFIG, MEMC_ADDR_LO   , (uint32_t)buf_paddr );
    boot_mmc_set_register(cxy, MEMC_CONFIG, MEMC_ADDR_HI   , (uint32_t)(buf_paddr>>32) );
    boot_mmc_set_register(cxy, MEMC_CONFIG, MEMC_BUF_LENGTH, buf_length );
    boot_mmc_set_register(cxy, MEMC_CONFIG, MEMC_CMD_TYPE  , MEMC_CMD_INVAL );

    return 0;
}

// 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

