/*
Copyright (C) 2008, 2009  GE Intelligent Platforms, Inc
 
This program 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; either version 2
of the License, or (at your option) any later version.
 
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

/* regIf - Register interface library */

/*

DESCRIPTION:
    Contains definitions used in register interface library

INCLUDES:

SEE ALSO:

*/
#ifndef __REG_IF_H__
#define __REG_IF_H__

/*
 * Check for varoius byte boundaries
 */
#define ADDRESS_8(addr)     ((unsigned int)(addr) & 0x1)
#define ADDRESS_16(addr)    ((unsigned int)(addr) & 0x2)

/*
 * Various width memory read and write
 */
#ifdef SIMULATE_DEVICE
#define READ16(addr)            ((uint32)addr)
#define READ32(addr)            ((uint32)addr)
#define WRITE16(addr, data)     osPrintf("WRITE16 %p 0x%x\n", addr, data)
#define WRITE32(addr, data)     osPrintf("WRITE32 %p 0x%x\n", addr, data)
#else
#define READ16(addr)            (*((uint16_t *)(addr)))
#define READ32(addr)            (*((uint32_t *)(addr)))
#define WRITE16(addr, data)     (*((uint16_t *)(addr)) = data)
#define WRITE32(addr, data)     (*((uint32_t *)(addr)) = data)
#endif

#define INST1   1       /* one instance */
#define INST3   3       /* three instances */
#define INST2   2       /* two instances */
#define INST5   5       /* five instances */
#define INST9   9       /* nine instances */
#define INST24  24      /* twenty four instances */
#define INST128 128     /* one twenty eight instances */

#define ALL_INST    -1  /* used with regSet to set all instances
                           of a register with same value */

/*
 * Trace debug (function in/out) and Error debug
 */
#define regTrace(fmt, args...)      if (gRegifDebug & 0x1) \
                                      osPrintf("%s -> "fmt,__FUNCTION__, ## args)
#define regDetail(fmt, args...)     if (gRegifDebug & 0x2) \
                                      osPrintf("%s -> "fmt,__FUNCTION__, ## args)
#define regError                    if (gRegifDebug & 0x4)osPrintf

/*
 * Register property definition bits
 */
#define PROP_RD                 0x0001
#define PROP_WR                 0x0002
#define PROP_INIT_DEF           0x0004    /* initialize with default value */
#define PROP_WHOLE              0x0008
#define PROP_MDIO               0x0010    /* This is set/reset dynamically */
#define PROP_SWAP               0x0020    /* endian swap */
#define PROP_MDIO_INDIRECT      0x0040    /* use mdio cmd/data reg to R/W */
#define PROP_MDIO_EXTENDED      0x0080    /* extended (clause 45) mdio method */
#define PROP_RO                 PROP_RD
#define PROP_WO                 PROP_WD
#define PROP_RW                 (PROP_RD | PROP_WR)
#define PROP_RW_DEF             (PROP_RW | PROP_INIT_DEF)
#define PROP_RW_WHOLE           (PROP_RW | PROP_WHOLE)
#define PROP_RD_WHOLE           (PROP_RD | PROP_WHOLE)

#define isRegRead(prop)         ((prop) & PROP_RD)
#define isRegWrite(prop)        ((prop) & PROP_WR)
#define isRegInitDefault(prop)  ((prop) & PROP_INIT_DEF)
#define isRegWhole(prop)        ((prop) & PROP_WHOLE)

/*
 * Logical Register Information.
 */
typedef struct {
    int             regid;              /* register Id */
    char            *name;              /* register name */
    unsigned int    offset;             /* offset from device base addr */

    int             hiBit;              /* register high bit */
    int             loBit;              /* register low bit */
    unsigned int    properties;         /* read/write... properties */
    unsigned int    instOffset;         /* instance seperation offset */
    int             instMax;            /* max number of this register instance */
    unsigned int    defaultVal;
    int             mdio_da;            /* mdio device address */
    int             mdio_ra;            /* mdio register address */

    /*
     * following gets computed/initialized during regdbInit()
     */
    int             mdio_pa;            /* MDIO port address */
    unsigned int    addr;               /* absolute address (base + offset) */
    unsigned int    mask;               /* loBit to hiBit mask */
} reginfo_t;

/* Function Prototypes */
int regdbInit (reginfo_t [], unsigned int);

unsigned int readAddress (unsigned int address);
void writeAddress(unsigned int address, unsigned int data);
unsigned int readRegister (reginfo_t *regp, int inst);
void writeRegister (reginfo_t *regp, int inst, unsigned int data);
int regGet (reginfo_t [], int, unsigned int, unsigned int *);
int regSet (reginfo_t [], int, unsigned int, unsigned int);

/* register display functions */
unsigned int buildMask (int hiBit, int loBit);
int validateReg (reginfo_t *regp, int regid, int inst, int prop);

#endif /* __REG_IF_H__ */

