spbx/roms/srcs/tools/switch_mirror/bcm_mirror.c

522 lines
11 KiB
C
Raw Permalink Normal View History

2019-03-11 00:13:23 +00:00
#include <linux/spi/spi.h>
#include "bcm_mirror.h"
#include "spi_mpc.h"
#include "mirror_drv.h"
#include "spbx_log/spbx_log.h"
#define MIR_PORT_PAG (0x3)
#define MIR_CTL_REG (0x10)
#define MIR_CAP_PORT_REG (0x18)
#define EN_OUT_MIR_FLTR (1<<4)
#define EN_IN_MIR_FLTR (1<<5)
#define MIR_CAP_PORT(x) (1 <<(x))
#define SW_READ_MODE (0x60)
#define SW_WRITE_MODE (0x61)
#define SW_SPI_DATA_REG(x) (0xF0 + (x))
#define SW_SPI_STATUS_REG (0xFE)
#define SW_SPI_PAGE_REG (0xFF)
#define SW_STATUS_SPIF (1<<7)
#define SW_STATUS_WCOL (1<<6)
#define SW_STATUS_RACK (1<<5)
#define SW_STATUS_MDIO_ST (1<<2)
#define SW_STATUS_RXRDY (1<<1)
#define SW_STATUS_TXRDY (0<<1)
#define SW_MAX_TIME (10)
#define MAX_PORT (28)
static unsigned char g_page_addr = 0;
static int sw_get_spi_status(unsigned char* status)
{
char temp_rx[3];
char temp_tx[3];
struct spi_transfer t;
struct spi_message m;
struct spi_device* spi = DRV_GetDrvDetail()->pSPIDevice;
memset(temp_rx, 0, 3);
memset(temp_tx, 0, 3);
temp_tx[0] = SW_READ_MODE;
temp_tx[1] = SW_SPI_STATUS_REG;
temp_tx[2] = 0x0;
spi_message_init(&m);
t.tx_buf = temp_tx;
t.rx_buf = temp_rx;
t.len = 3;
spi_message_add_tail(&t, &m);
if(spi_sync(spi, &m) < 0)
{
printk(KERN_ERR "RD error in spi operation\n");
return -1;
}
*status = temp_rx[2];
return 0;
}
static int sw_set_page_addr(unsigned char page)
{
struct spi_device* spi = DRV_GetDrvDetail()->pSPIDevice;
char temp_rx[3];
char temp_tx[3];
struct spi_transfer t;
struct spi_message m;
memset(temp_rx, 0, 3);
memset(temp_tx, 0, 3);
temp_tx[0] = SW_WRITE_MODE;
temp_tx[1] = SW_SPI_PAGE_REG;
temp_tx[2] = page;
spi_message_init(&m);
t.tx_buf = temp_tx;
t.rx_buf = temp_rx;
t.len = 3;
spi_message_add_tail(&t, &m);
if(spi_sync(spi, &m) < 0)
{
printk(KERN_ERR "RD error in spi operation\n");
return -1;
}
return 0;
}
static int dummy_read(PBCM_REGS pRegs)
{
struct spi_device* spi = DRV_GetDrvDetail()->pSPIDevice;
unsigned char len = 3;
char temp_rx[3];
char temp_tx[3];
struct spi_transfer t;
struct spi_message m;
memset(temp_rx , 0, len);
memset(temp_tx , 0, len);
temp_tx[0] = SW_READ_MODE;
temp_tx[1] = pRegs->reg_addr;
temp_tx[2] = 0;
spi_message_init(&m);
t.tx_buf = temp_tx;
t.rx_buf = temp_rx;
t.len = 3;
spi_message_add_tail(&t, &m);
if(spi_sync(spi, &m) < 0)
{
printk(KERN_ERR "RD error in spi operation\n");
return -1;
}
return 0;
}
static unsigned int sw_read_reg(PBCM_REGS pRegs)
{
unsigned int index = 0;
unsigned char status;
unsigned char page_addr = pRegs->page_addr;
struct spi_device* spi = DRV_GetDrvDetail()->pSPIDevice;
if(spi == NULL || pRegs == NULL)
{
return -1;
}
do
{
if(sw_get_spi_status(&status))
{
status = -1;
index++;
}
}
while((status & SW_STATUS_SPIF) != 0 && index < SW_MAX_TIME);
if(index >= SW_MAX_TIME)
{
printk("status :0x%x,SPIF !=0\n", status);
return -1;
}
if(page_addr != g_page_addr)
{
unsigned char page_addr = pRegs->page_addr;
if(!sw_set_page_addr(page_addr))
{
g_page_addr = page_addr;
}
else
{
printk("page addr set fail\n");
return -1;
}
}
if(!dummy_read(pRegs))
{
do
{
if(sw_get_spi_status(&status))
{
status = -1;
index++;
}
}
while(((status & SW_STATUS_RACK) == 0) && (index < SW_MAX_TIME));
if(index >= SW_MAX_TIME)
{
printk("status :0x%x,SPIF !=0\n", status);
return -1;
}
do
{
int i;
unsigned char len = pRegs->len;
char temp_rx[len + 2];
char temp_tx[len + 2];
struct spi_transfer t;
struct spi_message m;
memset(temp_rx , 0, len + 2);
memset(temp_tx , 0, len + 2);
temp_tx[0] = SW_READ_MODE;
temp_tx[1] = SW_SPI_DATA_REG(0);
spi_message_init(&m);
t.tx_buf = temp_tx;
t.rx_buf = temp_rx;
t.len = len + 2;
spi_message_add_tail(&t, &m);
if(spi_sync(spi, &m) < 0)
{
printk(KERN_ERR "RD error in spi operation\n");
return -1;
}
for(i = 0; i < len; i++)
{
pRegs->buf[i] = temp_rx[len + 2 - 1 - i];
}
}
while(0);
}
else
{
printk("dummy_read fail\n");
return -1;
}
return 0;
}
static int sw_write_reg(PBCM_REGS pRegs)
{
unsigned int index = 0;
unsigned char status;
unsigned char page_addr = pRegs->page_addr;
struct spi_device* spi = DRV_GetDrvDetail()->pSPIDevice;
if(spi == NULL || pRegs == NULL)
{
return -1;
}
do
{
if(sw_get_spi_status(&status))
{
status = -1;
index++;
}
}
while((status & SW_STATUS_SPIF) != 0 && (index < SW_MAX_TIME));
if(index >= SW_MAX_TIME)
{
printk("status :0x%x,SPIF !=0\n", status);
return -1;
}
// printk("page_addr:0x%x,g_page_addr:0x%x\n",page_addr,g_page_addr);
if(page_addr != g_page_addr)
{
unsigned char page_addr = pRegs->page_addr;
if(!sw_set_page_addr(page_addr))
{
g_page_addr = page_addr;
}
else
{
printk("page addr set fail\n");
return -1;
}
}
do
{
int i;
unsigned char len = pRegs->len;
char temp_rx[len + 2];
char temp_tx[len + 2];
struct spi_transfer t;
struct spi_message m;
memset(temp_rx , 0, len + 2);
memset(temp_tx , 0, len + 2);
temp_tx[0] = SW_WRITE_MODE;
temp_tx[1] = pRegs->reg_addr;
for(i = 0; i < len; i++)
{
// printk("value[%d] = 0x%x\n",i,pRegs->buf[i]);
temp_tx[2 + i] = pRegs->buf[len - 1 - i];
}
spi_message_init(&m);
t.tx_buf = temp_tx;
t.rx_buf = temp_rx;
t.len = len + 2;
spi_message_add_tail(&t, &m);
if(spi_sync(spi, &m) < 0)
{
printk(KERN_ERR "RD error in spi operation\n");
return -1;
}
}
while(0);
return 0;
}
static int bcm_mir_disable(void)
{
BCM_REGS bcmRegs = {0};
PBCM_REGS pRegs = &bcmRegs;
memset(pRegs, 0, sizeof(BCM_REGS));
pRegs->page_addr = MIR_PORT_PAG;
pRegs->reg_addr = MIR_CAP_PORT_REG;
pRegs->len = 4;
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_write_reg(pRegs);
sw_read_reg(pRegs);
pRegs->reg_addr = EG_MIR_PORT_REG;
pRegs->len = 4;
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_write_reg(pRegs);
sw_read_reg(pRegs);
pRegs->reg_addr = ING_MIR_PORT_REG;
pRegs->len = 4;
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_write_reg(pRegs);
sw_read_reg(pRegs);
pRegs->reg_addr = MIR_CTL_REG;
pRegs->len = 1;
pRegs->buf[0] = 0;
sw_write_reg(pRegs);
sw_read_reg(pRegs);
return (0);
}
static int bcm_mir_access_on(unsigned int src, unsigned int dst, MIR_REG off)
{
BCM_REGS bcmRegs = {0};
PBCM_REGS pRegs = &bcmRegs;
if(src >= MAX_PORT || dst >= MAX_PORT)
{
return 0;
}
memset(pRegs, 0, sizeof(BCM_REGS));
pRegs->page_addr = MIR_PORT_PAG;
pRegs->reg_addr = MIR_CAP_PORT_REG;
pRegs->len = 4;
sw_read_reg(pRegs);
pRegs->buf[0] |= (MIR_CAP_PORT(dst) >> 24) & 0xff;
pRegs->buf[1] |= (MIR_CAP_PORT(dst) >> 16) & 0xff;
pRegs->buf[2] |= (MIR_CAP_PORT(dst) >> 8) & 0xff;
pRegs->buf[3] |= (MIR_CAP_PORT(dst) >> 0) & 0xff;
sw_write_reg(pRegs);
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_read_reg(pRegs);
#if 0
printk("R:PAGE:%d,REG:%d,VALUE:0x%x 0x%x 0x%x 0x%x\n",
pRegs->page_addr,
pRegs->reg_addr,
pRegs->buf[0],
pRegs->buf[1],
pRegs->buf[2],
pRegs->buf[3]);
#endif
pRegs->reg_addr = off ;
pRegs->len = 4;
sw_read_reg(pRegs);
pRegs->buf[0] |= (MIR_CAP_PORT(src) >> 24) & 0xff;
pRegs->buf[1] |= (MIR_CAP_PORT(src) >> 16) & 0xff;
pRegs->buf[2] |= (MIR_CAP_PORT(src) >> 8) & 0xff;
pRegs->buf[3] |= (MIR_CAP_PORT(src) >> 0) & 0xff;
sw_write_reg(pRegs);
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_read_reg(pRegs);
/*
printk("R:PAGE:%d,REG:%d,VALUE:0x%x 0x%x 0x%x 0x%x\n",
pRegs->page_addr,
pRegs->reg_addr,
pRegs->buf[0],
pRegs->buf[1],
pRegs->buf[2],
pRegs->buf[3]);
*/
pRegs->reg_addr = MIR_CTL_REG;
pRegs->len = 1;
sw_read_reg(pRegs);
pRegs->buf[0] |= (off == ING_MIR_PORT_REG ?
EN_IN_MIR_FLTR :
EN_OUT_MIR_FLTR);
sw_write_reg(pRegs);
pRegs->buf[0] = 0;
sw_read_reg(pRegs);
//printk("R:PAGE:%d,REG:%d,VALUE:0x%x\n", pRegs->page_addr, pRegs->reg_addr, pRegs->buf[0]);
return 0;
}
static int bcm_mir_access_off(unsigned int fe, MIR_REG off)
{
BCM_REGS bcmRegs = {0};
PBCM_REGS pRegs = &bcmRegs;
if(fe >= MAX_PORT)
{
return 0;
}
memset(pRegs, 0, sizeof(BCM_REGS));
pRegs->page_addr = MIR_PORT_PAG;
pRegs->reg_addr = off;
pRegs->len = 4;
sw_read_reg(pRegs);
pRegs->buf[0] &= ~((MIR_CAP_PORT(fe) >> 24) & 0xff);
pRegs->buf[1] &= ~((MIR_CAP_PORT(fe) >> 16) & 0xff);
pRegs->buf[2] &= ~((MIR_CAP_PORT(fe) >> 8) & 0xff);
pRegs->buf[3] &= ~((MIR_CAP_PORT(fe) >> 0) & 0xff);
sw_write_reg(pRegs);
pRegs->buf[0] = 0;
pRegs->buf[1] = 0;
pRegs->buf[2] = 0;
pRegs->buf[3] = 0;
sw_read_reg(pRegs);
/*
printk("R:PAGE:%d,REG:%d,VALUE:0x%x 0x%x 0x%x 0x%x\n",
pRegs->page_addr,
pRegs->reg_addr,
pRegs->buf[0],
pRegs->buf[1],
pRegs->buf[2],
pRegs->buf[3]);
*/
return 0;
}
int bcm_mir_out_on(unsigned int src, unsigned int dst)
{
return bcm_mir_access_on(src, dst, ING_MIR_PORT_REG);
}
int bcm_mir_in_on(unsigned int src, unsigned int dst)
{
return bcm_mir_access_on(src, dst, EG_MIR_PORT_REG);
}
int bcm_mir_out_off(unsigned int fe)
{
return bcm_mir_access_off(fe, ING_MIR_PORT_REG);
}
int bcm_mir_in_off(unsigned int fe)
{
return bcm_mir_access_off(fe, EG_MIR_PORT_REG);
}