Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Software for White Rabbit PTP Core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
32
Issues
32
List
Board
Labels
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Software for White Rabbit PTP Core
Commits
a9966510
Commit
a9966510
authored
Aug 05, 2014
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'ohwr/switch-v4.0' into rubi-printf
parents
6cd04b91
74378610
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
497 additions
and
426 deletions
+497
-426
ad9516.c
dev/ad9516.c
+0
-1
cmd_pll.c
shell/cmd_pll.c
+3
-1
softpll_regs.h
softpll/hw/softpll_regs.h
+106
-93
softpll_ng.c
softpll/softpll_ng.c
+128
-90
softpll_ng.h
softpll/softpll_ng.h
+10
-3
spll_common.c
softpll/spll_common.c
+12
-1
spll_common.h
softpll/spll_common.h
+17
-0
spll_external.c
softpll/spll_external.c
+146
-127
spll_external.h
softpll/spll_external.h
+13
-53
spll_helper.c
softpll/spll_helper.c
+12
-1
spll_helper.h
softpll/spll_helper.h
+1
-0
spll_main.c
softpll/spll_main.c
+44
-52
spll_main.h
softpll/spll_main.h
+1
-1
wrc_main.c
wrc_main.c
+1
-1
wrc_ptp_noposix.c
wrc_ptp_noposix.c
+1
-0
wrs_main.c
wrs_main.c
+2
-2
No files found.
dev/ad9516.c
View file @
a9966510
...
...
@@ -153,7 +153,6 @@ int ad9516_set_output_divider(int output, int ratio, int phase_offset)
ad9516_write_reg
(
base
+
1
,
div_ctl
|
(
1
<<
7
)
|
(
phase_offset
&
0xf
));
}
else
{
uint8_t
div_ctl
=
ad9516_read_reg
(
base
+
1
);
TRACE
(
"DivCtl: %x
\n
"
,
div_ctl
);
ad9516_write_reg
(
base
+
1
,
(
div_ctl
&
(
~
(
1
<<
7
)))
|
(
phase_offset
&
0xf
));
/* disable bypass bit */
ad9516_write_reg
(
base
,
(
lcycles
<<
4
)
|
hcycles
);
}
...
...
shell/cmd_pll.c
View file @
a9966510
...
...
@@ -53,7 +53,9 @@ static int cmd_pll(const char *args[])
if
(
!
args
[
1
])
return
-
EINVAL
;
mprintf
(
"%d
\n
"
,
spll_get_dac
(
atoi
(
args
[
1
])));
}
else
}
else
if
(
!
strcasecmp
(
args
[
0
],
"checkvco"
))
check_vco_frequencies
();
else
return
-
EINVAL
;
return
0
;
...
...
softpll/hw/softpll_regs.h
View file @
a9966510
...
...
@@ -3,7 +3,7 @@
* File : softpll_regs.h
* Author : auto-generated by wbgen2 from spll_wb_slave.wb
* Created :
Thu Jul 25 11:14:53 2013
* Created :
Mon Jul 21 13:49:11 2014
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE spll_wb_slave.wb
...
...
@@ -34,62 +34,101 @@
/* definitions for register: SPLL Control/Status Register */
/* definitions for field: Unused (kept for software compatibility). in reg: SPLL Control/Status Register */
#define SPLL_CSR_UNUSED0_MASK WBGEN2_GEN_MASK(
0
, 6)
#define SPLL_CSR_UNUSED0_SHIFT
0
#define SPLL_CSR_UNUSED0_W(value) WBGEN2_GEN_WRITE(value,
0
, 6)
#define SPLL_CSR_UNUSED0_R(reg) WBGEN2_GEN_READ(reg,
0
, 6)
#define SPLL_CSR_UNUSED0_MASK WBGEN2_GEN_MASK(
8
, 6)
#define SPLL_CSR_UNUSED0_SHIFT
8
#define SPLL_CSR_UNUSED0_W(value) WBGEN2_GEN_WRITE(value,
8
, 6)
#define SPLL_CSR_UNUSED0_R(reg) WBGEN2_GEN_READ(reg,
8
, 6)
/* definitions for field: Number of reference channels (max: 32) in reg: SPLL Control/Status Register */
#define SPLL_CSR_N_REF_MASK WBGEN2_GEN_MASK(
8
, 6)
#define SPLL_CSR_N_REF_SHIFT
8
#define SPLL_CSR_N_REF_W(value) WBGEN2_GEN_WRITE(value,
8
, 6)
#define SPLL_CSR_N_REF_R(reg) WBGEN2_GEN_READ(reg,
8
, 6)
#define SPLL_CSR_N_REF_MASK WBGEN2_GEN_MASK(
16
, 6)
#define SPLL_CSR_N_REF_SHIFT
16
#define SPLL_CSR_N_REF_W(value) WBGEN2_GEN_WRITE(value,
16
, 6)
#define SPLL_CSR_N_REF_R(reg) WBGEN2_GEN_READ(reg,
16
, 6)
/* definitions for field: Number of output channels (max: 8) in reg: SPLL Control/Status Register */
#define SPLL_CSR_N_OUT_MASK WBGEN2_GEN_MASK(
16
, 3)
#define SPLL_CSR_N_OUT_SHIFT
16
#define SPLL_CSR_N_OUT_W(value) WBGEN2_GEN_WRITE(value,
16
, 3)
#define SPLL_CSR_N_OUT_R(reg) WBGEN2_GEN_READ(reg,
16
, 3)
#define SPLL_CSR_N_OUT_MASK WBGEN2_GEN_MASK(
24
, 3)
#define SPLL_CSR_N_OUT_SHIFT
24
#define SPLL_CSR_N_OUT_W(value) WBGEN2_GEN_WRITE(value,
24
, 3)
#define SPLL_CSR_N_OUT_R(reg) WBGEN2_GEN_READ(reg,
24
, 3)
/* definitions for field: Debug queue supported in reg: SPLL Control/Status Register */
#define SPLL_CSR_DBG_SUPPORTED WBGEN2_GEN_MASK(
19
, 1)
#define SPLL_CSR_DBG_SUPPORTED WBGEN2_GEN_MASK(
27
, 1)
/* definitions for register: External Clock Control Register */
/* definitions for field: Enable External Clock
BB Detector
in reg: External Clock Control Register */
/* definitions for field: Enable External Clock
PLL
in reg: External Clock Control Register */
#define SPLL_ECCR_EXT_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: External Clock Input Available in reg: External Clock Control Register */
#define SPLL_ECCR_EXT_SUPPORTED WBGEN2_GEN_MASK(1, 1)
/* definitions for field: E
nable PPS/phase alignm
ent in reg: External Clock Control Register */
#define SPLL_ECCR_
ALIGN_EN
WBGEN2_GEN_MASK(2, 1)
/* definitions for field: E
xternal Clock Reference Pres
ent in reg: External Clock Control Register */
#define SPLL_ECCR_
EXT_REF_PRESENT
WBGEN2_GEN_MASK(2, 1)
/* definitions for field: PPS/phase alignment done in reg: External Clock Control Register */
#define SPLL_ECCR_ALIGN_DONE WBGEN2_GEN_MASK(3, 1)
/* definitions for register: Aligner Control Register */
/* definitions for field: External Clock Reference Present in reg: External Clock Control Register */
#define SPLL_ECCR_EXT_REF_PRESENT WBGEN2_GEN_MASK(4, 1)
/* definitions for field: Aligner sample valid/select on channel in reg: Aligner Control Register */
#define SPLL_AL_CR_VALID_MASK WBGEN2_GEN_MASK(0, 9)
#define SPLL_AL_CR_VALID_SHIFT 0
#define SPLL_AL_CR_VALID_W(value) WBGEN2_GEN_WRITE(value, 0, 9)
#define SPLL_AL_CR_VALID_R(reg) WBGEN2_GEN_READ(reg, 0, 9)
/* definitions for field: Aligner required on channel in reg: Aligner Control Register */
#define SPLL_AL_CR_REQUIRED_MASK WBGEN2_GEN_MASK(9, 9)
#define SPLL_AL_CR_REQUIRED_SHIFT 9
#define SPLL_AL_CR_REQUIRED_W(value) WBGEN2_GEN_WRITE(value, 9, 9)
#define SPLL_AL_CR_REQUIRED_R(reg) WBGEN2_GEN_READ(reg, 9, 9)
/* definitions for register: Aligner Counter REF register */
/* definitions for register: Aligner Counter IN register */
/* definitions for register: DMTD VCO Frequency */
/* definitions for field: FREQ in reg: DMTD VCO Frequency */
#define SPLL_F_DMTD_FREQ_MASK WBGEN2_GEN_MASK(0, 28)
#define SPLL_F_DMTD_FREQ_SHIFT 0
#define SPLL_F_DMTD_FREQ_W(value) WBGEN2_GEN_WRITE(value, 0, 28)
#define SPLL_F_DMTD_FREQ_R(reg) WBGEN2_GEN_READ(reg, 0, 28)
/* definitions for field: VALID in reg: DMTD VCO Frequency */
#define SPLL_F_DMTD_VALID WBGEN2_GEN_MASK(28, 1)
/* definitions for register: REF VCO Frequency */
/* definitions for field: FREQ in reg: REF VCO Frequency */
#define SPLL_F_REF_FREQ_MASK WBGEN2_GEN_MASK(0, 28)
#define SPLL_F_REF_FREQ_SHIFT 0
#define SPLL_F_REF_FREQ_W(value) WBGEN2_GEN_WRITE(value, 0, 28)
#define SPLL_F_REF_FREQ_R(reg) WBGEN2_GEN_READ(reg, 0, 28)
/* definitions for field: VALID in reg: REF VCO Frequency */
#define SPLL_F_REF_VALID WBGEN2_GEN_MASK(28, 1)
/* definitions for register: EXT VCO Frequency */
/* definitions for field: FREQ in reg: EXT VCO Frequency */
#define SPLL_F_EXT_FREQ_MASK WBGEN2_GEN_MASK(0, 28)
#define SPLL_F_EXT_FREQ_SHIFT 0
#define SPLL_F_EXT_FREQ_W(value) WBGEN2_GEN_WRITE(value, 0, 28)
#define SPLL_F_EXT_FREQ_R(reg) WBGEN2_GEN_READ(reg, 0, 28)
/* definitions for field: VALID in reg: EXT VCO Frequency */
#define SPLL_F_EXT_VALID WBGEN2_GEN_MASK(28, 1)
/* definitions for register: Output Channel Control Register */
/* definitions for field: Output Channel HW enable flag in reg: Output Channel Control Register */
#define SPLL_OCCR_OUT_EN_MASK WBGEN2_GEN_MASK(
0
, 8)
#define SPLL_OCCR_OUT_EN_SHIFT
0
#define SPLL_OCCR_OUT_EN_W(value) WBGEN2_GEN_WRITE(value,
0
, 8)
#define SPLL_OCCR_OUT_EN_R(reg) WBGEN2_GEN_READ(reg,
0
, 8)
#define SPLL_OCCR_OUT_EN_MASK WBGEN2_GEN_MASK(
8
, 8)
#define SPLL_OCCR_OUT_EN_SHIFT
8
#define SPLL_OCCR_OUT_EN_W(value) WBGEN2_GEN_WRITE(value,
8
, 8)
#define SPLL_OCCR_OUT_EN_R(reg) WBGEN2_GEN_READ(reg,
8
, 8)
/* definitions for field: Output Channel locked flag in reg: Output Channel Control Register */
#define SPLL_OCCR_OUT_LOCK_MASK WBGEN2_GEN_MASK(8, 8)
#define SPLL_OCCR_OUT_LOCK_SHIFT 8
#define SPLL_OCCR_OUT_LOCK_W(value) WBGEN2_GEN_WRITE(value, 8, 8)
#define SPLL_OCCR_OUT_LOCK_R(reg) WBGEN2_GEN_READ(reg, 8, 8)
/* definitions for field: Output Channel Phase Detector Type in reg: Output Channel Control Register */
#define SPLL_OCCR_OUT_DET_TYPE_MASK WBGEN2_GEN_MASK(16, 8)
#define SPLL_OCCR_OUT_DET_TYPE_SHIFT 16
#define SPLL_OCCR_OUT_DET_TYPE_W(value) WBGEN2_GEN_WRITE(value, 16, 8)
#define SPLL_OCCR_OUT_DET_TYPE_R(reg) WBGEN2_GEN_READ(reg, 16, 8)
#define SPLL_OCCR_OUT_LOCK_MASK WBGEN2_GEN_MASK(16, 8)
#define SPLL_OCCR_OUT_LOCK_SHIFT 16
#define SPLL_OCCR_OUT_LOCK_W(value) WBGEN2_GEN_WRITE(value, 16, 8)
#define SPLL_OCCR_OUT_LOCK_R(reg) WBGEN2_GEN_READ(reg, 16, 8)
/* definitions for register: Reference Channel Tagging Enable Register */
...
...
@@ -127,36 +166,6 @@
#define SPLL_DFR_SPLL_EOS_W(value) WBGEN2_GEN_WRITE(value, 31, 1)
#define SPLL_DFR_SPLL_EOS_R(reg) WBGEN2_GEN_READ(reg, 31, 1)
/* definitions for register: Counter Resync Register - input channels */
/* definitions for register: Counter Resync Register - output channels */
/* definitions for register: Aux clock configuration register */
/* definitions for field: Aux output select in reg: Aux clock configuration register */
#define SPLL_AUX_CR_AUX_SEL_MASK WBGEN2_GEN_MASK(0, 3)
#define SPLL_AUX_CR_AUX_SEL_SHIFT 0
#define SPLL_AUX_CR_AUX_SEL_W(value) WBGEN2_GEN_WRITE(value, 0, 3)
#define SPLL_AUX_CR_AUX_SEL_R(reg) WBGEN2_GEN_READ(reg, 0, 3)
/* definitions for field: BB reference divider in reg: Aux clock configuration register */
#define SPLL_AUX_CR_DIV_REF_MASK WBGEN2_GEN_MASK(3, 6)
#define SPLL_AUX_CR_DIV_REF_SHIFT 3
#define SPLL_AUX_CR_DIV_REF_W(value) WBGEN2_GEN_WRITE(value, 3, 6)
#define SPLL_AUX_CR_DIV_REF_R(reg) WBGEN2_GEN_READ(reg, 3, 6)
/* definitions for field: BB feedback divider in reg: Aux clock configuration register */
#define SPLL_AUX_CR_DIV_FB_MASK WBGEN2_GEN_MASK(9, 6)
#define SPLL_AUX_CR_DIV_FB_SHIFT 9
#define SPLL_AUX_CR_DIV_FB_W(value) WBGEN2_GEN_WRITE(value, 9, 6)
#define SPLL_AUX_CR_DIV_FB_R(reg) WBGEN2_GEN_READ(reg, 9, 6)
/* definitions for field: BB gating frequency select in reg: Aux clock configuration register */
#define SPLL_AUX_CR_GATE_MASK WBGEN2_GEN_MASK(15, 4)
#define SPLL_AUX_CR_GATE_SHIFT 15
#define SPLL_AUX_CR_GATE_W(value) WBGEN2_GEN_WRITE(value, 15, 4)
#define SPLL_AUX_CR_GATE_R(reg) WBGEN2_GEN_READ(reg, 15, 4)
/* definitions for register: Interrupt disable register */
/* definitions for field: Got a tag in reg: Interrupt disable register */
...
...
@@ -234,49 +243,53 @@ PACKED struct SPLL_WB {
uint32_t
CSR
;
/* [0x4]: REG External Clock Control Register */
uint32_t
ECCR
;
/* padding to: 4 words */
uint32_t
__padding_0
[
2
];
/* [0x10]: REG Output Channel Control Register */
/* [0x8]: REG Aligner Control Register */
uint32_t
AL_CR
;
/* [0xc]: REG Aligner Counter REF register */
uint32_t
AL_CREF
;
/* [0x10]: REG Aligner Counter IN register */
uint32_t
AL_CIN
;
/* [0x14]: REG DMTD VCO Frequency */
uint32_t
F_DMTD
;
/* [0x18]: REG REF VCO Frequency */
uint32_t
F_REF
;
/* [0x1c]: REG EXT VCO Frequency */
uint32_t
F_EXT
;
/* [0x20]: REG Output Channel Control Register */
uint32_t
OCCR
;
/* [0x
1
4]: REG Reference Channel Tagging Enable Register */
/* [0x
2
4]: REG Reference Channel Tagging Enable Register */
uint32_t
RCER
;
/* [0x
1
8]: REG Output Channel Tagging Enable Register */
/* [0x
2
8]: REG Output Channel Tagging Enable Register */
uint32_t
OCER
;
/* padding to:
8
words */
uint32_t
__padding_
1
[
1
];
/* [0x
2
0]: REG Helper DAC Output */
/* padding to:
16
words */
uint32_t
__padding_
0
[
5
];
/* [0x
4
0]: REG Helper DAC Output */
uint32_t
DAC_HPLL
;
/* [0x
2
4]: REG Main DAC Output */
/* [0x
4
4]: REG Main DAC Output */
uint32_t
DAC_MAIN
;
/* [0x
2
8]: REG DDMTD Deglitcher threshold */
/* [0x
4
8]: REG DDMTD Deglitcher threshold */
uint32_t
DEGLITCH_THR
;
/* [0x
2
c]: REG Debug FIFO Register - SPLL side */
/* [0x
4
c]: REG Debug FIFO Register - SPLL side */
uint32_t
DFR_SPLL
;
/* [0x30]: REG Counter Resync Register - input channels */
uint32_t
CRR_IN
;
/* [0x34]: REG Counter Resync Register - output channels */
uint32_t
CRR_OUT
;
/* [0x38]: REG Aux clock configuration register */
uint32_t
AUX_CR
;
/* padding to: 16 words */
uint32_t
__padding_2
[
1
];
/* [0x40]: REG Interrupt disable register */
/* padding to: 24 words */
uint32_t
__padding_1
[
4
];
/* [0x60]: REG Interrupt disable register */
uint32_t
EIC_IDR
;
/* [0x
4
4]: REG Interrupt enable register */
/* [0x
6
4]: REG Interrupt enable register */
uint32_t
EIC_IER
;
/* [0x
4
8]: REG Interrupt mask register */
/* [0x
6
8]: REG Interrupt mask register */
uint32_t
EIC_IMR
;
/* [0x
4
c]: REG Interrupt status register */
/* [0x
6
c]: REG Interrupt status register */
uint32_t
EIC_ISR
;
/* [0x
5
0]: REG FIFO 'Debug FIFO Register - Host side' data output register 0 */
/* [0x
7
0]: REG FIFO 'Debug FIFO Register - Host side' data output register 0 */
uint32_t
DFR_HOST_R0
;
/* [0x
5
4]: REG FIFO 'Debug FIFO Register - Host side' data output register 1 */
/* [0x
7
4]: REG FIFO 'Debug FIFO Register - Host side' data output register 1 */
uint32_t
DFR_HOST_R1
;
/* [0x
5
8]: REG FIFO 'Debug FIFO Register - Host side' control/status register */
/* [0x
7
8]: REG FIFO 'Debug FIFO Register - Host side' control/status register */
uint32_t
DFR_HOST_CSR
;
/* [0x
5
c]: REG FIFO 'Tag Readout Register' data output register 0 */
/* [0x
7
c]: REG FIFO 'Tag Readout Register' data output register 0 */
uint32_t
TRR_R0
;
/* [0x
6
0]: REG FIFO 'Tag Readout Register' control/status register */
/* [0x
8
0]: REG FIFO 'Tag Readout Register' control/status register */
uint32_t
TRR_CSR
;
};
...
...
softpll/softpll_ng.c
View file @
a9966510
...
...
@@ -75,6 +75,21 @@ struct softpll_state {
struct
spll_ptracker_state
ptrackers
[
MAX_PTRACKERS
];
};
static
const
struct
stringlist_entry
seq_states
[]
=
{
{
SEQ_START_EXT
,
"start-ext"
},
{
SEQ_WAIT_EXT
,
"wait-ext"
},
{
SEQ_START_HELPER
,
"start-helper"
},
{
SEQ_WAIT_HELPER
,
"wait-helper"
},
{
SEQ_START_MAIN
,
"start-main"
},
{
SEQ_WAIT_MAIN
,
"wait-main"
},
{
SEQ_DISABLED
,
"disabled"
},
{
SEQ_READY
,
"ready"
},
{
SEQ_CLEAR_DACS
,
"clear-dacs"
},
{
SEQ_WAIT_CLEAR_DACS
,
"wait-clear-dacs"
},
{
0
,
NULL
}
};
static
volatile
struct
softpll_state
softpll
;
static
volatile
int
ptracker_mask
=
0
;
...
...
@@ -153,8 +168,10 @@ static inline void sequencing_fsm(struct softpll_state *s, int tag_value, int ta
/* State "Wait until we are locked to external 10MHz clock" */
case
SEQ_WAIT_EXT
:
{
if
(
external_locked
(
&
s
->
ext
))
s
->
seq_state
=
SEQ_START_HELPER
;
if
(
external_locked
(
&
s
->
ext
))
{
start_ptrackers
(
s
);
s
->
seq_state
=
SEQ_READY
;
}
break
;
}
...
...
@@ -190,7 +207,7 @@ static inline void sequencing_fsm(struct softpll_state *s, int tag_value, int ta
case
SEQ_WAIT_MAIN
:
{
if
(
s
->
mpll
.
ld
.
locked
)
if
(
s
->
mpll
.
ld
.
locked
)
{
start_ptrackers
(
s
);
s
->
seq_state
=
SEQ_READY
;
...
...
@@ -200,16 +217,13 @@ static inline void sequencing_fsm(struct softpll_state *s, int tag_value, int ta
case
SEQ_READY
:
{
if
(
!
s
->
helper
.
ld
.
locked
)
{
if
(
s
->
mode
==
SPLL_MODE_GRAND_MASTER
&&
!
external_locked
(
&
s
->
ext
))
{
s
->
delock_count
++
;
s
->
seq_state
=
SEQ_CLEAR_DACS
;
}
else
if
(
s
->
mode
==
SPLL_MODE_GRAND_MASTER
&&
!
external_locked
(
&
s
->
ext
))
{
}
else
if
(
!
s
->
helper
.
ld
.
locked
)
{
s
->
delock_count
++
;
s
->
seq_state
=
SEQ_START_EXT
;
}
else
if
(
s
->
mode
==
SPLL_MODE_SLAVE
&&
!
s
->
mpll
.
ld
.
locked
)
{
s
->
seq_state
=
SEQ_CLEAR_DACS
;
}
else
if
(
s
->
mode
==
SPLL_MODE_SLAVE
&&
!
s
->
mpll
.
ld
.
locked
)
{
s
->
delock_count
++
;
s
->
seq_state
=
SEQ_CLEAR_DACS
;
}
...
...
@@ -220,47 +234,22 @@ static inline void sequencing_fsm(struct softpll_state *s, int tag_value, int ta
static
inline
void
update_loops
(
struct
softpll_state
*
s
,
int
tag_value
,
int
tag_source
)
{
if
(
s
->
mode
==
SPLL_MODE_GRAND_MASTER
)
{
switch
(
s
->
seq_state
)
{
case
SEQ_WAIT_EXT
:
case
SEQ_START_HELPER
:
case
SEQ_WAIT_HELPER
:
case
SEQ_START_MAIN
:
case
SEQ_WAIT_MAIN
:
case
SEQ_READY
:
external_update
(
&
s
->
ext
,
tag_value
,
tag_source
);
break
;
}
}
switch
(
s
->
seq_state
)
{
case
SEQ_WAIT_HELPER
:
case
SEQ_START_MAIN
:
case
SEQ_WAIT_MAIN
:
case
SEQ_READY
:
helper_update
(
&
s
->
helper
,
tag_value
,
tag_source
);
break
;
}
if
(
s
->
seq_state
==
SEQ_WAIT_MAIN
)
{
mpll_update
(
&
s
->
mpll
,
tag_value
,
tag_source
);
}
helper_update
(
&
s
->
helper
,
tag_value
,
tag_source
);
if
(
s
->
seq_state
==
SEQ_READY
)
if
(
s
->
helper
.
ld
.
locked
)
{
if
(
s
->
mode
==
SPLL_MODE_SLAVE
)
{
int
i
;
mpll_update
(
&
s
->
mpll
,
tag_value
,
tag_source
);
mpll_update
(
&
s
->
mpll
,
tag_value
,
tag_source
);
for
(
i
=
0
;
i
<
spll_n_chan_out
-
1
;
i
++
)
mpll_update
(
&
s
->
aux
[
i
].
pll
.
dmtd
,
tag_value
,
tag_source
);
// fixme: bb hooks here
if
(
s
->
seq_state
==
SEQ_READY
)
{
if
(
s
->
mode
==
SPLL_MODE_SLAVE
)
{
int
i
;
for
(
i
=
0
;
i
<
spll_n_chan_out
-
1
;
i
++
)
mpll_update
(
&
s
->
aux
[
i
].
pll
.
dmtd
,
tag_value
,
tag_source
);
}
update_ptrackers
(
s
,
tag_value
,
tag_source
);
}
update_ptrackers
(
s
,
tag_value
,
tag_source
);
}
}
...
...
@@ -301,7 +290,6 @@ void spll_init(int mode, int slave_ref_channel, int align_pps)
spll_n_chan_ref
=
SPLL_CSR_N_REF_R
(
csr
);
spll_n_chan_out
=
SPLL_CSR_N_OUT_R
(
csr
);
s
->
mode
=
mode
;
s
->
delock_count
=
0
;
...
...
@@ -318,16 +306,6 @@ void spll_init(int mode, int slave_ref_channel, int align_pps)
PPSG
->
ESCR
=
0
;
PPSG
->
CR
=
PPSG_CR_CNT_EN
|
PPSG_CR_CNT_RST
|
PPSG_CR_PWIDTH_W
(
PPS_WIDTH
);
if
(
mode
==
SPLL_MODE_GRAND_MASTER
)
{
if
(
SPLL
->
ECCR
&
SPLL_ECCR_EXT_SUPPORTED
)
external_init
(
&
s
->
ext
,
spll_n_chan_ref
+
spll_n_chan_out
,
align_pps
);
else
{
TRACE_DEV
(
"softpll: attempting to enable GM mode on non-GM hardware.
\n
"
);
return
;
}
}
if
(
mode
==
SPLL_MODE_DISABLED
)
s
->
seq_state
=
SEQ_DISABLED
;
else
...
...
@@ -354,6 +332,17 @@ void spll_init(int mode, int slave_ref_channel, int align_pps)
for
(
i
=
0
;
i
<
spll_n_chan_ref
;
i
++
)
ptracker_init
(
&
s
->
ptrackers
[
i
],
i
,
PTRACKER_AVERAGE_SAMPLES
);
if
(
mode
==
SPLL_MODE_GRAND_MASTER
)
{
if
(
SPLL
->
ECCR
&
SPLL_ECCR_EXT_SUPPORTED
)
{
s
->
ext
.
helper
=
&
s
->
helper
;
s
->
ext
.
main
=
&
s
->
mpll
;
external_init
(
&
s
->
ext
,
spll_n_chan_ref
+
spll_n_chan_out
,
align_pps
);
}
else
{
TRACE_DEV
(
"softpll: attempting to enable GM mode on non-GM hardware.
\n
"
);
return
;
}
}
TRACE_DEV
(
"softpll: mode %s, %d ref channels, %d out channels
\n
"
,
modes
[
mode
],
spll_n_chan_ref
,
spll_n_chan_out
);
...
...
@@ -400,6 +389,11 @@ void spll_stop_channel(int channel)
mpll_stop
(
&
s
->
aux
[
channel
-
1
].
pll
.
dmtd
);
}
int
spll_ext_locked
()
{
return
external_locked
(
(
struct
spll_external_state
*
)
&
softpll
.
ext
);
}
int
spll_check_lock
(
int
channel
)
{
if
(
!
channel
)
...
...
@@ -409,29 +403,6 @@ int spll_check_lock(int channel)
&&
softpll
.
aux
[
channel
-
1
].
pll
.
dmtd
.
ld
.
locked
;
}
#ifdef CONFIG_PPSI
/* use __div64_32 from ppsi library to save libgcc memory */
static
int32_t
from_picos
(
int32_t
ps
)
{
extern
uint32_t
__div64_32
(
uint64_t
*
n
,
uint32_t
base
);
uint64_t
ups
=
ps
;
if
(
ps
>=
0
)
{
ups
*=
1
<<
HPLL_N
;
__div64_32
(
&
ups
,
CLOCK_PERIOD_PICOSECONDS
);
return
ups
;
}
ups
=
-
ps
*
(
1
<<
HPLL_N
);
__div64_32
(
&
ups
,
CLOCK_PERIOD_PICOSECONDS
);
return
-
ups
;
}
#else
/* previous implementation: ptp-noposix has no __div64_32 available */
static
int32_t
from_picos
(
int32_t
ps
)
{
return
(
int32_t
)
((
int64_t
)
ps
*
(
int64_t
)
(
1
<<
HPLL_N
)
/
(
int64_t
)
CLOCK_PERIOD_PICOSECONDS
);
}
#endif
static
int32_t
to_picos
(
int32_t
units
)
{
return
(
int32_t
)
(((
int64_t
)
units
*
...
...
@@ -443,8 +414,7 @@ static void set_phase_shift(int channel, int32_t value_picoseconds)
{
struct
spll_main_state
*
st
=
(
struct
spll_main_state
*
)
(
!
channel
?
&
softpll
.
mpll
:
&
softpll
.
aux
[
channel
-
1
].
pll
.
dmtd
);
int
div
=
(
DIVIDE_DMTD_CLOCKS_BY_2
?
2
:
1
);
mpll_set_phase_shift
(
st
,
from_picos
(
value_picoseconds
)
/
div
);
mpll_set_phase_shift
(
st
,
value_picoseconds
);
softpll
.
mpll_shift_ps
=
value_picoseconds
;
}
...
...
@@ -502,15 +472,12 @@ void spll_get_num_channels(int *n_ref, int *n_out)
void
spll_show_stats
()
{
if
(
softpll
.
mode
>
0
)
TRACE_DEV
(
"softpll: irq_count %d sequencer_state %d mode %d "
"alignment_state %d HL%d EL%d ML%d HY=%d "
"MY=%d EY=%d DelCnt=%d extsc=%d
\n
"
,
irq_count
,
softpll
.
seq_state
,
softpll
.
mode
,
softpll
.
ext
.
realign_state
,
softpll
.
helper
.
ld
.
locked
,
softpll
.
ext
.
ld
.
locked
,
softpll
.
mpll
.
ld
.
locked
,
softpll
.
helper
.
pi
.
y
,
softpll
.
mpll
.
pi
.
y
,
softpll
.
ext
.
pi
.
y
,
softpll
.
delock_count
,
softpll
.
ext
.
sample_n
);
TRACE_DEV
(
"softpll: irqs %d seq %s mode %d "
"alignment_state %d HL%d ML%d HY=%d MY=%d DelCnt=%d
\n
"
,
irq_count
,
stringlist_lookup
(
seq_states
,
softpll
.
seq_state
),
softpll
.
mode
,
softpll
.
ext
.
align_state
,
softpll
.
helper
.
ld
.
locked
,
softpll
.
mpll
.
ld
.
locked
,
softpll
.
helper
.
pi
.
y
,
softpll
.
mpll
.
pi
.
y
,
softpll
.
delock_count
);
}
int
spll_shifter_busy
(
int
channel
)
...
...
@@ -666,3 +633,74 @@ void spll_set_dac(int index, int value)
softpll
.
aux
[
index
-
1
].
pll
.
dmtd
.
pi
.
y
=
value
;
}
}
void
spll_update
()
{
switch
(
softpll
.
mode
)
{
case
SPLL_MODE_GRAND_MASTER
:
external_align_fsm
(
&
softpll
.
ext
);
break
;
}
spll_update_aux_clocks
();
}
static
int
spll_measure_frequency
(
int
osc
)
{
volatile
uint32_t
*
reg
;
switch
(
osc
)
{
case
SPLL_OSC_REF
:
reg
=
&
SPLL
->
F_REF
;
break
;
case
SPLL_OSC_DMTD
:
reg
=
&
SPLL
->
F_DMTD
;
break
;
case
SPLL_OSC_EXT
:
reg
=
&
SPLL
->
F_EXT
;
break
;
}
timer_delay_ms
(
2000
);
return
(
*
reg
)
&
(
0xfffffff
);
}
static
int
calc_apr
(
int
meas_min
,
int
meas_max
,
int
f_center
)
{
// apr_min is in PPM
int64_t
delta_low
=
meas_min
-
f_center
;
int64_t
delta_hi
=
meas_max
-
f_center
;
if
(
delta_low
>=
0
)
return
-
1
;
if
(
delta_hi
<=
0
)
return
-
1
;
int
ppm_lo
=
-
(
int64_t
)
delta_low
*
1000000LL
/
f_center
;
int
ppm_hi
=
(
int64_t
)
delta_hi
*
1000000LL
/
f_center
;
return
ppm_lo
<
ppm_hi
?
ppm_lo
:
ppm_hi
;
}
void
check_vco_frequencies
()
{
disable_irq
();
int
f_min
,
f_max
;
TRACE_DEV
(
"SoftPLL VCO Frequency/APR test:
\n
"
);
spll_set_dac
(
-
1
,
0
);
f_min
=
spll_measure_frequency
(
SPLL_OSC_DMTD
);
spll_set_dac
(
-
1
,
65535
);
f_max
=
spll_measure_frequency
(
SPLL_OSC_DMTD
);
TRACE_DEV
(
"DMTD VCO: Low=%d Hz Hi=%d Hz, APR = %d ppm.
\n
"
,
f_min
,
f_max
,
calc_apr
(
f_min
,
f_max
,
62500000
));
spll_set_dac
(
0
,
0
);
f_min
=
spll_measure_frequency
(
SPLL_OSC_REF
);
spll_set_dac
(
0
,
65535
);
f_max
=
spll_measure_frequency
(
SPLL_OSC_REF
);
TRACE_DEV
(
"REF VCO: Low=%d Hz Hi=%d Hz, APR = %d ppm.
\n
"
,
f_min
,
f_max
,
calc_apr
(
f_min
,
f_max
,
REF_CLOCK_FREQ_HZ
));
f_min
=
spll_measure_frequency
(
SPLL_OSC_EXT
);
TRACE_DEV
(
"EXT clock: Freq=%d Hz
\n
"
,
f_min
);
}
softpll/softpll_ng.h
View file @
a9966510
...
...
@@ -39,6 +39,10 @@
#define SPLL_PD_DDMTD 0
#define SPLL_PD_BANGBANG 1
/* Channels for spll_measure_frequency() */
#define SPLL_OSC_REF 0
#define SPLL_OSC_DMTD 1
#define SPLL_OSC_EXT 2
/* Note on channel naming:
- ref_channel means a PHY recovered clock input. There can be one (as in WR core) or more (WR switch).
...
...
@@ -101,9 +105,10 @@ void spll_enable_ptracker(int ref_channel, int enable);
/* Reads tracked phase shift value for given reference channel */
int
spll_read_ptracker
(
int
ref_channel
,
int32_t
*
phase_ps
,
int
*
enabled
);
/* Calls aux clock handling state machine. Must be called regularly (although it is not time-critical)
in the main loop of the program if aux clocks are used in the design. */
int
spll_update_aux_clocks
();
/* Calls non-realtime update state machine. Must be called regularly (although
* it is not time-critical) in the main loop of the program if aux clocks or
* external reference are used in the design. */
void
spll_update
();
/* Returns the status of given aux clock output (SPLL_AUX_) */
int
spll_get_aux_status
(
int
out_channel
);
...
...
@@ -122,5 +127,7 @@ void spll_set_dac(int out_channel, int value);
/* Returns current DAC sample value for output (out_channel) */
int
spll_get_dac
(
int
out_channel
);
void
check_vco_frequencies
();
#endif // __SOFTPLL_NG_H
softpll/spll_common.c
View file @
a9966510
...
...
@@ -125,6 +125,7 @@ Channels (spll_n_chan_ref ... spll_n_chan_out + spll_n_chan_ref-1) are the outpu
void
spll_enable_tagger
(
int
channel
,
int
enable
)
{
TRACE_DEV
(
"EnableTagger %d %d
\n
"
,
channel
,
enable
);
if
(
channel
>=
spll_n_chan_ref
)
{
/* Output channel? */
if
(
enable
)
SPLL
->
OCER
|=
1
<<
(
channel
-
spll_n_chan_ref
);
...
...
@@ -137,7 +138,7 @@ void spll_enable_tagger(int channel, int enable)
SPLL
->
RCER
&=
~
(
1
<<
channel
);
}
// TRACE
("%s: ch %d, OCER 0x%x, RCER 0x%x\n", __FUNCTION__, channel, SPLL->OCER, SPLL->RCER);
TRACE_DEV
(
"%s: ch %d, OCER 0x%x, RCER 0x%x
\n
"
,
__FUNCTION__
,
channel
,
SPLL
->
OCER
,
SPLL
->
RCER
);
}
void
biquad_init
(
spll_biquad_t
*
bq
,
const
int
*
coefs
,
int
shift
)
...
...
@@ -167,3 +168,13 @@ int biquad_update(spll_biquad_t *bq, int x)
return
y
;
}
const
char
*
stringlist_lookup
(
const
struct
stringlist_entry
*
slist
,
int
id
)
{
int
i
;
for
(
i
=
0
;
slist
[
i
].
str
;
i
++
)
{
if
(
slist
[
i
].
id
==
id
)
return
slist
[
i
].
str
;
}
return
"<unknown>"
;
}
softpll/spll_common.h
View file @
a9966510
...
...
@@ -66,6 +66,21 @@ typedef struct {
int
yd
[
2
],
xd
[
2
];
/* I/O delay lines */
}
spll_biquad_t
;
/* long-term-average filter */
typedef
struct
{
int
acc
;
int
n
;
int
window
;
int
pos
;
int
size
;
int
log
[
16
];
}
spll_lta_t
;
struct
stringlist_entry
{
int
id
;
const
char
*
str
;
};
/* initializes the PI controller state. Currently almost a stub. */
void
pi_init
(
spll_pi_t
*
pi
);
...
...
@@ -83,4 +98,6 @@ void spll_enable_tagger(int channel, int enable);
void
biquad_init
(
spll_biquad_t
*
bq
,
const
int
*
coefs
,
int
shift
);
int
biquad_update
(
spll_biquad_t
*
bq
,
int
x
);
const
char
*
stringlist_lookup
(
const
struct
stringlist_entry
*
slist
,
int
id
);
#endif // __SPLL_COMMON_H
softpll/spll_external.c
View file @
a9966510
...
...
@@ -13,152 +13,171 @@
#include "spll_external.h"
#include "spll_debug.h"
#define BB_ERROR_BITS 16
#include "trace.h"
#include "irq.h"
void
external_init
(
volatile
struct
spll_external_state
*
s
,
int
ext_ref
,
int
realign_clocks
)
{
#define ALIGN_STATE_EXT_OFF 0
#define ALIGN_STATE_START 1
#define ALIGN_STATE_INIT_CSYNC 2
#define ALIGN_STATE_WAIT_CSYNC 3
#define ALIGN_STATE_START_ALIGNMENT 7
#define ALIGN_STATE_WAIT_SAMPLE 4
#define ALIGN_STATE_COMPENSATE_DELAY 5
#define ALIGN_STATE_LOCKED 6
#define ALIGN_STATE_START_MAIN 8
s
->
pi
.
y_min
=
5
;
s
->
pi
.
y_max
=
(
1
<<
DAC_BITS
)
-
5
;
s
->
pi
.
kp
=
(
int
)(
300
);
s
->
pi
.
ki
=
(
int
)(
1
);
s
->
pi
.
anti_windup
=
1
;
s
->
pi
.
bias
=
32768
;
/* Phase branch lock detection */
s
->
ld
.
threshold
=
400
;
s
->
ld
.
lock_samples
=
10000
;
s
->
ld
.
delock_samples
=
9990
;
s
->
ref_src
=
ext_ref
;
s
->
ph_err_cur
=
0
;
s
->
ph_err_d0
=
0
;
s
->
ph_raw_d0
=
0
;
s
->
realign_clocks
=
realign_clocks
;
s
->
realign_state
=
(
realign_clocks
?
REALIGN_STAGE1
:
REALIGN_DISABLED
);
pi_init
((
spll_pi_t
*
)
&
s
->
pi
);
ld_init
((
spll_lock_det_t
*
)
&
s
->
ld
);
lowpass_init
((
spll_lowpass_t
*
)
&
s
->
lp_short
,
4000
);
lowpass_init
((
spll_lowpass_t
*
)
&
s
->
lp_long
,
300
);
}
#define ALIGN_SAMPLE_PERIOD 100000
#define ALIGN_TARGET 0
static
inline
void
realign_fsm
(
struct
spll_external_state
*
s
)
{
switch
(
s
->
realign_state
)
{
case
REALIGN_STAGE1
:
SPLL
->
ECCR
|=
SPLL_ECCR_ALIGN_EN
;
#define EXT_PERIOD_NS 100
#define EXT_FREQ_HZ 10000000
#define EXT_PPS_LATENCY_PS 30000 // fixme: make configurable
s
->
realign_state
=
REALIGN_STAGE1_WAIT
;
s
->
realign_timer
=
timer_get_tics
()
+
2
*
TICS_PER_SECOND
;
break
;
case
REALIGN_STAGE1_WAIT
:
void
external_init
(
volatile
struct
spll_external_state
*
s
,
int
ext_ref
,
int
realign_clocks
)
{
int
idx
=
spll_n_chan_ref
+
spll_n_chan_out
;
if
(
SPLL
->
ECCR
&
SPLL_ECCR_ALIGN_DONE
)
s
->
realign_state
=
REALIGN_STAGE2
;
else
if
(
time_after
(
timer_get_tics
(),
s
->
realign_timer
))
{
SPLL
->
ECCR
&=
~
SPLL_ECCR_ALIGN_EN
;
s
->
realign_state
=
REALIGN_PPS_INVALID
;
}
break
;
case
REALIGN_STAGE2
:
if
(
s
->
ld
.
locked
)
{
PPSG
->
CR
=
PPSG_CR_CNT_RST
|
PPSG_CR_CNT_EN
;
PPSG
->
ADJ_UTCLO
=
0
;
PPSG
->
ADJ_UTCHI
=
0
;
PPSG
->
ADJ_NSEC
=
0
;
PPSG
->
ESCR
=
PPSG_ESCR_SYNC
;
s
->
realign_state
=
REALIGN_STAGE2_WAIT
;
s
->
realign_timer
=
timer_get_tics
()
+
2
*
TICS_PER_SECOND
;
}
break
;
case
REALIGN_STAGE2_WAIT
:
if
(
PPSG
->
ESCR
&
PPSG_ESCR_SYNC
)
{
PPSG
->
ESCR
=
PPSG_ESCR_PPS_VALID
|
PPSG_ESCR_TM_VALID
;
s
->
realign_state
=
REALIGN_DONE
;
}
else
if
(
time_after
(
timer_get_tics
(),
s
->
realign_timer
))
{
PPSG
->
ESCR
=
0
;
s
->
realign_state
=
REALIGN_PPS_INVALID
;
}
break
;
helper_init
(
s
->
helper
,
idx
);
mpll_init
(
s
->
main
,
idx
,
spll_n_chan_ref
);
case
REALIGN_PPS_INVALID
:
case
REALIGN_DISABLED
:
case
REALIGN_DONE
:
return
;
}
s
->
align_state
=
ALIGN_STATE_EXT_OFF
;
s
->
enabled
=
0
;
}
int
external_update
(
struct
spll_external_state
*
s
,
int
tag
,
int
source
)
void
external_start
(
struct
spll_external_state
*
s
)
{
int
err
,
y
,
y2
,
ylt
;
if
(
source
==
s
->
ref_src
)
{
int
wrap
=
tag
&
(
1
<<
BB_ERROR_BITS
)
?
1
:
0
;
realign_fsm
(
s
);
tag
&=
((
1
<<
BB_ERROR_BITS
)
-
1
);
// mprintf("err %d\n", tag);
if
(
wrap
)
{
if
(
tag
>
s
->
ph_raw_d0
)
s
->
ph_err_offset
-=
(
1
<<
BB_ERROR_BITS
);
else
if
(
tag
<=
s
->
ph_raw_d0
)
s
->
ph_err_offset
+=
(
1
<<
BB_ERROR_BITS
);
}
s
->
ph_raw_d0
=
tag
;
helper_start
(
s
->
helper
);
err
=
(
tag
+
s
->
ph_err_offset
)
-
s
->
ph_err_d0
;
s
->
ph_err_d0
=
(
tag
+
s
->
ph_err_offset
);
y
=
pi_update
(
&
s
->
pi
,
err
);
y2
=
lowpass_update
(
&
s
->
lp_short
,
y
);
ylt
=
lowpass_update
(
&
s
->
lp_long
,
y
);
if
(
!
(
SPLL
->
ECCR
&
SPLL_ECCR_EXT_REF_PRESENT
))
{
/* no reference? de-lock now */
ld_init
(
&
s
->
ld
);
y2
=
32000
;
}
SPLL
->
DAC_MAIN
=
y2
&
0xffff
;
SPLL
->
ECCR
=
SPLL_ECCR_EXT_EN
;
spll_debug
(
DBG_ERR
|
DBG_EXT
,
ylt
,
0
);
spll_debug
(
DBG_SAMPLE_ID
|
DBG_EXT
,
s
->
sample_n
++
,
0
);
spll_debug
(
DBG_Y
|
DBG_EXT
,
y2
,
1
);
s
->
align_state
=
ALIGN_STATE_START
;
s
->
enabled
=
1
;
spll_debug
(
DBG_EVENT
|
DBG_EXT
,
DBG_EVT_START
,
1
);
}
if
(
ld_update
(
&
s
->
ld
,
y2
-
ylt
))
return
SPLL_LOCKED
;
int
external_locked
(
struct
spll_external_state
*
s
)
{
if
(
!
s
->
helper
->
ld
.
locked
||
!
s
->
main
->
ld
.
locked
)
return
0
;
switch
(
s
->
align_state
)
{
case
ALIGN_STATE_EXT_OFF
:
case
ALIGN_STATE_START
:
case
ALIGN_STATE_START_MAIN
:
case
ALIGN_STATE_INIT_CSYNC
:
case
ALIGN_STATE_WAIT_CSYNC
:
return
0
;
default:
return
1
;
}
return
SPLL_LOCKING
;
}
void
external_start
(
struct
spll_external_state
*
s
)
static
int
align_sample
(
int
channel
,
int
*
v
)
{
SPLL
->
ECCR
=
0
;
s
->
sample_n
=
0
;
s
->
realign_state
=
(
s
->
realign_clocks
?
REALIGN_STAGE1
:
REALIGN_DISABLED
);
SPLL
->
ECCR
=
SPLL_ECCR_EXT_EN
;
spll_debug
(
DBG_EVENT
|
DBG_EXT
,
DBG_EVT_START
,
1
);
int
mask
=
(
1
<<
channel
);
if
(
SPLL
->
AL_CR
&
mask
)
{
SPLL
->
AL_CR
=
mask
;
// ack
int
ci
=
SPLL
->
AL_CIN
;
if
(
ci
>
100
&&
ci
<
(
EXT_FREQ_HZ
-
100
)
)
{
// give some metastability margin, when the counter transitions from EXT_FREQ_HZ-1 to 0
*
v
=
ci
*
EXT_PERIOD_NS
;
return
1
;
}
}
return
0
;
// sample not valid
}
int
external_locked
(
struct
spll_external_state
*
s
)
void
external_align_fsm
(
struct
spll_external_state
*
s
)
{
return
(
s
->
ld
.
locked
&&
(
s
->
realign_clocks
?
s
->
realign_state
==
REALIGN_DONE
:
1
));
int
v
;
switch
(
s
->
align_state
)
{
case
ALIGN_STATE_EXT_OFF
:
break
;
case
ALIGN_STATE_START
:
if
(
s
->
helper
->
ld
.
locked
)
{
disable_irq
();
mpll_start
(
s
->
main
);
enable_irq
();
s
->
align_state
=
ALIGN_STATE_START_MAIN
;
}
break
;
case
ALIGN_STATE_START_MAIN
:
SPLL
->
AL_CR
=
2
;
if
(
s
->
helper
->
ld
.
locked
&&
s
->
main
->
ld
.
locked
)
{
PPSG
->
CR
=
PPSG_CR_CNT_EN
|
PPSG_CR_PWIDTH_W
(
10
);
PPSG
->
ADJ_NSEC
=
3
;
PPSG
->
ESCR
=
PPSG_ESCR_SYNC
;
s
->
align_state
=
ALIGN_STATE_INIT_CSYNC
;
TRACE_DEV
(
"EXT: DMTD locked.
\n
"
);
}
break
;
case
ALIGN_STATE_INIT_CSYNC
:
if
(
PPSG
->
ESCR
&
PPSG_ESCR_SYNC
)
{
PPSG
->
ESCR
=
PPSG_ESCR_PPS_VALID
;
// enable PPS output (even though it's not aligned yet)
s
->
align_timer
=
timer_get_tics
()
+
2
*
TICS_PER_SECOND
;
s
->
align_state
=
ALIGN_STATE_WAIT_CSYNC
;
}
break
;
case
ALIGN_STATE_WAIT_CSYNC
:
if
(
timer_get_tics
()
>=
s
->
align_timer
)
{
s
->
align_state
=
ALIGN_STATE_START_ALIGNMENT
;
s
->
align_shift
=
0
;
TRACE_DEV
(
"EXT: CSync complete.
\n
"
);
}
break
;
case
ALIGN_STATE_START_ALIGNMENT
:
if
(
align_sample
(
1
,
&
v
))
{
v
%=
ALIGN_SAMPLE_PERIOD
;
if
(
v
==
0
||
v
>=
ALIGN_SAMPLE_PERIOD
/
2
)
{
s
->
align_target
=
EXT_PERIOD_NS
;
s
->
align_step
=
-
100
;
}
else
if
(
s
>
0
)
{
s
->
align_target
=
0
;
s
->
align_step
=
100
;
}
TRACE_DEV
(
"EXT: Align target %d, step %d.
\n
"
,
s
->
align_target
,
s
->
align_step
);
s
->
align_state
=
ALIGN_STATE_WAIT_SAMPLE
;
}
break
;
case
ALIGN_STATE_WAIT_SAMPLE
:
if
(
!
mpll_shifter_busy
(
s
->
main
)
&&
align_sample
(
1
,
&
v
))
{
v
%=
ALIGN_SAMPLE_PERIOD
;
if
(
v
!=
s
->
align_target
)
{
s
->
align_shift
+=
s
->
align_step
;
mpll_set_phase_shift
(
s
->
main
,
s
->
align_shift
);
}
else
if
(
v
==
s
->
align_target
)
{
s
->
align_shift
+=
EXT_PPS_LATENCY_PS
;
mpll_set_phase_shift
(
s
->
main
,
s
->
align_shift
);
s
->
align_state
=
ALIGN_STATE_COMPENSATE_DELAY
;
}
}
break
;
case
ALIGN_STATE_COMPENSATE_DELAY
:
if
(
!
mpll_shifter_busy
(
s
->
main
))
{
TRACE_DEV
(
"EXT: Align done.
\n
"
);
s
->
align_state
=
ALIGN_STATE_LOCKED
;
}
break
;
case
ALIGN_STATE_LOCKED
:
if
(
!
external_locked
(
s
))
{
s
->
align_state
=
ALIGN_STATE_START
;
}
break
;
default:
break
;
}
}
softpll/spll_external.h
View file @
a9966510
...
...
@@ -14,69 +14,29 @@
#define __SPLL_EXTERNAL_H
#include "spll_common.h"
#include "spll_helper.h"
#include "spll_main.h"
/* Alignment FSM states */
/* 1st alignment stage, done before starting the ext channel PLL:
alignment of the rising edge of the external clock (10 MHz), with
the rising edge of the local reference (62.5/125 MHz) and the PPS
signal. Because of non-integer ratio (6.25 or 12.5), the PLL must
know which edges shall be kept at phase==0. We align to the edge of
the 10 MHz clock which comes right after the edge of the PPS pulse
(see drawing below):
PLL reference (62.5 MHz) ____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|
External clock (10 MHz) ^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|___
External PPS ___________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
#define REALIGN_STAGE1 1
#define REALIGN_STAGE1_WAIT 2
/* 2nd alignment stage, done after the ext channel PLL has locked. We
make sure that the switch's internal PPS signal is produced exactly
on the edge of PLL reference in-phase with 10 MHz clock edge, which
has come right after the PPS input
PLL reference (62.5 MHz) ____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|^^^^|____|
External clock (10 MHz) ^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|________________________|^^^^^^^^^^^^^^^^^^^^^^^^^|___
External PPS ___________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Internal PPS __________________________________|^^^^^^^^^|______________________________________________________________________
^ aligned clock edges and PPS
*/
#define REALIGN_STAGE2 3
#define REALIGN_STAGE2_WAIT 4
/* Error state - PPS signal missing or of bad frequency */
#define REALIGN_PPS_INVALID 5
/* Realignment is disabled (i.e. the switch inputs only the reference
* frequency, but not time) */
#define REALIGN_DISABLED 6
struct
spll_external_state
{
struct
spll_helper_state
*
helper
;
struct
spll_main_state
*
main
;
/* Realignment done */
#define REALIGN_DONE 7
int
enabled
;
struct
spll_external_state
{
int
ref_src
;
int
sample_n
;
int
ph_err_offset
,
ph_err_cur
,
ph_err_d0
,
ph_raw_d0
;
int
realign_clocks
;
int
realign_state
;
int
realign_timer
;
spll_pi_t
pi
;
spll_lowpass_t
lp_short
,
lp_long
;
spll_lock_det_t
ld
;
int
align_state
;
int
align_timer
;
int
align_target
;
int
align_step
;
int
align_shift
;
};
void
external_init
(
volatile
struct
spll_external_state
*
s
,
int
ext_ref
,
int
realign_clocks
);
int
external_update
(
struct
spll_external_state
*
s
,
int
tag
,
int
source
);
void
external_start
(
struct
spll_external_state
*
s
);
int
external_locked
(
struct
spll_external_state
*
s
);
void
external_align_fsm
(
struct
spll_external_state
*
s
);
#endif // __SPLL_EXTERNAL_H
softpll/spll_helper.c
View file @
a9966510
...
...
@@ -65,7 +65,6 @@ int helper_update(struct spll_helper_state *s, int tag,
err
=
HELPER_ERROR_CLAMP
;
}
// err = biquad_update(&s->precomp, err);
if
((
tag
+
s
->
p_adder
)
>
HELPER_TAG_WRAPAROUND
&&
s
->
p_setpoint
>
HELPER_TAG_WRAPAROUND
)
{
...
...
@@ -108,3 +107,15 @@ void helper_start(struct spll_helper_state *s)
spll_enable_tagger
(
s
->
ref_src
,
1
);
spll_debug
(
DBG_EVENT
|
DBG_HELPER
,
DBG_EVT_START
,
1
);
}
void
helper_switch_reference
(
struct
spll_helper_state
*
s
,
int
new_ref
)
{
#if 0
disable_irq();
s->ref-src = 1;
s->tag_d0 = -1;
s->p-addr = 0;
enable_irq();
spll_enable_tagger(s->ref_src, 1);
#endif
}
softpll/spll_helper.h
View file @
a9966510
...
...
@@ -41,5 +41,6 @@ int helper_update(struct spll_helper_state *s, int tag,
int
source
);
void
helper_start
(
struct
spll_helper_state
*
s
);
void
helper_switch_reference
(
struct
spll_helper_state
*
s
,
int
new_ref
);
#endif // __SPLL_HELPER_H
softpll/spll_main.c
View file @
a9966510
...
...
@@ -27,10 +27,10 @@ void mpll_init(struct spll_main_state *s, int id_ref,
s
->
pi
.
y_min
=
5
;
s
->
pi
.
y_max
=
65530
;
s
->
pi
.
anti_windup
=
1
;
s
->
pi
.
bias
=
65
000
;
s
->
pi
.
bias
=
30
000
;
#if defined(CONFIG_WR_SWITCH)
s
->
pi
.
kp
=
1
5
00
;
// / 2;
s
->
pi
.
ki
=
7
;
// / 2;
s
->
pi
.
kp
=
1
1
00
;
// / 2;
s
->
pi
.
ki
=
30
;
// / 2;
#elif defined(CONFIG_WR_NODE)
s
->
pi
.
kp
=
1100
;
// / 2;
s
->
pi
.
ki
=
30
;
// / 2;
...
...
@@ -47,12 +47,16 @@ void mpll_init(struct spll_main_state *s, int id_ref,
s
->
id_out
=
id_out
;
s
->
dac_index
=
id_out
-
spll_n_chan_ref
;
TRACE_DEV
(
"ref %d out %d idx %x"
,
s
->
id_ref
,
s
->
id_out
,
s
->
dac_index
);
pi_init
((
spll_pi_t
*
)
&
s
->
pi
);
ld_init
((
spll_lock_det_t
*
)
&
s
->
ld
);
}
void
mpll_start
(
struct
spll_main_state
*
s
)
{
TRACE_DEV
(
"MPLL_Start [dac %d]
\n
"
,
s
->
dac_index
);
s
->
adder_ref
=
s
->
adder_out
=
0
;
s
->
tag_ref
=
-
1
;
s
->
tag_out
=
-
1
;
...
...
@@ -83,63 +87,28 @@ int mpll_update(struct spll_main_state *s, int tag, int source)
{
int
err
,
y
;
#ifdef WITH_SEQUENCING
int
new_ref
=
-
1
,
new_out
=
-
1
;
if
(
source
==
s
->
id_ref
)
{
new_ref
=
tag
;
s
->
seq_ref
++
;
}
else
if
(
source
==
s
->
id_out
)
{
new_out
=
tag
;
s
->
seq_out
++
;
}
switch
(
s
->
match_state
)
{
case
MATCH_NEXT_TAG
:
if
(
new_ref
>
0
&&
s
->
seq_out
<
s
->
seq_ref
)
{
s
->
tag_ref
=
new_ref
;
s
->
match_seq
=
s
->
seq_ref
;
s
->
match_state
=
MATCH_WAIT_OUT
;
}
if
(
new_out
>
0
&&
s
->
seq_out
>
s
->
seq_ref
)
{
s
->
tag_out
=
new_out
;
s
->
match_seq
=
s
->
seq_out
;
s
->
match_state
=
MATCH_WAIT_REF
;
}
break
;
case
MATCH_WAIT_REF
:
if
(
new_ref
>
0
&&
s
->
seq_ref
==
s
->
match_seq
)
{
s
->
match_state
=
MATCH_NEXT_TAG
;
s
->
tag_ref
=
new_ref
;
}
break
;
case
MATCH_WAIT_OUT
:
if
(
new_out
>
0
&&
s
->
seq_out
==
s
->
match_seq
)
{
s
->
match_state
=
MATCH_NEXT_TAG
;
s
->
tag_out
=
new_out
;
}
break
;
}
#else
if
(
source
==
s
->
id_ref
)
s
->
tag_ref
=
tag
;
if
(
source
==
s
->
id_out
)
s
->
tag_out
=
tag
;
#endif
if
(
s
->
tag_ref
>=
0
)
{
if
(
s
->
tag_ref_d
>=
0
&&
s
->
tag_ref_d
>
s
->
tag_ref
)
s
->
adder_ref
+=
(
1
<<
TAG_BITS
);
if
(
s
->
tag_ref
>=
0
&&
s
->
tag_out
>=
0
)
{
s
->
tag_ref_d
=
s
->
tag_ref
;
}
if
(
s
->
tag_ref_d
>=
0
&&
s
->
tag_ref_d
>
s
->
tag_ref
)
s
->
adder_ref
+=
(
1
<<
TAG_BITS
);
if
(
s
->
tag_out_d
>=
0
&&
s
->
tag_out_d
>
s
->
tag_out
)
if
(
s
->
tag_out
>=
0
)
{
if
(
s
->
tag_out_d
>=
0
&&
s
->
tag_out_d
>
s
->
tag_out
)
s
->
adder_out
+=
(
1
<<
TAG_BITS
);
s
->
tag_ref_d
=
s
->
tag_ref
;
s
->
tag_out_d
=
s
->
tag_out
;
}
if
(
s
->
tag_ref
>=
0
&&
s
->
tag_out
>=
0
)
{
err
=
s
->
adder_ref
+
s
->
tag_ref
-
s
->
adder_out
-
s
->
tag_out
;
#ifndef WITH_SEQUENCING
...
...
@@ -192,16 +161,39 @@ int mpll_update(struct spll_main_state *s, int tag, int source)
}
if
(
ld_update
((
spll_lock_det_t
*
)
&
s
->
ld
,
err
))
return
SPLL_LOCKED
;
}
return
SPLL_LOCKING
;
}
#ifdef CONFIG_PPSI
/* use __div64_32 from ppsi library to save libgcc memory */
static
int32_t
from_picos
(
int32_t
ps
)
{
extern
uint32_t
__div64_32
(
uint64_t
*
n
,
uint32_t
base
);
uint64_t
ups
=
ps
;
if
(
ps
>=
0
)
{
ups
*=
1
<<
HPLL_N
;
__div64_32
(
&
ups
,
CLOCK_PERIOD_PICOSECONDS
);
return
ups
;
}
ups
=
-
ps
*
(
1
<<
HPLL_N
);
__div64_32
(
&
ups
,
CLOCK_PERIOD_PICOSECONDS
);
return
-
ups
;
}
#else
/* previous implementation: ptp-noposix has no __div64_32 available */
static
int32_t
from_picos
(
int32_t
ps
)
{
return
(
int32_t
)
((
int64_t
)
ps
*
(
int64_t
)
(
1
<<
HPLL_N
)
/
(
int64_t
)
CLOCK_PERIOD_PICOSECONDS
);
}
#endif
int
mpll_set_phase_shift
(
struct
spll_main_state
*
s
,
int
desired_shift
)
int
desired_shift
_ps
)
{
s
->
phase_shift_target
=
desired_shift
;
int
div
=
(
DIVIDE_DMTD_CLOCKS_BY_2
?
2
:
1
);
s
->
phase_shift_target
=
from_picos
(
desired_shift_ps
)
/
div
;
return
0
;
}
...
...
softpll/spll_main.h
View file @
a9966510
...
...
@@ -47,7 +47,7 @@ void mpll_start(struct spll_main_state *s);
int
mpll_update
(
struct
spll_main_state
*
s
,
int
tag
,
int
source
);
int
mpll_set_phase_shift
(
struct
spll_main_state
*
s
,
int
desired_shift
);
int
desired_shift
_ps
);
int
mpll_shifter_busy
(
struct
spll_main_state
*
s
);
...
...
wrc_main.c
View file @
a9966510
...
...
@@ -269,7 +269,7 @@ int main(void)
ui_update
();
wrc_ptp_update
();
spll_update
_aux_clocks
();
spll_update
();
check_stack
();
}
}
wrc_ptp_noposix.c
View file @
a9966510
...
...
@@ -126,6 +126,7 @@ int wrc_ptp_set_mode(int mode)
shw_pps_gen_enable_output
(
0
);
while
(
!
spll_check_lock
(
0
)
&&
lock_timeout
)
{
spll_update
();
timer_delay_ms
(
1000
);
mprintf
(
"."
);
if
(
time_after
(
timer_get_tics
(),
start_tics
+
lock_timeout
))
{
...
...
wrs_main.c
View file @
a9966510
...
...
@@ -14,7 +14,7 @@ int main(void)
uart_init_hw
();
TRACE
(
"WR Switch Real Time Subsystem (c) CERN 2011 - 201
3
\n
"
);
TRACE
(
"WR Switch Real Time Subsystem (c) CERN 2011 - 201
4
\n
"
);
TRACE
(
"Revision: %s, built %s.
\n
"
,
build_revision
,
build_date
);
TRACE
(
"--"
);
...
...
@@ -28,12 +28,12 @@ int main(void)
if
(
time_after
(
tics
,
start_tics
+
TICS_PER_SECOND
/
5
))
{
// TRACE("tick!\n");
spll_show_stats
();
start_tics
=
tics
;
}
rts_update
();
rtipc_action
();
spll_update
();
}
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment