Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit Switch - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
86
Issues
86
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
White Rabbit Switch - Software
Commits
55c40f75
Commit
55c40f75
authored
Jan 24, 2012
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
userspace: stripped down libswitchhw to a bare minimum
parent
df8edea4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1 addition
and
7724 deletions
+1
-7724
Makefile
userspace/libswitchhw/Makefile
+1
-3
ad9516.c
userspace/libswitchhw/ad9516.c
+0
-292
ad9516_default_regs.h
userspace/libswitchhw/ad9516_default_regs.h
+0
-157
clkb_io.c
userspace/libswitchhw/clkb_io.c
+0
-116
fpga_io.c
userspace/libswitchhw/fpga_io.c
+0
-61
init.c
userspace/libswitchhw/init.c
+0
-24
lzoconf.h
userspace/libswitchhw/minilzo/lzoconf.h
+0
-417
lzodefs.h
userspace/libswitchhw/minilzo/lzodefs.h
+0
-1807
minilzo.c
userspace/libswitchhw/minilzo/minilzo.c
+0
-4112
minilzo.h
userspace/libswitchhw/minilzo/minilzo.h
+0
-106
pio.c
userspace/libswitchhw/pio.c
+0
-214
pio_pins.c
userspace/libswitchhw/pio_pins.c
+0
-159
xpoint.c
userspace/libswitchhw/xpoint.c
+0
-256
No files found.
userspace/libswitchhw/Makefile
View file @
55c40f75
...
...
@@ -3,9 +3,7 @@ CC = $(CROSS_COMPILE)gcc
AR
=
$(CROSS_COMPILE)
ar
CFLAGS
=
-I
.
-O2
-I
../include
-DDEBUG
-I
./minilzo
OBJS
=
pio.o pio_pins.o trace.o init.o fpga_io.o util.o ad9516.o
\
fpgaboot.o minilzo/minilzo.o clkb_io.o xpoint.o
\
mblaster.o pps_gen.o
OBJS
=
trace.o init.o fpga_io.o util.o pps_gen.o
LIB
=
libswitchhw.a
...
...
userspace/libswitchhw/ad9516.c
deleted
100644 → 0
View file @
df8edea4
/* Analog Devices AD9516-4 PLL driver */
#include <math.h>
#include <hw/pio.h>
#include <hw/trace.h>
#include <hw/ad9516.h>
/* SPI bit delay, in microseconds */
#define SPI_DELAY 50
#define AD9516_OP_READ 0x80
#define AD9516_OP_WRITE 0x00
#define AD9516_MAX_REGS 1024
struct
ad9516_regs
{
struct
{
uint16_t
addr
;
uint8_t
value
;
}
regs
[
AD9516_MAX_REGS
];
int
nregs
;
};
int
shw_ad9516_set_output_delay
(
int
output
,
float
delay_ns
,
int
bypass
);
/* for the standard PLL setups - generated by Analog Devices' software */
#include "ad9516_default_regs.h"
/* Indicates whether to generate the reference clock from the local VCTCXO (0)
or the external 10 MHz input (cesium, etc. - 1) */
static
int
use_ext_ref
=
0
;
/* Enables/disables locking the 125 MHz reference clock to an externally provided
10 Mhz Reference (when enable = 1). Otherwise, the reference clock is produced
from the local voltage controlled oscillator (which can be locked by the DMPLL
to a reference from one of the uplink ports.
Note: can *ONLY* be called before initializing the libswitchhw. Reference source
cannot be switched on-the-fly. */
int
shw_use_external_reference
(
int
enable
)
{
if
(
enable
)
TRACE
(
TRACE_INFO
,
"Using external 10 MHz reference clock (grandmaster mode)"
);
use_ext_ref
=
enable
;
}
/* Reads a byte from the AD9516 SPI interface by bit-banging the CPU pins */
static
uint8_t
ad9516_spi_read8
()
{
uint8_t
rx
=
0
;
int
i
;
shw_pio_setdir
(
PIN_ad9516_sdio
,
PIO_IN
);
shw_pio_set0
(
PIN_ad9516_sclk
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
shw_udelay
(
SPI_DELAY
);
rx
<<=
1
;
if
(
shw_pio_get
(
PIN_ad9516_sdio
))
rx
|=
1
;
shw_udelay
(
SPI_DELAY
);
shw_pio_set1
(
PIN_ad9516_sclk
);
shw_udelay
(
SPI_DELAY
);
shw_pio_set0
(
PIN_ad9516_sclk
);
}
shw_udelay
(
SPI_DELAY
);
return
rx
;
}
/* Writes a byte (tx) to the AD9516 SPI interface by bit-banging the CPU pins */
static
uint8_t
ad9516_spi_write8
(
uint8_t
tx
)
{
int
i
;
shw_pio_setdir
(
PIN_ad9516_sdio
,
PIO_OUT
);
shw_pio_set0
(
PIN_ad9516_sclk
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
shw_udelay
(
SPI_DELAY
);
shw_pio_set
(
PIN_ad9516_sdio
,
tx
&
0x80
);
tx
<<=
1
;
shw_udelay
(
SPI_DELAY
);
shw_pio_set1
(
PIN_ad9516_sclk
);
shw_udelay
(
SPI_DELAY
);
shw_pio_set0
(
PIN_ad9516_sclk
);
}
shw_udelay
(
SPI_DELAY
);
}
/* Reads an AD9516 register from address addr and returns its 8-bit value */
static
uint8_t
ad9516_read_reg
(
uint16_t
addr
)
{
uint8_t
val
;
shw_pio_set0
(
PIN_ad9516_cs
);
shw_udelay
(
SPI_DELAY
);
ad9516_spi_write8
(
AD9516_OP_READ
|
(
addr
>>
8
));
ad9516_spi_write8
(
addr
&
0xff
);
val
=
ad9516_spi_read8
();
shw_udelay
(
SPI_DELAY
);
shw_pio_set1
(
PIN_ad9516_cs
);
shw_udelay
(
SPI_DELAY
);
return
val
;
}
/* Writes AD9516 register located at addr with value data */
static
void
ad9516_write_reg
(
uint16_t
addr
,
uint8_t
data
)
{
shw_pio_set0
(
PIN_ad9516_cs
);
shw_udelay
(
SPI_DELAY
);
ad9516_spi_write8
(
AD9516_OP_WRITE
|
(
addr
>>
8
));
ad9516_spi_write8
(
addr
&
0xff
);
ad9516_spi_write8
(
data
);
shw_udelay
(
SPI_DELAY
);
shw_pio_set1
(
PIN_ad9516_cs
);
shw_udelay
(
SPI_DELAY
);
}
/* Performs a HW reset of the AD9516 by asserting it's RSTN pin */
static
void
ad9516_reset
()
{
shw_pio_set0
(
PIN_ad9516_nrst
);
shw_udelay
(
100
);
shw_pio_set1
(
PIN_ad9516_nrst
);
shw_udelay
(
100
);
}
/* Checks for the presence of 10 MHz external reference signal on the AD9516 ref input.
Returns non-zero if the signal is present. */
int
ad9516_detect_external_ref
()
{
ad9516_write_reg
(
0x4
,
0x1
);
// readback active regs
ad9516_write_reg
(
0x1c
,
0x06
);
// enable ref1/reg2
ad9516_write_reg
(
0x1b
,
0xe0
);
// enable refin monitor
ad9516_write_reg
(
0x232
,
1
);
// commit
usleep
(
200000
);
return
ad9516_read_reg
(
0x1f
)
;
}
/* Loads and updates the configuration provided in "regs" into the AD9516. */
static
int
ad9516_load_state
(
const
struct
ad9516_regs
*
regs
)
{
int
i
;
TRACE
(
TRACE_INFO
,
"Loading AD9516 state (%d registers)"
,
regs
->
nregs
);
for
(
i
=
0
;
i
<
regs
->
nregs
;
i
++
)
ad9516_write_reg
(
regs
->
regs
[
i
].
addr
,
regs
->
regs
[
i
].
value
);
/* Trigger the actual register reload (regs are just buffered after being written),
in order to load the new values simultaneously one must trigger an update. */
ad9516_write_reg
(
AD9516_UPDATE_ALL
,
1
);
return
0
;
}
/* Checks if the PLL is locked (digital lock detection). Returns non-zero if true */
static
int
ad9516_check_lock
()
{
uint8_t
pll_readback
=
ad9516_read_reg
(
AD9516_PLLREADBACK
);
return
pll_readback
&
1
;
}
#define assert_init(proc) { int ret; if((ret = proc) < 0) return ret; }
/* Initializes the AD9516: sets up the reference source, PLL multiply/divide ratios,
enables clock outputs. */
int
shw_ad9516_init
()
{
int
retries
=
100
;
TRACE
(
TRACE_INFO
,
"Initializing AD9516 PLL...."
);
/* The AD9516 uses CPU GPIO pins (it couldn't be connected to the FPGA,
because it supplies clock for it (and a clock-less FPGA wouldn't work). */
shw_pio_configure
(
PIN_ad9516_cs
);
shw_pio_configure
(
PIN_ad9516_nrst
);
shw_pio_configure
(
PIN_ad9516_refsel
);
shw_pio_configure
(
PIN_ad9516_sclk
);
shw_pio_configure
(
PIN_ad9516_sdio
);
shw_pio_configure
(
PIN_ad9516_sdo
);
/* Make sure the pins are stable after the configuration (no glitches, etc.) */
shw_udelay
(
100
);
/* Reset AD9516 and give it some time to recover */
ad9516_reset
();
shw_udelay
(
10000
);
/* Detect the presence by comparing a read register with it's reset value */
if
(
ad9516_read_reg
(
AD9516_SERIALPORT
)
!=
0x18
)
{
TRACE
(
TRACE_FATAL
,
"AD9516 not responding!"
);
return
-
1
;
}
/* Now just initialize. There are two pre-defined register sets, one for
the internal 25 MHz VCTCXO and the other for 10 MHz GPS/Cesium external reference */
if
(
use_ext_ref
)
{
assert_init
(
ad9516_load_state
(
&
ad9516_regs_ext_10m
));
}
else
{
assert_init
(
ad9516_load_state
(
&
ad9516_regs_tcxo_25m
));
}
/* Wait for the PLL to lock. */
while
(
retries
--
)
{
if
(
ad9516_check_lock
())
break
;
shw_udelay
(
1000
);
}
/* Signal integrity bugfix: delay Uplink 0 PHY clock a bit (to increase tSetup on
the PHY TX inputs */
shw_ad9516_set_output_delay
(
9
,
0
.
5
,
0
);
return
0
;
}
/* Finds the parameters of the output skew adjustment unit of AD9516 for a given delay value. */
static
int
find_optimal_params
(
float
delay_ns
,
int
*
caps
,
int
*
frac
,
int
*
ramp
,
float
*
best
)
{
int
r
,
i
,
ncaps
,
f
;
float
best_error
=
10000
;
for
(
r
=
0
;
r
<
8
;
r
++
)
{
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
i
==
0
)
ncaps
=
0
;
else
if
(
i
==
1
||
i
==
2
||
i
==
4
)
ncaps
=
1
;
else
if
(
i
==
3
||
i
==
6
||
i
==
5
)
ncaps
=
2
;
else
ncaps
=
3
;
for
(
f
=
0
;
f
<=
0x2f
;
f
++
)
{
float
iramp
=
(
float
)(
r
+
1
)
*
200
.
0
;
float
del_range
=
200
.
0
*
((
float
)(
ncaps
+
3
)
/
iramp
)
*
1
.
3286
;
float
offset
=
0
.
34
+
(
1600
.
0
-
iramp
)
*
10e-4
+
(
float
)(
ncaps
-
1
)
/
iramp
*
6
.
0
;
// printf("range: %.3f offset %.3f\n", del_range, offset);
float
del_fine
=
del_range
*
(
float
)
f
/
63
.
0
+
offset
;
if
(
fabs
(
del_fine
-
delay_ns
)
<
best_error
)
{
// printf("New Best: %.3f\n", del_fine);
best_error
=
fabs
(
del_fine
-
delay_ns
);
*
best
=
del_fine
;
*
caps
=
i
;
*
ramp
=
r
;
*
frac
=
f
;
}
}
}
}
}
/* Sets the extra delay on given output to delay_ns. Used for de-skewing clocks.
When bypass is 1, the delay block is disabled. */
int
shw_ad9516_set_output_delay
(
int
output
,
float
delay_ns
,
int
bypass
)
{
uint16_t
regbase
=
0xa0
+
3
*
(
output
-
6
);
int
ramp
,
frac
,
caps
;
float
best_dly
;
find_optimal_params
(
delay_ns
,
&
caps
,
&
frac
,
&
ramp
,
&
best_dly
);
ad9516_write_reg
(
regbase
,
bypass
?
1
:
0
);
ad9516_write_reg
(
regbase
+
1
,
(
caps
<<
3
)
|
(
ramp
));
ad9516_write_reg
(
regbase
+
2
,
frac
);
ad9516_write_reg
(
AD9516_UPDATE_ALL
,
1
);
/* Acknowledge register update */
return
0
;
}
userspace/libswitchhw/ad9516_default_regs.h
deleted
100644 → 0
View file @
df8edea4
/* Pre-defined AD9516 PLL configs, both for 25 MHz TCXO and external 10 MHz reference. */
static
const
struct
ad9516_regs
ad9516_regs_tcxo_25m
=
{
{
{
0x0018
,
0x00
},
{
0x0232
,
0x00
},
{
0x0000
,
0x18
},
{
0x0001
,
0x00
},
{
0x0002
,
0x10
},
{
0x0003
,
0xc3
},
{
0x0004
,
0x00
},
{
0x0010
,
0x7c
},
{
0x0011
,
5
},
// R div
{
0x0012
,
0x00
},
{
0x0013
,
12
},
// A div
{
0x0014
,
18
},
// B div -- vco =
{
0x0015
,
0x00
},
{
0x0016
,
5
},
// 16/17 mode
{
0x0017
,
0x00
},
{
0x0018
,
0x07
},
{
0x0019
,
0x00
},
{
0x001a
,
0x00
},
{
0x001b
,
0x00
},
{
0x001c
,
0x02
},
// back to ref1
{
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
,
0x0a
},
{
0x00f5
,
0x08
},
{
0x0140
,
0x42
},
{
0x0141
,
0x42
},
{
0x0142
,
0x42
},
{
0x0143
,
0x5a
},
{
0x0190
,
0x00
},
{
0x0191
,
0x80
},
{
0x0192
,
0x00
},
{
0x0193
,
0x22
},
{
0x0194
,
0x00
},
{
0x0195
,
0x00
},
{
0x0196
,
0x22
},
{
0x0197
,
0x00
},
{
0x0198
,
0x00
},
{
0x0199
,
0x22
},
{
0x019a
,
0x00
},
{
0x019b
,
0x11
},
{
0x019c
,
0x20
},
{
0x019d
,
0x00
},
{
0x019e
,
0x22
},
{
0x019f
,
0x00
},
{
0x01a0
,
0x11
},
{
0x01a1
,
0x20
},
{
0x01a2
,
0x00
},
{
0x01a3
,
0x00
},
{
0x01e0
,
0x00
},
{
0x01e1
,
0x02
},
{
0x0230
,
0x00
},
{
0x0231
,
0x00
},
{
0x0232
,
0x00
},
{
0x0232
,
0x00
},
{
0
}},
71
};
static
const
struct
ad9516_regs
ad9516_regs_ext_10m
=
{
{
{
0x0018
,
0x00
},
{
0x0232
,
0x00
},
{
0x0000
,
0x18
},
{
0x0001
,
0x00
},
{
0x0002
,
0x10
},
{
0x0003
,
0xc3
},
{
0x0004
,
0x00
},
{
0x0010
,
0x7c
},
{
0x0011
,
2
},
// prescaler R div (2 = 10 MHz, 4 = 20 MHz)
{
0x0012
,
0x00
},
{
0x0013
,
12
},
// A div
{
0x0014
,
18
},
// B div -- vco = 1.5 GHz
{
0x0015
,
0x00
},
{
0x0016
,
5
},
// 16/17 mode
{
0x0017
,
0x00
},
{
0x0018
,
0x07
},
{
0x0019
,
0x00
},
{
0x001a
,
0x00
},
{
0x001b
,
0x00
},
{
0x001c
,
0x44
},
{
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
,
0x0a
},
{
0x00f5
,
0x08
},
{
0x0140
,
0x42
},
{
0x0141
,
0x42
},
{
0x0142
,
0x42
},
{
0x0143
,
0x5a
},
{
0x0190
,
0x00
},
{
0x0191
,
0x80
},
{
0x0192
,
0x00
},
{
0x0193
,
0x22
},
{
0x0194
,
0x00
},
{
0x0195
,
0x00
},
{
0x0196
,
0x22
},
// was 0x32
{
0x0197
,
0x00
},
{
0x0198
,
0x00
},
{
0x0199
,
0x22
},
{
0x019a
,
0x00
},
{
0x019b
,
0x11
},
{
0x019c
,
0x20
},
{
0x019d
,
0x00
},
{
0x019e
,
0x22
},
{
0x019f
,
0x00
},
{
0x01a0
,
0x11
},
{
0x01a1
,
0x20
},
{
0x01a2
,
0x00
},
{
0x01a3
,
0x00
},
{
0x01e0
,
0x00
},
{
0x01e1
,
0x02
},
{
0x0230
,
0x00
},
{
0x0231
,
0x00
},
{
0x0232
,
0x00
},
{
0x0232
,
0x00
},
{
0
}},
71
};
\ No newline at end of file
userspace/libswitchhw/clkb_io.c
deleted
100644 → 0
View file @
df8edea4
/* Routines for accessing the timing FPGA */
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
#include <hw/trace.h>
#include <hw/clkb_io.h>
#include <hw/pio.h>
#define SPI_CLKDIV_VAL 50
#define CLKB_IDCODE 0xdeadbeef
/* Some protos */
int
shw_clkb_write_reg
(
uint32_t
reg
,
uint32_t
val
);
uint32_t
shw_clkb_read_reg
(
uint32_t
reg
);
/* Initializes the SPI link between the main FPGA and the timing FPGA.
clkdiv = SPI SCLK division ratio. */
static
void
cmi_init
(
int
clkdiv
)
{
uint32_t
val
=
SPICTL_ENABLE
(
1
)
|
SPICTL_CLKDIV
(
clkdiv
);
_fpga_writel
(
FPGA_BASE_SPIM
+
SPI_REG_SPICTL
,
val
);
}
/* Returns non-zero if the SPI controller is busy sending/receiving data */
static
inline
int
cmi_busy
()
{
uint32_t
ctl
;
ctl
=
_fpga_readl
(
FPGA_BASE_SPIM
+
SPI_REG_SPICTL
);
return
SPICTL_BUSY
(
ctl
);
}
/* Enables (cs=1) or disables (cs=1) the SPI chip-select line */
static
inline
int
cmi_cs
(
int
cs
)
{
uint32_t
ctl
;
ctl
=
_fpga_readl
(
FPGA_BASE_SPIM
+
SPI_REG_SPICTL
);
if
(
cs
)
ctl
|=
SPICTL_CSEN
(
1
);
else
ctl
|=
SPICTL_CSDIS
(
1
);
_fpga_writel
(
FPGA_BASE_SPIM
+
SPI_REG_SPICTL
,
ctl
);
}
/* Sends/receives a number (n) of 32-bit words (d_in) to/from the timing
FPGA. Received words are stored in (d_out). */
static
void
cmi_transfer
(
uint32_t
*
d_in
,
uint32_t
*
d_out
,
int
n
)
{
int
i
;
uint32_t
ctl
,
tmp
;
while
(
cmi_busy
());
cmi_cs
(
1
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
_fpga_writel
(
FPGA_BASE_SPIM
+
SPI_REG_SPITX
,
d_in
[
i
]);
while
(
cmi_busy
());
tmp
=
_fpga_readl
(
FPGA_BASE_SPIM
+
SPI_REG_SPIRX
);
if
(
d_out
)
d_out
[
i
]
=
tmp
;
}
cmi_cs
(
0
);
}
/* Initializes the Inter-FPGA link (just the link, not the timing FPGA). */
int
shw_clkb_init_cmi
()
{
TRACE
(
TRACE_INFO
,
"initializing Clocking Mezzanine Interface"
);
cmi_init
(
SPI_CLKDIV_VAL
);
return
0
;
}
/* Initializes the Timing FPGA. Currently the initialization is just
resetting the chip. */
int
shw_clkb_init
()
{
shw_pio_configure
(
PIN_clkb_fpga_nrst
);
shw_pio_set0
(
PIN_clkb_fpga_nrst
);
shw_udelay
(
1000
);
shw_pio_set1
(
PIN_clkb_fpga_nrst
);
shw_udelay
(
1000
);
}
/* Writes a 32-bit value (val) to the register (reg) in the Timing FPGA.
Returns 0 on success. */
int
shw_clkb_write_reg
(
uint32_t
reg
,
uint32_t
val
)
{
uint32_t
rx
[
2
],
tx
[
2
];
tx
[
0
]
=
(
reg
>>
2
)
&
0x7fffffff
;
tx
[
1
]
=
val
;
cmi_transfer
(
tx
,
rx
,
2
);
if
(
rx
[
1
]
!=
0xaa
)
{
TRACE
(
TRACE_ERROR
,
"invalid ack (0x%08x)"
,
rx
[
1
]);
return
-
1
;
}
return
0
;
}
/* Reads the value of a 32-bit register (reg) from the Timing FPGA and
returns it. */
uint32_t
shw_clkb_read_reg
(
uint32_t
reg
)
{
uint32_t
rx
[
2
],
tx
[
2
];
tx
[
0
]
=
(
reg
>>
2
)
|
0x80000000
;
tx
[
1
]
=
0xffffffff
;
cmi_transfer
(
tx
,
rx
,
2
);
return
rx
[
1
];
}
userspace/libswitchhw/fpga_io.c
deleted
100644 → 0
View file @
df8edea4
/* Userspace /dev/mem I/O functions for accessing the Main FPGA */
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <fcntl.h>
#include <poll.h>
#include <hw/switch_hw.h>
#define SMC_CS0_BASE 0x70000000
#define SMC_CS0_SIZE 0x200000
#define SPI_CLKDIV_VAL 20 // clock divider for CMI SPI bus clock
/* Virtual base address of the Main FPGA address space. */
volatile
uint8_t
*
_fpga_base_virt
;
/* Initializes the mapping of the Main FPGA to the CPU address space. */
int
shw_fpga_mmap_init
()
{
int
fd
;
TRACE
(
TRACE_INFO
,
"Initializing FPGA memory mapping."
);
fd
=
open
(
"/dev/mem"
,
O_RDWR
);
if
(
!
fd
)
return
-
1
;
_fpga_base_virt
=
mmap
(
NULL
,
SMC_CS0_SIZE
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
SMC_CS0_BASE
);
if
(
_fpga_base_virt
==
NULL
)
{
perror
(
"mmap()"
);
close
(
fd
);
return
-
1
;
}
TRACE
(
TRACE_INFO
,
"FPGA virtual base = 0x%08x"
,
_fpga_base_virt
);
return
0
;
}
/* Resets the Main FPGA. */
void
shw_main_fpga_reset
()
{
shw_pio_set0
(
PIN_main_fpga_nrst
);
usleep
(
10000
);
shw_pio_set1
(
PIN_main_fpga_nrst
);
usleep
(
10000
);
}
/* Initializes the Main FPGA - that means (currently) just resetting it. */
int
shw_main_fpga_init
()
{
shw_pio_configure
(
PIN_main_fpga_nrst
);
shw_main_fpga_reset
();
return
0
;
}
userspace/libswitchhw/init.c
View file @
55c40f75
...
...
@@ -11,31 +11,7 @@ int shw_init()
{
/* Map the the FPGA memory space */
assert_init
(
shw_fpga_mmap_init
());
/* Map the CPU GPIO memory space */
assert_init
(
shw_pio_mmap_init
());
/* Initialize the AD9516 and the clock distribution. Now we can start accessing the FPGAs. */
assert_init
(
shw_ad9516_init
());
/* Initialize the main FPGA */
assert_init
(
shw_main_fpga_init
());
/* Sets up the directions of all CPU GPIO pins */
assert_init
(
shw_pio_configure_all_cpu_pins
());
/* Initialize the bootloader and try to boot up the Main FPGA. */
assert_init
(
shw_fpgaboot_init
());
assert_init
(
shw_boot_fpga
(
FPGA_ID_MAIN
));
/* Initialize the main FPGA and its GPIO controller */
assert_init
(
shw_main_fpga_init
());
assert_init
(
shw_pio_configure_all_fpga_pins
());
/* Initialize the CMI link prior to booting the CLKB FPGA, so the FPGA bootloader could check the REVID. */
assert_init
(
shw_clkb_init_cmi
());
/* Boot up and init the Timing FPGA */
assert_init
(
shw_boot_fpga
(
FPGA_ID_CLKB
));
assert_init
(
shw_clkb_init
());
/* Start-up the PLLs. */
/* no more shw_hpll_init(); */
/* no more shw_dmpll_init(); */
/* Initialize the calibrator (requires the DMTD clock to be operational) */
/* no more shw_cal_init(); */
/* Start-up the PPS generator */
assert_init
(
shw_pps_gen_init
());
/* ... and the SPI link with the watchdog */
/* no more shw_watchdog_init(); */
...
...
userspace/libswitchhw/minilzo/lzoconf.h
deleted
100644 → 0
View file @
df8edea4
This diff is collapsed.
Click to expand it.
userspace/libswitchhw/minilzo/lzodefs.h
deleted
100644 → 0
View file @
df8edea4
This diff is collapsed.
Click to expand it.
userspace/libswitchhw/minilzo/minilzo.c
deleted
100644 → 0
View file @
df8edea4
This diff is collapsed.
Click to expand it.
userspace/libswitchhw/minilzo/minilzo.h
deleted
100644 → 0
View file @
df8edea4
/* minilzo.h -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __MINILZO_H
#define __MINILZO_H
#define MINILZO_VERSION 0x2030
#ifdef __LZOCONF_H
# error "you cannot use both LZO and miniLZO"
#endif
#undef LZO_HAVE_CONFIG_H
#include "lzoconf.h"
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
# error "version mismatch in header files"
#endif
#ifdef __cplusplus
extern
"C"
{
#endif
/***********************************************************************
//
************************************************************************/
/* Memory required for the wrkmem parameter.
* When the required size is 0, you can also pass a NULL pointer.
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
/* compression */
LZO_EXTERN
(
int
)
lzo1x_1_compress
(
const
lzo_bytep
src
,
lzo_uint
src_len
,
lzo_bytep
dst
,
lzo_uintp
dst_len
,
lzo_voidp
wrkmem
);
/* decompression */
LZO_EXTERN
(
int
)
lzo1x_decompress
(
const
lzo_bytep
src
,
lzo_uint
src_len
,
lzo_bytep
dst
,
lzo_uintp
dst_len
,
lzo_voidp
wrkmem
/* NOT USED */
);
/* safe decompression with overrun testing */
LZO_EXTERN
(
int
)
lzo1x_decompress_safe
(
const
lzo_bytep
src
,
lzo_uint
src_len
,
lzo_bytep
dst
,
lzo_uintp
dst_len
,
lzo_voidp
wrkmem
/* NOT USED */
);
#ifdef __cplusplus
}
/* extern "C" */
#endif
#endif
/* already included */
userspace/libswitchhw/pio.c
deleted
100644 → 0
View file @
df8edea4
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <fcntl.h>
#include <hw/pio.h>
#include <hw/fpga_regs.h>
#include <hw/trace.h>
static
const
pio_pin_t
pck_port_mapping
[]
=
{
{
PIOA
,
13
,
PIO_MODE_PERIPH_B
,
PIO_OUT
},
{
PIOB
,
10
,
PIO_MODE_PERIPH_B
,
PIO_OUT
},
{
PIOA
,
6
,
PIO_MODE_PERIPH_B
,
PIO_OUT
},
{
PIOE
,
11
,
PIO_MODE_PERIPH_B
,
PIO_OUT
},
{
0
}
};
volatile
uint8_t
*
_pio_base
[
4
][
NUM_PIO_BANKS
+
1
];
volatile
uint8_t
*
_sys_base
;
int
shw_pio_mmap_init
()
{
int
i
;
int
fd
=
open
(
"/dev/mem"
,
O_RDWR
);
if
(
!
fd
)
{
TRACE
(
TRACE_FATAL
,
"can't open /dev/mem! (no root?)"
);
exit
(
-
1
);
}
_sys_base
=
mmap
(
NULL
,
0x2000
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
AT91_BASE_SYS
);
if
(
_sys_base
==
NULL
)
{
TRACE
(
TRACE_FATAL
,
"can't mmap CPU GPIO regs"
);
close
(
fd
);
exit
(
-
1
);
}
TRACE
(
TRACE_INFO
,
"AT91_SYS virtual base = 0x%08x"
,
_sys_base
);
// fprintf(stderr,"AT91_SYS mmapped to: 0x%08x\n", _sys_base);
_pio_base
[
REG_BASE
][
PIOA
]
=
_sys_base
+
AT91_PIOA
;
_pio_base
[
REG_BASE
][
PIOB
]
=
_sys_base
+
AT91_PIOB
;
_pio_base
[
REG_BASE
][
PIOC
]
=
_sys_base
+
AT91_PIOC
;
_pio_base
[
REG_BASE
][
PIOD
]
=
_sys_base
+
AT91_PIOD
;
_pio_base
[
REG_BASE
][
PIOE
]
=
_sys_base
+
AT91_PIOE
;
for
(
i
=
1
;
i
<=
5
;
i
++
)
{
_pio_base
[
REG_CODR
][
i
]
=
_pio_base
[
REG_BASE
][
i
]
+
PIO_CODR
;
_pio_base
[
REG_SODR
][
i
]
=
_pio_base
[
REG_BASE
][
i
]
+
PIO_SODR
;
_pio_base
[
REG_PDSR
][
i
]
=
_pio_base
[
REG_BASE
][
i
]
+
PIO_PDSR
;
}
_pio_base
[
REG_BASE
][
PIO_FPGA
]
=
_fpga_base_virt
+
FPGA_BASE_GPIO
;
_pio_base
[
REG_CODR
][
PIO_FPGA
]
=
_fpga_base_virt
+
FPGA_BASE_GPIO
+
GPIO_REG_CODR
;
_pio_base
[
REG_SODR
][
PIO_FPGA
]
=
_fpga_base_virt
+
FPGA_BASE_GPIO
+
GPIO_REG_SODR
;
_pio_base
[
REG_PDSR
][
PIO_FPGA
]
=
_fpga_base_virt
+
FPGA_BASE_GPIO
+
GPIO_REG_PSR
;
return
0
;
}
int
shw_pio_configure_all_cpu_pins
()
{
int
i
;
TRACE
(
TRACE_INFO
,
"Configuring CPU PIO pins..."
);
for
(
i
=
0
;
_all_cpu_gpio_pins
[
i
];
i
++
)
{
shw_pio_configure_pins
(
_all_cpu_gpio_pins
[
i
]);
}
TRACE
(
TRACE_INFO
,
"...done!"
);
}
int
shw_pio_configure_all_fpga_pins
()
{
int
i
;
TRACE
(
TRACE_INFO
,
"Configuring FPGA PIO pins..."
);
for
(
i
=
0
;
_all_fpga_gpio_pins
[
i
];
i
++
)
{
shw_pio_configure_pins
(
_all_fpga_gpio_pins
[
i
]);
}
TRACE
(
TRACE_INFO
,
"...done!"
);
}
void
shw_pio_configure
(
const
pio_pin_t
*
pin
)
{
uint32_t
mask
=
(
1
<<
pin
->
pin
);
uint32_t
ddr
;
volatile
uint8_t
*
base
=
(
_pio_base
[
REG_BASE
][
pin
->
port
]);
switch
(
pin
->
port
)
{
case
PIOA
:
case
PIOB
:
case
PIOC
:
case
PIOD
:
case
PIOE
:
// TRACE(TRACE_INFO, "-- configure CPU PIO PIN: P%c.%d base=0x%x", pin->port-PIOA+'A', pin->pin, base);
_writel
(
base
+
PIO_IDR
,
mask
);
// disable irq
if
(
pin
->
mode
&
PIO_MODE_PULLUP
)
_writel
(
base
+
PIO_PUER
,
mask
);
// enable pullup
else
_writel
(
base
+
PIO_PUDR
,
mask
);
// disable pullup
switch
(
pin
->
mode
&
0x3
)
{
case
PIO_MODE_GPIO
:
_writel
(
base
+
PIO_PER
,
mask
);
// enable gpio mode
break
;
case
PIO_MODE_PERIPH_A
:
_writel
(
base
+
PIO_PDR
,
mask
);
// disable gpio mode
_writel
(
base
+
PIO_ASR
,
mask
);
// select peripheral A
break
;
case
PIO_MODE_PERIPH_B
:
_writel
(
base
+
PIO_PDR
,
mask
);
// disable gpio mode
_writel
(
base
+
PIO_BSR
,
mask
);
// select peripheral B
break
;
}
if
(
pin
->
dir
==
PIO_OUT_1
)
{
_writel
(
base
+
PIO_SODR
,
mask
);
_writel
(
base
+
PIO_OER
,
mask
);
// select output, set it to 1
}
else
if
(
pin
->
dir
==
PIO_OUT_0
)
{
_writel
(
base
+
PIO_CODR
,
mask
);
_writel
(
base
+
PIO_OER
,
mask
);
// select output, set it to 0
}
else
{
_writel
(
base
+
PIO_ODR
,
mask
);
// select input
}
break
;
case
PIO_FPGA
:
// TRACE(TRACE_INFO, "-- configure FPGA PIO PIN: P%d", pin->pin);
ddr
=
_readl
(
base
+
GPIO_REG_DDR
);
if
(
pin
->
dir
==
PIO_OUT_1
)
{
_writel
(
base
+
GPIO_REG_SODR
,
mask
);
ddr
|=
mask
;
}
else
if
(
pin
->
dir
==
PIO_OUT_0
)
{
_writel
(
base
+
GPIO_REG_CODR
,
mask
);
ddr
|=
mask
;
}
else
ddr
&=
~
mask
;
_writel
(
base
+
GPIO_REG_DDR
,
ddr
);
break
;
}
}
void
shw_pio_configure_pins
(
const
pio_pin_t
*
pins
)
{
while
(
pins
->
port
)
{
shw_pio_configure
(
pins
);
pins
++
;
}
}
int
shw_clock_out_enable
(
int
pck_num
,
int
prescaler
,
int
source
)
{
if
(
pck_num
>
3
)
return
-
1
;
shw_pio_configure
(
&
pck_port_mapping
[
pck_num
]);
_writel
(
_sys_base
+
AT91_PMC_PCKR
(
pck_num
),
source
|
prescaler
);
_writel
(
_sys_base
+
AT91_PMC_SCER
,
(
1
<<
(
8
+
pck_num
)));
return
0
;
}
volatile
uint8_t
*
shw_pio_get_sys_base
()
{
return
_sys_base
;
}
volatile
uint8_t
*
shw_pio_get_port_base
(
int
port
)
{
return
_pio_base
[
REG_BASE
][
port
];
}
void
shw_set_fp_led
(
int
led
,
int
state
)
{
if
(
state
==
LED_GREEN
)
{
shw_pio_set
(
&
_fp_leds
[
led
][
0
],
1
);
shw_pio_set
(
&
_fp_leds
[
led
][
1
],
0
);
}
else
if
(
state
==
LED_RED
)
{
shw_pio_set
(
&
_fp_leds
[
led
][
0
],
0
);
shw_pio_set
(
&
_fp_leds
[
led
][
1
],
1
);
}
else
{
shw_pio_set
(
&
_fp_leds
[
led
][
0
],
1
);
shw_pio_set
(
&
_fp_leds
[
led
][
1
],
1
);
}
}
userspace/libswitchhw/pio_pins.c
deleted
100644 → 0
View file @
df8edea4
/* GPIO pin definitions */
#include <hw/pio.h>
#define LED_OFF 0
#define LED_RED 1
#define LED_GREEN 2
#define LED_YELLOW 3
// definitions of commonly used pins
// reset signal for main FPGA
const
pio_pin_t
PIN_main_fpga_nrst
[]
=
{{
PIOB
,
20
,
PIO_MODE_GPIO
,
PIO_OUT
},
{
0
}};
// Front panel LEDs
const
pio_pin_t
PIN_fled0
[]
=
{{
PIOC
,
5
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIOC
,
12
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled1
[]
=
{{
PIOC
,
7
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIOC
,
19
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled2
[]
=
{{
PIOC
,
9
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIOC
,
17
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled3
[]
=
{{
PIOC
,
14
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIOC
,
6
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled4
[]
=
{{
PIO_FPGA
,
0
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIO_FPGA
,
1
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled5
[]
=
{{
PIO_FPGA
,
2
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIO_FPGA
,
3
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled6
[]
=
{{
PIO_FPGA
,
4
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIO_FPGA
,
5
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
const
pio_pin_t
PIN_fled7
[]
=
{{
PIO_FPGA
,
6
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
PIO_FPGA
,
7
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
// uTCA front panel LEDs
const
pio_pin_t
PIN_uled0
[]
=
{{
PIOC
,
11
,
PIO_MODE_GPIO
,
PIO_OUT
},
{
0
}};
const
pio_pin_t
PIN_uled1
[]
=
{{
PIOC
,
15
,
PIO_MODE_GPIO
,
PIO_OUT
},
{
0
}};
const
pio_pin_t
PIN_uled2
[]
=
{{
PIOC
,
18
,
PIO_MODE_GPIO
,
PIO_OUT
},
{
0
}};
const
pio_pin_t
PIN_uled3
[]
=
{{
PIOC
,
13
,
PIO_MODE_GPIO
,
PIO_OUT
},
{
0
}};
// AD9516 PLL control signals
const
pio_pin_t
PIN_ad9516_cs
[]
=
{{
PIOC
,
10
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
// clkb_cpupin3 -> pc10
const
pio_pin_t
PIN_ad9516_sclk
[]
=
{{
PIOC
,
16
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
// clkb_cpupin1 -> pc16
const
pio_pin_t
PIN_ad9516_sdio
[]
=
{{
PIOB
,
30
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
// clkb_cpupin5 -> pb30
const
pio_pin_t
PIN_ad9516_sdo
[]
=
{{
PIOC
,
8
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}
};
// clkb_cpupin0 -> pc8
const
pio_pin_t
PIN_ad9516_refsel
[]
=
{{
PIOB
,
26
,
PIO_MODE_GPIO
,
PIO_OUT_0
},
{
0
}
};
// clkb_cpupin4 -> pb26
const
pio_pin_t
PIN_ad9516_nrst
[]
=
{{
PIOC
,
3
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}
};
// clkb_cpupin2 -> pc3
// uTCA Hotswap switch
const
pio_pin_t
PIN_hotswap_switch
[]
=
{{
PIOC
,
1
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}
};
// main FPGA passive serial configuration signals
const
pio_pin_t
PIN_main_fpga_dclk
[]
=
{{
PIOB
,
1
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_main_fpga_nconfig
[]
=
{{
PIOB
,
22
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_main_fpga_data
[]
=
{{
PIOB
,
2
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_main_fpga_nstatus
[]
=
{{
PIOB
,
31
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_main_fpga_confdone
[]
=
{{
PIOB
,
18
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
// INVERTED!
// clocking board FPGA passive serial configuration signals
const
pio_pin_t
PIN_clkb_fpga_dclk
[]
=
{{
PIOB
,
7
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_clkb_fpga_nconfig
[]
=
{{
PIOB
,
23
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_clkb_fpga_data
[]
=
{{
PIOB
,
8
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_clkb_fpga_nstatus
[]
=
{{
PIOB
,
28
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_clkb_fpga_confdone
[]
=
{{
PIOB
,
24
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
// INVERTED!
const
pio_pin_t
PIN_clkb_fpga_nrst
[]
=
{{
PIOB
,
25
,
PIO_MODE_GPIO
,
PIO_OUT_0
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_sda
[]
=
{{
PIO_FPGA
,
8
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_scl
[]
=
{{
PIO_FPGA
,
9
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_los
[]
=
{{
PIO_FPGA
,
10
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_tx_fault
[]
=
{{
PIO_FPGA
,
11
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_tx_disable
[]
=
{{
PIO_FPGA
,
12
,
PIO_MODE_GPIO
,
PIO_OUT_0
},
{
0
}};
const
pio_pin_t
PIN_up0_sfp_detect
[]
=
{{
PIO_FPGA
,
13
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_sda
[]
=
{{
PIO_FPGA
,
18
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_scl
[]
=
{{
PIO_FPGA
,
19
,
PIO_MODE_GPIO
,
PIO_OUT_1
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_los
[]
=
{{
PIO_FPGA
,
20
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_tx_fault
[]
=
{{
PIO_FPGA
,
21
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_tx_disable
[]
=
{{
PIO_FPGA
,
22
,
PIO_MODE_GPIO
,
PIO_OUT_0
},
{
0
}};
const
pio_pin_t
PIN_up1_sfp_detect
[]
=
{{
PIO_FPGA
,
23
,
PIO_MODE_GPIO
,
PIO_IN
},
{
0
}};
const
pio_pin_t
*
_all_cpu_gpio_pins
[]
=
{
PIN_fled0
,
PIN_fled1
,
PIN_fled2
,
PIN_fled3
,
PIN_uled0
,
PIN_uled1
,
PIN_uled2
,
PIN_uled3
,
PIN_hotswap_switch
,
NULL
};
const
pio_pin_t
*
_all_fpga_gpio_pins
[]
=
{
PIN_fled4
,
PIN_fled5
,
PIN_fled6
,
PIN_fled7
,
PIN_up0_sfp_sda
,
PIN_up0_sfp_scl
,
PIN_up0_sfp_los
,
PIN_up0_sfp_tx_fault
,
PIN_up0_sfp_tx_disable
,
PIN_up0_sfp_detect
,
PIN_up1_sfp_sda
,
PIN_up1_sfp_scl
,
PIN_up1_sfp_los
,
PIN_up1_sfp_tx_fault
,
PIN_up1_sfp_tx_disable
,
PIN_up1_sfp_detect
,
NULL
};
const
pio_pin_t
*
_fp_leds
[]
=
{
PIN_fled0
,
PIN_fled1
,
PIN_fled2
,
PIN_fled3
,
PIN_fled4
,
PIN_fled5
,
PIN_fled6
,
PIN_fled7
};
userspace/libswitchhw/xpoint.c
deleted
100644 → 0
View file @
df8edea4
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
#include <hw/trace.h>
#include <hw/clkb_io.h>
#include <hw/pio.h>
// The I2C bus which goes to ADN4600 is currently connected to the GPIO pins of CLKB FPGA.
#define MASK_SCL_OUT (1<<0)
#define MASK_SDA_OUT (1<<1)
#define MASK_SCL_IN (1<<2)
#define MASK_SDA_IN (1<<3)
#define M_SDA_OUT(x) { \
if(x) \
shw_clkb_write_reg(CLKB_BASE_GPIO + GPIO_REG_SODR, MASK_SDA_OUT); \
else \
shw_clkb_write_reg(CLKB_BASE_GPIO + GPIO_REG_CODR, MASK_SDA_OUT); \
}
#define M_SCL_OUT(x) { \
if(x) \
shw_clkb_write_reg(CLKB_BASE_GPIO + GPIO_REG_SODR, MASK_SCL_OUT); \
else \
shw_clkb_write_reg(CLKB_BASE_GPIO + GPIO_REG_CODR, MASK_SCL_OUT); \
}
#define M_SDA_IN (shw_clkb_read_reg(CLKB_BASE_GPIO + GPIO_REG_PSR) & MASK_SDA_IN)
// ADN4600 register addresses
#define ADN4600_ADDR 0x90
#define ADN4600_RESET 0x0
#define ADN4600_XPT_CONFIG 0x40
#define ADN4600_XPT_UPDATE 0x41
#define ADN4600_RX_CONFIG(channel) (0x80 + channel * 8)
#define ADN4600_TX_CONFIG(channel) (((channel<4)?(0xc0 + channel * 8) : (0xe0 + (7-channel)*8)))
// crosspoint I/O map:
// up0 tx -> IN1 inverted
// up1 tx -> IN0 inverted
// sfp0 tx -> IN2 inverted
// sfp1 tx -> IN3 inverted
// up0 rx <- OUT0
// up1 rx <- OUT1
// sfp0 rx <- OUT7
// sfp1 rx <- OUT6
// feedback <- OUT3
#define XPT_UP0_TX 1
#define XPT_UP1_TX 0
#define XPT_SFP0_TX 2
#define XPT_SFP1_TX 3
#define XPT_UP0_RX 0
#define XPT_UP1_RX 1
#define XPT_SFP0_RX 7
#define XPT_SFP1_RX 6
#define XPT_FEEDBACK 3
#define RX_CONFIG_PNSWAP 0x40
#define RX_CONFIG_RXEN 0x10
#define RX_CONFIG_EQBY 0x20
#define RX_CONFIG_RXEQ(eq) (eq&0x7)
#define TX_CONFIG_TXEN 0x20
#define TX_CONFIG_TXDR 0x10
#define TX_CONFIG_TXPE(pe) (pe&0x7)
static
void
mi2c_start
()
{
M_SDA_OUT
(
0
);
M_SCL_OUT
(
0
);
}
static
void
mi2c_repeat_start
()
{
M_SDA_OUT
(
1
);
M_SCL_OUT
(
1
);
M_SDA_OUT
(
0
);
M_SCL_OUT
(
0
);
}
static
void
mi2c_stop
()
{
M_SDA_OUT
(
0
);
M_SCL_OUT
(
1
);
M_SDA_OUT
(
1
);
}
static
unsigned
char
mi2c_put_byte
(
unsigned
char
data
)
{
char
i
;
unsigned
char
ack
;
for
(
i
=
0
;
i
<
8
;
i
++
,
data
<<=
1
)
{
M_SDA_OUT
(
data
&
0x80
);
M_SCL_OUT
(
1
);
M_SCL_OUT
(
0
);
}
M_SDA_OUT
(
1
);
M_SCL_OUT
(
1
);
ack
=
M_SDA_IN
;
/* ack: sda is pulled low ->success. */
M_SCL_OUT
(
0
);
M_SDA_OUT
(
0
);
return
ack
!=
0
;
}
static
void
mi2c_get_byte
(
unsigned
char
*
data
)
{
int
i
;
unsigned
char
indata
=
0
;
/* assert: scl is low */
M_SCL_OUT
(
0
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
M_SCL_OUT
(
1
);
indata
<<=
1
;
if
(
M_SDA_IN
)
indata
|=
0x01
;
M_SCL_OUT
(
0
);
}
M_SDA_OUT
(
1
);
*
data
=
indata
;
}
static
void
mi2c_init
()
{
shw_clkb_write_reg
(
CLKB_BASE_GPIO
+
GPIO_REG_DDR
,
MASK_SCL_OUT
|
MASK_SDA_OUT
);
M_SCL_OUT
(
1
);
M_SDA_OUT
(
1
);
}
static
uint8_t
adn4600_read_reg
(
uint8_t
reg
)
{
uint8_t
rval
;
mi2c_start
();
if
(
mi2c_put_byte
(
ADN4600_ADDR
))
goto
rxerr
;
if
(
mi2c_put_byte
(
reg
))
goto
rxerr
;
mi2c_repeat_start
();
if
(
mi2c_put_byte
(
ADN4600_ADDR
|
1
))
goto
rxerr
;
mi2c_get_byte
(
&
rval
);
mi2c_stop
();
return
rval
;
rxerr:
TRACE
(
TRACE_ERROR
,
"No I2C ack from ADN4600!"
);
mi2c_stop
();
return
0
;
}
static
void
adn4600_write_reg
(
uint8_t
reg
,
uint8_t
value
)
{
uint8_t
rval
;
mi2c_start
();
if
(
mi2c_put_byte
(
ADN4600_ADDR
))
goto
txerr
;
if
(
mi2c_put_byte
(
reg
))
goto
txerr
;
if
(
mi2c_put_byte
(
value
))
goto
txerr
;
mi2c_stop
();
txerr:
TRACE
(
TRACE_FATAL
,
"No I2C ack from ADN4600!"
);
mi2c_stop
();
}
void
xpoint_route
(
int
in
,
int
out
)
{
adn4600_write_reg
(
ADN4600_XPT_CONFIG
,
(
in
<<
4
)
|
out
);
adn4600_write_reg
(
ADN4600_XPT_UPDATE
,
1
);
}
int
xpoint_configure
()
{
TRACE
(
TRACE_INFO
,
"Initializing ADN4600 crosspoint"
);
mi2c_init
();
adn4600_write_reg
(
ADN4600_RESET
,
0x1
);
// Uplink 1 TX
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
0
),
RX_CONFIG_PNSWAP
|
RX_CONFIG_RXEN
|
RX_CONFIG_RXEQ
(
0
));
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
1
),
RX_CONFIG_PNSWAP
|
RX_CONFIG_RXEN
|
RX_CONFIG_RXEQ
(
0
));
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
2
),
RX_CONFIG_PNSWAP
|
RX_CONFIG_RXEN
|
RX_CONFIG_RXEQ
(
0
));
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
3
),
RX_CONFIG_PNSWAP
|
RX_CONFIG_RXEN
|
RX_CONFIG_RXEQ
(
0
));
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
4
),
0
);
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
5
),
0
);
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
6
),
0
);
adn4600_write_reg
(
ADN4600_RX_CONFIG
(
7
),
0
);
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
0
),
TX_CONFIG_TXEN
|
TX_CONFIG_TXPE
(
0
));
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
1
),
TX_CONFIG_TXEN
|
TX_CONFIG_TXPE
(
0
));
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
6
),
TX_CONFIG_TXEN
|
TX_CONFIG_TXPE
(
0
));
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
7
),
TX_CONFIG_TXEN
|
TX_CONFIG_TXPE
(
0
));
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
XPT_FEEDBACK
),
TX_CONFIG_TXPE
(
0
));
xpoint_route
(
XPT_UP1_TX
,
XPT_SFP1_RX
);
xpoint_route
(
XPT_UP0_TX
,
XPT_SFP0_RX
);
xpoint_route
(
XPT_SFP1_TX
,
XPT_UP1_RX
);
xpoint_route
(
XPT_SFP0_TX
,
XPT_UP0_RX
);
return
0
;
}
// port: 0 = uplink0, 1 = uplink 1
// txrx: 0 = tx calibration, 1 = rx calibration
// on: 0 = disable, 1= enable
void
xpoint_cal_feedback
(
int
on
,
int
port
,
int
txrx
)
{
int
port_map
[]
=
{
XPT_UP0_TX
,
XPT_SFP0_TX
,
XPT_UP1_TX
,
XPT_SFP1_TX
};
int
index
=
(
port
*
2
+
(
txrx
?
1
:
0
));
if
(
!
on
)
{
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
XPT_FEEDBACK
),
TX_CONFIG_TXPE
(
0
));
}
else
{
xpoint_route
(
port_map
[
index
],
XPT_FEEDBACK
);
adn4600_write_reg
(
ADN4600_TX_CONFIG
(
XPT_FEEDBACK
),
TX_CONFIG_TXEN
|
TX_CONFIG_TXPE
(
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