blob: a161db8c053d428ca94527dae1cf783cf9a3a2f0 [file] [log] [blame]
/*
* This file contains SFF related definitions
*/
#ifndef PRISM_SFF_H
#define PRISM_SFF_H
#include <common.h>
#include <command.h>
#include <environment.h>
#include <i2c.h>
#include <malloc.h>
#include <asm/byteorder.h>
#include "mvTypes.h"
/**************************************************
* Definitions
**************************************************/
#if defined(SFF_CMD_DBG)
#if defined(PRISM_DBG)
#undef PRISM_DBG
#endif
#define PRISM_DBG(format, args...) \
printf("%s: "format"\n", __func__, ## args)
#elif !defined(PRISM_DBG)
#define PRISM_DBG(format, args...)
#endif
#define SFF_ADDR_A0 0x50 /* A0 = 10100000X b7:1 address, b0 r/w bit */
#define SFF_ADDR_A2 0x51 /* A0 = 10100001X b7:1 address, b0 r/w bit */
#define SFF_BUF_LEN 128
#define SFF_ADDR_LEN 1 /* SFF address length */
#define CC_BASE "ccb"
#define CC_EXT "cce"
#define CC_DMI "ccd"
#if (defined(CONFIG_POST) && defined(CONFIG_SYS_POST_I2C))
#define I2C_ADDR_LIST { \
SFF_ADDR_A0, \
SFF_ADDR_A2, \
0x64, \
CONFIG_SYS_I2C_RTC_ADDR, \
}
#define SFF_LOG(format, args...)
#define SFF_ERR_LOG(format, args...) \
post_log("I2C: "format"\n", ## args)
#else
#define SFF_LOG(format, args...) printf(format"\n", ## args)
#define SFF_ERR_LOG SFF_LOG
#endif /* end of CONFIG_POST & CONFIG_SYS_POST_I2C */
/* SFF field starting data address and data length */
/* A0 starting address per group */
#define SFF_A0_BASE_ID 0
#define SFF_A0_EXT_ID 64
#define SFF_A0_VEND_SPEC 96
#define SFF_A0_END 127
/* A0 group lengths */
#define A0_BASE_ID_L (SFF_A0_EXT_ID - SFF_A0_BASE_ID)
#define A0_EXT_ID_L (SFF_A0_VEND_SPEC - SFF_A0_EXT_ID)
#define A0_VEND_SPEC_L (SFF_A0_END + 1 - SFF_A0_VEND_SPEC)
/* A0 checksum addresses */
#define SFF_A0_CC_BASE 63
#define SFF_A0_CC_EXT 95
/* A2 starting address per group */
#define SFF_A2_ALRM_WARN 0
#define SFF_A2_EXT_CONSTS 56
#define SFF_A2_RT_DIAG 96
#define SFF_A2_END 179
/* A2 group lengths */
#define A2_ALRM_WARN_L (SFF_A2_EXT_CONSTS - SFF_A2_ALRM_WARN)
#define A2_CC_DMI_CHKSUM_L (SFF_A2_RT_DIAG - SFF_A2_ALRM_WARN)
/**************************************************
* local data and function
**************************************************/
/* SFF verify-checksum command entry */
typedef struct csum_vfy_func_entry_ {
char *name; /* cmd string */
int chip; /* SFF addr */
int daddr; /* data addr to access of the SFF addr */
int nbytes; /* number of bytes to access */
} csum_vfy_func_entry, sff_addr;
/* Command lookup table
* - For verifying CCB_BASE and CC_EXC checksums, read in all of data in
* the range including checksum bytes.
*/
static const csum_vfy_func_entry sff_csum_vfy_sub_cmds[] = {
/* name, chip, daddr, nbyte */
{CC_BASE, SFF_ADDR_A0, SFF_A0_BASE_ID, A0_BASE_ID_L},
{CC_EXT, SFF_ADDR_A0, SFF_A0_EXT_ID, A0_EXT_ID_L},
{CC_DMI, SFF_ADDR_A2, SFF_A2_ALRM_WARN, A2_CC_DMI_CHKSUM_L},
};
#define SIZEOF_CSUM_VFY_SUB_CMD_TBL (sizeof(sff_csum_vfy_sub_cmds)/sizeof(csum_vfy_func_entry))
/*
* 8-bit checksum
* (Copied the routine from mv_feroceon/mv_kw2_mv_cmd.c)
*/
static uchar checksum8(uchar *start, uchar len, uchar csum)
{
uchar sum = csum;
volatile uchar *startp = (volatile uchar *)start;
do {
sum += *startp;
startp++;
} while(--len);
return (sum);
} /* end of checksum */
static int sff_read_verify_checksum(char *csum_name)
{
int ret = 1; /* default fail */
int i;
uchar sff_buf[SFF_BUF_LEN];
uchar csum = 0;
csum_vfy_func_entry *ptable = (csum_vfy_func_entry *)sff_csum_vfy_sub_cmds;
MV_BOOL found = MV_FALSE;
do {
/* Lookup the command table and find the sub-cmd entry */
for (i = 0; i < SIZEOF_CSUM_VFY_SUB_CMD_TBL; i++, ptable++) {
PRISM_DBG("name=%s, len=%d\n", ptable->name, (int)strlen(ptable->name));
if (!strncmp(csum_name, ptable->name, (int)strlen(ptable->name))) {
/* Found the diag func, return entry address */
found = MV_TRUE;
break;
}
}
if (found != MV_TRUE) {
PRISM_DBG("Invalid command....\n");
break; /* not found. exit */
}
/* read and verify the checksum
* buffer all read data, so we can make sure data is read only once.
*/
ret = i2c_read(
ptable->chip, ptable->daddr, SFF_ADDR_LEN,
sff_buf, ptable->nbytes);
if (ret != 0) {
SFF_ERR_LOG("failed to access the sff chip addr (0x%02x).\n",
(ptable->chip<<1));
break;
}
/* Calculate 8-bit checksum */
csum = checksum8(sff_buf, (ptable->nbytes-1), 0);
PRISM_DBG("calculated csum=0x%02X, csum=0x%02X",
csum, sff_buf[ptable->nbytes-1]);
if (csum != sff_buf[ptable->nbytes-1]) {
SFF_ERR_LOG("csum mismatched - chip=0x%02x, off= 0x%02x, csum=0x%02x, "
"calculated csum=0x%02x",
(ptable->chip<<1), (ptable->daddr +ptable->nbytes-1),
sff_buf[ptable->nbytes-1], csum);
ret = 1; /* fail */
} else {
SFF_LOG("csum matched - chip=0x%02x, off= 0x%02x, csum=0x%02x",
(ptable->chip<<1), (ptable->daddr+ptable->nbytes-1), csum);
ret = 0; /* success */
}
} while (0);
return(ret);
} /* end of sff_read_print_group */
#endif /* end of PRISM_SFF_H */