Commit f8eb98c3 authored by Aurelio Colosimo's avatar Aurelio Colosimo

update arch-spec from wrpc-sw, commit 82fd420e88

parent f7117620
......@@ -106,7 +106,7 @@ int ep_enable(int enabled, int 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 */
spec_udelay(200);
timer_delay(200);
pcs_write(MDIO_REG_MCR, MDIO_MCR_RESET); /* reset the PHY */
pcs_write(MDIO_REG_MCR, 0); /* reset the PHY */
......@@ -145,32 +145,11 @@ int ep_get_deltas(uint32_t *delta_tx, uint32_t *delta_rx)
{
/* 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 = 0;
*delta_rx = 15000 - 7000 + 195000 + 32000 + PICOS_PER_SERIAL_BIT * MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC)) + 2800 - 9000 - 40000 + 2700;
*delta_tx = 46407;
*delta_rx = 273593 + PICOS_PER_SERIAL_BIT * MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC));
return 0;
}
/* Prints out the RMON statistic counters */
void ep_show_counters()
{
int i;
for(i=0;i<16;i++)
TRACE_DEV("cntr%d = %d\n", i, (int)(EP->RMON_RAM[i]));
}
int ep_get_psval(int32_t *psval)
{
uint32_t val;
val = EP->DMSR;
if(val & EP_DMSR_PS_RDY)
*psval = EP_DMSR_PS_VAL_R(val);
else
*psval = 0;
return val & EP_DMSR_PS_RDY ? 1 : 0;
}
int ep_cal_pattern_enable()
{
......
......@@ -232,13 +232,25 @@ void pfilter_init_default()
pfilter_cmp(0, EP->MACH & 0xffff, 0xffff, MOV, 3);
pfilter_cmp(1, EP->MACL >> 16, 0xffff, AND, 3);
pfilter_cmp(2, EP->MACL & 0xffff, 0xffff, AND, 3); /* r3 = 1 when the packet is unicast to our own MAC */
pfilter_cmp(6, 0xa0a0, 0xffff, MOV, 4); /* r4 = 1 when ethertype = 0xa0a0 */
pfilter_cmp(6, 0x0800, 0xffff, MOV, 4); /* r4 = 1 when ethertype = IPv4 */
pfilter_cmp(6, 0x88f7, 0xffff, MOV, 5); /* r5 = 1 when ethertype = PTPv2 */
pfilter_cmp(6, 0x0806, 0xffff, MOV, 6); /* r6 = 1 when ethertype = ARP */
pfilter_logic3(7, 3, AND, 4, OR, 5); /* r5 = PTP or etherbone */
pfilter_logic2(R_DROP, 7, NOT, 0); /* Neither PTP or etherbone? drop */
pfilter_logic2(R_CLASS(7), 3, AND, 4); // class 7: minibone unicasts
pfilter_logic2(R_CLASS(0), 5, MOV, 0); // class 7: minibone unicasts
/* Ethernet = 14 bytes, Offset to type in IP: 8 bytes = 22/2 = 11 */
pfilter_cmp(11,0x0001, 0x00ff, MOV, 7); /* r7 = 1 when IP type = ICMP */
pfilter_cmp(11,0x0011, 0x00ff, MOV, 8); /* r8 = 1 when IP type = UDP */
pfilter_logic3(10, 3, OR, 0, AND, 4); /* r10 = IP(unicast) */
pfilter_logic3(11, 1, OR, 3, AND, 4); /* r11 = IP(unicast+broadcast) */
pfilter_logic3(14, 1, AND, 6, OR, 5); /* r14 = ARP(broadcast) or PTPv2 */
pfilter_logic3(15, 10, AND, 7, OR, 14); /* r15 = ICMP/IP(unicast) or ARP(broadcast) or PTPv2 */
pfilter_logic3(20, 11, AND, 8, OR, 15); /* r16 = Something we accept */
pfilter_logic2(R_DROP, 20, NOT, 0); /* None match? drop */
pfilter_logic2(R_CLASS(7), 11, AND, 8); /* class 7: UDP/IP(unicast|broadcast) => external fabric */
pfilter_logic2(R_CLASS(0), 15, MOV, 0); /* class 0: ICMP/IP(unicast) or ARP(broadcast) or PTPv2 => PTP LM32 core */
pfilter_load();
......
//#include <stdio.h>
/*#include <stdio.h>*/
//#include "types.h"
/*#include "types.h"*/
#include "../spec.h"
#include "pps_gen.h" /* for pps_gen_get_time() */
//#include "minic.h"
#include "minic.h"
#include <hw/minic_regs.h>
......@@ -27,8 +27,6 @@
#define TX_DESC_HAS_OWN_MAC (1<<28)
#define RX_OOB_SIZE 6
#define REFCLK_FREQ 125000000
#define ETH_HEADER_SIZE 14
......@@ -46,7 +44,7 @@ struct wr_minic {
volatile uint32_t *rx_head, *rx_base;
uint32_t rx_avail, rx_size;
volatile uint32_t *tx_head, *tx_base;
uint32_t tx_size;
uint32_t tx_avail, tx_size;
int tx_count, rx_count;
};
......@@ -117,6 +115,7 @@ static void minic_rxbuf_free(uint32_t words)
static void minic_new_tx_buffer()
{
minic.tx_head = minic.tx_base;
minic.tx_avail = minic.tx_size>>2;
minic_writel(MINIC_REG_TX_ADDR, (uint32_t) minic.tx_base);
}
......@@ -194,22 +193,23 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_
if(RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL)
{
uint32_t counter_r, counter_f, counter_ppsg, utc;
uint32_t counter_r, counter_f, counter_ppsg;
uint64_t sec;
int cntr_diff;
uint16_t dhdr;
payload_size -= RX_OOB_SIZE;
minic_rx_memcpy(&raw_ts, (uint8_t *)minic.rx_head + payload_size + 6, 4); /* fixme: ugly way of doing unaligned read */
minic_rx_memcpy(&dhdr, (uint8_t *)minic.rx_head + payload_size + 4, 2);
minic_rx_memcpy((uint8_t *)&raw_ts, (uint8_t *)minic.rx_head + payload_size + 6, 4); /* fixme: ugly way of doing unaligned read */
minic_rx_memcpy((uint8_t *)&dhdr, (uint8_t *)minic.rx_head + payload_size + 4, 2);
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
pps_gen_get_time(&utc, &counter_ppsg);
pps_gen_get_time(&sec, &counter_ppsg);
if(counter_r > 3*125000000/4 && counter_ppsg < 125000000/4)
utc--;
if(counter_r > 3*REF_CLOCK_FREQ_HZ/4 && counter_ppsg < 250000000)
sec--;
hwts->utc = utc & 0x7fffffff ;
hwts->sec = sec & 0x7fffffff ;
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
......@@ -218,7 +218,7 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_
else
hwts->ahead = 0;
hwts->nsec = counter_r * 8;
hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS/1000);
hwts->valid = (dhdr & RXOOB_TS_INCORRECT) ? 0 : 1;
if (!hwts->valid) {
int k;
......@@ -238,7 +238,7 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_
n_recvd = -1;
}
minic_rxbuf_free(num_words);
minic.rx_head = (uint32_t)minic.rx_base + ((uint32_t)minic.rx_head+(num_words<<2) - (uint32_t)minic.rx_base) % minic.rx_size;
minic.rx_head = (uint32_t * ) ((uint32_t)minic.rx_base + ((uint32_t)minic.rx_head+(num_words<<2) - (uint32_t)minic.rx_base) % minic.rx_size);
cur_avail = minic_readl(MINIC_REG_RX_AVAIL);
......@@ -290,16 +290,14 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time
while((minic_readl(MINIC_REG_MCR) & MINIC_MCR_TX_IDLE) == 0);
#if 1
if(hwts) /* wait for the timestamp */
{
uint32_t raw_ts;
uint16_t fid;
uint32_t counter_r, counter_f;
uint32_t utc;
uint64_t sec;
uint32_t nsec;
//while((minic_readl(MINIC_REG_TSR0) & MINIC_TSR0_VALID) == 0);
ts_valid = (uint8_t) (minic_readl(MINIC_REG_TSR0) & MINIC_TSR0_VALID);
raw_ts = minic_readl(MINIC_REG_TSR1);
......@@ -310,13 +308,13 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time
TRACE_DEV("minic_tx_frame: unmatched fid %d vs %d\n", fid, tx_oob_val);
}
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
pps_gen_get_time(&utc, &nsec);
pps_gen_get_time(&sec, &nsec);
if(counter_r > 3*125000000/4 && nsec < 125000000/4)
utc--;
if(counter_r > 3*REF_CLOCK_FREQ_HZ/4 && nsec < 250000000)
sec--;
hwts->valid = ts_valid;
hwts->utc = utc;
hwts->sec = sec;
hwts->ahead = 0;
hwts->nsec = counter_r * 8;
......@@ -325,9 +323,8 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time
}
// TRACE_DEV("minic_tx_frame [%d bytes] TS: %d.%d valid %d\n", size, hwts->utc, hwts->nsec, hwts->valid);
minic.tx_count++;
}
#endif
tx_oob_val++;
return size;
......
#include "../spec.h"
#include <hw/pps_gen_regs.h>
#include <pps_gen.h>
//#include <inttypes.h>
/*#include <inttypes.h>*/
#include <hw/pps_gen_regs.h>
/* PPS Generator driver */
#define PPS_PULSE_WIDTH 100000
/* Warning: references to "UTC" in the registers DO NOT MEAN actual UTC time, it's just a plain second counter
It doesn't care about leap seconds. */
static volatile struct PPSG_WB *PPSG = (volatile struct PPS_GEN_WB *) BASE_PPSGEN;
/* Default width (in 8ns units) of the pulses on the PPS output */
static inline uint32_t ppsg_readl(uint32_t reg)
{
return *(volatile uint32_t *)(BASE_PPSGEN + reg);
}
#define PPS_WIDTH 100000
void pps_gen_init()
#define ppsg_write(reg, val) \
*(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg))) = (val)
#define ppsg_read(reg) \
*(volatile uint32_t *) (BASE_PPS_GEN + (offsetof(struct PPSG_WB, reg)))
int pps_gen_init()
{
uint32_t cr;
cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH);
cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_WIDTH);
PPSG->CR = cr;
PPSG->ESCR = 0;
ppsg_write(CR, cr);
PPSG->ADJ_UTCLO = 100;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = 0;
ppsg_write(ADJ_UTCLO, 0);
ppsg_write(ADJ_UTCHI, 0);
ppsg_write(ADJ_NSEC, 0);
#ifdef PPSI_SLAVE
/* Random initial time:q for slave */
PPSG->ADJ_UTCLO = 123456;
PPSG->ADJ_NSEC = 987654;
#endif
PPSG->CR = cr | PPSG_CR_CNT_SET;
PPSG->CR = cr;
ppsg_write(CR, cr | PPSG_CR_CNT_SET);
ppsg_write(CR, cr);
ppsg_write(ESCR, 0x6); /* enable PPS output */
}
void pps_gen_set(int32_t sec, int32_t nsec)
/* Adjusts the nanosecond (refclk cycle) counter by atomically adding (how_much) cycles. */
int pps_gen_adjust(int counter, int64_t how_much)
{
PPSG->ADJ_UTCLO = sec;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = nsec;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) |
PPSG_CR_CNT_SET;
PP_PRINTF("UTC set %d.%d\n", sec, nsec);
uint32_t cr;
if(counter == PPSG_ADJUST_NSEC)
{
ppsg_write(ADJ_UTCLO, 0);
ppsg_write(ADJ_UTCHI, 0);
ppsg_write(ADJ_NSEC, (int32_t) ((int64_t) how_much * 1000LL / (int64_t)REF_CLOCK_PERIOD_PS));
} else {
ppsg_write(ADJ_UTCLO, (uint32_t ) (how_much & 0xffffffffLL));
ppsg_write(ADJ_UTCHI, (uint32_t ) (how_much >> 32) & 0xff);
ppsg_write(ADJ_NSEC, 0);
}
ppsg_write(CR, ppsg_read(CR) | PPSG_CR_CNT_ADJ);
return 0;
}
void pps_gen_adjust_nsec(int32_t how_much)
/* Sets the current time */
int pps_gen_set_time(uint64_t seconds, uint32_t nanoseconds)
{
#if 1
PPSG->ADJ_UTCLO = 0;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = how_much; /* FIXME check: removed division by 8? */
uint32_t cr;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ;
#endif
ppsg_write(ADJ_UTCLO, (uint32_t ) (seconds & 0xffffffffLL));
ppsg_write(ADJ_UTCHI, (uint32_t ) (seconds >> 32) & 0xff);
ppsg_write(ADJ_NSEC, (int32_t) ((int64_t) nanoseconds * 1000LL / (int64_t)REF_CLOCK_PERIOD_PS));
ppsg_write(CR, ppsg_read(CR) | PPSG_CR_CNT_SET);
return 0;
}
void pps_gen_adjust_utc(int32_t how_much)
void pps_gen_get_time(uint64_t *seconds, uint32_t *nanoseconds)
{
uint32_t ns_cnt;
uint64_t sec1, sec2;
#if 1
PPSG->ADJ_UTCLO = how_much;
PPSG->ADJ_UTCHI = 0;
PPSG->ADJ_NSEC = 0;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ;
#endif
do {
sec1 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
ns_cnt = ppsg_read(CNTR_NSEC);
sec2 = (uint64_t)ppsg_read(CNTR_UTCLO) | (uint64_t)ppsg_read(CNTR_UTCHI) << 32;
} while(sec2 != sec1);
if(seconds) *seconds = sec2;
if(nanoseconds) *nanoseconds = (uint32_t) ((int64_t)ns_cnt * (int64_t) REF_CLOCK_PERIOD_PS / 1000LL);
}
/* Returns 1 when the adjustment operation is not yet finished */
int pps_gen_busy()
{
return PPSG->CR & PPSG_CR_CNT_ADJ ? 0 : 1;
uint32_t cr = ppsg_read(CR);
return cr & PPSG_CR_CNT_ADJ ? 0 : 1;
}
void pps_gen_get_time(uint32_t *utc, uint32_t *cntr_nsec)
/* Enables/disables PPS output */
int pps_gen_enable_output(int enable)
{
uint32_t nsec;
uint32_t utc_lo1, utc_lo2;
utc_lo1 = PPSG->CNTR_UTCLO;
nsec = PPSG->CNTR_NSEC & 0xfffffff;
utc_lo2 = PPSG->CNTR_UTCLO;
if (utc_lo2 != utc_lo1)
nsec = PPSG->CNTR_NSEC & 0xfffffff;
if(utc) *utc = utc_lo2;
if(cntr_nsec) *cntr_nsec = nsec;
}
uint32_t escr = ppsg_read(ESCR);
if(enable)
ppsg_write(ESCR, escr | PPSG_ESCR_PPS_VALID);
else
ppsg_write(ESCR, escr & ~PPSG_ESCR_PPS_VALID);
void pps_gen_enable_output(int enable)
{
if(enable)
PPSG->ESCR = PPSG_ESCR_PPS_VALID | PPSG_ESCR_TM_VALID;
else
PPSG->ESCR = 0;
return 0;
}
......@@ -19,7 +19,7 @@ uint32_t timer_get_tics()
return syscon->TVR;
}
void spec_udelay(int usecs)
void timer_delay(uint32_t usecs)
{
uint32_t start, end;
......@@ -33,6 +33,20 @@ void spec_udelay(int usecs)
;
}
/*
void timer_delay(uint32_t how_long)
{
uint32_t t_start;
// timer_init(1);
do
{
t_start = timer_get_tics();
} while(t_start > UINT32_MAX - how_long); //in case of overflow
while(t_start + how_long > timer_get_tics());
}*/
/* return a monotonic seconds count from the counter above; horrible code */
int spec_time(void)
{
......
......@@ -18,7 +18,7 @@ NOT=7
void ep_init(uint8_t mac_addr[]);
void get_mac_addr(uint8_t dev_addr[]);
int ep_enable(int enabled, int autoneg);
int ep_link_up();
int ep_link_up(uint16_t *lpa);
int ep_get_deltas(uint32_t *delta_tx, uint32_t *delta_rx);
int ep_get_psval(int32_t *psval);
int ep_cal_pattern_enable();
......
......@@ -3,10 +3,26 @@
#include <inttypes.h>
void pps_gen_init();
void pps_gen_adjust_nsec(int32_t how_much);
void shw_pps_gen_adjust_utc(int32_t how_much);
#define PPSG_ADJUST_SEC 0x1
#define PPSG_ADJUST_NSEC 0x2
/* Initializes the PPS Generator. 0 on success, negative on failure. */
int pps_gen_init();
/* Adjusts the <counter> (PPSG_ADJUST_SEC/NSEC) by (how_much) seconds/nanoseconds */
int pps_gen_adjust(int counter, int64_t how_much);
/* Returns 1 when the PPS is busy adjusting its time counters, 0 if PPS gen idle */
int pps_gen_busy();
void pps_gen_get_time(uint32_t *utc, uint32_t *cntr_nsec);
/* Enables/disables PPS Generator PPS output */
int pps_gen_enable_output(int enable);
/* Reads the current time and stores at <seconds,nanoseconds>. */
void pps_gen_get_time(uint64_t *seconds, uint32_t *nanoseconds);
/* Sets the time to <seconds,nanoseconds>. */
int pps_gen_set_time(uint64_t seconds, uint32_t nanoseconds);
#endif
......@@ -15,4 +15,6 @@ typedef signed short int16_t;
typedef signed long int32_t;
typedef signed long long int64_t;
#define UINT32_MAX 4294967295U
#endif /* __ARCH_SPEC_STDINT_H__ */
#ifndef __SYSCON_H
#define __SYSCON_H
......@@ -36,8 +37,7 @@ extern struct s_i2c_if i2c_if[2];
void timer_init(uint32_t enable);
uint32_t timer_get_tics();
void spec_udelay(int usec);
int spec_time(void);
void timer_delay(uint32_t how_long);
static volatile struct SYSCON_WB *syscon = (volatile struct SYSCON_WB *) BASE_SYSCON;
......@@ -57,5 +57,10 @@ static inline int gpio_in(int pin)
return syscon->GPSR & pin ? 1: 0;
}
static inline int sysc_get_memsize()
{
return (SYSC_HWFR_MEMSIZE_R(syscon->HWFR) + 1) * 16;
}
#endif
......@@ -26,14 +26,16 @@ void spec_main_loop(struct pp_instance *ppi)
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
delay_ms = pp_state_machine(ppi, NULL, 0);
while (1) {
unsigned char _packet[1500];
/* FIXME Alignment */
unsigned char *packet = _packet + 2;
/* Wait for a packet or for the timeout */
while (delay_ms && !minic_poll_rx()) {
spec_udelay(1000);
timer_delay(1000);
delay_ms--;
}
if (!minic_poll_rx()) {
......@@ -61,4 +63,5 @@ void spec_main_loop(struct pp_instance *ppi)
continue;
delay_ms = pp_state_machine(ppi, packet + eth_ofst, i - eth_ofst);
}
pp_printf("OUT MAIN LOOP\n");
}
......@@ -3,6 +3,7 @@
*/
#include <ppsi/ppsi.h>
#include <hw/wb_uart.h>
#include <pps_gen.h>
#include "spec.h"
const Integer32 PP_ADJ_FREQ_MAX = 512000; //GGDD value ?
......@@ -92,14 +93,14 @@ int32_t spec_set_tstamp(TimeInternal *t)
{
TimeInternal tp_orig;
pps_gen_set(t->seconds, t->nanoseconds);
pps_gen_set_time(t->seconds, t->nanoseconds);
return 0; /* SPEC uses a sort of monotonic tstamp for timers */
}
int spec_adj_freq(Integer32 adj)
{
pps_gen_adjust_nsec(adj);
pps_gen_adjust(PPSG_ADJUST_NSEC, adj);
return 0;
}
......
......@@ -44,7 +44,7 @@ int spec_recv_packet(struct pp_instance *ppi, void *pkt, int len,
if (t) {
//add phase value and linearize function for WR support
t->seconds = hwts.utc;
t->seconds = hwts.sec;
t->nanoseconds = hwts.nsec;
PP_VPRINTF("%s: got=%d, sec=%d, nsec=%d\n", __FUNCTION__, got,
......@@ -75,7 +75,7 @@ int spec_send_packet(struct pp_instance *ppi, void *pkt, int len,
if (t) {
/* add phase value and linearize function for WR support */
t->seconds = hwts.utc;
t->seconds = hwts.sec;
t->nanoseconds = hwts.nsec;
PP_VPRINTF("%s: got=%d, sec=%d, nsec=%d\n", __FUNCTION__, got,
......
......@@ -70,14 +70,15 @@ struct spec_ethhdr {
/* Low-level details (from board.h in wr-core-tools) */
#define BASE_MINIC 0x20000
#define BASE_EP 0x20100
#define BASE_SOFTPLL 0x20200
#define BASE_PPSGEN 0x20300
#define BASE_MINIC 0x20000
#define BASE_EP 0x20100
#define BASE_SOFTPLL 0x20200
#define BASE_PPS_GEN 0x20300
#define BASE_SYSCON 0x20400
#define BASE_UART 0x20500
#define BASE_UART 0x20500
#define BASE_ONEWIRE 0x20600
//#define BASE_TIMER 0x61000
#define FMC_EEPROM_ADR 0x50
#define CPU_CLOCK 62500000ULL
......@@ -97,7 +98,7 @@ struct spec_ethhdr {
struct hw_timestamp {
uint8_t valid;
int ahead;
uint32_t utc;
uint64_t sec;
uint32_t nsec;
uint32_t phase;
};
......@@ -107,4 +108,9 @@ struct hw_timestamp {
#define NULL 0
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
#define REF_CLOCK_PERIOD_PS 8000
#define REF_CLOCK_FREQ_HZ 125000000
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment