h1r9: add Si5351A support

This commit is contained in:
Michael Ossmann
2022-09-08 03:33:47 -04:00
committed by Mike Walters
parent 6d48671084
commit 1f73f2fd25
2 changed files with 127 additions and 45 deletions

View File

@ -36,6 +36,7 @@
#include "i2c_lpc.h"
#include "cpld_jtag.h"
#include "platform_detect.h"
#include "clkin.h"
#include <libopencm3/lpc43xx/cgu.h>
#include <libopencm3/lpc43xx/ccu.h>
#include <libopencm3/lpc43xx/scu.h>
@ -414,14 +415,26 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
MSx_P2 = (128 * b) % c;
MSx_P3 = c;
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
/*
* On HackRF One r9 all sample clocks are externally derived
* from MS1/CLK1 operating at twice the sample rate.
*/
si5351c_configure_multisynth(&clock_gen, 1, MSx_P1, MSx_P2, MSx_P3, 0);
} else {
/*
* On other platforms the clock generator produces three
* different sample clocks, all derived from multisynth 0.
*/
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter
}
if (streaming) {
sgpio_cpld_stream_enable(&sgpio_config);
@ -482,14 +495,38 @@ bool sample_rate_set(const uint32_t sample_rate_hz)
return false;
}
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
/*
* On HackRF One r9 all sample clocks are externally derived
* from MS1/CLK1 operating at twice the sample rate.
*/
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 0);
} else {
/*
* On other platforms the clock generator produces three
* different sample clocks, all derived from multisynth 0.
*/
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(&clock_gen, 1, p1, 0, 1, 0); //p1 doesn't matter
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(
&clock_gen,
1,
p1,
0,
1,
0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(&clock_gen, 2, p1, 0, 1, 0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(
&clock_gen,
2,
p1,
0,
1,
0); //p1 doesn't matter
}
return true;
}
@ -596,7 +633,12 @@ void cpu_clock_init(void)
si5351c_configure_pll_multisynth(&clock_gen);
/*
* Clocks:
* Clocks on HackRF One r9:
* CLK0 -> MAX5864/CPLD/SGPIO (sample clocks)
* CLK1 -> RFFC5072/MAX2837
* CLK2 -> External Clock Output/LPC43xx (power down at boot)
*
* Clocks on other platforms:
* CLK0 -> MAX5864/CPLD
* CLK1 -> CPLD
* CLK2 -> SGPIO
@ -607,22 +649,33 @@ void cpu_clock_init(void)
* CLK7 -> LPC43xx (uses a 12MHz crystal by default)
*/
/* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */
si5351c_configure_multisynth(
&clock_gen,
4,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
/* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */
si5351c_configure_multisynth(
&clock_gen,
5,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
/* MS0/CLK0 is the reference for both RFFC5071 and MAX2837. */
si5351c_configure_multisynth(
&clock_gen,
0,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
} else {
/* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */
si5351c_configure_multisynth(
&clock_gen,
4,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
/* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */
si5351c_configure_multisynth(
&clock_gen,
5,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
}
/* MS6/CLK6 is unused. */
/* MS7/CLK7 is unused. */
@ -766,6 +819,10 @@ void cpu_clock_init(void)
// CCU2_CLK_APLL_CFG = 0;
// CCU2_CLK_SDIO_CFG = 0;
#endif
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
clkin_detect_init();
}
}
clock_source_t activate_best_clock_source(void)

View File

@ -191,7 +191,7 @@ void si5351c_configure_clock_control(
const enum pll_sources source)
{
uint8_t pll;
uint8_t clk3_ctrl;
uint8_t clkout_ctrl;
#ifdef RAD1O
(void) source;
@ -201,31 +201,29 @@ void si5351c_configure_clock_control(
#if (defined JAWBREAKER || defined HACKRF_ONE)
if (source == PLL_SOURCE_CLKIN) {
if (detected_platform() < BOARD_ID_HACKRF1_R9) {
/* PLLB on CLKIN */
pll = SI5351C_CLK_PLL_SRC_B;
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
/*
* HackRF One r9 always uses PLL A on the XTAL input
* but externally switches that input to CLKIN.
*/
pll = SI5351C_CLK_PLL_SRC_A;
gpio_set(&gpio_h1r9_clkin_en);
} else {
/* PLLB on CLKIN */
pll = SI5351C_CLK_PLL_SRC_B;
}
} else {
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
if (detected_platform() < BOARD_ID_HACKRF1_R9) {
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
gpio_clear(&gpio_h1r9_clkin_en);
}
}
#endif
if (clkout_enabled) {
clk3_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
} else {
clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
clkout_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
}
/* Clock to CPU is deactivated as it is not used and creates noise */
@ -241,7 +239,7 @@ void si5351c_configure_clock_control(
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
clk3_ctrl,
clkout_ctrl,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
@ -249,18 +247,28 @@ void si5351c_configure_clock_control(
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,
SI5351C_CLK_INT_MODE, /* not connected, but: PLL A int mode */
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */
};
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
data[3] = clkout_ctrl;
data[4] = SI5351C_CLK_POWERDOWN;
data[5] = SI5351C_CLK_POWERDOWN;
data[6] = SI5351C_CLK_POWERDOWN;
}
si5351c_write(drv, data, sizeof(data));
}
#define SI5351C_CLK_ENABLE(x) (0 << x)
#define SI5351C_CLK_DISABLE(x) (1 << x)
#define SI5351C_REG_OUTPUT_EN (3)
#define SI5351C_REG_CLK3_CTRL (19)
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
{
@ -270,8 +278,19 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
uint8_t value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) |
SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) |
SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7);
uint8_t clkout = 3;
value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(3) : SI5351C_CLK_DISABLE(3);
/* HackRF One r9 has only three clock generator outputs. */
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
clkout = 2;
value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) |
SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) |
SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_DISABLE(7);
}
value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) :
SI5351C_CLK_DISABLE(clkout);
uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value};
si5351c_write(drv, data, sizeof(data));
@ -325,8 +344,14 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
{
clkout_enabled = (enable > 0);
//FIXME this should be somewhere else
uint8_t clkout = 3;
/* HackRF One r9 has only three clock generator outputs. */
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
clkout = 2;
}
/* Configure clock to 10MHz */
si5351c_configure_multisynth(drv, 3, 80 * 128 - 512, 0, 1, 0);
si5351c_configure_multisynth(drv, clkout, 80 * 128 - 512, 0, 1, 0);
si5351c_configure_clock_control(drv, active_clock_source);
si5351c_enable_clock_outputs(drv);