1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#
# Copyright 2018 Ettus Research, a National Instruments Company
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
"""
DS125DF410 driver class
For use with TI's retimer chip
"""
import math
from builtins import object
from usrp_mpm.mpmlog import get_logger
LINE_RATE_PRESETS = {'Ethernet': 0xF6, 'CPRI1': 0x36, 'CPRI2': 0x46}
ALL_CHANS = range(4)
class DS125DF410(object):
"""
Driver class for DS125DF410 access.
Inputs:
regs_iface : regs_iface bus driver to access device
parent_log : logger of parent
"""
# (deemphasis, swing)
DRIVER_PRESETS = {}
def __init__(self, regs_iface, parent_log=None):
self.log = \
parent_log.getChild("DS125DF410") if parent_log is not None \
else get_logger("DS125DF410")
self.regs_iface = regs_iface
# Set channel select register to control set
self.regs_iface.poke8(0xFF, 0)
# Probe chip ID
chip_id = self.regs_iface.peek8(0x01)
assert chip_id == 0xd1
self.log.debug("Probed DS125DF410 retimer")
for chan in ALL_CHANS:
self._set_chan_select(chan)
# Reset channel registers
self.regs_iface.poke8(0x00, 0x04)
# Enable DFE mode
self.regs_iface.poke8(0x1E, 0xE1)
self.regs_iface.poke8(0x31, 0x40)
def _rmw(self, addr, data, mask):
""" Read, modify, write """
base = self.regs_iface.peek8(addr) & ~mask
data = (data & mask) | base
self.regs_iface.poke8(addr, data)
def _set_chan_select(self, chan):
"""
Channel select
"""
assert chan in ALL_CHANS
self.regs_iface.poke8(0xFF, chan + 4)
def set_rate_preset(self, preset, channels=None):
"""
Set rate preset
"""
channels = channels or ALL_CHANS
assert preset in LINE_RATE_PRESETS.keys()
for chan in channels:
self._set_chan_select(chan)
self.regs_iface.poke8(0x2F, LINE_RATE_PRESETS[preset])
def set_rate(self, rate, channels=None):
"""
Set rate
"""
channels = channels or ALL_CHANS
self.log.trace("Writing custom line rate {}".format(rate))
ppm_val = int(math.ceil(rate*1280.0))
assert ppm_val <= 0x7FFF
for chan in channels:
assert chan in ALL_CHANS
self._set_chan_select(chan)
# Set VCO divider to 1
self.regs_iface.poke8(0x2F, 0xC6)
# Set frequency range detection
self.regs_iface.poke8(0x60, (ppm_val & 0x00FF))
self.regs_iface.poke8(0x62, (ppm_val & 0x00FF))
self.regs_iface.poke8(0x61, 0x80 | ((ppm_val >> 8) & 0x00FF))
self.regs_iface.poke8(0x63, 0x80 | ((ppm_val >> 8) & 0x00FF))
# Set VCO tolerance range to max
self.regs_iface.poke8(0x64, 0xFF)
def set_driver_preset(self, preset, channels=None):
"""
Set driver preset
"""
channels = channels or ALL_CHANS
assert preset in self.DRIVER_PRESETS.keys()
self.log.trace("Setting retimer's driver for " + preset + " preset")
deemphasis, swing = self.DRIVER_PRESETS[preset]
for chan in channels:
self._set_chan_select(chan)
self._rmw(0x15, deemphasis, 0x47)
self._rmw(0x2D, swing, 0x07)
|