Commit 0a497ec0 authored by li hongming's avatar li hongming

Add another WR port. Change many variables to lists.

parent 9fb9a6bd
......@@ -11,8 +11,8 @@
#include <libsdbfs.h>
/* The following pointers are exported */
unsigned char *BASE_MINIC;
unsigned char *BASE_EP;
unsigned char *BASE_MINIC[wr_num_ports];
unsigned char *BASE_EP[wr_num_ports];
unsigned char *BASE_SOFTPLL;
unsigned char *BASE_PPS_GEN;
unsigned char *BASE_SYSCON;
......@@ -65,8 +65,10 @@ struct wrc_device {
};
struct wrc_device devs[] = {
{&BASE_MINIC, VID_CERN, 0xab28633a},
{&BASE_EP, VID_CERN, 0x650c2d4f},
{&BASE_MINIC[0], VID_CERN, 0xab28633a},
{&BASE_MINIC[1], VID_CERN, 0xa224633b},
{&BASE_EP[0], VID_CERN, 0x650c2d4f},
{&BASE_EP[1], VID_CERN, 0x621c2d4e},
{&BASE_SOFTPLL, VID_CERN, 0x65158dc0},
{&BASE_PPS_GEN, VID_CERN, 0xde0d8ced},
{&BASE_SYSCON, VID_CERN, 0xff07fc47},
......
......@@ -59,7 +59,7 @@
#define SFP_DB_EMPTY 0xff
static uint8_t sfpcount = SFP_DB_EMPTY;
static uint8_t sfpcount[2] = {SFP_DB_EMPTY,SFP_DB_EMPTY};
uint8_t has_eeprom = 0;
......
......@@ -27,115 +27,115 @@
#define DMTD_AVG_SAMPLES 256
static int autoneg_enabled;
volatile struct EP_WB *EP;
volatile struct EP_WB *EP[wr_num_ports];
/* functions for accessing PCS (MDIO) registers */
static uint16_t pcs_read(int location)
static uint16_t pcs_read(int location, int port)
{
EP->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2);
while ((EP->MDIO_ASR & EP_MDIO_ASR_READY) == 0) ;
return EP_MDIO_ASR_RDATA_R(EP->MDIO_ASR) & 0xffff;
EP[port]->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2);
while ((EP[port]->MDIO_ASR & EP_MDIO_ASR_READY) == 0) ;
return EP_MDIO_ASR_RDATA_R(EP[port]->MDIO_ASR) & 0xffff;
}
static void pcs_write(int location, int value)
static void pcs_write(int location, int value, int port)
{
EP->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2)
EP[port]->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2)
| EP_MDIO_CR_DATA_W(value)
| EP_MDIO_CR_RW;
while ((EP->MDIO_ASR & EP_MDIO_ASR_READY) == 0) ;
while ((EP[port]->MDIO_ASR & EP_MDIO_ASR_READY) == 0) ;
}
/* MAC address setting */
void set_mac_addr(uint8_t dev_addr[])
void set_mac_addr(uint8_t dev_addr[], int port)
{
EP->MACL = ((uint32_t) dev_addr[2] << 24)
EP[port]->MACL = ((uint32_t) dev_addr[2] << 24)
| ((uint32_t) dev_addr[3] << 16)
| ((uint32_t) dev_addr[4] << 8)
| ((uint32_t) dev_addr[5]);
EP->MACH = ((uint32_t) dev_addr[0] << 8)
EP[port]->MACH = ((uint32_t) dev_addr[0] << 8)
| ((uint32_t) dev_addr[1]);
}
void get_mac_addr(uint8_t dev_addr[])
void get_mac_addr(uint8_t dev_addr[], int port)
{
dev_addr[5] = (EP->MACL & 0x000000ff);
dev_addr[4] = (EP->MACL & 0x0000ff00) >> 8;
dev_addr[3] = (EP->MACL & 0x00ff0000) >> 16;
dev_addr[2] = (EP->MACL & 0xff000000) >> 24;
dev_addr[1] = (EP->MACH & 0x000000ff);
dev_addr[0] = (EP->MACH & 0x0000ff00) >> 8;
dev_addr[5] = (EP[port]->MACL & 0x000000ff);
dev_addr[4] = (EP[port]->MACL & 0x0000ff00) >> 8;
dev_addr[3] = (EP[port]->MACL & 0x00ff0000) >> 16;
dev_addr[2] = (EP[port]->MACL & 0xff000000) >> 24;
dev_addr[1] = (EP[port]->MACH & 0x000000ff);
dev_addr[0] = (EP[port]->MACH & 0x0000ff00) >> 8;
}
/* Initializes the endpoint and sets its local MAC address */
void ep_init(uint8_t mac_addr[])
void ep_init(uint8_t mac_addr[], int port)
{
EP = (volatile struct EP_WB *)BASE_EP;
set_mac_addr(mac_addr);
ep_sfp_enable(1);
EP[port] = (volatile struct EP_WB *)BASE_EP[port];
set_mac_addr(mac_addr,port);
ep_sfp_enable(1,port);
if (!IS_WR_NODE_SIM){
*(unsigned int *)(0x62000) = 0x2; // reset network stuff (cleanup required!)
*(unsigned int *)(0x62000) = 0;
}
EP->ECR = 0; /* disable Endpoint */
EP->VCR0 = EP_VCR0_QMODE_W(3); /* disable VLAN unit - not used by WRPC */
EP->RFCR = EP_RFCR_MRU_W(1518); /* Set the max RX packet size */
EP->TSCR = EP_TSCR_EN_TXTS | EP_TSCR_EN_RXTS; /* Enable timestamping */
EP[port]->ECR = 0; /* disable Endpoint */
EP[port]->VCR0 = EP_VCR0_QMODE_W(3); /* disable VLAN unit - not used by WRPC */
EP[port]->RFCR = EP_RFCR_MRU_W(1518); /* Set the max RX packet size */
EP[port]->TSCR = EP_TSCR_EN_TXTS | EP_TSCR_EN_RXTS; /* Enable timestamping */
/* Configure DMTD phase tracking */
EP->DMCR = EP_DMCR_EN | EP_DMCR_N_AVG_W(DMTD_AVG_SAMPLES);
EP[port]->DMCR = EP_DMCR_EN | EP_DMCR_N_AVG_W(DMTD_AVG_SAMPLES);
}
/* Enables/disables transmission and reception. When autoneg is set to 1,
starts up 802.3 autonegotiation process */
int ep_enable(int enabled, int autoneg)
int ep_enable(int enabled, int autoneg, int port)
{
uint16_t mcr;
if (!enabled) {
EP->ECR = 0;
EP[port]->ECR = 0;
return 0;
}
/* Disable the endpoint */
EP->ECR = 0;
EP[port]->ECR = 0;
if (!IS_WR_NODE_SIM)
pp_printf("ID: %x\n", EP->IDCODE);
pp_printf("ID: %x\n", EP[port]->IDCODE);
/* Load default packet classifier rules - see ep_pfilter.c for details */
pfilter_init_default();
pfilter_init_default(port);
/* Enable TX/RX paths, reset RMON counters */
EP->ECR = EP_ECR_TX_EN | EP_ECR_RX_EN | EP_ECR_RST_CNT;
EP[port]->ECR = EP_ECR_TX_EN | EP_ECR_RX_EN | EP_ECR_RST_CNT;
autoneg_enabled = autoneg;
/* Reset the GTP Transceiver - it's important to do the GTP phase alignment every time
we start up the software, otherwise the calibration RX/TX deltas may not be correct */
pcs_write(MDIO_REG_MCR, MDIO_MCR_PDOWN); /* reset the PHY */
pcs_write(MDIO_REG_MCR, MDIO_MCR_PDOWN,port); /* reset the PHY */
if (!IS_WR_NODE_SIM)
timer_delay_ms(200);
pcs_write(MDIO_REG_MCR, MDIO_MCR_RESET); /* reset the PHY */
pcs_write(MDIO_REG_MCR, 0); /* reset the PHY */
pcs_write(MDIO_REG_MCR, MDIO_MCR_RESET,port); /* reset the PHY */
pcs_write(MDIO_REG_MCR, 0,port); /* reset the PHY */
/* Don't advertise anything - we don't want flow control */
pcs_write(MDIO_REG_ADVERTISE, 0);
pcs_write(MDIO_REG_ADVERTISE, 0,port);
mcr = MDIO_MCR_SPEED1000_MASK | MDIO_MCR_FULLDPLX_MASK;
if (autoneg)
mcr |= MDIO_MCR_ANENABLE | MDIO_MCR_ANRESTART;
pcs_write(MDIO_REG_MCR, mcr);
pcs_write(MDIO_REG_MCR, mcr,port);
return 0;
}
/* Checks the link status. If the link is up, returns non-zero
and stores the Link Partner Ability (LPA) autonegotiation register at *lpa */
int ep_link_up(uint16_t * lpa)
int ep_link_up(uint16_t * lpa,int port)
{
uint16_t flags = MDIO_MSR_LSTATUS;
volatile uint16_t msr;
......@@ -143,70 +143,70 @@ int ep_link_up(uint16_t * lpa)
if (autoneg_enabled)
flags |= MDIO_MSR_ANEGCOMPLETE;
msr = pcs_read(MDIO_REG_MSR);
msr = pcs_read(MDIO_REG_MSR); /* Read this flag twice to make sure the status is updated */
msr = pcs_read(MDIO_REG_MSR,port);
msr = pcs_read(MDIO_REG_MSR,port); /* Read this flag twice to make sure the status is updated */
if (lpa)
*lpa = pcs_read(MDIO_REG_LPA);
*lpa = pcs_read(MDIO_REG_LPA,port);
return (msr & flags) == flags ? 1 : 0;
}
int ep_get_bitslide()
int ep_get_bitslide(int port)
{
return PICOS_PER_SERIAL_BIT *
MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC));
MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC,port));
}
/* Returns the TX/RX latencies. They are valid only when the link is up. */
int ep_get_deltas(uint32_t * delta_tx, uint32_t * delta_rx)
int ep_get_deltas(uint32_t * delta_tx, uint32_t * delta_rx, int port)
{
/* fixme: these values should be stored in calibration block in the EEPROM on the FMC. Also, the TX/RX delays of a particular SFP
should be added here */
*delta_tx = sfp_deltaTx;
*delta_tx = sfp_deltaTx[port];
*delta_rx =
sfp_deltaRx +
sfp_deltaRx[port] +
PICOS_PER_SERIAL_BIT *
MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC));
MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC,port));
return 0;
}
int ep_cal_pattern_enable()
int ep_cal_pattern_enable(int port)
{
uint32_t val;
val = pcs_read(MDIO_REG_WR_SPEC);
val = pcs_read(MDIO_REG_WR_SPEC,port);
val |= MDIO_WR_SPEC_TX_CAL;
pcs_write(MDIO_REG_WR_SPEC, val);
pcs_write(MDIO_REG_WR_SPEC, val,port);
return 0;
}
int ep_cal_pattern_disable()
int ep_cal_pattern_disable(int port)
{
uint32_t val;
val = pcs_read(MDIO_REG_WR_SPEC);
val = pcs_read(MDIO_REG_WR_SPEC,port);
val &= (~MDIO_WR_SPEC_TX_CAL);
pcs_write(MDIO_REG_WR_SPEC, val);
pcs_write(MDIO_REG_WR_SPEC, val,port);
return 0;
}
int ep_timestamper_cal_pulse()
int ep_timestamper_cal_pulse(int port)
{
EP->TSCR |= EP_TSCR_RX_CAL_START;
EP[port]->TSCR |= EP_TSCR_RX_CAL_START;
timer_delay_ms(1);
return EP->TSCR & EP_TSCR_RX_CAL_RESULT ? 1 : 0;
return EP[port]->TSCR & EP_TSCR_RX_CAL_RESULT ? 1 : 0;
}
int ep_sfp_enable(int ena)
int ep_sfp_enable(int ena, int port)
{
uint32_t val;
val = pcs_read(MDIO_REG_ECTRL);
val = pcs_read(MDIO_REG_ECTRL,port);
if(ena)
val &= (~MDIO_ECTRL_SFP_TX_DISABLE);
else
val |= MDIO_ECTRL_SFP_TX_DISABLE;
pcs_write(MDIO_REG_ECTRL, val);
pcs_write(MDIO_REG_ECTRL, val,port);
return 0;
}
......@@ -39,7 +39,7 @@ struct rule_set {
};
extern volatile struct EP_WB *EP;
extern volatile struct EP_WB *EP[wr_num_ports];
static uint32_t swap32(uint32_t v)
{
......@@ -52,7 +52,7 @@ static uint32_t swap32(uint32_t v)
return res;
}
void pfilter_init_default(void)
void pfilter_init_default(int port)
{
struct rule_set *s;
uint8_t mac[6];
......@@ -60,7 +60,7 @@ void pfilter_init_default(void)
uint32_t m, *vini, *vend, *v, *v_vlan = NULL;
uint64_t cmd_word;
int i;
static int inited;
static int inited[2];
uint32_t latency_ethtype = CONFIG_LATENCY_ETHTYPE;
/* If vlan, use rule-set 1, else rule-set 0 */
......@@ -92,20 +92,20 @@ void pfilter_init_default(void)
* First time: be extra-careful that the rule-set is ok. But if
* we change MAC address, this is re-called, and v[] is already changed
*/
if (!inited) {
if (!inited[port]) {
if ( (((v[2] >> 13) & 0xffff) != 0x1234)
|| (((v[4] >> 13) & 0xffff) != 0x5678)
|| (((v[6] >> 13) & 0xffff) != 0x9abc)) {
pp_printf("pfilter: wrong rule-set, can't apply\n");
return;
}
inited++;
inited[port]++;
}
/*
* Patch the local MAC address in place,
* in the first three instructions after NOP
*/
get_mac_addr(mac);
get_mac_addr(mac,port);
v[2] &= ~(0xffff << 13);
v[4] &= ~(0xffff << 13);
v[6] &= ~(0xffff << 13);
......@@ -143,7 +143,7 @@ void pfilter_init_default(void)
}
}
EP->PFCR0 = 0; // disable pfilter
EP[port]->PFCR0 = 0; // disable pfilter
for (i = 0, v = vini + 1; v < vend; v += 2, i++) {
uint32_t cr0, cr1;
......@@ -157,8 +157,8 @@ void pfilter_init_default(void)
cr0 = EP_PFCR0_MM_ADDR_W(i) | EP_PFCR0_MM_DATA_MSB_W(cmd_word >> 12) |
EP_PFCR0_MM_WRITE_MASK;
EP->PFCR1 = cr1;
EP->PFCR0 = cr0;
EP[port]->PFCR1 = cr1;
EP[port]->PFCR0 = cr0;
}
/* Restore the 0xaaa vlan number, so we can re-patch next time */
......@@ -177,5 +177,5 @@ void pfilter_init_default(void)
v[4] |= 0x5678 << 13;
v[6] |= 0x9abc << 13;
EP->PFCR0 = EP_PFCR0_ENABLE;
EP[port]->PFCR0 = EP_PFCR0_ENABLE;
}
......@@ -31,37 +31,39 @@
#define RX_OOB_SIZE 3 /* as the number of FIFO data words */
#define ETH_HEADER_SIZE 14
// extracts the values of TS rising and falling edge counters from the descriptor header
#define EXPLODE_WR_TIMESTAMP(raw, rc, fc) \
rc = (raw) & 0xfffffff; \
fc = (raw >> 28) & 0xf;
struct wr_minic minic;
struct wr_minic minic[wr_num_ports];
int ver_supported;
static inline void minic_writel(uint32_t reg, uint32_t data)
static inline void minic_writel(uint32_t reg, uint32_t data, int port)
{
*(volatile uint32_t *)(BASE_MINIC + reg) = data;
*(volatile uint32_t *)(BASE_MINIC[port] + reg) = data;
}
static inline uint32_t minic_readl(uint32_t reg)
static inline uint32_t minic_readl(uint32_t reg, int port)
{
return *(volatile uint32_t *)(BASE_MINIC + reg);
return *(volatile uint32_t *)(BASE_MINIC[port] + reg);
}
static inline void minic_txword(uint8_t type, uint16_t word)
static inline void minic_txword(uint8_t type, uint16_t word, int port)
{
minic_writel(MINIC_REG_TX_FIFO,
MINIC_TX_FIFO_TYPE_W(type) | MINIC_TX_FIFO_DAT_W(word));
MINIC_TX_FIFO_TYPE_W(type) | MINIC_TX_FIFO_DAT_W(word),port);
}
static inline void minic_rxword(uint8_t *type, uint16_t *data, uint8_t *empty,
uint8_t *full)
uint8_t *full, int port)
{
uint32_t rx;
rx = minic_readl(MINIC_REG_RX_FIFO);
rx = minic_readl(MINIC_REG_RX_FIFO, port);
*type = (uint8_t) MINIC_RX_FIFO_TYPE_R(rx);
*data = (uint16_t) MINIC_RX_FIFO_DAT_R(rx);
if (empty)
......@@ -70,12 +72,12 @@ static inline void minic_rxword(uint8_t *type, uint16_t *data, uint8_t *empty,
*full = (rx & MINIC_RX_FIFO_FULL) ? 1 : 0;
}
void minic_init()
void minic_init(int port)
{
uint32_t mcr;
/* before doing anything, check the HDL interface version */
mcr = minic_readl(MINIC_REG_MCR);
mcr = minic_readl(MINIC_REG_MCR, port);
if (MINIC_MCR_VER_R(mcr) != MINIC_HDL_VERSION) {
pp_printf("Error: Minic HDL version %d not supported by sw\n",
MINIC_MCR_VER_R(mcr));
......@@ -86,31 +88,31 @@ void minic_init()
/* disable interrupts, driver does polling */
minic_writel(MINIC_REG_EIC_IDR, MINIC_EIC_IDR_TX |
MINIC_EIC_IDR_RX | MINIC_EIC_IDR_TXTS);
MINIC_EIC_IDR_RX | MINIC_EIC_IDR_TXTS, port);
/* enable RX path */
minic_writel(MINIC_REG_MCR, mcr | MINIC_MCR_RX_EN);
minic_writel(MINIC_REG_MCR, mcr | MINIC_MCR_RX_EN, port);
}
void minic_disable()
void minic_disable(int port)
{
minic_writel(MINIC_REG_MCR, 0);
minic_writel(MINIC_REG_MCR, 0, port);
}
int minic_poll_rx()
int minic_poll_rx(port)
{
uint32_t mcr;
if (!ver_supported)
return 0;
mcr = minic_readl(MINIC_REG_MCR);
mcr = minic_readl(MINIC_REG_MCR, port);
return (mcr & MINIC_MCR_RX_EMPTY) ? 0 : 1;
}
int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts)
struct hw_timestamp *hwts, int port)
{
uint32_t hdr_size, payload_size;
uint32_t raw_ts;
......@@ -125,7 +127,7 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
/* check if there is something in the Rx FIFO to be retrieved */
if ((minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_EMPTY) || !ver_supported)
if ((minic_readl(MINIC_REG_MCR, port) & MINIC_MCR_RX_EMPTY) || !ver_supported)
return 0;
hdr_size = 0;
......@@ -135,7 +137,7 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
ptr16_payload = (uint16_t *)payload;
/* Read the whole frame till OOB or till the FIFO is empty */
do {
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full);
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full, port);
if (rx_type == WRF_DATA && hdr_size < ETH_HEADER_SIZE) {
/* reading header */
......@@ -177,7 +179,7 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
raw_ts = (rx_data << 16) & 0xffff0000;
else if (oob_cnt == 2)
raw_ts |= (rx_data & 0x0000ffff);
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full);
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full, port);
oob_cnt++;
}
......@@ -211,9 +213,9 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
}
/* Increment Rx counter for statistics */
minic.rx_count++;
minic[port].rx_count++;
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL)
if (minic_readl(MINIC_REG_MCR, port) & MINIC_MCR_RX_FULL)
pp_printf("Warning: Minic Rx fifo full, expect wrong frames\n");
/* return number of bytes written to the *payload buffer */
......@@ -221,7 +223,7 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
}
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
struct hw_timestamp *hwts)
struct hw_timestamp *hwts, int port)
{
uint32_t d_hdr, mcr, pwords, hwords;
uint8_t ts_valid;
......@@ -244,44 +246,44 @@ int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
d_hdr = 0;
/* First we write status word (empty status for Tx) */
minic_txword(WRF_STATUS, 0);
minic_txword(WRF_STATUS, 0, port);
/* Write the header of the frame */
ptr = (uint16_t *)hdr;
for (i = 0; i < hwords; ++i)
minic_txword(WRF_DATA, ptr[i]);
minic_txword(WRF_DATA, ptr[i], port);
/* Write the payload without the last word (which can be one byte) */
ptr = (uint16_t *)payload;
for (i = 0; i < pwords-1; ++i)
minic_txword(WRF_DATA, ptr[i]);
minic_txword(WRF_DATA, ptr[i], port);
/* Write last word of the payload (which can be one byte) */
if (size % 2 == 0)
minic_txword(WRF_DATA, ptr[i]);
minic_txword(WRF_DATA, ptr[i], port);
else
minic_txword(WRF_BYTESEL, ptr[i]);
minic_txword(WRF_BYTESEL, ptr[i], port);
/* Write also OOB if needed */
if (hwts) {
minic_txword(WRF_OOB, TX_OOB);
minic_txword(WRF_OOB, WRPC_FID);
minic_txword(WRF_OOB, TX_OOB, port);
minic_txword(WRF_OOB, WRPC_FID, port);
}
/* Start sending the frame, and while we read mcr check for fifo full */
mcr = minic_readl(MINIC_REG_MCR);
mcr = minic_readl(MINIC_REG_MCR, port);
assert_warn((mcr & MINIC_MCR_TX_FULL) == 0, "Minic tx fifo full");
minic_writel(MINIC_REG_MCR, mcr | MINIC_MCR_TX_START);
minic_writel(MINIC_REG_MCR, mcr | MINIC_MCR_TX_START, port);
/* wait for the DMA to finish */
for (i = 0; i < 1000; ++i) {
mcr = minic_readl(MINIC_REG_MCR);
mcr = minic_readl(MINIC_REG_MCR, port);
if ((mcr & MINIC_MCR_TX_IDLE) != 0) break;
timer_delay_ms(1);
}
if (i == 1000)
pp_printf("Warning: tx not terminated infinite mcr=0x%x\n",mcr);
pp_printf("Warning: tx not terminated infinite mcr=0x%x, port = %d\n",mcr, port);
if (hwts) {
uint32_t raw_ts;
......@@ -292,7 +294,7 @@ int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
/* wait for the timestamp */
for (i = 0; i < 100; ++i) {
mcr = minic_readl(MINIC_REG_MCR);
mcr = minic_readl(MINIC_REG_MCR,port);
if ((mcr & MINIC_MCR_TX_TS_READY) != 0) break;
timer_delay_ms(1);
}
......@@ -301,21 +303,21 @@ int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
if (i == 100)
{
pp_printf("Warning: tx timestamp never became available\n");
pp_printf("Warning: tx timestamp never became available, port = %d\n", port);
ts_valid = 0;
}
if(ts_valid)
ts_valid = (uint8_t)(minic_readl(MINIC_REG_TSR0)
ts_valid = (uint8_t)(minic_readl(MINIC_REG_TSR0, port)
& MINIC_TSR0_VALID);
raw_ts = minic_readl(MINIC_REG_TSR1);
fid = MINIC_TSR0_FID_R(minic_readl(MINIC_REG_TSR0));
raw_ts = minic_readl(MINIC_REG_TSR1, port);
fid = MINIC_TSR0_FID_R(minic_readl(MINIC_REG_TSR0, port));
if (fid != WRPC_FID) {
wrc_verbose("minic_tx_frame: unmatched fid %d vs %d\n",
fid, WRPC_FID);
wrc_verbose("minic_tx_frame: unmatched fid %d vs %d, port: %d\n",
fid, WRPC_FID, port);
}
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
......@@ -329,14 +331,14 @@ int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
hwts->ahead = 0;
hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000);
minic.tx_count++;
minic[port].tx_count++;
}
return size;
}
void minic_get_stats(int *tx_frames, int *rx_frames)
void minic_get_stats(int *tx_frames, int *rx_frames, int port)
{
*tx_frames = minic.tx_count;
*rx_frames = minic.rx_count;
*tx_frames = minic[port].tx_count;
*rx_frames = minic[port].rx_count;
}
......@@ -122,7 +122,7 @@ static int cal_cur_phase;
ptpnetif's check lock function when the PLL has already locked, to avoid
complicating the API of ptp-noposix/ppsi. */
void rxts_calibration_start(void)
void rxts_calibration_start(uint8_t port)
{
cal_cur_phase = 0;
det_rising.prev_val = det_falling.prev_val = -1;
......@@ -136,7 +136,7 @@ void rxts_calibration_start(void)
/* Updates RX timestamper state machine. Non-zero return value means that
calibration is done. */
int rxts_calibration_update(uint32_t *t24p_value)
int rxts_calibration_update(uint32_t *t24p_value, int port)
{
int32_t ttrans = 0;
......@@ -145,7 +145,7 @@ int rxts_calibration_update(uint32_t *t24p_value)
/* generate a fake RX timestamp and check if falling edge counter is
ahead of rising edge counter */
int flip = ep_timestamper_cal_pulse();
int flip = ep_timestamper_cal_pulse(port);
/* look for transitions (with deglitching) */
lookup_transition(&det_rising, flip, cal_cur_phase, 1);
......@@ -193,82 +193,82 @@ int rxts_calibration_update(uint32_t *t24p_value)
}
/* legacy function for 'calibration force' command */
int measure_t24p(uint32_t *value)
int measure_t24p(uint32_t *value, int port)
{
int rv;
pp_printf("Waiting for link...\n");
while (!ep_link_up(NULL))
while (!ep_link_up(NULL, port))
timer_delay_ms(100);
spll_init(SPLL_MODE_SLAVE, 0, 1);
spll_init(SPLL_MODE_SLAVE, port, 1);
pp_printf("Locking PLL...\n");
while (!spll_check_lock(0))
timer_delay_ms(100);
pp_printf("\n");
pp_printf("Calibrating RX timestamper...\n");
rxts_calibration_start();
rxts_calibration_start(port);
while (!(rv = rxts_calibration_update(value))) ;
while (!(rv = rxts_calibration_update(value,port))) ;
return rv;
}
/* Delays for master must have been calibrated while running as slave */
static int calib_t24p_master(uint32_t *value)
static int calib_t24p_master(uint32_t *value, int port)
{
int rv;
rv = storage_phtrans(value, 0);
rv = storage_phtrans(value, 0, port);
if(rv < 0) {
pp_printf("Error %d while reading t24p from storage\n", rv);
return rv;
}
pp_printf("t24p read from storage: %d ps\n", *value);
pp_printf("port %d t24p read from storage: %d ps\n", port,*value);
return rv;
}
/*SoftPLL must be locked prior calling this function*/
static int calib_t24p_slave(uint32_t *value)
static int calib_t24p_slave(uint32_t *value, int port)
{
int rv;
uint32_t prev;
int retries = 0;
while (!(rv = rxts_calibration_update(value))) {
if (retries > CALIB_RETRIES || ep_link_up(NULL) == LINK_DOWN)
while (!(rv = rxts_calibration_update(value,port))) {
if (retries > CALIB_RETRIES || ep_link_up(NULL, port) == LINK_DOWN)
return -1;
retries++;
}
if (rv < 0) {
/* Fall back on master == eeprom-or-error */
return calib_t24p_master(value);
return calib_t24p_master(value,port);
}
/*
* Let's see if we have a matching value in EEPROM: