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
ea6fc5c7
Commit
ea6fc5c7
authored
Jan 20, 2020
by
Peter Jansweijer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added support for LTC6950 PLL (SPEC7 Version 2)
parent
59775109
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
274 additions
and
3 deletions
+274
-3
dev.mk
dev/dev.mk
+1
-0
ltc6950.c
dev/ltc6950.c
+193
-0
ltc6950_config.h
dev/ltc6950_config.h
+54
-0
wrc_syscon_regs.h
include/hw/wrc_syscon_regs.h
+13
-1
syscon.h
include/syscon.h
+2
-0
wrc.h
include/wrc.h
+6
-0
wrc_main.c
wrc_main.c
+5
-2
No files found.
dev/dev.mk
View file @
ea6fc5c7
...
...
@@ -8,6 +8,7 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/endpoint.o \
dev/ep_pfilter.o \
dev/i2c.o \
dev/ltc6950.o \
dev/minic.o \
dev/syscon.o \
dev/sfp.o \
...
...
dev/ltc6950.c
0 → 100644
View file @
ea6fc5c7
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2020 CERN/Nikhef (www.cern.ch, www.nikhef.nl)
* Author: Peter Jansweijer <peterj@nikhef.nl>, based on work from
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*
* Trivial pll programmer using an spi controller.
* PLL is LTC6950, SPI is opencores
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <wrc.h>
#include "board.h"
#include "syscon.h"
#ifdef CONFIG_WR_NODE
#else
/* CONFIG_WR_SWITCH */
#include "gpio-wrs.h"
#endif
#include "rt_ipc.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
static
inline
void
writel
(
uint32_t
data
,
void
*
where
)
{
*
(
volatile
uint32_t
*
)
where
=
data
;
}
static
inline
uint32_t
readl
(
void
*
where
)
{
return
*
(
volatile
uint32_t
*
)
where
;
}
struct
ltc6950_reg
{
uint16_t
reg
;
uint8_t
val
;
};
#include "ltc6950_config.h"
/*
* SPI stuff, used by later code
*/
#define SPI_REG_RX0 0
#define SPI_REG_TX0 0
#define SPI_REG_RX1 4
#define SPI_REG_TX1 4
#define SPI_REG_RX2 8
#define SPI_REG_TX2 8
#define SPI_REG_RX3 12
#define SPI_REG_TX3 12
#define SPI_REG_CTRL 16
#define SPI_REG_DIVIDER 20
#define SPI_REG_SS 24
#define SPI_CTRL_ASS (1<<13)
#define SPI_CTRL_IE (1<<12)
#define SPI_CTRL_LSB (1<<11)
#define SPI_CTRL_TXNEG (1<<10)
#define SPI_CTRL_RXNEG (1<<9)
#define SPI_CTRL_GO_BSY (1<<8)
#define SPI_CTRL_CHAR_LEN(x) ((x) & 0x7f)
#define CS_PLL 0
/* LTC6950 on SPI CS0 */
static
int
oc_spi_init
(
void
*
base_addr
)
{
writel
(
100
,
base_addr
+
SPI_REG_DIVIDER
);
return
0
;
}
static
int
oc_spi_txrx
(
void
*
base
,
int
ss
,
int
nbits
,
uint32_t
in
,
uint32_t
*
out
)
{
uint32_t
rval
;
if
(
!
out
)
out
=
&
rval
;
writel
(
SPI_CTRL_ASS
|
SPI_CTRL_CHAR_LEN
(
nbits
)
|
SPI_CTRL_TXNEG
,
base
+
SPI_REG_CTRL
);
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
,
base
+
SPI_REG_CTRL
);
while
(
readl
(
base
+
SPI_REG_CTRL
)
&
SPI_CTRL_GO_BSY
)
;
*
out
=
readl
(
base
+
SPI_REG_RX0
);
return
0
;
}
/*
* LTC6950 stuff, using SPI, used by later code.
* "reg" is 7 bits, "val" is 8 bits, but both are better used as int
* Serial port sequence:
* A6|A5|A4|A3|A2|A1|A0|RW|D7|D6|D5|D4|D3|D2|D1|D0
*/
static
void
ltc6950_write_reg
(
void
*
base
,
int
reg
,
int
val
)
{
oc_spi_txrx
(
base
,
CS_PLL
,
16
,
(
reg
<<
9
)
|
val
,
NULL
);
}
static
int
ltc6950_read_reg
(
void
*
base
,
int
reg
)
{
uint32_t
rval
;
oc_spi_txrx
(
base
,
CS_PLL
,
16
,
(
reg
<<
9
)
|
(
1
<<
8
),
&
rval
);
return
rval
&
0xff
;
}
static
void
ltc6950_load_regset
(
void
*
base
,
const
struct
ltc6950_reg
*
regs
,
int
n_regs
,
int
commit
)
{
int
i
;
for
(
i
=
0
;
i
<
n_regs
;
i
++
)
ltc6950_write_reg
(
base
,
regs
[
i
].
reg
,
regs
[
i
].
val
);
}
static
void
ltc6950_wait_lock
(
void
*
base
)
{
while
((
ltc6950_read_reg
(
base
,
0x00
)
&
4
)
==
0
);
}
static
void
pll_wr_mode_init
(
int
mode
)
{
gpio_out
(
GPIO_PLL_WR_MODE0
,
mode
&
0x01
);
pp_printf
(
"GPIO_PLL_WR_MODE0 %x
\n
"
,
mode
&
0x01
);
gpio_out
(
GPIO_PLL_WR_MODE1
,
mode
&
0x02
);
pp_printf
(
"GPIO_PLL_WR_MODE1 %x
\n
"
,
mode
&
0x02
);
}
#ifdef CONFIG_WR_NODE
int
spec7_ltc6950_init
(
int
pll_wr_mode
)
{
pp_printf
(
"Initializing SPEC7 LTC6950 PLL...
\n
"
);
oc_spi_init
((
void
*
)
BASE_SPI
);
void
*
spi_base
=
(
void
*
)
BASE_SPI
;
/* reset the PLL (RES6950 clears itself)*/
ltc6950_write_reg
(
spi_base
,
0x03
,
4
);
timer_delay
(
10
);
/* Check the presence of the chip */
if
(
ltc6950_read_reg
(
spi_base
,
0x16
)
!=
0x65
)
{
pp_printf
(
"Error: ltc6950 PLL not responding.
\n
"
);
return
-
1
;
}
pll_wr_mode_init
(
pll_wr_mode
);
if
(
pll_wr_mode
==
PLL_WR_MODE_MASTER
|
pll_wr_mode
==
PLL_WR_MODE_GM
)
{
/* Configuration for the SPEC7:
External 10 MHZ In (Bulls-Eye B03/B04) => 125 MHz (PLL_WR_MODE_GM) OR
10 MHZ from TCXO (PLL_WR_MODE_MASTER) on outputs 0, 1, 2
*/
ltc6950_load_regset
(
spi_base
,
ltc6950_10mhz_base_config_spec7
,
ARRAY_SIZE
(
ltc6950_10mhz_base_config_spec7
),
0
);
ltc6950_wait_lock
(
spi_base
);
pp_printf
(
"ltc6950 locked.
\n
"
);
}
else
{
/* Configuration for the SPEC7: Forward 125 MHz VCXO_REFCLK at CLK input to outputs 0, 1, 2 */
ltc6950_load_regset
(
spi_base
,
ltc6950_base_config_spec7
,
ARRAY_SIZE
(
ltc6950_base_config_spec7
),
0
);
timer_delay
(
10
);
}
pp_printf
(
"Switch clk_sys source from free running clk_dmtd to ltc6950 output.
\n
"
);
/* ltc6950 now initialized so switch clk_sys from free running clk_dmtd to ltc6950 output */
gpio_out
(
GPIO_PLL_CLK_SEL
,
1
);
timer_delay
(
1000
);
pp_printf
(
"now running on ref clock.
\n
"
);
}
#endif
dev/ltc6950_config.h
0 → 100644
View file @
ea6fc5c7
/* Configuration for the SPEC7: Forward 125 MHz VCXO_REFCLK at CLK input to outputs 0, 1, 2 */
const
struct
ltc6950_reg
ltc6950_base_config_spec7
[]
=
{
//{0x0000, 0x08}, /* Reg 0 = status info, read only */
{
0x0001
,
0x00
},
/* STAT1 mask */
{
0x0002
,
0x00
},
/* STAT2 mask */
{
0x0003
,
0x70
},
/* Power Down PLL, VCO and REF, no LKEN, Enable OUT[0] */
{
0x0004
,
0xf0
},
/* Power Down OUT[4:3]; Enable OUT[2:1]*/
{
0x0005
,
0x98
},
/* LKWIN = 30ns; LKCT = 128 cycles; cp = 4mA */
{
0x0006
,
0x00
},
/* No ChargePump intervention */
{
0x0007
,
0x00
},
/* No REST_R = 0 */
{
0x0008
,
0x02
},
/* R divider = 2 */
{
0x0009
,
0x00
},
/* No REST_N = 0 */
{
0x000A
,
0x19
},
/* N divider = 25 */
{
0x000B
,
0x41
},
/* SYNCMD = StandAlone; No FILTV/R */
{
0x000C
,
0x80
},
/* set SYNC_EN0; DEL0=0 */
{
0x000D
,
0x81
},
/* set IBIAS0; output divider M0 = 1 */
{
0x000E
,
0x80
},
/* set SYNC_EN1; DEL1=0 */
{
0x000F
,
0x81
},
/* set IBIAS1; output divider M1 = 1 */
{
0x0010
,
0x80
},
/* set SYNC_EN2; DEL2=0 */
{
0x0011
,
0x81
},
/* set IBIAS2; output divider M2 = 1 */
{
0x0012
,
0x00
},
/* no SYNC_EN2; DEL3=0 */
{
0x0013
,
0x01
},
/* no IBIAS3; output divider M3 = 1 */
{
0x0014
,
0x00
},
/* no SYNC_EN4; DEL0=0 */
{
0x0015
,
0x01
}
/* no RDIVOUT; output divider M4 = 1 */
//{0x0016, 0x65} /* Reg 16 = REVision and PARTnumber, read only => 0x65 */
};
/* Configuration for the SPEC7: External 10 MHZ In (Bulls-Eye B03/B04) => 125 MHz on outputs 0, 1, 2 */
const
struct
ltc6950_reg
ltc6950_10mhz_base_config_spec7
[]
=
{
//{0x0000, 0x04}, /* Reg 0 = status info, read only */
{
0x0001
,
0x04
},
/* STAT1 mask LOCK */
{
0x0002
,
0x3b
},
/* STAT2 mask NO_VCO, NO_REF, UNLOCK, THI, TLO*/
{
0x0003
,
0x08
},
/* Power PLL, VCO and REF, set LKEN, Enable OUT[0] */
{
0x0004
,
0xf0
},
/* Power Down OUT[4:3]; Enable OUT[2:1]*/
{
0x0005
,
0x98
},
/* LKWIN = 30ns; LKCT = 128 cycles; cp = 4mA */
{
0x0006
,
0x00
},
/* No ChargePump intervention */
{
0x0007
,
0x00
},
/* No REST_R = 0 */
{
0x0008
,
0x02
},
/* R divider = 2 */
{
0x0009
,
0x00
},
/* No REST_N = 0 */
{
0x000A
,
0x19
},
/* N divider = 25 */
{
0x000B
,
0x41
},
/* SYNCMD = StandAlone; No FILTV/R */
{
0x000C
,
0x80
},
/* set SYNC_EN0; DEL0=0 */
{
0x000D
,
0x81
},
/* set IBIAS0; output divider M0 = 1 */
{
0x000E
,
0x80
},
/* set SYNC_EN1; DEL1=0 */
{
0x000F
,
0x81
},
/* set IBIAS1; output divider M1 = 1 */
{
0x0010
,
0x80
},
/* set SYNC_EN2; DEL2=0 */
{
0x0011
,
0x81
},
/* set IBIAS2; output divider M2 = 1 */
{
0x0012
,
0x00
},
/* no SYNC_EN2; DEL3=0 */
{
0x0013
,
0x01
},
/* no IBIAS3; output divider M3 = 1 */
{
0x0014
,
0x00
},
/* no SYNC_EN4; DEL0=0 */
{
0x0015
,
0x01
}
/* no RDIVOUT; output divider M4 = 1 */
//{0x0016, 0x65} /* Reg 16 = REVision and PARTnumber, read only => 0x65 */
};
include/hw/wrc_syscon_regs.h
View file @
ea6fc5c7
...
...
@@ -3,7 +3,7 @@
* File : wrc_syscon_regs.h
* Author : auto-generated by wbgen2 from wrc_syscon_wb.wb
* Created :
11/22/19 16:40:26
* Created :
01/20/20 09:14:48
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrc_syscon_wb.wb
...
...
@@ -98,6 +98,12 @@
/* definitions for field: PLL_CLK_SEL in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_PLL_CLK_SEL WBGEN2_GEN_MASK(17, 1)
/* definitions for field: PLL_WR_MODE0 in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_PLL_WR_MODE0 WBGEN2_GEN_MASK(18, 1)
/* definitions for field: PLL_WR_MODE1 in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_PLL_WR_MODE1 WBGEN2_GEN_MASK(19, 1)
/* definitions for register: GPIO Clear Register */
/* definitions for field: Status LED in reg: GPIO Clear Register */
...
...
@@ -133,6 +139,12 @@
/* definitions for field: PLL_CLK_SEL in reg: GPIO Clear Register */
#define SYSC_GPCR_PLL_CLK_SEL WBGEN2_GEN_MASK(17, 1)
/* definitions for field: PLL_WR_MODE0 in reg: GPIO Clear Register */
#define SYSC_GPCR_PLL_WR_MODE0 WBGEN2_GEN_MASK(18, 1)
/* definitions for field: PLL_WR_MODE1 in reg: GPIO Clear Register */
#define SYSC_GPCR_PLL_WR_MODE1 WBGEN2_GEN_MASK(19, 1)
/* definitions for register: Hardware Feature Register */
/* definitions for field: Memory size in reg: Hardware Feature Register */
...
...
include/syscon.h
View file @
ea6fc5c7
...
...
@@ -92,6 +92,8 @@ struct SYSCON_WB {
#define GPIO_PLL_LOCK SYSC_GPSR_PLL_LOCK
#define GPIO_PLL_STATUS SYSC_GPSR_PLL_STATUS
#define GPIO_PLL_CLK_SEL SYSC_GPSR_PLL_CLK_SEL
#define GPIO_PLL_WR_MODE0 SYSC_GPSR_PLL_WR_MODE0
#define GPIO_PLL_WR_MODE1 SYSC_GPSR_PLL_WR_MODE1
#define WRPC_FMC_I2C 0
#define WRPC_SFP_I2C 1
...
...
include/wrc.h
View file @
ea6fc5c7
...
...
@@ -48,6 +48,11 @@
# define IS_WR_NODE_SIM 0
#endif
// PLL WR_MODE options:
# define PLL_WR_MODE_MASTER 1
# define PLL_WR_MODE_SLAVE 2
# define PLL_WR_MODE_GM 3
extern
int
wrc_vlan_number
;
int
wrc_mon_gui
(
void
);
...
...
@@ -72,6 +77,7 @@ extern int wrc_ui_refperiod;
/* Init functions and defaults for the wrs build */
int
ad9516_init
(
int
scb_ver
,
int
ljd_present
);
int
spec7_ad9516_init
(
int
ext_10mhz
);
int
spec7_ltc6950_init
(
int
pll_wr_mode
);
int
ljd_ad9516_init
(
void
);
void
rts_init
(
void
);
int
rtipc_init
(
void
);
...
...
wrc_main.c
View file @
ea6fc5c7
...
...
@@ -52,7 +52,9 @@ static uint32_t prev_nanos_for_profile;
static
uint32_t
prev_ticks_for_profile
;
uint32_t
print_task_time_threshold
=
CONFIG_DEFAULT_PRINT_TASK_TIME_THRESHOLD
;
int
ext_10mhz
=
0
;
//int pll_wr_mode = PLL_WR_MODE_MASTER;
//int pll_wr_mode = PLL_WR_MODE_SLAVE;
int
pll_wr_mode
=
PLL_WR_MODE_GM
;
static
void
wrc_initialize
(
void
)
{
...
...
@@ -94,7 +96,8 @@ static void wrc_initialize(void)
mac_addr
[
0
],
mac_addr
[
1
],
mac_addr
[
2
],
mac_addr
[
3
],
mac_addr
[
4
],
mac_addr
[
5
]);
spec7_ad9516_init
(
ext_10mhz
);
//spec7_ad9516_init(ext_10mhz);
spec7_ltc6950_init
(
pll_wr_mode
);
net_rst
();
ep_init
(
mac_addr
);
/* Sleep for 1s to make sure WRS v4.2 always realizes that
...
...
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