/*
 * soclib_mmc.h - SOCLIB_MMC (TSAR L2 cache) driver definition.
 *
 * Author    Alain Greiner
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _SOCLIB_MMC_H_
#define _SOCLIB_MMC_H_

#include <chdev.h>
#include <dev_mmc.h>
#include <hal_kernel_types.h>

/********************************************************************************************
 * This driver supports the SocLib VciMemCache component, that is the L2 cache used
 * by the TSAR architure.
 *******************************************************************************************/

/********************************************************************************************
 *       SOCLIB_MMC registers offset 
 *  - the register index is coded on 7 address bits : A[8:2]
 *  - the functionnality is coded on 2 address bits : A[10:9]
 *******************************************************************************************/

enum SoclibMemCacheFunc
{
    SOCLIB_MMC_CC_FUNC    = 0,
    SOCLIB_MMC_INSTR_FUNC = 1,
    SOCLIB_MMC_ERROR_FUNC = 2,

    SOCLIB_MMC_FUNC_SPAN  = 0x200
};

enum SoclibMemCacheCCRegs
{
    SOCLIB_MMC_ADDR_LO    = 0,
    SOCLIB_MMC_ADDR_HI    = 1,
    SOCLIB_MMC_BUF_LENGTH = 2,
    SOCLIB_MMC_CMD_TYPE   = 3,
};

enum SoclibMemCacheConfigCmd
{
    SOCLIB_MMC_CC_NOP     = 0,
    SOCLIB_MMC_CC_INVAL   = 1,
    SOCLIB_MMC_CC_SYNC    = 2,
};

enum SoclibMemCacheInstrRegs 
{

    // NUMBER OF LOCAL TRANSACTIONS ON DIRECT NETWORK 

    SOCLIB_MMC_LOCAL_READ_LO     = 0x00,
    SOCLIB_MMC_LOCAL_READ_HI     = 0x01,
    SOCLIB_MMC_LOCAL_WRITE_LO    = 0x02,
    SOCLIB_MMC_LOCAL_WRITE_HI    = 0x03,
    SOCLIB_MMC_LOCAL_LL_LO       = 0x04,
    SOCLIB_MMC_LOCAL_LL_HI       = 0x05,
    SOCLIB_MMC_LOCAL_SC_LO       = 0x06,
    SOCLIB_MMC_LOCAL_SC_HI       = 0x07,
    SOCLIB_MMC_LOCAL_CAS_LO      = 0x08,
    SOCLIB_MMC_LOCAL_CAS_HI      = 0x09,

    // NUMBER OF REMOTE TRANSACTIONS ON DIRECT NETWORK 

    SOCLIB_MMC_REMOTE_READ_LO    = 0x10,
    SOCLIB_MMC_REMOTE_READ_HI    = 0x11,
    SOCLIB_MMC_REMOTE_WRITE_LO   = 0x12,
    SOCLIB_MMC_REMOTE_WRITE_HI   = 0x13,
    SOCLIB_MMC_REMOTE_LL_LO      = 0x14,
    SOCLIB_MMC_REMOTE_LL_HI      = 0x15,
    SOCLIB_MMC_REMOTE_SC_LO      = 0x16,
    SOCLIB_MMC_REMOTE_SC_HI      = 0x17,
    SOCLIB_MMC_REMOTE_CAS_LO     = 0x18,
    SOCLIB_MMC_REMOTE_CAS_HI     = 0x19,

    // COST OF TRANSACTIONS ON DIRECT NETWORK

    SOCLIB_MMC_COST_READ_LO      = 0x20,
    SOCLIB_MMC_COST_READ_HI      = 0x21,
    SOCLIB_MMC_COST_WRITE_LO     = 0x22,
    SOCLIB_MMC_COST_WRITE_HI     = 0x23,
    SOCLIB_MMC_COST_LL_LO        = 0x24,
    SOCLIB_MMC_COST_LL_HI        = 0x25,
    SOCLIB_MMC_COST_SC_LO        = 0x26,
    SOCLIB_MMC_COST_SC_HI        = 0x27,
    SOCLIB_MMC_COST_CAS_LO       = 0x28,
    SOCLIB_MMC_COST_CAS_HI       = 0x29,

    // NUMBER OF LOCAL TRANSACTIONS ON CC NETWORK

    SOCLIB_MMC_LOCAL_MUPDATE_LO  = 0x40,
    SOCLIB_MMC_LOCAL_MUPDATE_HI  = 0x41,
    SOCLIB_MMC_LOCAL_MINVAL_LO   = 0x42,
    SOCLIB_MMC_LOCAL_MINVAL_HI   = 0x43,
    SOCLIB_MMC_LOCAL_CLEANUP_LO  = 0x44,
    SOCLIB_MMC_LOCAL_CLEANUP_HI  = 0x45,

    // NUMBER OF REMOTE TRANSACTIONS ON CC NETWORK

    SOCLIB_MMC_REMOTE_MUPDATE_LO = 0x50,
    SOCLIB_MMC_REMOTE_MUPDATE_HI = 0x51,
    SOCLIB_MMC_REMOTE_MINVAL_LO  = 0x52,
    SOCLIB_MMC_REMOTE_MINVAL_HI  = 0x53,
    SOCLIB_MMC_REMOTE_CLEANUP_LO = 0x54,
    SOCLIB_MMC_REMOTE_CLEANUP_HI = 0x55,

    // COST OF TRANSACTIONS ON CC NETWORK

    SOCLIB_MMC_COST_MUPDATE_LO   = 0x60,
    SOCLIB_MMC_COST_MUPDATE_HI   = 0x61,
    SOCLIB_MMC_COST_MINVAL_LO    = 0x62,
    SOCLIB_MMC_COST_MINVAL_HI    = 0x63,
    SOCLIB_MMC_COST_CLEANUP_LO   = 0x64,
    SOCLIB_MMC_COST_CLEANUP_HI   = 0x65,

    // TOTAL

    SOCLIB_MMC_TOTAL_MUPDATE_LO  = 0x68,
    SOCLIB_MMC_TOTAL_MUPDATE_HI  = 0x69,
    SOCLIB_MMC_TOTAL_MINVAL_LO   = 0x6A,
    SOCLIB_MMC_TOTAL_MINVAL_HI   = 0x6B,
    SOCLIB_MMC_TOTAL_BINVAL_LO   = 0x6C,
    SOCLIB_MMC_TOTAL_BINVAL_HI   = 0x6D,
};

enum SoclibMemCacheRerrorRegs
{
    SOCLIB_MMC_ERROR_ADDR_LO     = 0,
    SOCLIB_MMC_ERROR_ADDR_HI     = 1,
    SOCLIB_MMC_ERROR_SRCID       = 2, 
    SOCLIB_MMC_ERROR_IRQ_RESET   = 3,
    SOCLIB_MMC_ERROR_IRQ_ENABLE  = 4,
};


#define MMC_REG(func,index) ((func<<7)|index) 


/********************************************************************************************
 * This function initializes the SOCLIB_MMC peripheral hardware registers related
 * to error signaling. It enables the MMC peripheral IRQ.
 ********************************************************************************************
 * @ chdev      : local pointer on the MMC chdev descriptor.
 *******************************************************************************************/
extern void soclib_mmc_init( chdev_t * chdev );

/********************************************************************************************
 * This blocking function can be called by any thread running in any cluster.
 * It executes the command registered in the calling thread descriptor.
 * The MMC device spinlock must have been taken by the calling thead.
 ********************************************************************************************
 * @ thread_xp  : extended pointer on the client thread.
 *******************************************************************************************/
extern void soclib_mmc_cmd( xptr_t thread_xp );

/********************************************************************************************
 * This Interrupt Service Routine is executed when the MMC IRQ signals a faulty address.
 * The ISR should access the vci_mem_cache component to get the faulty physical address 
 * and the associated SRCID, and acknowledges the IRQ.
 ********************************************************************************************
 * @ chdev     : local pointer on the MMC chdev descriptor.
 *******************************************************************************************/
extern void soclib_mmc_isr( chdev_t * chdev );


#endif // SOCLIB_MMC_H_
