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
6
Merge Requests
6
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
b088f445
Commit
b088f445
authored
Dec 21, 2016
by
Mattia Rizzi
Committed by
Grzegorz Daniluk
Aug 15, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Functions and configuration to dialogue with the external AD9516
parent
780ed522
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
191 additions
and
70 deletions
+191
-70
ad9516.c
dev/ad9516.c
+113
-67
ad9516_config.h
dev/ad9516_config.h
+78
-3
No files found.
dev/ad9516.c
View file @
b088f445
...
...
@@ -20,6 +20,7 @@
#include "board.h"
#include "syscon.h"
#include "gpio-wrs.h"
#include "ext-board.h"
#include "rt_ipc.h"
...
...
@@ -75,17 +76,13 @@ struct ad9516_reg {
#define CS_PLL 0
/* AD9516 on SPI CS0 */
static
void
*
oc_spi_base
;
static
int
oc_spi_init
(
void
*
base_addr
)
{
oc_spi_base
=
base_addr
;
writel
(
100
,
oc_spi_base
+
SPI_REG_DIVIDER
);
writel
(
100
,
base_addr
+
SPI_REG_DIVIDER
);
return
0
;
}
static
int
oc_spi_txrx
(
int
ss
,
int
nbits
,
uint32_t
in
,
uint32_t
*
out
)
static
int
oc_spi_txrx
(
void
*
base
,
int
ss
,
int
nbits
,
uint32_t
in
,
uint32_t
*
out
)
{
uint32_t
rval
;
...
...
@@ -94,17 +91,17 @@ static int oc_spi_txrx(int ss, int nbits, uint32_t in, uint32_t *out)
writel
(
SPI_CTRL_ASS
|
SPI_CTRL_CHAR_LEN
(
nbits
)
|
SPI_CTRL_TXNEG
,
oc_spi_
base
+
SPI_REG_CTRL
);
base
+
SPI_REG_CTRL
);
writel
(
in
,
oc_spi_
base
+
SPI_REG_TX0
);
writel
((
1
<<
ss
),
oc_spi_
base
+
SPI_REG_SS
);
writel
(
in
,
base
+
SPI_REG_TX0
);
writel
((
1
<<
ss
),
base
+
SPI_REG_SS
);
writel
(
SPI_CTRL_ASS
|
SPI_CTRL_CHAR_LEN
(
nbits
)
|
SPI_CTRL_TXNEG
|
SPI_CTRL_GO_BSY
,
oc_spi_
base
+
SPI_REG_CTRL
);
base
+
SPI_REG_CTRL
);
while
(
readl
(
oc_spi_
base
+
SPI_REG_CTRL
)
&
SPI_CTRL_GO_BSY
)
while
(
readl
(
base
+
SPI_REG_CTRL
)
&
SPI_CTRL_GO_BSY
)
;
*
out
=
readl
(
oc_spi_
base
+
SPI_REG_RX0
);
*
out
=
readl
(
base
+
SPI_REG_RX0
);
return
0
;
}
...
...
@@ -113,39 +110,39 @@ static int oc_spi_txrx(int ss, int nbits, uint32_t in, uint32_t *out)
* "reg" is 12 bits, "val" is 8 bits, but both are better used as int
*/
static
void
ad9516_write_reg
(
int
reg
,
int
val
)
static
void
ad9516_write_reg
(
void
*
base
,
int
reg
,
int
val
)
{
oc_spi_txrx
(
CS_PLL
,
24
,
(
reg
<<
8
)
|
val
,
NULL
);
oc_spi_txrx
(
base
,
CS_PLL
,
24
,
(
reg
<<
8
)
|
val
,
NULL
);
}
static
int
ad9516_read_reg
(
int
reg
)
static
int
ad9516_read_reg
(
void
*
base
,
int
reg
)
{
uint32_t
rval
;
oc_spi_txrx
(
CS_PLL
,
24
,
(
reg
<<
8
)
|
(
1
<<
23
),
&
rval
);
oc_spi_txrx
(
base
,
CS_PLL
,
24
,
(
reg
<<
8
)
|
(
1
<<
23
),
&
rval
);
return
rval
&
0xff
;
}
static
void
ad9516_load_regset
(
const
struct
ad9516_reg
*
regs
,
int
n_regs
,
int
commit
)
static
void
ad9516_load_regset
(
void
*
base
,
const
struct
ad9516_reg
*
regs
,
int
n_regs
,
int
commit
)
{
int
i
;
for
(
i
=
0
;
i
<
n_regs
;
i
++
)
ad9516_write_reg
(
regs
[
i
].
reg
,
regs
[
i
].
val
);
ad9516_write_reg
(
base
,
regs
[
i
].
reg
,
regs
[
i
].
val
);
if
(
commit
)
ad9516_write_reg
(
0x232
,
1
);
ad9516_write_reg
(
base
,
0x232
,
1
);
}
static
void
ad9516_wait_lock
(
void
)
static
void
ad9516_wait_lock
(
void
*
base
)
{
while
((
ad9516_read_reg
(
0x1f
)
&
1
)
==
0
);
while
((
ad9516_read_reg
(
base
,
0x1f
)
&
1
)
==
0
);
}
#define SECONDARY_DIVIDER 0x100
static
int
ad9516_set_output_divider
(
int
output
,
int
ratio
,
int
phase_offset
)
static
int
ad9516_set_output_divider
(
void
*
spi_base
,
int
output
,
int
ratio
,
int
phase_offset
)
{
uint8_t
lcycles
=
(
ratio
/
2
)
-
1
;
uint8_t
hcycles
=
(
ratio
-
(
ratio
/
2
))
-
1
;
...
...
@@ -158,12 +155,12 @@ static int ad9516_set_output_divider(int output, int ratio, int phase_offset)
if
(
ratio
==
1
)
/* bypass the divider */
{
uint8_t
div_ctl
=
ad9516_read_reg
(
base
+
1
);
ad9516_write_reg
(
base
+
1
,
div_ctl
|
(
1
<<
7
)
|
(
phase_offset
&
0xf
));
uint8_t
div_ctl
=
ad9516_read_reg
(
spi_base
,
base
+
1
);
ad9516_write_reg
(
spi_base
,
base
+
1
,
div_ctl
|
(
1
<<
7
)
|
(
phase_offset
&
0xf
));
}
else
{
uint8_t
div_ctl
=
ad9516_read_reg
(
base
+
1
);
ad9516_write_reg
(
base
+
1
,
(
div_ctl
&
(
~
(
1
<<
7
)))
|
(
phase_offset
&
0xf
));
/* disable bypass bit */
ad9516_write_reg
(
base
,
(
lcycles
<<
4
)
|
hcycles
);
uint8_t
div_ctl
=
ad9516_read_reg
(
spi_base
,
base
+
1
);
ad9516_write_reg
(
spi_base
,
base
+
1
,
(
div_ctl
&
(
~
(
1
<<
7
)))
|
(
phase_offset
&
0xf
));
/* disable bypass bit */
ad9516_write_reg
(
spi_base
,
base
,
(
lcycles
<<
4
)
|
hcycles
);
}
}
else
{
/* LVDS/CMOS outputs */
...
...
@@ -174,16 +171,16 @@ static int ad9516_set_output_divider(int output, int ratio, int phase_offset)
if
(
!
secondary
)
{
if
(
ratio
==
1
)
/* bypass the divider 1 */
ad9516_write_reg
(
base
+
3
,
ad9516_read_reg
(
base
+
3
)
|
0x10
);
ad9516_write_reg
(
spi_base
,
base
+
3
,
ad9516_read_reg
(
spi_base
,
base
+
3
)
|
0x10
);
else
{
ad9516_write_reg
(
base
,
(
lcycles
<<
4
)
|
hcycles
);
ad9516_write_reg
(
base
+
1
,
phase_offset
&
0xf
);
ad9516_write_reg
(
spi_base
,
base
,
(
lcycles
<<
4
)
|
hcycles
);
ad9516_write_reg
(
spi_base
,
base
+
1
,
phase_offset
&
0xf
);
}
}
else
{
if
(
ratio
==
1
)
/* bypass the divider 2 */
ad9516_write_reg
(
base
+
3
,
ad9516_read_reg
(
base
+
3
)
|
0x20
);
ad9516_write_reg
(
spi_base
,
base
+
3
,
ad9516_read_reg
(
spi_base
,
base
+
3
)
|
0x20
);
else
{
ad9516_write_reg
(
base
+
2
,
(
lcycles
<<
4
)
|
hcycles
);
ad9516_write_reg
(
spi_base
,
base
+
2
,
(
lcycles
<<
4
)
|
hcycles
);
// ad9516_write_reg(base + 1, phase_offset & 0xf);
}
...
...
@@ -191,33 +188,45 @@ static int ad9516_set_output_divider(int output, int ratio, int phase_offset)
}
/* update */
ad9516_write_reg
(
0x232
,
0x0
);
ad9516_write_reg
(
0x232
,
0x1
);
ad9516_write_reg
(
0x232
,
0x0
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x1
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
return
0
;
}
static
int
ad9516_set_vco_divider
(
int
ratio
)
/* Sets the VCO divider (2..6) or 0 to enable static output */
static
int
ad9516_set_vco_divider
(
void
*
spi_base
,
int
ratio
)
/* Sets the VCO divider (2..6) or 0 to enable static output */
{
if
(
ratio
==
0
)
ad9516_write_reg
(
0x1e0
,
0x5
);
/* static mode */
ad9516_write_reg
(
spi_base
,
0x1e0
,
0x5
);
/* static mode */
else
ad9516_write_reg
(
0x1e0
,
(
ratio
-
2
));
ad9516_write_reg
(
0x232
,
0x1
);
ad9516_write_reg
(
spi_base
,
0x1e0
,
(
ratio
-
2
));
ad9516_write_reg
(
spi_base
,
0x232
,
0x1
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
return
0
;
}
static
void
ad9516_sync_outputs
(
void
)
static
void
ad9516_sync_outputs
(
void
*
spi_base
)
{
/* VCO divider: static mode */
ad9516_write_reg
(
0x1E0
,
0x7
);
ad9516_write_reg
(
0x232
,
0x1
);
ad9516_write_reg
(
spi_base
,
0x1E0
,
0x7
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x1
);
/* Sync the outputs when they're inactive to avoid +-1 cycle uncertainity */
ad9516_write_reg
(
0x230
,
1
);
ad9516_write_reg
(
0x232
,
1
);
ad9516_write_reg
(
0x230
,
0
);
ad9516_write_reg
(
0x232
,
1
);
ad9516_write_reg
(
spi_base
,
0x230
,
1
);
ad9516_write_reg
(
spi_base
,
0x232
,
1
);
ad9516_write_reg
(
spi_base
,
0x230
,
0
);
ad9516_write_reg
(
spi_base
,
0x232
,
1
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
}
int
ext_ad9516_locked
(
void
)
{
if
((
ad9516_read_reg
((
void
*
)
BASE_SPI_EXT_BOARD
,
0x1f
)
&
1
))
return
1
;
return
0
;
}
int
ad9516_init
(
int
scb_version
)
...
...
@@ -225,6 +234,8 @@ int ad9516_init(int scb_version)
pp_printf
(
"Initializing AD9516 PLL...
\n
"
);
oc_spi_init
((
void
*
)
BASE_SPI
);
void
*
spi_base
=
(
void
*
)
BASE_SPI
;
gpio_out
(
GPIO_SYS_CLK_SEL
,
0
);
/* switch to the standby reference clock, since the PLL is off after reset */
...
...
@@ -235,30 +246,31 @@ int ad9516_init(int scb_version)
timer_delay
(
10
);
/* Use unidirectional SPI mode */
ad9516_write_reg
(
0x000
,
0x99
);
ad9516_write_reg
(
spi_base
,
0x000
,
0x99
);
/* Check the presence of the chip */
if
(
ad9516_read_reg
(
0x3
)
!=
0xc3
)
{
if
(
ad9516_read_reg
(
spi_base
,
0x3
)
!=
0xc3
)
{
pp_printf
(
"Error: AD9516 PLL not responding.
\n
"
);
return
-
1
;
}
if
(
scb_version
>=
34
)
//New SCB v3.4. 10MHz Output.
ad9516_load_regset
(
ad9516_base_config_34
,
ARRAY_SIZE
(
ad9516_base_config_34
),
0
);
ad9516_load_regset
(
spi_base
,
ad9516_base_config_34
,
ARRAY_SIZE
(
ad9516_base_config_34
),
0
);
else
//Old one
ad9516_load_regset
(
ad9516_base_config_33
,
ARRAY_SIZE
(
ad9516_base_config_33
),
0
);
ad9516_load_regset
(
spi_base
,
ad9516_base_config_33
,
ARRAY_SIZE
(
ad9516_base_config_33
),
0
);
ad9516_load_regset
(
ad9516_ref_tcxo
,
ARRAY_SIZE
(
ad9516_ref_tcxo
),
1
);
ad9516_wait_lock
();
ad9516_load_regset
(
spi_base
,
ad9516_ref_tcxo
,
ARRAY_SIZE
(
ad9516_ref_tcxo
),
1
);
ad9516_wait_lock
(
spi_base
);
ad9516_sync_outputs
();
ad9516_sync_outputs
(
spi_base
);
if
(
scb_version
>=
34
)
{
//New SCB v3.4. 10MHz Output.
ad9516_set_output_divider
(
2
,
4
,
0
);
// OUT2. 187.5 MHz. - not anymore
ad9516_set_output_divider
(
3
,
4
,
0
);
// OUT3. 187.5 MHz. - not anymore
ad9516_set_output_divider
(
spi_base
,
2
,
4
,
0
);
// OUT2. 187.5 MHz. - not anymore
ad9516_set_output_divider
(
spi_base
,
3
,
4
,
0
);
// OUT3. 187.5 MHz. - not anymore
ad9516_set_output_divider
(
4
,
1
,
0
);
// OUT4. 500 MHz.
ad9516_set_output_divider
(
spi_base
,
4
,
1
,
0
);
// OUT4. 500 MHz.
ad9516_set_output_divider
(
spi_base
,
9
,
20
,
0
);
/*The following PLL outputs have been configured through the ad9516_base_config_34 register,
* so it doesn't need to replicate the configuration:
...
...
@@ -271,13 +283,13 @@ int ad9516_init(int scb_version)
}
else
{
//Old one
ad9516_set_output_divider
(
9
,
4
,
0
);
/* AUX/SWCore = 187.5 MHz */
//not needed anymore
ad9516_set_output_divider
(
7
,
8
,
0
);
/* REF = 62.5 MHz */
ad9516_set_output_divider
(
4
,
8
,
0
);
/* GTX = 62.5 MHz */
ad9516_set_output_divider
(
spi_base
,
9
,
4
,
0
);
/* AUX/SWCore = 187.5 MHz */
//not needed anymore
ad9516_set_output_divider
(
spi_base
,
7
,
8
,
0
);
/* REF = 62.5 MHz */
ad9516_set_output_divider
(
spi_base
,
4
,
8
,
0
);
/* GTX = 62.5 MHz */
}
ad9516_sync_outputs
();
ad9516_set_vco_divider
(
3
);
ad9516_sync_outputs
(
spi_base
);
ad9516_set_vco_divider
(
spi_base
,
3
);
pp_printf
(
"AD9516 locked.
\n
"
);
...
...
@@ -288,6 +300,40 @@ int ad9516_init(int scb_version)
return
0
;
}
int
ext_ad9516_init
(
void
)
{
pp_printf
(
"Initializing external AD9516 PLL...
\n
"
);
oc_spi_init
((
void
*
)
BASE_SPI_EXT_BOARD
);
void
*
spi_base
=
(
void
*
)
BASE_SPI_EXT_BOARD
;
/* reset the PLL */
gpio_out
(
GPIO_EXT_PLL_RESET_N
,
0
);
timer_delay
(
10
);
gpio_out
(
GPIO_EXT_PLL_RESET_N
,
1
);
timer_delay
(
10
);
/* Use unidirectional SPI mode */
ad9516_write_reg
((
void
*
)
spi_base
,
0x000
,
0x99
);
/* Check the presence of the chip */
if
(
ad9516_read_reg
((
void
*
)
spi_base
,
0x3
)
!=
0xc3
)
{
pp_printf
(
"Error: External AD9516 PLL not responding.
\n
"
);
return
-
1
;
}
ad9516_write_reg
(
spi_base
,
0x018
,
0x0
);
// reset VCO calibration
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x1
);
ad9516_write_reg
(
spi_base
,
0x232
,
0x0
);
ad9516_set_vco_divider
(
spi_base
,
3
);
ad9516_load_regset
(
spi_base
,
ad9516_ext_base_config
,
ARRAY_SIZE
(
ad9516_ext_base_config
),
1
);
ad9516_set_output_divider
(
spi_base
,
6
,
8
,
0
);
// OUT6. 62.5MHz
ad9516_set_output_divider
(
spi_base
,
8
,
20
,
0
);
// OUT6. 62.5MHz
return
0
;
}
int
rts_debug_command
(
int
command
,
int
value
)
{
...
...
@@ -296,13 +342,13 @@ int rts_debug_command(int command, int value)
case
RTS_DEBUG_ENABLE_SERDES_CLOCKS
:
if
(
value
)
{
ad9516_write_reg
(
0xf4
,
0x08
);
// OUT4 enabled
ad9516_write_reg
(
0x232
,
0x0
);
ad9516_write_reg
(
0x232
,
0x1
);
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0xf4
,
0x08
);
// OUT4 enabled
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0x232
,
0x0
);
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0x232
,
0x1
);
}
else
{
ad9516_write_reg
(
0xf4
,
0x0a
);
// OUT4 power-down, no serdes clock
ad9516_write_reg
(
0x232
,
0x0
);
ad9516_write_reg
(
0x232
,
0x1
);
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0xf4
,
0x0a
);
// OUT4 power-down, no serdes clock
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0x232
,
0x0
);
ad9516_write_reg
(
(
void
*
)
BASE_SPI
,
0x232
,
0x1
);
}
break
;
}
...
...
dev/ad9516_config.h
View file @
b088f445
...
...
@@ -78,7 +78,7 @@ const struct ad9516_reg ad9516_base_config_34[] = {
{
0x0003
,
0xC3
},
{
0x0004
,
0x00
},
{
0x0010
,
0x7C
},
{
0x0011
,
0x0
5
},
{
0x0011
,
0x0
4
},
{
0x0012
,
0x00
},
{
0x0013
,
0x0C
},
{
0x0014
,
0x12
},
...
...
@@ -143,10 +143,85 @@ const struct ad9516_reg ad9516_base_config_34[] = {
{
0x0231
,
0x00
},
};
/* Configuration for the SCB version greater than or equal 3.4: Base + 6, 7, 8, 9 outputs*/
const
struct
ad9516_reg
ad9516_ext_base_config
[]
=
{
{
0x0000
,
0x99
},
{
0x0001
,
0x00
},
{
0x0002
,
0x10
},
{
0x0003
,
0xC3
},
{
0x0004
,
0x00
},
{
0x0010
,
0x4C
},
{
0x0011
,
0x00
},
{
0x0012
,
0x00
},
{
0x0013
,
0x06
},
{
0x0014
,
0x12
},
{
0x0015
,
0x00
},
{
0x0016
,
0x04
},
{
0x0017
,
0x00
},
{
0x0018
,
0x07
},
{
0x0019
,
0x00
},
{
0x001A
,
0x00
},
{
0x001B
,
0x00
},
{
0x001C
,
0x01
},
{
0x001D
,
0x00
},
{
0x001E
,
0x00
},
{
0x001F
,
0x0E
},
{
0x00A0
,
0x01
},
{
0x00A1
,
0x00
},
{
0x00A2
,
0x00
},
{
0x00A3
,
0x01
},
{
0x00A4
,
0x00
},
{
0x00A5
,
0x00
},
{
0x00A6
,
0x01
},
{
0x00A7
,
0x00
},
{
0x00A8
,
0x00
},
{
0x00A9
,
0x01
},
{
0x00AA
,
0x00
},
{
0x00AB
,
0x00
},
{
0x00F0
,
0x0A
},
{
0x00F1
,
0x0A
},
{
0x00F2
,
0x0A
},
{
0x00F3
,
0x0A
},
{
0x00F4
,
0x08
},
{
0x00F5
,
0x08
},
// The following registers configure the PLL outputs from 6 to 9.
{
0x0140
,
0x42
},
{
0x0141
,
0x42
},
{
0x0142
,
0x08
},
{
0x0143
,
0x4E
},
{
0x0190
,
0x55
},
{
0x0191
,
0x00
},
{
0x0192
,
0x00
},
{
0x0193
,
0x11
},
{
0x0194
,
0x00
},
{
0x0195
,
0x00
},
{
0x0196
,
0x10
},
{
0x0197
,
0x00
},
{
0x0198
,
0x00
},
{
0x0199
,
0x33
},
{
0x019A
,
0x00
},
{
0x019B
,
0x11
},
{
0x019C
,
0x20
},
{
0x019D
,
0x00
},
{
0x019E
,
0x33
},
{
0x019F
,
0x00
},
{
0x01A0
,
0x11
},
{
0x01A1
,
0x20
},
{
0x01A2
,
0x00
},
{
0x01A3
,
0x00
},
//
{
0x01E0
,
0x01
},
{
0x01E1
,
0x02
},
{
0x0230
,
0x00
},
{
0x0231
,
0x00
},
};
/* Config for 25 MHz VCTCXO reference (RDiv = 5, use REF1) */
const
struct
ad9516_reg
ad9516_ref_tcxo
[]
=
{
{
0x0011
,
0x0
5
},
{
0x0012
,
0x00
},
/* RDiv =
5
*/
{
0x0011
,
0x0
4
},
{
0x0012
,
0x00
},
/* RDiv =
4
*/
{
0x001C
,
0x06
}
/* Use REF1 */
};
...
...
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