From nobody Thu Apr 2 18:46:12 2026 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE2AB21CC64 for ; Thu, 12 Feb 2026 15:00:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770908421; cv=none; b=SoM3CgmzIvE3QF8Ryqi+0nyHuWYleKlNBzV2gWqk0DR2JLYlIPXPKvSmxCXjCFOKVBJlD7o1qTsq8grXE8RMG+hjxPDuvhZFwYQgLLAij/k1NxkiE9H3t9PnOiffuQ336BjcZgzcH1nqCRVZqvps6oADxjn65Ul7nruzlynjWo0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770908421; c=relaxed/simple; bh=Gg1yRjRA/eUBpU9/Krqz2Cdk0QEo9yoYCCfWG7WPwAs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=s9Lr+kQBC/6DQqdRqpt+3fMtytaespRi6OhSTLerZ/MY1GHAwjLn9GLP4fHmjbiuZBIUbimW7h0feWhcEbc0EA6yupWQSvxzhHwTKI4vldvXy7RSxvlMJK96NTvNnsVojPcQke+wHlvEf9TCC5Otj8GKWLjXWhqcEXhPBYnPHfg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RCbTKVLW; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RCbTKVLW" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-4362d4050c1so6472531f8f.2 for ; Thu, 12 Feb 2026 07:00:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770908417; x=1771513217; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=An+1kJUAIGNhzzmZlVTiy8K8oJ6z4LO1tolxkdeyVeo=; b=RCbTKVLW9VgdS/pNhuWqrT9mLYPOzbSBoDZVC6DsKS3D8DDGveOstDJl6rXxnn2nHQ yBezwyEvir39nyuLL0haDuOPhISv93e7eDp8yXQOXhbtdQH5jHveVTvyrFjuCMvVabVd juT/J/xZ1ZBacI7KbMzY1B5XeoVrlTI8DBsQvqhf9of+io3QIovFT7UStX3v45Vsw4sd vT+IwDq1QZK5aNkC/hrRggrnjZyEmhb0vjyEOKRBLUC4lMIyeODwkXM4pelmR4/RXrhb MI5MPmyXHvWllsOpLu6BY2uA3xq3ZMOJTEOIOm3D/BrX94AizMDdqWzuT1r9Y2aowjRi GfQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770908417; x=1771513217; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=An+1kJUAIGNhzzmZlVTiy8K8oJ6z4LO1tolxkdeyVeo=; b=ocIu2V5lB5lSkjvd6sOYNd3oAa9ydtETbsQNVyqjlzFNuZNsJzlK7xG1y0B6xsQCIK D2xYNKjyUMa27VgTeUpoCp+2d8kuvhwu0WsL/bI3lXS1BnCAK+x60jL9/pcTEUpEMRpH YY7WUR/VxesSMrnWvOanVq5hcGO+EkqwYjvsr4XjHiElaOuN+gV4DAW15JnQPzf3aLhK 4AxIxPqiYg7wa3hi0Z9GTMqFgqO6QpCWbdf84HFSy137gai2zfeVOEAjg096/6VAGqs5 R8yEYuep0pxQuzT+6CfrgkekTBJvC+kZIXAX82D66+DAcJAEJJBwVrdbt4c+OZv3lSH7 Rbbw== X-Gm-Message-State: AOJu0YxIbQwIC0ssh8nE6QmdUuWvdAWDONfPdq6bC1IX7hzJMZkos2vQ ujN/MOl4hfHoW9ho5VNqscetPSCHu7oyd1G+G6XDoTAH7FttsWS3CIZi X-Gm-Gg: AZuq6aKI8pLd9yNeXpZX0KPD23sdt9Fo6sS46Fk3na93Oqqny0J7PKEDnyOJOOgn8Cv ZmsAlIkC5xShbTLWtYD3uQxOAlIFnIxWiHnHkqUlpOUHUHzhkNa2XVhvGwm9n0CZHedQNLNNd2n qLiPempoOVoFzfmslc0RLBGTsxXkiCLbm4QY+iorJg7HhVp4FV3qIBDvd+uRMMKHot1nN11GTda 7imT+cViF9ROA6bkCFzlywS1VJvm13g5pd1ChT00kTHs6zrx/5RImRqv7amXD2E/BgYjo6mhqm5 mlv3H/4MsLZiT7CqGn0OT19WdpjcCFhdn/DNFrdg2rm8XiGRGoIfTFUUYUndeg4jugwwIrw3H28 KusivJrd3CZvSP7Njf1cEi3/+Qn/tmxdWWgqUmsBGlwlBJAd0hJFLdyZmxPz8W2/ZE+ElQrj6rW 0h0BuL/WI8Ea7q/0f67bLkxd8VlhgGYNgwR/3wWrBzf6iAYg== X-Received: by 2002:a05:6000:2903:b0:431:35a:4a8f with SMTP id ffacd0b85a97d-4378ada9afdmr5737341f8f.47.1770908416644; Thu, 12 Feb 2026 07:00:16 -0800 (PST) Received: from fedora.advaoptical.com ([82.166.23.19]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43783dfc8b9sm12573651f8f.24.2026.02.12.07.00.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Feb 2026 07:00:16 -0800 (PST) From: Sagi Maimon To: jonathan.lemon@gmail.com, vadim.fedorenko@linux.dev, richardcochran@gmail.com, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Sagi Maimon Subject: [PATCH v1] ptp: ocp: Add Xilinx-based Adva Timecard support Date: Thu, 12 Feb 2026 17:00:07 +0200 Message-ID: <20260212150007.6628-1-maimon.sagi@gmail.com> X-Mailer: git-send-email 2.47.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for the Adva TimeCard variant that uses a Xilinx-based design. This patch introduces the necessary handling to identify and integrate this hardware into the existing OCP timecard framework. The new variant reuses the common code paths already present in the driver, requiring only minimal additions. Signed-off-by: Sagi Maimon --- drivers/ptp/ptp_ocp.c | 318 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index 65fe05cac8c4..d436380442c6 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -35,6 +35,7 @@ =20 #define PCI_VENDOR_ID_ADVA 0xad5a #define PCI_DEVICE_ID_ADVA_TIMECARD 0x0400 +#define PCI_DEVICE_ID_ADVA_TIMECARD_X1 0x0410 =20 static struct class timecard_class =3D { .name =3D "timecard", @@ -418,12 +419,16 @@ static int ptp_ocp_art_board_init(struct ptp_ocp *bp,= struct ocp_resource *r); =20 static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource= *r); =20 +static int ptp_ocp_adva_board_x1_init(struct ptp_ocp *bp, struct ocp_resou= rce *r); + static const struct ocp_attr_group fb_timecard_groups[]; =20 static const struct ocp_attr_group art_timecard_groups[]; =20 static const struct ocp_attr_group adva_timecard_groups[]; =20 +static const struct ocp_attr_group adva_timecard_x1_groups[]; + struct ptp_ocp_eeprom_map { u16 off; u16 len; @@ -1028,11 +1033,212 @@ static struct ocp_resource ocp_adva_resource[] =3D= { { } }; =20 +static struct ocp_resource ocp_adva_x1_resource[] =3D { + { + OCP_MEM_RESOURCE(reg), + .offset =3D 0x01000000, .size =3D 0x10000, + }, + { + OCP_EXT_RESOURCE(ts0), + .offset =3D 0x01010000, .size =3D 0x10000, .irq_vec =3D 1, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 0, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + { + OCP_EXT_RESOURCE(ts1), + .offset =3D 0x01020000, .size =3D 0x10000, .irq_vec =3D 2, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 1, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + { + OCP_EXT_RESOURCE(ts2), + .offset =3D 0x01060000, .size =3D 0x10000, .irq_vec =3D 6, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 2, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + { + OCP_EXT_RESOURCE(ts3), + .offset =3D 0x01110000, .size =3D 0x10000, .irq_vec =3D 15, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 3, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + { + OCP_EXT_RESOURCE(ts4), + .offset =3D 0x01120000, .size =3D 0x10000, .irq_vec =3D 16, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 4, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + /* Timestamp for PHC and/or PPS generator */ + { + OCP_EXT_RESOURCE(pps), + .offset =3D 0x010C0000, .size =3D 0x10000, .irq_vec =3D 0, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 5, + .irq_fcn =3D ptp_ocp_ts_irq, + .enable =3D ptp_ocp_ts_enable, + }, + }, + { + OCP_EXT_RESOURCE(signal_out[0]), + .offset =3D 0x010D0000, .size =3D 0x10000, .irq_vec =3D 11, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 1, + .irq_fcn =3D ptp_ocp_signal_irq, + .enable =3D ptp_ocp_signal_enable, + }, + }, + { + OCP_EXT_RESOURCE(signal_out[1]), + .offset =3D 0x010E0000, .size =3D 0x10000, .irq_vec =3D 12, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 2, + .irq_fcn =3D ptp_ocp_signal_irq, + .enable =3D ptp_ocp_signal_enable, + }, + }, + { + OCP_EXT_RESOURCE(signal_out[2]), + .offset =3D 0x010F0000, .size =3D 0x10000, .irq_vec =3D 13, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 3, + .irq_fcn =3D ptp_ocp_signal_irq, + .enable =3D ptp_ocp_signal_enable, + }, + }, + { + OCP_EXT_RESOURCE(signal_out[3]), + .offset =3D 0x01100000, .size =3D 0x10000, .irq_vec =3D 14, + .extra =3D &(struct ptp_ocp_ext_info) { + .index =3D 4, + .irq_fcn =3D ptp_ocp_signal_irq, + .enable =3D ptp_ocp_signal_enable, + }, + }, + { + OCP_MEM_RESOURCE(pps_to_ext), + .offset =3D 0x01030000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(pps_to_clk), + .offset =3D 0x01040000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(tod), + .offset =3D 0x01050000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(image), + .offset =3D 0x00020000, .size =3D 0x1000, + }, + { + OCP_MEM_RESOURCE(pps_select), + .offset =3D 0x00130000, .size =3D 0x1000, + }, + { + OCP_MEM_RESOURCE(sma_map1), + .offset =3D 0x00140000, .size =3D 0x1000, + }, + { + OCP_MEM_RESOURCE(sma_map2), + .offset =3D 0x00220000, .size =3D 0x1000, + }, + { + OCP_SERIAL_RESOURCE(port[PORT_GNSS]), + .offset =3D 0x00160000 + 0x1000, .irq_vec =3D 3, + .extra =3D &(struct ptp_ocp_serial_port) { + .baud =3D 9600, + }, + }, + { + OCP_SERIAL_RESOURCE(port[PORT_MAC]), + .offset =3D 0x00180000 + 0x1000, .irq_vec =3D 5, + .extra =3D &(struct ptp_ocp_serial_port) { + .baud =3D 115200, + }, + }, + { + OCP_MEM_RESOURCE(freq_in[0]), + .offset =3D 0x01200000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(freq_in[1]), + .offset =3D 0x01210000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(freq_in[2]), + .offset =3D 0x01220000, .size =3D 0x10000, + }, + { + OCP_MEM_RESOURCE(freq_in[3]), + .offset =3D 0x01230000, .size =3D 0x10000, + }, + { + OCP_SPI_RESOURCE(spi_flash), + .offset =3D 0x00310000, .size =3D 0x10000, .irq_vec =3D 9, + .extra =3D &(struct ptp_ocp_flash_info) { + .name =3D "xilinx_spi", .pci_offset =3D 0, + .data_size =3D sizeof(struct xspi_platform_data), + .data =3D &(struct xspi_platform_data) { + .num_chipselect =3D 1, + .bits_per_word =3D 8, + .num_devices =3D 1, + .force_irq =3D true, + .devices =3D &(struct spi_board_info) { + .modalias =3D "spi-nor", + }, + }, + }, + }, + { + OCP_I2C_RESOURCE(i2c_ctrl), + .offset =3D 0x00150000, .size =3D 0x10000, .irq_vec =3D 7, + .extra =3D &(struct ptp_ocp_i2c_info) { + .name =3D "xiic-i2c", + .fixed_rate =3D 50000000, + .data_size =3D sizeof(struct xiic_i2c_platform_data), + .data =3D &(struct xiic_i2c_platform_data) { + .num_devices =3D 2, + .devices =3D (struct i2c_board_info[]) { + { I2C_BOARD_INFO("24c02", 0x50) }, + { I2C_BOARD_INFO("24mac402", 0x58), + .platform_data =3D "mac" }, + }, + }, + }, + }, + { + .setup =3D ptp_ocp_adva_board_x1_init, + .extra =3D &(struct ptp_ocp_servo_conf) { + .servo_offset_p =3D 0xc000, + .servo_offset_i =3D 0x1000, + .servo_drift_p =3D 0, + .servo_drift_i =3D 0, + }, + }, + { } +}; + static const struct pci_device_id ptp_ocp_pcidev_id[] =3D { { PCI_DEVICE_DATA(META, TIMECARD, &ocp_fb_resource) }, { 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); @@ -1135,6 +1341,34 @@ static const struct ocp_selector ptp_ocp_adva_sma_ou= t[] =3D { { } }; =20 +static const struct ocp_selector ptp_ocp_adva_x1_sma_in[] =3D { + { .name =3D "PPS1", .value =3D 0x0001, .frequency =3D 1 }, + { .name =3D "TS1", .value =3D 0x0004, .frequency =3D 0 }, + { .name =3D "TS2", .value =3D 0x0008, .frequency =3D 0 }, + { .name =3D "TS3", .value =3D 0x0040, .frequency =3D 0 }, + { .name =3D "TS4", .value =3D 0x0080, .frequency =3D 0 }, + { .name =3D "FREQ1", .value =3D 0x0100, .frequency =3D 0 }, + { .name =3D "FREQ2", .value =3D 0x0200, .frequency =3D 0 }, + { .name =3D "FREQ3", .value =3D 0x0400, .frequency =3D 0 }, + { .name =3D "FREQ4", .value =3D 0x0800, .frequency =3D 0 }, + { .name =3D "None", .value =3D SMA_DISABLE, .frequency =3D 0 }, + { } +}; + +static const struct ocp_selector ptp_ocp_adva_x1_sma_out[] =3D { + { .name =3D "10Mhz", .value =3D 0x0000, .frequency =3D 10000000}, + { .name =3D "PHC", .value =3D 0x0001, .frequency =3D 1 }, + { .name =3D "MAC", .value =3D 0x0002, .frequency =3D 1 }, + { .name =3D "GNSS1", .value =3D 0x0004, .frequency =3D 1 }, + { .name =3D "GEN1", .value =3D 0x0040 }, + { .name =3D "GEN2", .value =3D 0x0080 }, + { .name =3D "GEN3", .value =3D 0x0100 }, + { .name =3D "GEN4", .value =3D 0x0200 }, + { .name =3D "GND", .value =3D 0x2000 }, + { .name =3D "VCC", .value =3D 0x4000 }, + { } +}; + struct ocp_sma_op { const struct ocp_selector *tbl[2]; void (*init)(struct ptp_ocp *bp); @@ -2638,6 +2872,14 @@ static const struct ocp_sma_op ocp_adva_sma_op =3D { .set_output =3D ptp_ocp_sma_adva_set_output, }; =20 +static const struct ocp_sma_op ocp_adva_x1_sma_op =3D { + .tbl =3D { ptp_ocp_adva_x1_sma_in, ptp_ocp_adva_x1_sma_out }, + .init =3D ptp_ocp_sma_fb_init, + .get =3D ptp_ocp_sma_fb_get, + .set_inputs =3D ptp_ocp_sma_adva_set_inputs, + .set_output =3D ptp_ocp_sma_adva_set_output, +}; + static int ptp_ocp_set_pins(struct ptp_ocp *bp) { @@ -2925,6 +3167,45 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct o= cp_resource *r) return ptp_ocp_init_clock(bp, r->extra); } =20 +/* ADVA specific board X initializers; last "resource" registered. */ +static int +ptp_ocp_adva_board_x1_init(struct ptp_ocp *bp, struct ocp_resource *r) +{ + int err; + u32 version; + + bp->flash_start =3D 0x1000000; + bp->eeprom_map =3D fb_eeprom_map; + bp->sma_op =3D &ocp_adva_x1_sma_op; + bp->signals_nr =3D 4; + bp->freq_in_nr =3D 4; + + version =3D ioread32(&bp->image->version); + /* if lower 16 bits are empty, this is the fw loader. */ + if ((version & 0xffff) =3D=3D 0) { + version =3D version >> 16; + bp->fw_loader =3D true; + } + bp->fw_tag =3D 3; + bp->fw_version =3D version & 0xffff; + bp->fw_cap =3D 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 =3D ptp_ocp_attr_group_add(bp, adva_timecard_x1_groups); + if (err) + return err; + + err =3D ptp_ocp_set_pins(bp); + if (err) + return err; + ptp_ocp_sma_init(bp); + + return ptp_ocp_init_clock(bp, r->extra); +} + static ssize_t ptp_ocp_show_output(const struct ocp_selector *tbl, u32 val, char *buf, int def_val) @@ -3981,6 +4262,43 @@ static const struct ocp_attr_group adva_timecard_gro= ups[] =3D { { }, }; =20 +static struct attribute *adva_timecard_x1_attrs[] =3D { + &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 =3D { + .attrs =3D adva_timecard_x1_attrs, +}; + +static const struct ocp_attr_group adva_timecard_x1_groups[] =3D { + { .cap =3D OCP_CAP_BASIC, .group =3D &adva_timecard_x1_group }, + { .cap =3D OCP_CAP_BASIC, .group =3D &ptp_ocp_timecard_tty_group }, + { .cap =3D OCP_CAP_SIGNAL, .group =3D &fb_timecard_signal0_group }, + { .cap =3D OCP_CAP_SIGNAL, .group =3D &fb_timecard_signal1_group }, + { .cap =3D OCP_CAP_SIGNAL, .group =3D &fb_timecard_signal2_group }, + { .cap =3D OCP_CAP_SIGNAL, .group =3D &fb_timecard_signal3_group }, + { .cap =3D OCP_CAP_FREQ, .group =3D &fb_timecard_freq0_group }, + { .cap =3D OCP_CAP_FREQ, .group =3D &fb_timecard_freq1_group }, + { .cap =3D OCP_CAP_FREQ, .group =3D &fb_timecard_freq2_group }, + { .cap =3D OCP_CAP_FREQ, .group =3D &fb_timecard_freq3_group }, + { }, +}; + static void gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit, const char *def) --=20 2.47.0