* [PATCH v2] ptp: ocp: Add support for Xilinx-based Adva TimeCard variant
@ 2026-03-08 8:09 Sagi Maimon
2026-03-09 16:05 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: Sagi Maimon @ 2026-03-08 8:09 UTC (permalink / raw)
To: jonathan.lemon, vadim.fedorenko, richardcochran, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: linux-kernel, netdev, Sagi Maimon
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 13603 bytes --]
Add support for the Adva TimeCard model built on a Xilinx-based design.
This patch enables detection and integration of the new hardware within
the existing OCP timecard framework.
The Xilinx variant relies on the shared driver infrastructure, requiring
only small, targeted additions to accommodate its specific
characteristics.
Signed-off-by: Sagi Maimon <maimon.sagi@gmail.com>
---
Addressed comments from Simon Horman and Vadim Fedorenko:
- https://www.spinics.net/lists/netdev/msg1160388.html
- https://www.spinics.net/lists/netdev/msg1160386.html
Changes since v1:
- Removed duplicated Adva init functions;
unified logic with variant‑specific data.
---
drivers/ptp/ptp_ocp.c | 341 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 325 insertions(+), 16 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index d88ab2f86b1b..c43ce18dfb42 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -35,6 +35,7 @@
#define PCI_VENDOR_ID_ADVA 0xad5a
#define PCI_DEVICE_ID_ADVA_TIMECARD 0x0400
+#define PCI_DEVICE_ID_ADVA_TIMECARD_X1 0x0410
static struct class timecard_class = {
.name = "timecard",
@@ -72,6 +73,20 @@ struct ptp_ocp_servo_conf {
u32 servo_drift_i;
};
+/*
+ * Combined servo + board-variant parameters for ADVA boards.
+ * Embedded in the resource table .extra so a single ptp_ocp_adva_board_init()
+ * can handle both ADVA and ADVA-X1 without per-variant init functions.
+ */
+struct ptp_ocp_adva_info {
+ struct ptp_ocp_servo_conf servo;
+ u32 flash_start;
+ const struct ocp_sma_op *sma_op;
+ u8 signals_nr;
+ u8 freq_in_nr;
+ const struct ocp_attr_group *attr_groups;
+};
+
#define OCP_CTRL_ENABLE BIT(0)
#define OCP_CTRL_ADJUST_TIME BIT(1)
#define OCP_CTRL_ADJUST_OFFSET BIT(2)
@@ -420,12 +435,17 @@ static int ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
+static const struct ocp_sma_op ocp_adva_sma_op;
+static const struct ocp_sma_op ocp_adva_x1_sma_op;
+
static const struct ocp_attr_group fb_timecard_groups[];
static const struct ocp_attr_group art_timecard_groups[];
static const struct ocp_attr_group adva_timecard_groups[];
+static const struct ocp_attr_group adva_timecard_x1_groups[];
+
struct ptp_ocp_eeprom_map {
u16 off;
u16 len;
@@ -1020,11 +1040,225 @@ static struct ocp_resource ocp_adva_resource[] = {
},
{
.setup = ptp_ocp_adva_board_init,
- .extra = &(struct ptp_ocp_servo_conf) {
- .servo_offset_p = 0xc000,
- .servo_offset_i = 0x1000,
- .servo_drift_p = 0,
- .servo_drift_i = 0,
+ .extra = &(struct ptp_ocp_adva_info) {
+ .servo = {
+ .servo_offset_p = 0xc000,
+ .servo_offset_i = 0x1000,
+ .servo_drift_p = 0,
+ .servo_drift_i = 0,
+ },
+ .flash_start = 0xA00000,
+ .sma_op = &ocp_adva_sma_op,
+ .signals_nr = 2,
+ .freq_in_nr = 2,
+ .attr_groups = adva_timecard_groups,
+ },
+ },
+ { }
+};
+
+static struct ocp_resource ocp_adva_x1_resource[] = {
+ {
+ OCP_MEM_RESOURCE(reg),
+ .offset = 0x01000000, .size = 0x10000,
+ },
+ {
+ OCP_EXT_RESOURCE(ts0),
+ .offset = 0x01010000, .size = 0x10000, .irq_vec = 1,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 0,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(ts1),
+ .offset = 0x01020000, .size = 0x10000, .irq_vec = 2,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 1,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(ts2),
+ .offset = 0x01060000, .size = 0x10000, .irq_vec = 6,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 2,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(ts3),
+ .offset = 0x01110000, .size = 0x10000, .irq_vec = 15,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 3,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(ts4),
+ .offset = 0x01120000, .size = 0x10000, .irq_vec = 16,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 4,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ /* Timestamp for PHC and/or PPS generator */
+ {
+ OCP_EXT_RESOURCE(pps),
+ .offset = 0x010C0000, .size = 0x10000, .irq_vec = 0,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 5,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(signal_out[0]),
+ .offset = 0x010D0000, .size = 0x10000, .irq_vec = 11,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 1,
+ .irq_fcn = ptp_ocp_signal_irq,
+ .enable = ptp_ocp_signal_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(signal_out[1]),
+ .offset = 0x010E0000, .size = 0x10000, .irq_vec = 12,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 2,
+ .irq_fcn = ptp_ocp_signal_irq,
+ .enable = ptp_ocp_signal_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(signal_out[2]),
+ .offset = 0x010F0000, .size = 0x10000, .irq_vec = 13,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 3,
+ .irq_fcn = ptp_ocp_signal_irq,
+ .enable = ptp_ocp_signal_enable,
+ },
+ },
+ {
+ OCP_EXT_RESOURCE(signal_out[3]),
+ .offset = 0x01100000, .size = 0x10000, .irq_vec = 14,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 4,
+ .irq_fcn = ptp_ocp_signal_irq,
+ .enable = ptp_ocp_signal_enable,
+ },
+ },
+ {
+ OCP_MEM_RESOURCE(pps_to_ext),
+ .offset = 0x01030000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(pps_to_clk),
+ .offset = 0x01040000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(tod),
+ .offset = 0x01050000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(image),
+ .offset = 0x00020000, .size = 0x1000,
+ },
+ {
+ OCP_MEM_RESOURCE(pps_select),
+ .offset = 0x00130000, .size = 0x1000,
+ },
+ {
+ OCP_MEM_RESOURCE(sma_map1),
+ .offset = 0x00140000, .size = 0x1000,
+ },
+ {
+ OCP_MEM_RESOURCE(sma_map2),
+ .offset = 0x00220000, .size = 0x1000,
+ },
+ {
+ OCP_SERIAL_RESOURCE(port[PORT_GNSS]),
+ .offset = 0x00160000 + 0x1000, .irq_vec = 3,
+ .extra = &(struct ptp_ocp_serial_port) {
+ .baud = 9600,
+ },
+ },
+ {
+ OCP_SERIAL_RESOURCE(port[PORT_MAC]),
+ .offset = 0x00180000 + 0x1000, .irq_vec = 5,
+ .extra = &(struct ptp_ocp_serial_port) {
+ .baud = 115200,
+ },
+ },
+ {
+ OCP_MEM_RESOURCE(freq_in[0]),
+ .offset = 0x01200000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(freq_in[1]),
+ .offset = 0x01210000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(freq_in[2]),
+ .offset = 0x01220000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(freq_in[3]),
+ .offset = 0x01230000, .size = 0x10000,
+ },
+ {
+ OCP_SPI_RESOURCE(spi_flash),
+ .offset = 0x00310000, .size = 0x10000, .irq_vec = 9,
+ .extra = &(struct ptp_ocp_flash_info) {
+ .name = "xilinx_spi", .pci_offset = 0,
+ .data_size = sizeof(struct xspi_platform_data),
+ .data = &(struct xspi_platform_data) {
+ .num_chipselect = 1,
+ .bits_per_word = 8,
+ .num_devices = 1,
+ .force_irq = true,
+ .devices = &(struct spi_board_info) {
+ .modalias = "spi-nor",
+ },
+ },
+ },
+ },
+ {
+ OCP_I2C_RESOURCE(i2c_ctrl),
+ .offset = 0x00150000, .size = 0x10000, .irq_vec = 7,
+ .extra = &(struct ptp_ocp_i2c_info) {
+ .name = "xiic-i2c",
+ .fixed_rate = 50000000,
+ .data_size = sizeof(struct xiic_i2c_platform_data),
+ .data = &(struct xiic_i2c_platform_data) {
+ .num_devices = 2,
+ .devices = (struct i2c_board_info[]) {
+ { I2C_BOARD_INFO("24c02", 0x50) },
+ { I2C_BOARD_INFO("24mac402", 0x58),
+ .platform_data = "mac" },
+ },
+ },
+ },
+ },
+ {
+ .setup = ptp_ocp_adva_board_init,
+ .extra = &(struct ptp_ocp_adva_info) {
+ .servo = {
+ .servo_offset_p = 0xc000,
+ .servo_offset_i = 0x1000,
+ .servo_drift_p = 0,
+ .servo_drift_i = 0,
+ },
+ .flash_start = 0x1000000,
+ .sma_op = &ocp_adva_x1_sma_op,
+ .signals_nr = 4,
+ .freq_in_nr = 4,
+ .attr_groups = adva_timecard_x1_groups,
},
},
{ }
@@ -1035,6 +1269,7 @@ static const struct pci_device_id ptp_ocp_pcidev_id[] = {
{ PCI_DEVICE_DATA(CELESTICA, TIMECARD, &ocp_fb_resource) },
{ PCI_DEVICE_DATA(OROLIA, ARTCARD, &ocp_art_resource) },
{ PCI_DEVICE_DATA(ADVA, TIMECARD, &ocp_adva_resource) },
+ { PCI_DEVICE_DATA(ADVA, TIMECARD_X1, &ocp_adva_x1_resource) },
{ }
};
MODULE_DEVICE_TABLE(pci, ptp_ocp_pcidev_id);
@@ -1137,6 +1372,34 @@ static const struct ocp_selector ptp_ocp_adva_sma_out[] = {
{ }
};
+static const struct ocp_selector ptp_ocp_adva_x1_sma_in[] = {
+ { .name = "PPS1", .value = 0x0001, .frequency = 1 },
+ { .name = "TS1", .value = 0x0004, .frequency = 0 },
+ { .name = "TS2", .value = 0x0008, .frequency = 0 },
+ { .name = "TS3", .value = 0x0040, .frequency = 0 },
+ { .name = "TS4", .value = 0x0080, .frequency = 0 },
+ { .name = "FREQ1", .value = 0x0100, .frequency = 0 },
+ { .name = "FREQ2", .value = 0x0200, .frequency = 0 },
+ { .name = "FREQ3", .value = 0x0400, .frequency = 0 },
+ { .name = "FREQ4", .value = 0x0800, .frequency = 0 },
+ { .name = "None", .value = SMA_DISABLE, .frequency = 0 },
+ { }
+};
+
+static const struct ocp_selector ptp_ocp_adva_x1_sma_out[] = {
+ { .name = "10Mhz", .value = 0x0000, .frequency = 10000000},
+ { .name = "PHC", .value = 0x0001, .frequency = 1 },
+ { .name = "MAC", .value = 0x0002, .frequency = 1 },
+ { .name = "GNSS1", .value = 0x0004, .frequency = 1 },
+ { .name = "GEN1", .value = 0x0040 },
+ { .name = "GEN2", .value = 0x0080 },
+ { .name = "GEN3", .value = 0x0100 },
+ { .name = "GEN4", .value = 0x0200 },
+ { .name = "GND", .value = 0x2000 },
+ { .name = "VCC", .value = 0x4000 },
+ { }
+};
+
struct ocp_sma_op {
const struct ocp_selector *tbl[2];
void (*init)(struct ptp_ocp *bp);
@@ -2639,6 +2902,14 @@ static const struct ocp_sma_op ocp_adva_sma_op = {
.set_output = ptp_ocp_sma_adva_set_output,
};
+static const struct ocp_sma_op ocp_adva_x1_sma_op = {
+ .tbl = { ptp_ocp_adva_x1_sma_in, ptp_ocp_adva_x1_sma_out },
+ .init = ptp_ocp_sma_fb_init,
+ .get = ptp_ocp_sma_fb_get,
+ .set_inputs = ptp_ocp_sma_adva_set_inputs,
+ .set_output = ptp_ocp_sma_adva_set_output,
+};
+
static int
ptp_ocp_set_pins(struct ptp_ocp *bp)
{
@@ -2887,18 +3158,19 @@ ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
return ptp_ocp_init_clock(bp, r->extra);
}
-/* ADVA specific board initializers; last "resource" registered. */
+/* ADVA board initializer; variant differences come from r->extra. */
static int
ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
{
- int err;
+ struct ptp_ocp_adva_info *info = r->extra;
u32 version;
+ int err;
- bp->flash_start = 0xA00000;
- bp->eeprom_map = fb_eeprom_map;
- bp->sma_op = &ocp_adva_sma_op;
- bp->signals_nr = 2;
- bp->freq_in_nr = 2;
+ bp->flash_start = info->flash_start;
+ bp->eeprom_map = fb_eeprom_map;
+ bp->sma_op = info->sma_op;
+ bp->signals_nr = info->signals_nr;
+ bp->freq_in_nr = info->freq_in_nr;
version = ioread32(&bp->image->version);
/* if lower 16 bits are empty, this is the fw loader. */
@@ -2906,15 +3178,15 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
version = version >> 16;
bp->fw_loader = true;
}
- bp->fw_tag = 3;
+ bp->fw_tag = 3;
bp->fw_version = version & 0xffff;
- bp->fw_cap = OCP_CAP_BASIC | OCP_CAP_SIGNAL | OCP_CAP_FREQ;
+ bp->fw_cap = OCP_CAP_BASIC | OCP_CAP_SIGNAL | OCP_CAP_FREQ;
ptp_ocp_tod_init(bp);
ptp_ocp_nmea_out_init(bp);
ptp_ocp_signal_init(bp);
- err = ptp_ocp_attr_group_add(bp, adva_timecard_groups);
+ err = ptp_ocp_attr_group_add(bp, info->attr_groups);
if (err)
return err;
@@ -2923,7 +3195,7 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
return err;
ptp_ocp_sma_init(bp);
- return ptp_ocp_init_clock(bp, r->extra);
+ return ptp_ocp_init_clock(bp, &info->servo);
}
static ssize_t
@@ -3982,6 +4254,43 @@ static const struct ocp_attr_group adva_timecard_groups[] = {
{ },
};
+static struct attribute *adva_timecard_x1_attrs[] = {
+ &dev_attr_serialnum.attr,
+ &dev_attr_gnss_sync.attr,
+ &dev_attr_clock_source.attr,
+ &dev_attr_available_clock_sources.attr,
+ &dev_attr_sma1.attr,
+ &dev_attr_sma2.attr,
+ &dev_attr_sma3.attr,
+ &dev_attr_sma4.attr,
+ &dev_attr_available_sma_inputs.attr,
+ &dev_attr_available_sma_outputs.attr,
+ &dev_attr_clock_status_drift.attr,
+ &dev_attr_clock_status_offset.attr,
+ &dev_attr_ts_window_adjust.attr,
+ &dev_attr_utc_tai_offset.attr,
+ &dev_attr_tod_correction.attr,
+ NULL,
+};
+
+static const struct attribute_group adva_timecard_x1_group = {
+ .attrs = adva_timecard_x1_attrs,
+};
+
+static const struct ocp_attr_group adva_timecard_x1_groups[] = {
+ { .cap = OCP_CAP_BASIC, .group = &adva_timecard_x1_group },
+ { .cap = OCP_CAP_BASIC, .group = &ptp_ocp_timecard_tty_group },
+ { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group },
+ { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group },
+ { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal2_group },
+ { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal3_group },
+ { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group },
+ { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq1_group },
+ { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq2_group },
+ { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq3_group },
+ { },
+};
+
static void
gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit,
const char *def)
--
2.47.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] ptp: ocp: Add support for Xilinx-based Adva TimeCard variant
2026-03-08 8:09 [PATCH v2] ptp: ocp: Add support for Xilinx-based Adva TimeCard variant Sagi Maimon
@ 2026-03-09 16:05 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-03-09 16:05 UTC (permalink / raw)
To: Sagi Maimon, jonathan.lemon, vadim.fedorenko, richardcochran,
andrew+netdev, davem, edumazet, kuba, pabeni
Cc: llvm, oe-kbuild-all, linux-kernel, netdev, Sagi Maimon
Hi Sagi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
[also build test WARNING on net/main linus/master v7.0-rc3 next-20260306]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sagi-Maimon/ptp-ocp-Add-support-for-Xilinx-based-Adva-TimeCard-variant/20260308-161130
base: net-next/main
patch link: https://lore.kernel.org/r/20260308080944.5200-1-maimon.sagi%40gmail.com
patch subject: [PATCH v2] ptp: ocp: Add support for Xilinx-based Adva TimeCard variant
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20260310/202603100054.UoKwTVMf-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260310/202603100054.UoKwTVMf-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603100054.UoKwTVMf-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/ptp/ptp_ocp.c:438:32: warning: tentative definition of variable with internal linkage has incomplete non-array type 'const struct ocp_sma_op' [-Wtentative-definition-incomplete-type]
438 | static const struct ocp_sma_op ocp_adva_sma_op;
| ^
drivers/ptp/ptp_ocp.c:84:15: note: forward declaration of 'struct ocp_sma_op'
84 | const struct ocp_sma_op *sma_op;
| ^
drivers/ptp/ptp_ocp.c:439:32: warning: tentative definition of variable with internal linkage has incomplete non-array type 'const struct ocp_sma_op' [-Wtentative-definition-incomplete-type]
439 | static const struct ocp_sma_op ocp_adva_x1_sma_op;
| ^
drivers/ptp/ptp_ocp.c:84:15: note: forward declaration of 'struct ocp_sma_op'
84 | const struct ocp_sma_op *sma_op;
| ^
2 warnings generated.
vim +438 drivers/ptp/ptp_ocp.c
437
> 438 static const struct ocp_sma_op ocp_adva_sma_op;
439 static const struct ocp_sma_op ocp_adva_x1_sma_op;
440
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-09 16:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-08 8:09 [PATCH v2] ptp: ocp: Add support for Xilinx-based Adva TimeCard variant Sagi Maimon
2026-03-09 16:05 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox