From: David Picard <david.picard@clermont.in2p3.fr>
To: Sascha Hauer <s.hauer@pengutronix.de>,
BAREBOX <barebox@lists.infradead.org>
Cc: David Picard <david.picard@clermont.in2p3.fr>
Subject: [PATCH v2 06/10] boards: enclustra-sa2: configure SI5338
Date: Thu, 25 Sep 2025 13:59:13 +0200 [thread overview]
Message-ID: <20250925-boards-enclustra-sa2-add-support-v2-6-6820ad6c6256@clermont.in2p3.fr> (raw)
In-Reply-To: <20250925-boards-enclustra-sa2-add-support-v2-0-6820ad6c6256@clermont.in2p3.fr>
Configure the SI5338 clock generator on the ST1 baseboard.
Signed-off-by: David Picard <david.picard@clermont.in2p3.fr>
---
v1 -> v2:
- replace custom functions to read and write a byte to a
I2C register with regmap functions.
- replace custom functions to update bits in a
I2C register with regmap functions.
---
---
arch/arm/boards/enclustra-sa2/Makefile | 2 +-
.../boards/enclustra-sa2/Si5338-RevB-Registers.h | 433 +++++++++++++++++++++
arch/arm/boards/enclustra-sa2/board.c | 6 +
arch/arm/boards/enclustra-sa2/si5338_config.c | 252 ++++++++++++
arch/arm/boards/enclustra-sa2/si5338_config.h | 22 ++
arch/arm/mach-socfpga/Kconfig | 4 +
6 files changed, 718 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boards/enclustra-sa2/Makefile b/arch/arm/boards/enclustra-sa2/Makefile
index 8c927fe291a6b3eb20a32a2db96c73f231ab4697..2185c84fc482776681a5f2fc3cad7434f0160561 100644
--- a/arch/arm/boards/enclustra-sa2/Makefile
+++ b/arch/arm/boards/enclustra-sa2/Makefile
@@ -1,2 +1,2 @@
-obj-y += lowlevel.o board.o
+obj-y += lowlevel.o board.o si5338_config.o
pbl-y += lowlevel.o
diff --git a/arch/arm/boards/enclustra-sa2/Si5338-RevB-Registers.h b/arch/arm/boards/enclustra-sa2/Si5338-RevB-Registers.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea9093e8601835e01391b4b19aa98787c4861b41
--- /dev/null
+++ b/arch/arm/boards/enclustra-sa2/Si5338-RevB-Registers.h
@@ -0,0 +1,433 @@
+//Register map for use with AN428 (JumpStart)
+//http://www.skyworksinc.com/timing
+//#BEGIN_HEADER
+//Date = Friday, June 09, 2023 5:03 PM
+//File version = 3
+//Software Name = ClockBuilder Pro
+//Software version = 4.9.0.0
+//Software date = 4 24, 2023
+//Chip = Si533x
+//Part Number = Si533x
+//#END_HEADER
+//Input Frequency (MHz) = 24.000000000
+//Input Type = CMOS_SSTL_HSTL
+//P1 = 1
+//Input Mux = RefClk
+//FDBK Input Frequency (MHz) = 24.000000000
+//FDBK Input Type = OFF
+//P2 = 1
+//FDBK Mux = NoClk
+//PFD Input Frequency (MHz) = 24.000000000
+//VCO Frequency (GHz) = 2.500000
+//N = 104 1/6 (104.1667)
+//Internal feedback enabled
+//Output Clock 0
+// Output Frequency (MHz) = 125.000000000
+// Mux Selection = IDn
+// MultiSynth = 20 (20.0000)
+// R = 1
+//Output Clock 1
+// Output is off
+//Output Clock 2
+// Output is off
+//Output Clock 3
+// Output Frequency (MHz) = 100.000000000
+// Mux Selection = IDn
+// MultiSynth = 25 (25.0000)
+// R = 1
+//Driver 0
+// Enabled
+// Powered on
+// Output voltage = 3.30
+// Output type = 3.3V LVDS
+// Output state when disabled = Tristate
+//Driver 1
+// Disabled
+// Powered off
+// Output voltage = 3.30
+// Output type = 3.3V LVDS
+// Output state when disabled = StopLow
+//Driver 2
+// Disabled
+// Powered off
+// Output voltage = 3.30
+// Output type = 3.3V LVDS
+// Output state when disabled = StopLow
+//Driver 3
+// Enabled
+// Powered on
+// Output voltage = 3.30
+// Output type = 3.3V CMOS on A
+// Output state when disabled = Tristate
+//Clock 0 phase inc/dec step size (ns) = 0.000
+//Clock 1 phase inc/dec step size (ns) = 0.000
+//Clock 2 phase inc/dec step size (ns) = 0.000
+//Clock 3 phase inc/dec step size (ns) = 0.000
+//Phase increment and decrement pin control is off
+//Frequency increment and decrement pin control is off
+//Frequency increment and decrement is disabled
+//Initial phase offset 0 (ns) = 0.000
+//Initial phase offset 1 (ns) = 0.000
+//Initial phase offset 2 (ns) = 0.000
+//Initial phase offset 3 (ns) = 0.000
+//SSC is disabled
+
+#define NUM_REGS_MAX 350
+
+typedef struct Reg_Data {
+ unsigned char Reg_Addr;
+ unsigned char Reg_Val;
+ unsigned char Reg_Mask;
+} Reg_Data;
+
+Reg_Data const Reg_Store[NUM_REGS_MAX] = {
+ { 0, 0x00, 0x00 },
+ { 1, 0x00, 0x00 },
+ { 2, 0x00, 0x00 },
+ { 3, 0x00, 0x00 },
+ { 4, 0x00, 0x00 },
+ { 5, 0x00, 0x00 },
+ { 6, 0x08, 0x1D },
+ { 7, 0x00, 0x00 },
+ { 8, 0x70, 0x00 },
+ { 9, 0x0F, 0x00 },
+ { 10, 0x00, 0x00 },
+ { 11, 0x00, 0x00 },
+ { 12, 0x00, 0x00 },
+ { 13, 0x00, 0x00 },
+ { 14, 0x00, 0x00 },
+ { 15, 0x00, 0x00 },
+ { 16, 0x00, 0x00 },
+ { 17, 0x00, 0x00 },
+ { 18, 0x00, 0x00 },
+ { 19, 0x00, 0x00 },
+ { 20, 0x00, 0x00 },
+ { 21, 0x00, 0x00 },
+ { 22, 0x00, 0x00 },
+ { 23, 0x00, 0x00 },
+ { 24, 0x00, 0x00 },
+ { 25, 0x00, 0x00 },
+ { 26, 0x00, 0x00 },
+ { 27, 0x70, 0x80 },
+ { 28, 0x0B, 0xFF },
+ { 29, 0x08, 0xFF },
+ { 30, 0xB0, 0xFF },
+ { 31, 0xC0, 0xFF },
+ { 32, 0xE3, 0xFF },
+ { 33, 0xE3, 0xFF },
+ { 34, 0xC0, 0xFF },
+ { 35, 0x00, 0xFF },
+ { 36, 0x06, 0x1F },
+ { 37, 0x00, 0x1F },
+ { 38, 0x00, 0x1F },
+ { 39, 0x01, 0x1F },
+ { 40, 0x63, 0xFF },
+ { 41, 0x0C, 0x7F },
+ { 42, 0x37, 0x3F },
+ { 43, 0x00, 0x00 },
+ { 44, 0x00, 0x00 },
+ { 45, 0x00, 0xFF },
+ { 46, 0x00, 0xFF },
+ { 47, 0x14, 0x3F },
+ { 48, 0x3C, 0xFF },
+ { 49, 0x00, 0xFF },
+ { 50, 0xC4, 0xFF },
+ { 51, 0x07, 0xFF },
+ { 52, 0x10, 0xFF },
+ { 53, 0x00, 0xFF },
+ { 54, 0x08, 0xFF },
+ { 55, 0x00, 0xFF },
+ { 56, 0x00, 0xFF },
+ { 57, 0x00, 0xFF },
+ { 58, 0x00, 0xFF },
+ { 59, 0x01, 0xFF },
+ { 60, 0x00, 0xFF },
+ { 61, 0x00, 0xFF },
+ { 62, 0x00, 0x3F },
+ { 63, 0x10, 0xFF },
+ { 64, 0x00, 0xFF },
+ { 65, 0x00, 0xFF },
+ { 66, 0x00, 0xFF },
+ { 67, 0x00, 0xFF },
+ { 68, 0x00, 0xFF },
+ { 69, 0x00, 0xFF },
+ { 70, 0x00, 0xFF },
+ { 71, 0x00, 0xFF },
+ { 72, 0x00, 0xFF },
+ { 73, 0x00, 0x3F },
+ { 74, 0x10, 0xFF },
+ { 75, 0x00, 0xFF },
+ { 76, 0x00, 0xFF },
+ { 77, 0x00, 0xFF },
+ { 78, 0x00, 0xFF },
+ { 79, 0x00, 0xFF },
+ { 80, 0x00, 0xFF },
+ { 81, 0x00, 0xFF },
+ { 82, 0x00, 0xFF },
+ { 83, 0x00, 0xFF },
+ { 84, 0x00, 0x3F },
+ { 85, 0x10, 0xFF },
+ { 86, 0x80, 0xFF },
+ { 87, 0x0A, 0xFF },
+ { 88, 0x00, 0xFF },
+ { 89, 0x00, 0xFF },
+ { 90, 0x00, 0xFF },
+ { 91, 0x00, 0xFF },
+ { 92, 0x01, 0xFF },
+ { 93, 0x00, 0xFF },
+ { 94, 0x00, 0xFF },
+ { 95, 0x00, 0x3F },
+ { 96, 0x10, 0x00 },
+ { 97, 0x15, 0xFF },
+ { 98, 0x32, 0xFF },
+ { 99, 0x08, 0xFF },
+ { 100, 0x00, 0xFF },
+ { 101, 0x00, 0xFF },
+ { 102, 0x00, 0xFF },
+ { 103, 0x06, 0xFF },
+ { 104, 0x00, 0xFF },
+ { 105, 0x00, 0xFF },
+ { 106, 0x80, 0xBF },
+ { 107, 0x00, 0xFF },
+ { 108, 0x00, 0xFF },
+ { 109, 0x00, 0xFF },
+ { 110, 0x00, 0xFF },
+ { 111, 0x00, 0xFF },
+ { 112, 0x00, 0xFF },
+ { 113, 0x00, 0xFF },
+ { 114, 0x40, 0xFF },
+ { 115, 0x00, 0xFF },
+ { 116, 0x80, 0xFF },
+ { 117, 0x00, 0xFF },
+ { 118, 0x40, 0xFF },
+ { 119, 0x00, 0xFF },
+ { 120, 0x00, 0xFF },
+ { 121, 0x00, 0xFF },
+ { 122, 0x00, 0xFF },
+ { 123, 0x00, 0xFF },
+ { 124, 0x00, 0xFF },
+ { 125, 0x00, 0xFF },
+ { 126, 0x00, 0xFF },
+ { 127, 0x00, 0xFF },
+ { 128, 0x00, 0xFF },
+ { 129, 0x00, 0x0F },
+ { 130, 0x00, 0x0F },
+ { 131, 0x00, 0xFF },
+ { 132, 0x00, 0xFF },
+ { 133, 0x00, 0xFF },
+ { 134, 0x00, 0xFF },
+ { 135, 0x00, 0xFF },
+ { 136, 0x00, 0xFF },
+ { 137, 0x00, 0xFF },
+ { 138, 0x00, 0xFF },
+ { 139, 0x00, 0xFF },
+ { 140, 0x00, 0xFF },
+ { 141, 0x00, 0xFF },
+ { 142, 0x00, 0xFF },
+ { 143, 0x00, 0xFF },
+ { 144, 0x00, 0xFF },
+ { 145, 0x00, 0x00 },
+ { 146, 0xFF, 0x00 },
+ { 147, 0x00, 0x00 },
+ { 148, 0x00, 0x00 },
+ { 149, 0x00, 0x00 },
+ { 150, 0x00, 0x00 },
+ { 151, 0x00, 0x00 },
+ { 152, 0x00, 0xFF },
+ { 153, 0x00, 0xFF },
+ { 154, 0x00, 0xFF },
+ { 155, 0x00, 0xFF },
+ { 156, 0x00, 0xFF },
+ { 157, 0x00, 0xFF },
+ { 158, 0x00, 0x0F },
+ { 159, 0x00, 0x0F },
+ { 160, 0x00, 0xFF },
+ { 161, 0x00, 0xFF },
+ { 162, 0x00, 0xFF },
+ { 163, 0x00, 0xFF },
+ { 164, 0x00, 0xFF },
+ { 165, 0x00, 0xFF },
+ { 166, 0x00, 0xFF },
+ { 167, 0x00, 0xFF },
+ { 168, 0x00, 0xFF },
+ { 169, 0x00, 0xFF },
+ { 170, 0x00, 0xFF },
+ { 171, 0x00, 0xFF },
+ { 172, 0x00, 0xFF },
+ { 173, 0x00, 0xFF },
+ { 174, 0x00, 0xFF },
+ { 175, 0x00, 0xFF },
+ { 176, 0x00, 0xFF },
+ { 177, 0x00, 0xFF },
+ { 178, 0x00, 0xFF },
+ { 179, 0x00, 0xFF },
+ { 180, 0x00, 0xFF },
+ { 181, 0x00, 0x0F },
+ { 182, 0x00, 0xFF },
+ { 183, 0x00, 0xFF },
+ { 184, 0x00, 0xFF },
+ { 185, 0x00, 0xFF },
+ { 186, 0x00, 0xFF },
+ { 187, 0x00, 0xFF },
+ { 188, 0x00, 0xFF },
+ { 189, 0x00, 0xFF },
+ { 190, 0x00, 0xFF },
+ { 191, 0x00, 0xFF },
+ { 192, 0x00, 0xFF },
+ { 193, 0x00, 0xFF },
+ { 194, 0x00, 0xFF },
+ { 195, 0x00, 0xFF },
+ { 196, 0x00, 0xFF },
+ { 197, 0x00, 0xFF },
+ { 198, 0x00, 0xFF },
+ { 199, 0x00, 0xFF },
+ { 200, 0x00, 0xFF },
+ { 201, 0x00, 0xFF },
+ { 202, 0x00, 0xFF },
+ { 203, 0x00, 0x0F },
+ { 204, 0x00, 0xFF },
+ { 205, 0x00, 0xFF },
+ { 206, 0x00, 0xFF },
+ { 207, 0x00, 0xFF },
+ { 208, 0x00, 0xFF },
+ { 209, 0x00, 0xFF },
+ { 210, 0x00, 0xFF },
+ { 211, 0x00, 0xFF },
+ { 212, 0x00, 0xFF },
+ { 213, 0x00, 0xFF },
+ { 214, 0x00, 0xFF },
+ { 215, 0x00, 0xFF },
+ { 216, 0x00, 0xFF },
+ { 217, 0x00, 0xFF },
+ { 218, 0x00, 0x00 },
+ { 219, 0x00, 0x00 },
+ { 220, 0x00, 0x00 },
+ { 221, 0x0D, 0x00 },
+ { 222, 0x00, 0x00 },
+ { 223, 0x00, 0x00 },
+ { 224, 0xF4, 0x00 },
+ { 225, 0xF0, 0x00 },
+ { 226, 0x00, 0x00 },
+ { 227, 0x00, 0x00 },
+ { 228, 0x00, 0x00 },
+ { 229, 0x00, 0x00 },
+ { 231, 0x00, 0x00 },
+ { 232, 0x00, 0x00 },
+ { 233, 0x00, 0x00 },
+ { 234, 0x00, 0x00 },
+ { 235, 0x00, 0x00 },
+ { 236, 0x00, 0x00 },
+ { 237, 0x00, 0x00 },
+ { 238, 0x14, 0x00 },
+ { 239, 0x00, 0x00 },
+ { 240, 0x00, 0x00 },
+ { 242, 0x02, 0x02 },
+ { 243, 0xF0, 0x00 },
+ { 244, 0x00, 0x00 },
+ { 245, 0x00, 0x00 },
+ { 247, 0x00, 0x00 },
+ { 248, 0x00, 0x00 },
+ { 249, 0xA8, 0x00 },
+ { 250, 0x00, 0x00 },
+ { 251, 0x84, 0x00 },
+ { 252, 0x00, 0x00 },
+ { 253, 0x00, 0x00 },
+ { 254, 0x00, 0x00 },
+ { 255, 1, 0xFF }, // set page bit to 1
+ { 0, 0x00, 0x00 },
+ { 1, 0x00, 0x00 },
+ { 2, 0x00, 0x00 },
+ { 3, 0x00, 0x00 },
+ { 4, 0x00, 0x00 },
+ { 5, 0x00, 0x00 },
+ { 6, 0x00, 0x00 },
+ { 7, 0x00, 0x00 },
+ { 8, 0x00, 0x00 },
+ { 9, 0x00, 0x00 },
+ { 10, 0x00, 0x00 },
+ { 11, 0x00, 0x00 },
+ { 12, 0x00, 0x00 },
+ { 13, 0x00, 0x00 },
+ { 14, 0x00, 0x00 },
+ { 15, 0x00, 0x00 },
+ { 16, 0x00, 0x00 },
+ { 17, 0x01, 0x00 },
+ { 18, 0x00, 0x00 },
+ { 19, 0x00, 0x00 },
+ { 20, 0x90, 0x00 },
+ { 21, 0x31, 0x00 },
+ { 22, 0x00, 0x00 },
+ { 23, 0x00, 0x00 },
+ { 24, 0x01, 0x00 },
+ { 25, 0x00, 0x00 },
+ { 26, 0x00, 0x00 },
+ { 27, 0x00, 0x00 },
+ { 28, 0x00, 0x00 },
+ { 29, 0x00, 0x00 },
+ { 30, 0x00, 0x00 },
+ { 31, 0x00, 0xFF },
+ { 32, 0x00, 0xFF },
+ { 33, 0x01, 0xFF },
+ { 34, 0x00, 0xFF },
+ { 35, 0x00, 0xFF },
+ { 36, 0x90, 0xFF },
+ { 37, 0x31, 0xFF },
+ { 38, 0x00, 0xFF },
+ { 39, 0x00, 0xFF },
+ { 40, 0x01, 0xFF },
+ { 41, 0x00, 0xFF },
+ { 42, 0x00, 0xFF },
+ { 43, 0x00, 0x0F },
+ { 44, 0x00, 0x00 },
+ { 45, 0x00, 0x00 },
+ { 46, 0x00, 0x00 },
+ { 47, 0x00, 0xFF },
+ { 48, 0x00, 0xFF },
+ { 49, 0x01, 0xFF },
+ { 50, 0x00, 0xFF },
+ { 51, 0x00, 0xFF },
+ { 52, 0x90, 0xFF },
+ { 53, 0x31, 0xFF },
+ { 54, 0x00, 0xFF },
+ { 55, 0x00, 0xFF },
+ { 56, 0x01, 0xFF },
+ { 57, 0x00, 0xFF },
+ { 58, 0x00, 0xFF },
+ { 59, 0x00, 0x0F },
+ { 60, 0x00, 0x00 },
+ { 61, 0x00, 0x00 },
+ { 62, 0x00, 0x00 },
+ { 63, 0x00, 0xFF },
+ { 64, 0x00, 0xFF },
+ { 65, 0x01, 0xFF },
+ { 66, 0x00, 0xFF },
+ { 67, 0x00, 0xFF },
+ { 68, 0x90, 0xFF },
+ { 69, 0x31, 0xFF },
+ { 70, 0x00, 0xFF },
+ { 71, 0x00, 0xFF },
+ { 72, 0x01, 0xFF },
+ { 73, 0x00, 0xFF },
+ { 74, 0x00, 0xFF },
+ { 75, 0x00, 0x0F },
+ { 76, 0x00, 0x00 },
+ { 77, 0x00, 0x00 },
+ { 78, 0x00, 0x00 },
+ { 79, 0x00, 0xFF },
+ { 80, 0x00, 0xFF },
+ { 81, 0x00, 0xFF },
+ { 82, 0x00, 0xFF },
+ { 83, 0x00, 0xFF },
+ { 84, 0x90, 0xFF },
+ { 85, 0x31, 0xFF },
+ { 86, 0x00, 0xFF },
+ { 87, 0x00, 0xFF },
+ { 88, 0x01, 0xFF },
+ { 89, 0x00, 0xFF },
+ { 90, 0x00, 0xFF },
+ { 91, 0x00, 0x0F },
+ { 92, 0x00, 0x00 },
+ { 93, 0x00, 0x00 },
+ { 94, 0x00, 0x00 },
+ { 255, 0, 0xFF } }; // set page bit to 0
+//End of file
diff --git a/arch/arm/boards/enclustra-sa2/board.c b/arch/arm/boards/enclustra-sa2/board.c
index 4c2b44252d84c78ed8de5754051d0bf194ce8d02..d2e539cbf9460adddc158885473f4ef0004dc284 100644
--- a/arch/arm/boards/enclustra-sa2/board.c
+++ b/arch/arm/boards/enclustra-sa2/board.c
@@ -14,6 +14,7 @@
#include <mach/socfpga/cyclone5-regs.h>
#include <net.h>
#include <linux/nvmem-consumer.h>
+#include "si5338_config.h"
/** Enclustra's MAC address vendor prefix is 20:B0:F7 */
#define ENCLUSTRA_PREFIX (0x20b0f7)
@@ -99,6 +100,11 @@ static int socfpga_init(void)
set_mac_addr();
+#ifdef CONFIG_MACH_SOCFPGA_ENCLUSTRA_SA2_SI5338
+ /* configure clock generator on the Enclustra ST1 baseboard: */
+ si5338_init();
+#endif
+
return 0;
}
late_initcall(socfpga_init);
diff --git a/arch/arm/boards/enclustra-sa2/si5338_config.c b/arch/arm/boards/enclustra-sa2/si5338_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..deb8a460be3dc8712add893710825e6b0746181a
--- /dev/null
+++ b/arch/arm/boards/enclustra-sa2/si5338_config.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <i2c/i2c.h>
+#include <clock.h>
+#include <linux/kernel.h> /* ARRAY_SIZE */
+#include <linux/regmap.h>
+#include "si5338_config.h"
+#include "Si5338-RevB-Registers.h"
+
+struct si5338 {
+ struct device *dev;
+ struct regmap *map;
+ struct i2c_client *client;
+ int revision;
+ int type;
+} si_dev = { NULL, NULL, NULL, 0, 0 };
+
+
+/**
+ * @brief Get the device from the devicetree
+ * @return A pointer to the device if found, or \t NULL otherwise.
+ */
+static struct device *get_dev(void)
+{
+ struct device *dev;
+ struct i2c_client *client;
+
+ dev = get_device_by_name("si53380");
+ if (dev == NULL) {
+ printf("%s() >> ERROR: can't find device SI5338\n", __func__);
+ return NULL;
+ }
+ client = to_i2c_client(dev);
+ debug("%s() >> SI5338 found at I2C address 0x%02x\n", __func__,
+ client->addr);
+
+ return dev;
+}
+
+/**
+ * @brief Write a single byte to a register in the SI5338
+ * @param[in] ctx A pointer to a struct si5338.
+ * @param[in] reg The register address.
+ * @param[in] val The byte to be written to the register.
+ * @return 0 on success, a negative value from `asm-generic/errno.h` on error.
+ */
+static int regmap_reg_write(void *ctx, unsigned int reg, unsigned int val)
+{
+ int ret;
+ struct si5338 *si = ctx;
+ u8 buf[] = { val }; /* register value */
+
+ ret = i2c_write_reg(si->client, reg, buf, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+
+/**
+ * @brief Read a single byte from a register in the SI5338
+ * @param[in] ctx A pointer to a struct si5338.
+ * @param[in] reg The register address.
+ * @param[out] val The byte to be written to the register.
+ * @return 0 on success, a negative value from `asm-generic/errno.h` on error.
+ */
+static int regmap_reg_read(void *ctx, unsigned int reg, unsigned int *val)
+{
+ struct si5338 *si = ctx;
+ u8 buf[1];
+ int ret;
+
+ ret = i2c_read_reg(si->client, reg, buf, 1);
+ *val = buf[0];
+
+ return ret == 1 ? 0 : ret;
+}
+
+/**
+ * @brief Validate input clock status
+ * @param[in] dev The I²C device.
+ *
+ * Loop until the \c LOS_CLKIN bit is clear.
+ *
+ * @return 0 on success, a negative value from `asm-generic/errno.h` on error.
+ */
+static int check_input_clock(struct device *dev)
+{
+ // validate input clock status
+ int ret;
+ unsigned int val;
+
+ do {
+ ret = regmap_reg_read(&si_dev, 218, &val);
+ if (ret) {
+ printf("%s() >> ERROR: SI5338 read failed addr: 218\n", __func__);
+ return ret;
+ }
+ } while (val & 0x04);
+
+ return 0;
+}
+
+/**
+ * @brief Check output PLL status
+ * @param[in] dev The I²C device.
+ *
+ * Loop until the \c PLL_LOL, \c LOS_CLKIN and \c SYS_CAL bits are clear.
+ *
+ * @return 0 on success, a negative value from `asm-generic/errno.h` on error
+ * (-EIO if too many trials).
+ */
+static int check_pll(struct device *dev)
+{
+ int ret;
+ int try = 0;
+ unsigned int val;
+
+ do {
+ ret = regmap_reg_read(&si_dev, 218, &val);
+ if (ret < 0)
+ return ret;
+ mdelay(100);
+ try++;
+ if (try > 10) {
+ printf("%s() >> ERROR: SI5338 PLL is not locking\n", __func__);
+ return -EIO;
+ }
+ } while (val & 0x15);
+
+ return 0;
+}
+
+int si5338_init(void)
+{
+ unsigned int val;
+ struct device *dev;
+ int ret;
+ struct regmap_config rgmp_cfg = {
+ .reg_bits = 8, /* register addresses are coded on 8 bits */
+ .reg_stride = 1, /* register addresses increment by 1 */
+ .pad_bits = 0,
+ .val_bits = 8,
+ .max_register = 0xff, /* maximum register address */
+ .reg_format_endian = REGMAP_ENDIAN_DEFAULT,
+ .val_format_endian = REGMAP_ENDIAN_DEFAULT,
+ .read_flag_mask = 0,
+ .write_flag_mask = 0,
+ };
+ struct regmap_bus rgmp_i2c_bus = {
+ .reg_write = regmap_reg_write,
+ .reg_read = regmap_reg_read,
+ };
+
+ si_dev.dev = get_dev();
+ if (si_dev.dev == NULL)
+ return -ENODEV;
+ si_dev.client = to_i2c_client(si_dev.dev);
+ si_dev.map = regmap_init(si_dev.dev, &rgmp_i2c_bus,
+ &si_dev, &rgmp_cfg);
+
+ dev = get_dev();
+ if (dev == NULL)
+ return -ENODEV;
+
+ /* Set PAGE_SEL bit to 0. If bit is 1, registers with address
+ * greater than 255 can be addressed.
+ */
+ if (regmap_reg_write(&si_dev, 255, 0x00))
+ return -1;
+
+ // disable outputs
+ if (regmap_update_bits(si_dev.map, 230, 0x10, 0x10))
+ return -1;
+
+ // pause lol
+ if (regmap_update_bits(si_dev.map, 241, 0x80, 0x80))
+ return -1;
+
+ // write new configuration
+ for (int i = 0; i < NUM_REGS_MAX; i++)
+ if (regmap_update_bits(si_dev.map, Reg_Store[i].Reg_Addr,
+ Reg_Store[i].Reg_Mask, Reg_Store[i].Reg_Val))
+ return -1;
+
+ ret = check_input_clock(dev);
+ if (ret)
+ return ret;
+
+ // configure PLL for locking
+ ret = regmap_update_bits(si_dev.map, 49, 0x80, 0x00);
+ if (ret)
+ return ret;
+
+ // initiate locking of PLL
+ ret = regmap_reg_write(&si_dev, 246, 0x02);
+ if (ret)
+ return ret;
+
+ // wait 25ms (100ms to be on the safe side)
+ mdelay(100);
+
+ // restart lol
+ ret = regmap_update_bits(si_dev.map, 241, 0xff, 0x65);
+ if (ret)
+ return ret;
+
+ ret = check_pll(dev);
+ if (ret)
+ return ret;
+
+ // copy fcal values to active registers: FCAL[17:16]
+ ret = regmap_reg_read(&si_dev, 237, &val);
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(si_dev.map, 47, 0x03, val);
+ if (ret)
+ return ret;
+
+ // copy fcal values to active registers: FCAL[15:8]
+ ret = regmap_reg_read(&si_dev, 236, &val);
+ if (ret)
+ return ret;
+ ret = regmap_reg_write(&si_dev, 46, val);
+ if (ret)
+ return ret;
+
+ // copy fcal values to active registers: FCAL[7:0]
+ ret = regmap_reg_read(&si_dev, 235, &val);
+ if (ret)
+ return ret;
+ ret = regmap_reg_write(&si_dev, 45, val);
+ if (ret)
+ return ret;
+
+ // Must write 000101b to these bits if the device is not factory programmed
+ ret = regmap_update_bits(si_dev.map, 47, 0xFC, 0x14);
+ if (ret)
+ return ret;
+
+ // set PLL to use FCAL values
+ ret = regmap_update_bits(si_dev.map, 49, 0x80, 0x80);
+ if (ret)
+ return ret;
+
+ // enable outputs
+ ret = regmap_reg_write(&si_dev, 230, 0x00);
+ if (ret)
+ return ret;
+
+ printf("SI5338 init successful\n");
+
+ return 0;
+}
diff --git a/arch/arm/boards/enclustra-sa2/si5338_config.h b/arch/arm/boards/enclustra-sa2/si5338_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..69eb81e57e55db4fecc5ba7307ec05cd2bcc772d
--- /dev/null
+++ b/arch/arm/boards/enclustra-sa2/si5338_config.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Initialize the Si5338 clock generator.
+ *
+ * Datasheet: https://www.skyworksinc.com/en/application-pages/-/media/SkyWorks/SL/documents/public/data-sheets/Si5338.pdf
+ * Reference manual: https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/reference-manuals/Si5338-RM.pdf
+ */
+
+#pragma once
+
+/**
+ * @brief Initialize the SI5338
+ *
+ * Get the I²C address from the devicetree and write the registers of the
+ * SI5338 after the configuration in \c Si5338-RevB-Registers.h, generated
+ * by [ClockBuilder Pro](https://www.skyworksinc.com/Application-Pages/Clockbuilder-Pro-Software).
+ *
+ * @return 0 on success, a negative value from `asm-generic/errno.h` on error.
+ */
+
+int si5338_init(void);
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 61935c260c8f06acec119377af7d46411e3e2744..7b05646eac0b39a119cf1bcc61b06ebc631feb28 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -42,6 +42,10 @@ config MACH_SOCFPGA_ENCLUSTRA_SA2
select ARCH_SOCFPGA_CYCLONE5
bool "Enclustra SA2"
+config MACH_SOCFPGA_ENCLUSTRA_SA2_SI5338
+ depends on MACH_SOCFPGA_ENCLUSTRA_SA2
+ bool "Configure the SI5338 clock generator on ST1 baseboard"
+
config MACH_SOCFPGA_TERASIC_DE0_NANO_SOC
select ARCH_SOCFPGA_CYCLONE5
bool "Terasic DE0-NANO-SoC aka Atlas"
--
2.43.0
next prev parent reply other threads:[~2025-09-25 12:00 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-25 11:59 [PATCH v2 00/10] ARM: boards: add support for Enclustra Mercury SA2 David Picard
2025-09-25 11:59 ` [PATCH v2 01/10] Add handoff files David Picard
2025-09-25 11:59 ` [PATCH v2 02/10] Add Enclustra Mercury+ SA2 module David Picard
2025-09-25 11:59 ` [PATCH v2 03/10] ARM: dts: socfpga: use upstream SA2 device tree David Picard
2025-09-25 11:59 ` [PATCH v2 04/10] ARM: dts: socfpga: adapt " David Picard
2025-09-25 11:59 ` [PATCH v2 05/10] boards: enclustra-sa2: read MAC address from EEPROM David Picard
2025-09-26 12:40 ` Sascha Hauer
2025-09-26 12:57 ` David Picard
2025-09-29 8:04 ` David Picard
2025-09-25 11:59 ` David Picard [this message]
2025-09-25 11:59 ` [PATCH v2 07/10] boards: enclustra-sa2: enable SI5338 David Picard
2025-09-25 11:59 ` [PATCH v2 08/10] lib: add crc16 support David Picard
2025-09-26 12:43 ` Sascha Hauer
2025-09-25 11:59 ` [PATCH v2 09/10] nvmem: add support for Atmel sha204(a) David Picard
2025-09-25 11:59 ` [PATCH v2 10/10] boards: enclustra-sa2: read S/N from EEPROM David Picard
2025-09-26 12:47 ` [PATCH v2 00/10] ARM: boards: add support for Enclustra Mercury SA2 Sascha Hauer
2025-09-30 10:40 ` Sascha Hauer
2025-09-30 11:47 ` David Picard
2025-09-30 11:49 ` David Picard
[not found] ` <aade6cdb-3244-4468-8bab-215a54fdef15@clermont.in2p3.fr>
2025-10-01 8:29 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250925-boards-enclustra-sa2-add-support-v2-6-6820ad6c6256@clermont.in2p3.fr \
--to=david.picard@clermont.in2p3.fr \
--cc=barebox@lists.infradead.org \
--cc=s.hauer@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox