Zynq-Linux移植学习笔记之66- 国产ZYNQ通过裕太PHY8521连接国产交换芯片

1、背景介绍

ZYNQ通过裕太PHY 8521主要连接两种国产交换芯片,一种为盛科的CTC8096,另一种为32所的JEM5396。框图示意如下:

2、硬件状态确认

首先检查phy的模式,确认为SGMII_MAC-RGMII_PHY

可通过读出A001寄存器确认状态

读出来应该是0x8155

这样确保状态对

3、PHY软件配置

PHY软件需要配置为强制千兆

./phyreg.elf eth1 0x0 0x340

设置phy的tx_delay

一般设置a003寄存器为0xf8或者0xfa

Phyreg代码如下

/*
 ============================================================================
 Name        : main.c
 Author      : 123
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/mii.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <linux/types.h>
#include <netinet/in.h>

#define reteck(ret) \
	if(ret < 0){ \
		printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \
		goto lab; \
}
#define help() \
	printf("mdio:\n"); \
	printf("read operation: mdio reg_addr\n"); \
	printf("write operation: mdio reg_addr value\n"); \
	printf("For example:\n"); \
	printf("mdio eth0 1\n"); \
	printf("mdio eth0 0 0x12\n\n"); \
	exit(0);

int sockfd;

int main(int argc, char *argv[]) {
	if (argc == 1 || !strcmp(argv[1], "-h")) {
		help()
		;
	}
	struct mii_ioctl_data *mii = NULL;
	struct ifreq ifr;
	int ret;
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, argv[1], IFNAMSIZ - 1);
	sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
	reteck(sockfd);
//get phy address in smi bus
	ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);
	reteck(ret);
	mii = (struct mii_ioctl_data*) &ifr.ifr_data;
	if (argc == 3) {
		mii->reg_num = (uint16_t) strtoul(argv[2], NULL, 0);
		ret = ioctl(sockfd, SIOCGMIIREG, &ifr);
		reteck(ret);
		printf("read phy addr: 0x%x reg: 0x%x value : 0x%x\n", mii->phy_id,
				mii->reg_num, mii->val_out);
	} else if (argc == 4) {
		mii->reg_num = (uint16_t) strtoul(argv[2], NULL, 0);
		mii->val_in = (uint16_t) strtoul(argv[3], NULL, 0);
		ret = ioctl(sockfd, SIOCSMIIREG, &ifr);
		reteck(ret);
		printf("write phy addr: 0x%x reg: 0x%x value : 0x%x\n", mii->phy_id,
				mii->reg_num, mii->val_in);
	}
	lab: close(sockfd);
	return 0;
}

4、交换芯片端配置

交换芯片端与PHY相连的端口需要配置强制千兆模式

针对CTC8096(一般SDK应用内配置

ctc8096端将对应端口强制千兆

port 0x0007 auto-neg disable

port 0x0007 property auto-neg-mode sgmii-slaver

针对JEM5396(一般UBOOT阶段配置

printf("Set Port 5 CONNECT TO ZYNQ SPEED 1000M\n");

workBuf[0] = 0x8b;

workBuf[1] = 0x0;

writeBCM5396_2(&spi, 0, 0x65, workBuf);  





workBuf[0] = 0x40;

workBuf[1] = 0x1;  

Status = writeBCM5396(&spi, 0x15, 0x0, workBuf );  

JEM5396配置的详细代码如下:

// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2001-2015
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 * Joe Hershberger, National Instruments
 */

#include <common.h>
#include <dm.h>
#include <environment.h>
#include <net.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>

#define XGpioPs_ReadReg(BaseAddr, RegOffset)		\
		(*(volatile u32 * )((BaseAddr) + (RegOffset)))


#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data)	\
		*(volatile u32 *) ((BaseAddr) + RegOffset) = Data


#define AD9520READ	(0x80)
#define AD9520WRITE	(0x00)

/*-----------------------国产ZYNQ GPIO  通用代码--------------------------------------------*/
#define XGPIOPS_DATA_LSW_OFFSET  0x00000000U  /* Mask and Data Register LSW, WO */
#define XGPIOPS_DATA_MSW_OFFSET  0x00000004U  /* Mask and Data Register MSW, WO */
#define XGPIOPS_DATA_OFFSET	 0x00000040U  /* Data Register, RW */
#define XGPIOPS_DATA_RO_OFFSET	 0x00000060U  /* Data Register - Input, RO */
#define XGPIOPS_DIRM_OFFSET	 0x00000004U  //0x00000204U  /* Direction Mode Register, RW */
#define XGPIOPS_OUTEN_OFFSET	 0x00000208U  /* Output Enable Register, RW */
#define XGPIOPS_INTMASK_OFFSET	 0x0000020CU  /* Interrupt Mask Register, RO */
#define XGPIOPS_INTEN_OFFSET	 0x00000210U  /* Interrupt Enable Register, WO */
#define XGPIOPS_INTDIS_OFFSET	 0x00000214U  /* Interrupt Disable Register, WO*/
#define XGPIOPS_INTSTS_OFFSET	 0x00000218U  /* Interrupt Status Register, RO */
#define XGPIOPS_INTTYPE_OFFSET	 0x0000021CU  /* Interrupt Type Register, RW */
#define XGPIOPS_INTPOL_OFFSET	 0x00000220U  /* Interrupt Polarity Register, RW */
#define XGPIOPS_INTANY_OFFSET	 0x00000224U  /* Interrupt On Any Register, RW */


#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U  /* Data/Mask Registers offset */
#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U  /* Data Registers offset */
#define XGPIOPS_REG_MASK_OFFSET  0x00000100U  /* Registers offset */ //0x00000040U 


/* For backwards compatibility */
#define XGPIOPS_BYPM_MASK_OFFSET	(u32)0x40

#define XGPIOPS_INTTYPE_BANK0_RESET  0xFFFFFFFFU
#define XGPIOPS_INTTYPE_BANK1_RESET  0x3FFFFFFFU
#define XGPIOPS_INTTYPE_BANK2_RESET  0xFFFFFFFFU
#define XGPIOPS_INTTYPE_BANK3_RESET  0xFFFFFFFFU

#define XGPIOPS_IRQ_TYPE_EDGE_RISING	0x00U  /**< Interrupt on Rising edge */
#define XGPIOPS_IRQ_TYPE_EDGE_FALLING	0x01U  /**< Interrupt Falling edge */
#define XGPIOPS_IRQ_TYPE_EDGE_BOTH	0x02U  /**< Interrupt on both edges */
#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH	0x03U  /**< Interrupt on high level */
#define XGPIOPS_IRQ_TYPE_LEVEL_LOW	0x04U  /**< Interrupt on low level */
/*@}*/

#define XGPIOPS_BANK0			0x00U  /**< GPIO Bank 0 */
#define XGPIOPS_BANK1			0x01U  /**< GPIO Bank 1 */
#define XGPIOPS_BANK2			0x02U  /**< GPIO Bank 2 */
#define XGPIOPS_BANK3			0x03U  /**< GPIO Bank 3 */

#define XGPIOPS_MAX_BANKS		0x04U  /**< Max banks in a GPIO device */
#define XGPIOPS_BANK_MAX_PINS		(u32)32 /**< Max pins in a GPIO bank */

#define XGPIOPS_DEVICE_MAX_PIN_NUM	(u32)118 /*< Max pins in the GPIO device*/

#define LED_DELAY 	10000000
#define FLASH_RESET_GPIO 0x41220000
#define FLASH_RST_PERIOD 600000

#define FIFO_CFG_GPIO 0x41210000
#define FIFO_DONE_GPIO 0x41220000

#define UBOOT_CFG_GPIO 0x41250000

#define GGF_REST_GPIO 0x41260000
#define DBFGKJ_REST_GPIO 0x412A0000
#define FIRST_V_GPIO 0x41260000
#define SECOND_V_GPIO 0x41270000
#define THIRD_V_GPIO 0x41280000
#define FORTH_V_GPIO 0x41290000


typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status);


typedef struct {
	u16 DeviceId;		/**< Unique ID of device */
	u32 BaseAddr;		/**< Register base address */
} XGpioPs_Config;


typedef struct {
	XGpioPs_Config GpioConfig;	/**< Device configuration */
	u32 IsReady;			/**< Device is initialized and ready */
	XGpioPs_Handler Handler;	/**< Status handlers for all banks */
	void *CallBackRef; 		/**< Callback ref for bank handlers */
} XGpioPs;


XGpioPs_Config XGpioPs_ConfigTable[] =
{
	{
		0,
		0xE0003000
	}
};

XGpioPs_Config *g_GpioConfig;

void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
{
	/*
	 * This structure defines the mapping of the pin numbers to the banks when
	 * the driver APIs are used for working on the individual pins.
	 */
	u32 XGpioPsPinTable[] = {
		(u32)31, /* 0 - 31, Bank 0 */
		(u32)63, /* 32 - 53, Bank 1 */
		(u32)95, /* 54 - 85, Bank 2 */
		(u32)127 /* 86 - 117 Bank 3 */
	};
	*BankNumber = 0U;
	while (*BankNumber < 4U) {
		if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
			break;
		}
		(*BankNumber)++;
    }
	if (*BankNumber == (u8)0) {
		*PinNumberInBank = PinNumber;
	} else {
		*PinNumberInBank = (u8)((u32)PinNumber %
					(XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1));
	}
}


void XGpioPs_SetDirectionPin(XGpioPs *InstancePtr, u32 Pin, u32 Direction)
{
	u8 Bank;
	u8 PinNumber;
	u32 DirModeReg;

	/*
	 * Get the Bank number and Pin number within the bank.
	 */
	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);

	DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
				      ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
				      XGPIOPS_DIRM_OFFSET);

//	DirModeReg = XGpioPs_ReadReg(0xE000A244,0);


	if (Direction!=(u32)0) { /*  input Direction */
		DirModeReg |= ((u32)1 << (u32)PinNumber);
	} else { /* output Direction */
		DirModeReg &= ~ ((u32)1 << (u32)PinNumber);
	}


	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
			 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
			 XGPIOPS_DIRM_OFFSET, DirModeReg);

//	XGpioPs_WriteReg(0xE000A244, 0,DirModeReg);
}


void XGpioPs_SetOutputEnablePin(XGpioPs *InstancePtr, u32 Pin, u32 OpEnable)
{
	u8 Bank;
	u8 PinNumber;
	u32 OpEnableReg;

	/*
	 * Get the Bank number and Pin number within the bank.
	 */
	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);


	OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
				       ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
				       XGPIOPS_OUTEN_OFFSET);

//	OpEnableReg = XGpioPs_ReadReg(0xE000A248,0);


	if (OpEnable != (u32)0) { /*  Enable Output Enable */
		OpEnableReg |= ((u32)1 << (u32)PinNumber);
	} else { /* Disable Output Enable */
		OpEnableReg &= ~ ((u32)1 << (u32)PinNumber);
	}
	

	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
			  ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
			  XGPIOPS_OUTEN_OFFSET, OpEnableReg);
//	XGpioPs_WriteReg(0xE000A248,0, OpEnableReg);
}


void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data)
{
	u32 Value;
	u8 Bank;
	u8 PinNumber;
	u32 DataVar = Data;

	/*
	 * Get the Bank number and Pin number within the bank.
	 */
	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
//
//	if (PinNumber > 15U) {
		/*
		 * There are only 16 data bits in bit maskable register.
		 */
//		PinNumber -= (u8)16;
//		RegOffset = XGPIOPS_DATA_MSW_OFFSET;
//	} else {
//		RegOffset = XGPIOPS_DATA_LSW_OFFSET;
//	}

	/*
	 * Get the 32 bit value to be written to the Mask/Data register where
	 * the upper 16 bits is the mask and lower 16 bits is the data.
	 */
	DataVar &= (u32)0x01;
	Value = ((DataVar << PinNumber) | 0x00000000U);

	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
			  ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
			  XGPIOPS_DATA_LSW_OFFSET, Value);
}

u32 XGpioPs_ReadPin(XGpioPs *InstancePtr, u32 Pin)
{
	u8 Bank;
	u8 PinNumber;

	/*
	 * Get the Bank number and Pin number within the bank.
	 */
	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);

	return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
				 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
				 XGPIOPS_DATA_LSW_OFFSET) >> (u32)PinNumber) & (u32)1;

}


void mygpio_init(int mioPinNum)
{
	XGpioPs Gpio;
	g_GpioConfig = &XGpioPs_ConfigTable[0];

	//Initialize the GPIO device.

	Gpio.IsReady = 0U;
	Gpio.GpioConfig.BaseAddr = g_GpioConfig->BaseAddr;

	Gpio.GpioConfig.DeviceId = 0;

	/*
	 * Indicate the component is now ready to use.
	 */
	Gpio.IsReady = 0x11111111U;

	//Initialize the GPIO device. end
	XGpioPs_SetDirectionPin(&Gpio, mioPinNum, 1);

	// MIO0
	XGpioPs_WritePin(&Gpio, mioPinNum, 0x1);
	if(XGpioPs_ReadPin(&Gpio,mioPinNum) != 1)
	printf("mio reset phy failed \n\r");
	udelay(2000);

	XGpioPs_WritePin(&Gpio, mioPinNum, 0x0);
	if(XGpioPs_ReadPin(&Gpio,mioPinNum) != 0)
	printf("mio reset phy failed \n\r");
	udelay(2000);

	XGpioPs_WritePin(&Gpio, mioPinNum, 0x1);
	if(XGpioPs_ReadPin(&Gpio,mioPinNum) != 1)
	printf("mio reset phy failed \n\r");

}


//
/*   		              JEM5396 读写通用代码                              */
//
#ifndef TRUE
#define TRUE		1U
#endif

#ifndef FALSE
#define FALSE		0U
#endif

#ifndef NULL
#define NULL		0U
#endif

#ifndef FPAR_SPIPS_0_DEVICE_ID
    #define FPS_SPI0_DEVICE_ID          (0)
#else
    #define FPS_SPI0_DEVICE_ID          FPAR_SPIPS_0_DEVICE_ID
#endif

#ifndef  FPS_SPI0_BASEADDR
    #define FPS_SPI0_BASEADDR           (0xe0001000)
#endif

#ifndef FPAR_SPIPS_1_DEVICE_ID
    #define FPS_SPI1_DEVICE_ID          (1)
#else
    #define FPS_SPI1_DEVICE_ID          FPAR_SPIPS_1_DEVICE_ID
#endif

#ifndef  FPS_SPI1_BASEADDR
    #define FPS_SPI1_BASEADDR           (0xe0021000)
#endif


#define SLCR_SPI0_CTRL       		(0x300)
#define SLCR_SPI1_CTRL       		(0x300)
#define SPI0_APB_RST         		(0x0)
#define SPI1_APB_RST         		(0x1)
#define SPI0_REF_RST         		(0x2)
#define SPI1_REF_RST        		(0x3)
#define SLCR_LOCK            		(0x004)
#define SLCR_UNLOCK         		(0x008)
#define FPS_SLCR_BASEADDR            	(0xE0026000)

register
#define SPIPS_MSTR_OFFSET           (0x100)
#define SPIPS_CTRLR0_OFFSET         (0x00)
#define SPIPS_CTRLR1_OFFSET         (0x04)
#define SPIPS_SSIENR_OFFSET         (0x08)
#define SPIPS_MVCR_OFFSET           (0x0C)
#define SPIPS_SER_OFFSET            (0x10)
#define SPIPS_BAUDR_OFFSET          (0x14)
#define SPIPS_TXFTLR_OFFSET         (0x18)
#define SPIPS_RXFTLR_OFFSET         (0x1C)
#define SPIPS_TXFLR_OFFSET          (0x20)
#define SPIPS_RXFLR_OFFSET          (0x24)
#define SPIPS_SR_OFFSET             (0x28)
#define SPIPS_IMR_OFFSET            (0x2C)
#define SPIPS_ISR_OFFSET            (0x30)
#define SPIPS_RISR_OFFSET           (0x34)
#define SPIPS_TXOICR_OFFSET         (0x38)
#define SPIPS_RXOICR_OFFSET         (0x3C)
#define SPIPS_RXUICR_OFFSET         (0x40)
#define SPIPS_MSTICR_OFFSET         (0x44)
#define SPIPS_ICR_OFFSET            (0x48)
#define SPIPS_DMACR_OFFSET          (0x4C)
#define SPIPS_DMATDLR_OFFSET        (0x50)
#define SPIPS_DMARDLR_OFFSET        (0x54)
#define SPIPS_IDR_OFFSET            (0x58)
#define SPIPS_VERSION_OFFSET        (0x5C)
#define SPIPS_DR_OFFSET             (0x60)
#define SPIPS_RX_SAMPLE_OFFSET      (0xf0)
#define SPIPS_SCTRLR0_OFFSET        (0xf4)
#define SPIPS_RSVD1_OFFSET          (0xf8)
#define SPIPS_RSVD2_OFFSET          (0xfc)

#define FMSH_ReadReg(baseAddr, offSet)		*((volatile unsigned int *)(baseAddr + offSet))
#define FMSH_WriteReg(baseAddr, offSet, data)	*((volatile unsigned int *)(baseAddr + offSet)) = data


typedef struct {
    u16 deviceId;		            /**< Unique ID of device */
    u32 baseAddress;                /**< APB Base address of the device */
} FSpiPs_Config_T;

#define FPS_SPI_NUM_INSTANCES       (1)

FSpiPs_Config_T FSpiPs_ConfigTable[] =
{
	{
		FPS_SPI0_DEVICE_ID,
		FPS_SPI0_BASEADDR
	},
	{
		FPS_SPI1_DEVICE_ID,
		FPS_SPI1_BASEADDR
	}
};
FSpiPs_Config_T* FSpiPs_LookupConfig(u16 deviceId)
{
    int index;
    FSpiPs_Config_T* cfgPtr = NULL;

    for (index = 0; index < FPS_SPI_NUM_INSTANCES; index++) {
        if (FSpiPs_ConfigTable[index].deviceId == deviceId) {
            cfgPtr = &FSpiPs_ConfigTable[index];
            break;
        }
    }
    return cfgPtr;
}

typedef unsigned char BOOL;

typedef void (*FSpiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent,
                                      u32 ByteCount);

typedef struct FSpiPs_Tag{
    FSpiPs_Config_T config;         /**< Configuration structure */

    u32 flag;
    BOOL isEnable;
    BOOL isBusy;
    BOOL isMaster;                  /**< Master/Slave */
    u8 frameSize;

    u32 totalBytes;
    u32 remainingBytes;
    u32 requestedBytes;
    u8* sendBufferPtr;	            /**< Buffer to send (state) */
    u8* recvBufferPtr;	            /**< Buffer to receive (state) */

    int (*Transfer)(struct FSpiPs_Tag spi, void* sendBuffer, void* recvBuffer, u32 byteCount);

    FSpiPs_StatusHandler statusHandler;
    void* statusRef;
} FSpiPs_T;

static void StubStatusHandler(void *callBackRef, u32 statusEvent,
                              u32 byteCount)
{
    (void) callBackRef;
    (void) statusEvent;
    (void) byteCount;
}

#define FMSH_SUCCESS          0L
#define FMSH_FAILURE          1L

int FSpiPs_CfgInitialize(FSpiPs_T* spi, FSpiPs_Config_T* configPtr)
{


    spi->config = *configPtr;

    spi->isBusy = FALSE;
    spi->remainingBytes = 0;
    spi->requestedBytes = 0;
    spi->sendBufferPtr = NULL;
    spi->recvBufferPtr = NULL;

    spi->flag = 0;
    spi->isEnable = FALSE;

    spi->isMaster = FALSE;

    spi->totalBytes = 0;


    spi->statusHandler = StubStatusHandler;

    return FMSH_SUCCESS;
}

void FSpiPs_Enable(FSpiPs_T* spi)
{

    FMSH_WriteReg(spi->config.baseAddress, SPIPS_SSIENR_OFFSET, 0x1);
    spi->isEnable = TRUE;
#if 0
u32 temp=0;

//add by fzx
printf("#########FMSH SPI REG IS BELOW\n");
temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_MSTR_OFFSET);
printf("SPIPS_MSTR_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET);
printf("SPIPS_CTRLR0_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR1_OFFSET);
printf("SPIPS_CTRLR1_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_SSIENR_OFFSET);
printf("SPIPS_SSIENR_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_MVCR_OFFSET);
printf("SPIPS_MVCR_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_SER_OFFSET);
printf("SPIPS_SER_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_BAUDR_OFFSET);
printf("SPIPS_BAUDR_OFFSET is 0x%x\n",temp);

temp=FMSH_ReadReg(spi->config.baseAddress, SPIPS_SR_OFFSET);
printf("SPIPS_SR_OFFSET is 0x%x\n",temp);
printf("############################\n");
printf("############################\n");
#endif

}

void FSpiPs_Disable(FSpiPs_T* spi)
{
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_SSIENR_OFFSET, 0x0);
    spi->isEnable = FALSE;
}

void FSpiPs_Mst(FSpiPs_T *spi)
{
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_MSTR_OFFSET, 0x1);
    spi->isMaster = TRUE;
}

#define SPIPS_CTRL0_SCPH_MASK       (0x1 << 6)
#define SPIPS_CTRL0_SCPOL_MASK      (0x1 << 7)
#define SPIPS_CTRL0_TMOD_MASK       (0x3 << 8)
#define SPIPS_CTRL0_SLVOE_MASK      (0x1 << 10)
#define SPIPS_CTRL0_SRL_MASK        (0x1 << 11)
#define SPIPS_CTRL0_DFS32_MASK      (0x1f << 16)

#define SPIPS_CTRL0_SCPH_SHIFT      (6)
#define SPIPS_CTRL0_TMOD_SHIFT      (8)
#define SPIPS_CTRL0_DFS32_SHIFT     (16)

#define SPIPS_TRANSFER_STATE        (0x0)
#define SPIPS_TRANSMIT_ONLY_STATE   (0x1)
#define SPIPS_RECEIVE_ONLY_STATE    (0x2)
#define SPIPS_EEPROM_STATE          (0x3)

int FSpiPs_SetTMod(FSpiPs_T* spi, u32 tmod)
{
    u32 configReg;

    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    if(tmod > 3)
    {
        return FMSH_FAILURE;
    }

    configReg = FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET);
    configReg &= ~SPIPS_CTRL0_TMOD_MASK;
    configReg |= (tmod << SPIPS_CTRL0_TMOD_SHIFT);
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET, configReg);

    return FMSH_SUCCESS;
}

int FSpiPs_SetSckMode(FSpiPs_T* spi, u32 sckMode)
{
    u32 configReg;

    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    if(sckMode > 3)
    {
        return FMSH_FAILURE;
    }
    configReg = FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET);
    configReg &= ~(SPIPS_CTRL0_SCPH_MASK | SPIPS_CTRL0_SCPOL_MASK);
    configReg |= (sckMode << SPIPS_CTRL0_SCPH_SHIFT);
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET, configReg);

    return FMSH_SUCCESS;
}

int FSpiPs_SetSckDv(FSpiPs_T* spi, u32 sckdv)
{
    if(spi->isEnable == TRUE || spi->isMaster == FALSE)
    {
        return FMSH_FAILURE;
    }

    FMSH_WriteReg(spi->config.baseAddress, SPIPS_BAUDR_OFFSET, sckdv);

    return FMSH_SUCCESS;
}

int FSpiPs_SetDFS32(FSpiPs_T* spi, u32 dfs32)
{
    u32 configReg;

    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    if(dfs32<4 || dfs32 > 0x20)
    {
        return FMSH_FAILURE;
    }

    configReg = FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET);
    configReg &= ~SPIPS_CTRL0_DFS32_MASK;
    configReg |= ((dfs32-1) << SPIPS_CTRL0_DFS32_SHIFT);
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET, configReg);

    spi->frameSize = dfs32;

    return FMSH_SUCCESS;
}

int FSpiPs_SetLoopBack(FSpiPs_T* spi, BOOL enable)
{
    u32 configReg;

    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    configReg = FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET);
    if(enable)
    {
        configReg |= SPIPS_CTRL0_SRL_MASK;
    }
    else
    {
        configReg &= ~SPIPS_CTRL0_SRL_MASK;
    }
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET, configReg);

    return FMSH_SUCCESS;
}

int FSpiPs_SetDFNum(FSpiPs_T* spi, u32 dfNum)
{
    if(spi->isEnable == TRUE || spi->isMaster == FALSE)
    {
        return FMSH_FAILURE;
    }
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_CTRLR1_OFFSET, dfNum-1);

    return FMSH_SUCCESS;
}

int FSpiPs_SetTxEmptyLvl(FSpiPs_T* spi, u8 tlvl)
{
    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_TXFTLR_OFFSET, tlvl);

    return FMSH_SUCCESS;
}

int FSpiPs_SetRxFullLvl(FSpiPs_T* spi, u8 tlvl)
{
    if(spi->isEnable == TRUE)
    {
        return FMSH_FAILURE;
    }
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_RXFTLR_OFFSET, tlvl);

    return FMSH_SUCCESS;
}

void FSpiPs_SetDMATLvl(FSpiPs_T* spi, u32 tlvl)
{
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_DMATDLR_OFFSET, tlvl);
}

void FSpiPs_SetDMARLvl(FSpiPs_T* spi, u32 tlvl)
{
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_DMARDLR_OFFSET, tlvl);
}

void FSpiPs_DisableIntr( FSpiPs_T* spi, u32 mask)
{
    u32 configReg;

    configReg = FMSH_ReadReg(spi->config.baseAddress, SPIPS_IMR_OFFSET);
    configReg &= ~mask;
    FMSH_WriteReg(spi->config.baseAddress, SPIPS_IMR_OFFSET, configReg);
}

int FSpiPs_SetSlave(FSpiPs_T* spi, u32 slaveNo)
{
    if(spi->isMaster == FALSE)
    {
        return FMSH_FAILURE;
    }
    if(slaveNo == 0)
    {
        FMSH_WriteReg(spi->config.baseAddress, SPIPS_SER_OFFSET, 0x0);
    }
    else
    {
        FMSH_WriteReg(spi->config.baseAddress, SPIPS_SER_OFFSET, 0x1 << (slaveNo - 1));
    }

    return FMSH_SUCCESS;
}

#define SPIPS_INTR_ALL              (0x3f)

int FSpiPs_Initialize_Master(FSpiPs_T* spi)
{
    int err = 0;

    // Check whether there is another transfer in progress. Not thread-safe
    if(spi->isBusy == TRUE)
    {
        return FMSH_FAILURE;
    }

    // Disable device
    FSpiPs_Disable(spi);
    // Select device as Master
    FSpiPs_Mst(spi);
    // CTRL (TMode, CkMode, BaudRate, DFSize, DFNum, isLoopBack)
    err |= FSpiPs_SetTMod(spi, SPIPS_TRANSFER_STATE);
    err |= FSpiPs_SetSckMode(spi, 3);
    err |= FSpiPs_SetSckDv(spi, 120);
    err |= FSpiPs_SetDFS32(spi, 8);
    err |= FSpiPs_SetLoopBack(spi, FALSE);
    err |= FSpiPs_SetDFNum(spi, 128);

    // Config Tx/Rx Threshold
    err |= FSpiPs_SetTxEmptyLvl(spi, 20);
    err |= FSpiPs_SetRxFullLvl(spi, 12);
    FSpiPs_SetDMATLvl(spi, 12);
    FSpiPs_SetDMARLvl(spi, 20);

    // Config IMR
    FSpiPs_DisableIntr(spi, SPIPS_INTR_ALL);

    // SlaveSelect
    err |= FSpiPs_SetSlave(spi, 1);

    if(err)
    {
        return FMSH_FAILURE;
    }
    // Enable device
    FSpiPs_Enable(spi);

    return FMSH_SUCCESS;
}

#define NREAD	(0x60)
#define NWRITE	(0x61)

#define SIO (0xF0)
#define STS (0xFE)
#define SPG (0xFF)

#define SPIPS_SR_DCOL               (0x40)
#define SPIPS_SR_TXE                (0x20)
#define SPIPS_SR_RFF                (0x10)
#define SPIPS_SR_RFNE               (0x08)
#define SPIPS_SR_TFE                (0x04)
#define SPIPS_SR_TFNF               (0x02)
#define SPIPS_SR_BUSY               (0x01)

void delay_us(u32 time_us)
{
	for(u32 i = 0; i < 100000; i++);
}

void delay_ms(u32 time_ms)
{
	for(u32 i = 0; i < 1000000; i++);
}

void FSpiPs_Send(FSpiPs_T* spi, u32 Data )
{
    u32 count = 0;
    u8 status;

    status = FMSH_ReadReg(spi->config.baseAddress, SPIPS_SR_OFFSET);
    while((status & SPIPS_SR_TFNF) == 0)   /* loop if TX fifo full */
    {
        delay_us(1);
        count++;
        if(count > 10000)
        {
            break;
        }
        status = FMSH_ReadReg(spi->config.baseAddress, SPIPS_SR_OFFSET);
    }

    FMSH_WriteReg(spi->config.baseAddress, SPIPS_DR_OFFSET, Data);
}

u32 FSpiPs_Recv(FSpiPs_T* spi )
{
    u32 count = 0;
    u8 status;

    status = FMSH_ReadReg(spi->config.baseAddress, SPIPS_SR_OFFSET);
    while((status & SPIPS_SR_RFNE) == 0)  /* loop if RX fifo empty */
    {
        delay_us(1);
        count++;
        if(count > 10000)
        {
            break;
        }
        status = FMSH_ReadReg(spi->config.baseAddress, SPIPS_SR_OFFSET);
    }

    return FMSH_ReadReg(spi->config.baseAddress, SPIPS_DR_OFFSET);
}

#define SPIPS_FIFO_DEPTH            (0x20)

int FSpiPs_PolledTransfer(FSpiPs_T* spi, u8* sendBuffer, u8* recvBuffer, u32 byteCount)
{
    u8 tmod;

    // Check whether there is another transfer in progress. Not thread-safe
    if(spi->isBusy == TRUE)
    {
        return FMSH_FAILURE;
    }

    // Get transfer mode
    tmod = (FMSH_ReadReg(spi->config.baseAddress, SPIPS_CTRLR0_OFFSET) & SPIPS_CTRL0_TMOD_MASK)
        >> SPIPS_CTRL0_TMOD_SHIFT;

    if(tmod == SPIPS_TRANSFER_STATE)
    {
        if(sendBuffer == NULL || recvBuffer == NULL)
        {
            return FMSH_FAILURE;
        }
        spi->totalBytes = byteCount;
        spi->remainingBytes = byteCount;
        spi->requestedBytes = byteCount;
        spi->sendBufferPtr = sendBuffer;
        spi->recvBufferPtr = recvBuffer;
    }
    else if(tmod == SPIPS_TRANSMIT_ONLY_STATE)
    {
        if(sendBuffer == NULL)
        {
            return FMSH_FAILURE;
        }
        spi->totalBytes = byteCount;
        spi->requestedBytes = 0;
        spi->remainingBytes = byteCount;
    }
    else if(tmod == SPIPS_RECEIVE_ONLY_STATE)
    {
        if(recvBuffer == NULL)
        {
            return FMSH_FAILURE;
        }
        spi->totalBytes = byteCount;
        spi->requestedBytes = byteCount;
        spi->remainingBytes = 0;
        /* Write one dummy data word to Tx FIFO */
        FSpiPs_Send(spi, 0xff);
    }
    else if(tmod == SPIPS_EEPROM_STATE)
    {
        if(sendBuffer == NULL || recvBuffer == NULL)
        {
            return FMSH_FAILURE;
        }
        spi->totalBytes = byteCount;
        spi->requestedBytes = 0;
        spi->remainingBytes = byteCount;
    }

    // Set the busy flag, cleared when transfer is done
    spi->isBusy = TRUE;

    //disable interrupt
    FSpiPs_DisableIntr(spi, SPIPS_INTR_ALL);

    //enable spi
    FSpiPs_Enable(spi);

    //polling tx fifo level until transfer complete
    int cnt;
    u32 txLvl;
    u32 txEmptyLvl = 10;
    while(spi->remainingBytes !=0 || spi->requestedBytes != 0)
    {
        txLvl = FMSH_ReadReg(spi->config.baseAddress, SPIPS_TXFLR_OFFSET);
        if(txLvl <= txEmptyLvl)
        {
            cnt = FMSH_ReadReg(spi->config.baseAddress, SPIPS_RXFLR_OFFSET);
            while(cnt > 0 && spi->requestedBytes != 0)
            {
                if(spi->frameSize == 8)
                {
                    *(u8*)(spi->recvBufferPtr) = (u8)FSpiPs_Recv(spi);
                }
                else if(spi->frameSize == 16)
                {
                    *(u16*)(spi->recvBufferPtr) = (u16)FSpiPs_Recv(spi);
                }
                else if(spi->frameSize == 32)
                {
                    *(u32*)(spi->recvBufferPtr) = (u32)FSpiPs_Recv(spi);
                }

                spi->recvBufferPtr += spi->frameSize >> 3;
                spi->requestedBytes -= spi->frameSize >> 3;
                cnt--;
            }
            cnt = SPIPS_FIFO_DEPTH - txEmptyLvl;
            while(cnt > 0 && spi->remainingBytes != 0)
            {
                if(spi->frameSize == 8)
                {
                    FSpiPs_Send(spi, *(u8*)spi->sendBufferPtr);
                }
                else if(spi->frameSize == 16)
                {
                    FSpiPs_Send(spi, *(u16*)spi->sendBufferPtr);
                }
                else if(spi->frameSize == 32)
                {
                    FSpiPs_Send(spi, *(u32*)spi->sendBufferPtr);
                }
                spi->sendBufferPtr += spi->frameSize >> 3;
                spi->remainingBytes -= spi->frameSize >> 3;
                cnt--;
            }
        }
    }

    //Clear the busy flag
    spi->isBusy = FALSE;

    //disable spi
    FSpiPs_Disable(spi);

    return FMSH_SUCCESS;
}

#define SPIF	(0x80)
#define RACK	(0x20)
#define RXRDY	(0x02)
#define TXRDY	(0x01

#define TIMEOUT_HANDLER	(retVal= FMSH_FAILURE);


int writeBCM5396( FSpiPs_T *Spi_ptr,u8 page, u8 offset, u8 *pBuffer )
{
	u8 data[20];
	u8 data_recv[20];
        s32 retVal;
	u32 u32SendNum, u32ReqRetNum;


	int i;
	for(i=0;i<20;i++)
		data[i]=i;
	// Set Page
	data[0] = NWRITE;
	data[1] = SPG;
	data[2] = page;
	u32SendNum = 3;
	u32ReqRetNum = 0;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum);//pBuffer
	if( retVal != FMSH_SUCCESS )
	{
		printf("Call XSpiPs_PT_SL 1 Failed\n\r");
	}

	// Read STS
READ_STS_1:
	data[0] = NREAD;
	data[1] = STS;
	u32SendNum = 2;
	u32ReqRetNum = 1;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);

	if( retVal == FMSH_SUCCESS )
	{
		if((data_recv[2] & SPIF)==0)//( workBuf[2] & SPIF )
		{
			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			// Write Data
			data[0] = NWRITE;
			data[1] = offset;
			data[2] = pBuffer[0];
			data[3] = pBuffer[1];
			u32SendNum = 4;
			u32ReqRetNum = 0;//1;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}

		}
		else
		{
			TIMEOUT_HANDLER;
			printf( "Timeout 1 Occured!\n\r" );
			delay_ms(100);

			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}

int readBCM5396(FSpiPs_T *Spi_ptr, u8 page, u8 offset, u8 *pBuffer )
{
//	_BCM_CMD_ bcmCmd;
	u8 data[8];//u8Idx;
        u8 data_recv[8] = {0};
	s32 retVal;
	u32 u32SendNum, u32ReqRetNum;


	// Set Page
	data[0] = NWRITE;
	data[1] = SPG;
	data[2] = page;

	u32SendNum = 3;
	u32ReqRetNum = 0;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum);
	if( retVal != FMSH_SUCCESS )
	{
		printf("Call XSpiPs_PT_SL 1 Failed\n\r");
	}
        delay_ms(10);
	// Read STS
READ_STS_1:

        data[0] = NREAD;
	data[1] = STS;
	u32SendNum = 2;
	u32ReqRetNum = 1;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
         delay_ms(10);

	if( retVal == FMSH_SUCCESS )
	{
		if( (data_recv[2] & SPIF)==0)
		{
			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			// Set Offset in Page, "Null" operation :)
			data[0] = NREAD;
			data[1] = offset;
			u32SendNum = 2;
			u32ReqRetNum = 1;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}


			// Read STS
READ_STS_2:
                        data[0] = NREAD;
                        data[1] = STS;
			u32SendNum = 2;
			u32ReqRetNum = 1;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal == FMSH_SUCCESS )
			{
				if( data_recv[2] & RACK )
				{
					/*
					bcmCmd.cmd = NREAD;
					bcmCmd.regAdrs = SIO;
					*/
					data[0] = NREAD;
				        data[1] = SIO;
					u32SendNum = 2;
					u32ReqRetNum = 4;
					retVal = FSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
				}
				else
				{
					TIMEOUT_HANDLER;
					printf( "Timeout 2 Occured!\n\r" );
					delay_ms(10);
					// Set Page
					data[0] = NWRITE;
					data[1] = SPG;
					data[2] = page;
					u32SendNum = 3;
					u32ReqRetNum = 0;
					retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
					if( retVal != FMSH_SUCCESS )
					{
						printf("Call XSpiPs_PT_SL 1 Failed\n\r");
					}

					goto READ_STS_2;
				}

			}
			else
				printf("Call XSpiPs_PT_SL 3 Failed\n\r");
		}
		else
		{
			TIMEOUT_HANDLER;
			printf( "Timeout 1 Occured!\n\r" );
			delay_ms(100);

			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}

int writeBCM5396_2( FSpiPs_T *Spi_ptr,u8 page, u8 offset, u8 *pBuffer )
{
	u8 data[20];
	u8 data_recv[20];
        s32 retVal;
	u32 u32SendNum, u32ReqRetNum;
        
        
	int i;
	for(i=0;i<20;i++)
		data[i]=i;
	// Set Page
	data[0] = NWRITE;
	data[1] = SPG;
	data[2] = page;
	u32SendNum = 3;
	u32ReqRetNum = 0;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum);//pBuffer
	if( retVal != FMSH_SUCCESS )
	{
		printf("Call XSpiPs_PT_SL 1 Failed\n\r");
	}

	// Read STS
READ_STS_1:
	data[0] = NREAD;
	data[1] = STS;
	u32SendNum = 2;
	u32ReqRetNum = 1;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
	//
	if( retVal == FMSH_SUCCESS ) 
	{
		if((data_recv[2] & SPIF)==0)//( workBuf[2] & SPIF )
		{
			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			// Write Data
			data[0] = NWRITE;
			data[1] = offset;
			data[2] = pBuffer[0];  
			u32SendNum = 3;
			u32ReqRetNum = 0;//1;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}

		}
		else
		{
			TIMEOUT_HANDLER;
			printf( "Timeout 1 Occured!\n\r" );
			delay_ms(50);

			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}

int writeBCM5396_4( FSpiPs_T *Spi_ptr,u8 page, u8 offset, u8 *pBuffer )
{
	u8 data[20];
	u8 data_recv[20];
        s32 retVal;
	u32 u32SendNum, u32ReqRetNum;
        
        
	int i;
	for(i=0;i<20;i++)
		data[i]=i;
	// Set Page
	data[0] = NWRITE;
	data[1] = SPG;
	data[2] = page;
	u32SendNum = 3;
	u32ReqRetNum = 0;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum);//pBuffer
	if( retVal != FMSH_SUCCESS )
	{
		printf("Call XSpiPs_PT_SL 1 Failed\n\r");
	}

	// Read STS
READ_STS_1:
	data[0] = NREAD;
	data[1] = STS;
	u32SendNum = 2;
	u32ReqRetNum = 1;
	retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
	//
	if( retVal == FMSH_SUCCESS ) 
	{
		if((data_recv[2] & SPIF)==0)//( workBuf[2] & SPIF )
		{
			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			// Write Data
			data[0] = NWRITE;
			data[1] = offset;
			data[2] = pBuffer[0];  
			u32SendNum = 6;
			u32ReqRetNum = 0;//1;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}

		}
		else
		{
			TIMEOUT_HANDLER;
			printf( "Timeout 1 Occured!\n\r" );
			delay_ms(50);

			// Set Page
			data[0] = NWRITE;
			data[1] = SPG;
			data[2] = page;
			u32SendNum = 3;
			u32ReqRetNum = 0;
			retVal = FSpiPs_PolledTransfer(Spi_ptr,data,data_recv,u32SendNum+u32ReqRetNum);
			if( retVal != FMSH_SUCCESS )
			{
				printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}

FSpiPs_T spi;
FSpiPs_T Spi[2];

int port_vlan_set(unsigned int port, unsigned int mask)
{
      u8 workBuf[10];
      int Status        = 0;
      int offset        = 0;
      
      offset = port*4;
     // printf("--------Set Port Vlan:port:%d-offset:%0x-mask:%0x---------\n\r", port, mask);
      
      workBuf[0] = (mask&0x000000ff);
      workBuf[1] = (mask&0x0000ff00)>>8;
      workBuf[2] = (mask&0x00010000)>>16;
      
      Status = writeBCM5396_4(&spi, 0x31, offset, workBuf); 
      
      return Status;
}
/***************************************BOARD SW1706 JEM5396 REG READ/WRITE*****************************/

void testwrite5396(int port, unsigned int offset ,unsigned int value)
{

	u8 workBuf[10];
	workBuf[0]=value & 0xff;
	workBuf[1]=(value>>8) & 0xff;
	writeBCM5396(&spi, port, offset, workBuf);
	udelay(1000);
        readBCM5396(&spi, port, offset, workBuf );
	printf("port=%d,offset=%xh,data=0x%x\n\r",port,offset,workBuf[2]);
	printf("port=%d,offset=%xh,data=0x%x\n\r",port,offset,workBuf[3]);
}
void testread5396()
{

	u8 workBuf[10];
       	readBCM5396(&spi, 2, 0x30, workBuf);
	printf("5396 Mode_ID=0x%x\n\r", workBuf[2]);
}

int ckoff_spi_5396()
{

	int ret = 0;
	int Status = 0;
	u8 workBuf[10];
	int i=0;

	/*init spi and read bcm5396 device id*/

	FSpiPs_Config_T *spi_cfgptr;

	spi_cfgptr = FSpiPs_LookupConfig(0);

	ret = FSpiPs_CfgInitialize(&spi, spi_cfgptr);

	if(ret == FMSH_SUCCESS)
	{
		printf("5396 Spi Init Success!\n\r");
	}	
	else
	{
	    printf("5396 Spi Init Failed!\n\r");
	    return -1;
	}

	/*Init master*/
	ret = FSpiPs_Initialize_Master(&spi);
	if(ret == FMSH_SUCCESS)
	{
		printf("spi Init Master Success!\n\r");
	}
	else
	{
		printf("spi Init Master Failed!\n\r");
		return -1;
	}	
	
	workBuf[0]=0xf1;
	workBuf[1]=0x28;
	workBuf[2]=0;


	for(i=0x10;i<=0x1f;i++)
	{
		Status = writeBCM5396(&spi, i, 0x12, workBuf );
	}


	workBuf[0]=0xf0;
	workBuf[1]=0x28;
	workBuf[2]=0;


	for(i=0x10;i<=0x1f;i++)
	{
		Status = writeBCM5396(&spi, i, 0x12, workBuf );
	}


	printf("JEM5396 CHECK OFF DONW\n");


	return 0;
}

/***************************************BOARD SW1706 JEM5396 REG READ/WRITE*****************************/
int init_spi_5396()
{

	int ret = 0;
	int Status = 0;
	u8 workBuf[10];
	int i=0;

	/*init spi and read bcm5396 device id*/
#if 0
	FSpiPs_Config_T *spi_cfgptr;

	spi_cfgptr = FSpiPs_LookupConfig(0);

	ret = FSpiPs_CfgInitialize(&spi, spi_cfgptr);

	if(ret == FMSH_SUCCESS)
	{
		printf("5396 Spi Init Success!\n\r");
	}	
	else
	{
	    printf("5396 Spi Init Failed!\n\r");
	    return -1;
	}

	/*Init master*/
	ret = FSpiPs_Initialize_Master(&spi);
	if(ret == FMSH_SUCCESS)
	{
		printf("spi Init Master Success!\n\r");
	}
	else
	{
		printf("spi Init Master Failed!\n\r");
		return -1;
	}	
#endif
	Status=readBCM5396(&spi, 2, 0x30, workBuf);
	printf("5396 Mode_ID=0x%x\n\r", workBuf[2]);

	Status=readBCM5396(&spi, 2, 0x40, workBuf);
	printf("5396 Reversion_ID=0x%x\n\r", workBuf[2]);

/***************************************JEM5396 CONFIG*****************************/
	

	/**PORT N STATE OVERRIDE REGISTER [0:15] (PAGE 00H: ADDRESS 60H–6FH) **/
	/**强制千兆全双工模式**/
	for(i=0x60;i<=0x6f;i++)
	{
		workBuf[0] = 0x8b;
		workBuf[1] = 0x0;
		if(i==0x65)
		{
			continue;
		}
		writeBCM5396_2(&spi, 0, i, workBuf);
	}


	workBuf[0]=0xf0;
	workBuf[1]=0x1;
	workBuf[2]=0;


	for(i=0x10;i<=0x1f;i++)
	{

		if(i==0x15)
		{
			continue;
		}

		Status = writeBCM5396(&spi, i, 0x20, workBuf );
	}

	workBuf[0]=0x40;
	workBuf[1]=0x13;
	workBuf[2]=0;


	for(i=0x10;i<=0x1f;i++)
	{

		if(i==0x15)
		{
			continue;
		}
		Status = writeBCM5396(&spi, i, 0x0, workBuf );
	}


	printf("Set Port 5 CONNECT TO ZYNQ SPEED FIXED 1000M\n");

	workBuf[0] = 0x8b;
	workBuf[1] = 0x0;
	writeBCM5396_2(&spi, 0, 0x65, workBuf);  


	workBuf[0] = 0x40;
	workBuf[1] = 0x1;  
	Status = writeBCM5396(&spi, 0x15, 0x0, workBuf );  

	printf("*****************Read SPI Reg of 5396******************\r\n");
	printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n");
	for(i=0x10;i<=0x1f;i++)
	{
		  Status = readBCM5396(&spi, i, 0x28, workBuf );
		  printf("port=%d,offset=0x28,data=0x%x\n",(i-0x10),workBuf[2]);
		  printf("port=%d,offset=0x29,data=0x%x\n",(i-0x10),workBuf[3]);
    	}

	printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n\r");
	for(i=0x10;i<=0x1f;i++)
	{
		  Status = readBCM5396(&spi, i, 0x20, workBuf );
		  printf("port=%d,offset=0x20,data=0x%x\n\r",(i-0x10),workBuf[2]);
		  printf("port=%d,offset=0x21,data=0x%x\n\r",(i-0x10),workBuf[3]);
    	}


#if 0
	workBuf[0]=0x00;
	workBuf[1]=0x00;
	workBuf[2]=0x00;
	Status =writeBCM5396(&spi, 0x31, 0x00, workBuf);//Port 0
	Status =writeBCM5396(&spi, 0x31, 0x04, workBuf);//Port 1
	Status =writeBCM5396(&spi, 0x31, 0x08, workBuf);//Port 2
	Status =writeBCM5396(&spi, 0x31, 0x0c, workBuf);//Port 3
	Status =writeBCM5396(&spi, 0x31, 0x10, workBuf);//Port 4
	Status =writeBCM5396(&spi, 0x31, 0x14, workBuf);//Port 5
	Status =writeBCM5396(&spi, 0x31, 0x18, workBuf);//Port 6
	Status =writeBCM5396(&spi, 0x31, 0x1c, workBuf);//Port 7
	Status =writeBCM5396(&spi, 0x31, 0x20, workBuf);//Port 8
	Status =writeBCM5396(&spi, 0x31, 0x24, workBuf);//Port 9
	Status =writeBCM5396(&spi, 0x31, 0x28, workBuf);//Port 10
	Status =writeBCM5396(&spi, 0x31, 0x2c, workBuf);//Port 11
	Status =writeBCM5396(&spi, 0x31, 0x30, workBuf);//Port 12
	Status =writeBCM5396(&spi, 0x31, 0x34, workBuf);//Port 13
	Status =writeBCM5396(&spi, 0x31, 0x38, workBuf);//Port 14
	Status =writeBCM5396(&spi, 0x31, 0x3c, workBuf);//Port 15
	Status =writeBCM5396(&spi, 0x31, 0x40, workBuf);//Port 15
	printf("5396 ALL Port Disconnect\n\r");
#endif
	return 0;
}


void FSlcrPs_setBitTo1(u32 baseAddr, u32 offSet,u32 bit_num)
{
    u32 value = 0;
    //First get the current value of the register
    value = FMSH_ReadReg(baseAddr, offSet);
    //Then write the given bit of data as 1
    value |= (1 << bit_num);
    //Finally, write the modified data to the register
    FMSH_WriteReg(baseAddr, offSet, value);
}
void FSlcrPs_setBitTo0(u32 baseAddr, u32 offSet,u32 bit_num)
{
    u32 value = 0;
    //First get the current value of the register
    value = FMSH_ReadReg(baseAddr, offSet);
    //Then write the given bit of data as 0
    value &= ~(1 << bit_num);
    //Finally, write the modified data to the register
    FMSH_WriteReg(baseAddr, offSet, value);
}

void FSlcrPs_unlock(void)
{
    FMSH_WriteReg(FPS_SLCR_BASEADDR,SLCR_UNLOCK,0xDF0D767B);   //SLCR UNLOCK
}
void FSlcrPs_lock(void)
{
    FMSH_WriteReg(FPS_SLCR_BASEADDR,SLCR_LOCK,0xDF0D767B);   //SLCR LOCK
}
void FSlcrPs_ipSetRst(u32 rst_id, u32 rst_mode)
{
    FSlcrPs_unlock();
    FSlcrPs_setBitTo1(FPS_SLCR_BASEADDR,rst_id,rst_mode);
    FSlcrPs_lock();
}
void FSlcrPs_ipReleaseRst(u32 rst_id, u32 rst_mode)
{
    FSlcrPs_unlock();
    FSlcrPs_setBitTo0(FPS_SLCR_BASEADDR,rst_id,rst_mode);
    FSlcrPs_lock();
}
void FSpiPs_Reset(FSpiPs_T* spi)
{
    if(spi->config.deviceId == FPS_SPI0_DEVICE_ID)
    {
        FSlcrPs_ipSetRst(SLCR_SPI0_CTRL, SPI0_APB_RST);
        FSlcrPs_ipSetRst(SLCR_SPI0_CTRL, SPI0_REF_RST);
        FSlcrPs_ipReleaseRst(SLCR_SPI0_CTRL, SPI0_APB_RST);
        FSlcrPs_ipReleaseRst(SLCR_SPI0_CTRL, SPI0_REF_RST);
    }
    else if(spi->config.deviceId == FPS_SPI1_DEVICE_ID)
    {
        FSlcrPs_ipSetRst(SLCR_SPI1_CTRL, SPI1_APB_RST);
        FSlcrPs_ipSetRst(SLCR_SPI1_CTRL, SPI1_REF_RST);
        FSlcrPs_ipReleaseRst(SLCR_SPI1_CTRL, SPI1_APB_RST);
        FSlcrPs_ipReleaseRst(SLCR_SPI1_CTRL, SPI1_REF_RST);
    }
}

配置完成后,网络就能ping通了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/170563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5的TimeLine的理解

一直以来&#xff0c;我对动画的理解一直是这样的&#xff1a; 所谓动画&#xff0c;就是可导致可视化内容变化的参数和时间的对应关系。 我不能说这个观点现在过时了&#xff0c;只能说自己狭隘了。因为UE的TimeLine的设计理念真让人竖大拇指。 当我第一次看到TimeLine节点的…

光谱图像超分辨率综述

光谱图像超分辨率综述 简介 ​ 论文链接&#xff1a;A Review of Hyperspectral Image Super-Resolution Based on Deep Learning UpSample网络框架 1.Front-end Upsampling ​ 在Front-end上采样中&#xff0c;是首先扩大LR图像&#xff0c;然后通过卷积网络对放大图像进行…

wsl-ubuntu 系统端口总被主机端口占用问题解决

wsl-ubuntu 系统端口总被主机端口占用问题解决 0. 问题描述1. 解决方法 0. 问题描述 wsl-ubuntu 子系统中的服务&#xff0c;总是启动失败&#xff0c;错误信息是端口被占用。 用一些命令查看&#xff0c;被占用的端口也没有用服务启动。 1. 解决方法 关闭进程中的 “虚拟机…

【Docker】从零开始:2.Docker三要素

【Docker】从零开始&#xff1a;2.Docker三要素 DockerDocker支持的系统CentOS DockerDocker三要素Docker镜像(Image):Docker容器(Container):1.从面向对象角度2.从镜像容器角度 Docker仓库(Repository) 总结 Docker docker官网&#xff1a;http://www.docker.com 仓库-Docker…

模具制造厂ERP都有哪些牌子?模具制造厂ERP有什么用

模具制造通常会涉及物料领用、成品入库、工艺流转、投入水口、配方、模具、生产啤数统计等众多环节&#xff0c;各个环节数据的实时和准确传递&#xff0c;有利于企业清晰掌握订单生产进度&#xff0c;及时调整制造策略等。 有些模具制造工厂采用传统的管理模式&#xff0c;随…

智慧工地网络广播系统

智慧工地网络广播系统 智慧工地网络广播&#xff0c;是智慧公司不可缺少的一环&#xff0c;对于工地广播来说&#xff0c;音质和传输稳定性都是非常重要的要素。尤其是在高楼大厦密集的地方&#xff0c;可能会存在信号干扰和传输受阻的情况&#xff0c;这时候可以考虑使用网络…

【CVE-2023-4357】Chrome-XXE 任意文件读取漏洞复现及原理解析

官方文档 https://bugs.chromium.org/p/chromium/issues/detail?id1458911 漏洞描述 Short description: Libxslt is the default XSL library used in WebKit based browsers such as chrome, safari etc. Libxslt allows external entities inside documents that are lo…

【Mycat2实战】四、Mycat实现分库分表【概念篇】

1. 什么是分库分表 首先&#xff0c;我们需要知道**所谓"分库分表"&#xff0c;根本就不是一件事儿&#xff0c;而是三件事儿&#xff0c;**他们要解决的问题也都不一样。 这三个事儿分别是"只分库不分表"、“只分表不分库”、以及"既分库又分表&qu…

关于WhatsApp群发营销价值、类型、优劣势……这里一次性讲清楚

01 社交销售互动&#xff1a;全球营销新趋势 当下&#xff0c;全球品牌的营销销售互动都步入了社交销售新时代&#xff0c;相比原来任何一种形式的互动沟通来说&#xff0c;其沟通效率、体验、效果都是无与伦比的。 企业与销售的互动&#xff0c;与通讯信息技术发展息息相关。…

PHP/Lerv通过经纬度计算距离获取附近商家

实际开发中,常常需要获取用户附近的商家,思路是 获取用户位置(经纬度信息)在数据库中查询在距离范围内的商家 注: 本文章内计算距离所使用地球半径统一为 6378.138 km public function mpa_list($latitude,$longitude,$distance){// $latitude 34.306465;// $longitude 10…

基于SpringBoot+Mybatis plus+React.js实现条件选择切换搜索功能

笔记/朱季谦 在写React前端逻辑时&#xff0c;经常遇到可以切换不同条件的列表查询功能&#xff0c;例如下边截图这样的&#xff0c;其实&#xff0c;这块代码基本都一个逻辑&#xff0c;可以一次性将实现过程记录下来&#xff0c;待以后再遇到时&#xff0c;直接根据笔记复用…

阿里云4核8G服务器优惠价格表,最低价格501.90元6个月、983.80元1年

阿里云4核8G服务器优惠价格表&#xff0c;云服务器ECS计算型c7实例4核8G配置3M带宽40GB ESSD云盘&#xff08;系统盘&#xff09;叠加使用优惠券后价格501.90元6个月、983.80元1年&#xff0c;现在购买经济型e、通用算力型u1、计算型c7和计算型c8a与c8i实例4核8G配置均有优惠&a…

怎么查看虚拟机的网关

1、点击编辑&#xff0c;再选择虚拟网络编辑器 2、选择VMnet8&#xff0c;点击NAT设置 3、查看网关IP

互联网行业以前是以前,现在是现在

目前互联网行业呈现出多个趋势与现状&#xff1a; 移动互联网普及&#xff1a;随着智能手机的普及&#xff0c;移动互联网已经成为主流&#xff0c;各种APP带来更加方便的服务&#xff0c;这也意味着PC端的互联网服务逐渐被取代。 数字化转型&#xff1a;各个行业都在进行数…

腾讯云轻量数据库试用初体验

腾讯云轻量数据库1核1G开箱测评&#xff0c;轻量数据库服务采用腾讯云自研的新一代云原生数据库TDSQL-C&#xff0c;轻量数据库兼100%兼容MySQL数据库&#xff0c;实现超百万级 QPS 的高吞吐&#xff0c;128TB海量分布式智能存储&#xff0c;虽然轻量数据库为单节点架构&#x…

【Go语言实战】(26) 分布式搜索引擎

Tangseng 基于Go语言的搜索引擎 github地址&#xff1a;https://github.com/CocaineCong/tangseng 详细介绍地址&#xff1a;https://cocainecong.github.io/tangseng 这两周我也抽空录成视频发到B站的&#xff5e; 本来应该10月份就要发了&#xff0c;结果一鸽就鸽到现在hh…

安全知识普及:了解端点检测与响应 (EDR)对企业的重要性

文章目录 EDR 的含义和定义EDR 是如何运作的&#xff1f;收集端点数据将数据发送到 EDR 平台分析数据标记可疑活动并做出响应保留数据以供日后使用 为什么 EDR 对企业至关重要大多数企业都有可能遭受各种网络攻击。有些攻击可以完全绕开企业的防御远程办公让员工缺乏足够的保护…

EOCR电机保护器的日常维护与保养技巧

EOCR是由施耐德韩国公司生产的电动机保护系列产品&#xff0c;由电子器件和互感器等部件组成&#xff0c;在正常状态下使用都有各自的机械寿命和电气寿命,若操作不当或异常条件下会加速电器元件的老化&#xff0c;缩短保护器的使用寿命&#xff0c;所以电机保护器的正确使用和正…

如何安装运行Wagtail,并结合cpolar内网穿透实现公网访问网站界面

Wagtail-基于Python Django的内容管理系统CMS实现公网访问 文章目录 Wagtail-基于Python Django的内容管理系统CMS实现公网访问前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个…