Received: by 2002:a05:7412:b995:b0:f9:9502:5bb8 with SMTP id it21csp279570rdb; Thu, 21 Dec 2023 08:57:24 -0800 (PST) X-Google-Smtp-Source: AGHT+IFsyLINiMuGfPCSe7NfchVgRDSV2uQH2uLsyytdaFPfHjzP6AFZwjd3oF1rkT2vRzJkW9xR X-Received: by 2002:ad4:5961:0:b0:67f:43f8:cc6f with SMTP id eq1-20020ad45961000000b0067f43f8cc6fmr9290261qvb.61.1703177843717; Thu, 21 Dec 2023 08:57:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703177843; cv=none; d=google.com; s=arc-20160816; b=hrY/rtcoHiZKemVcpfTqQ9ahPw1PyeqG5HexvI9FclvNOFn3YZW+x/52gcW9cQiYo3 SJY2hky6EWewm5V+TmkGMKH2wp68AC1hSqamQ38M+DPFC9GOM3iT76xV9SNgaIOz0x+E 6/QsIGsG61YgMOKuP7Zvf6j/0Wv9JWBBG8vFCBI/22ze0v/8nPYdIDDf8vbauqTStpas /8ZBMs+wliJ2wlYQdgQJlVft5jzkeT3Xp/JmDgSoc1KTvO0vsTdA5Ng25pAJ5SjAJHmy LMByqj6nvg6mX4dnDLRkUh7p3IcO1iRchRCyKzo1jKIBfkeHMQnUGOt52WQp72hbTLMC OPDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:date:dkim-signature:message-id; bh=dMCYkMM2NSBZF87b2hNzRnFk+D/F+OEGKsL46dDU7h4=; fh=F9WZcJWPwI6QMEF8R5K0PhQCpUp7LtDzNI5hdXsmGas=; b=1EF3mnrPL+dVXqqd94csjV2V6M8EP6pPzHsoHFmgZmWCJN/V1oTCDhnQJNVgz3Ekj8 UuLwztiGC7qks6xVLpBT0s3mbeSSnDWIa7xcCEJq2KVLFmnex7NM8rUAmOF5O/tO9j1l euAgD6uLaDALDZkBPcFOeRnGTa2jmTNtjBxhuiQZpTD8LMIuNlHlxYvqnVVA0yT3S+ya uwTb54Ekboh71G07Ko1uZgOb4SRz/95AlzCWRERc9ic9Ft2J1YVbyl/LD3RUmPsgcbIU KkRM/k7kOmyDI4jH5Z1f1YLe9Sq7/H5Z4KuDW6QOWRq+rexlss4UG+JhJf2Zl18PpYxx /kpA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=ShvUzgiw; spf=pass (google.com: domain of linux-kernel+bounces-8803-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-8803-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id f8-20020a0cf3c8000000b00679ff81cae5si2489142qvm.379.2023.12.21.08.57.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Dec 2023 08:57:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-8803-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=ShvUzgiw; spf=pass (google.com: domain of linux-kernel+bounces-8803-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-8803-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 6C3401C2488A for ; Thu, 21 Dec 2023 16:57:23 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EB54859917; Thu, 21 Dec 2023 16:56:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ShvUzgiw" X-Original-To: linux-kernel@vger.kernel.org Received: from out-172.mta0.migadu.com (out-172.mta0.migadu.com [91.218.175.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 257AC58224 for ; Thu, 21 Dec 2023 16:56:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Message-ID: <35550a06-c1fe-4e96-9705-ba0474cd94d1@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703177775; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dMCYkMM2NSBZF87b2hNzRnFk+D/F+OEGKsL46dDU7h4=; b=ShvUzgiwN2CpaC4h3xQRpkNdujC5TKt+MX9IBeeqT6MHDREB/iR30ttLGjJpsxVoJBJBZ7 kYKxwhESWKKCW5xkC8i4dd6GwOVNog94jESNef5HbWqvDhGhhIkNgjjtyk5q4wHpX6wfQY gsPjqFtyejxdHV5Rkmfv8s7CiW5cGrM= Date: Thu, 21 Dec 2023 16:56:09 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Subject: Re: [PATCH v1] ptp: ocp: add Adva timecard support Content-Language: en-US To: Sagi Maimon , richardcochran@gmail.com, jonathan.lemon@gmail.com Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org References: <20231221153755.2690-1-maimon.sagi@gmail.com> X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Vadim Fedorenko In-Reply-To: <20231221153755.2690-1-maimon.sagi@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Migadu-Flow: FLOW_OUT On 21/12/2023 15:37, Sagi Maimon wrote: > Adding support for the Adva timecard. > The card uses different drivers to provide access to the > firmware SPI flash (Altera based). > Other parts of the code are the same and could be reused. > > Signed-off-by: Sagi Maimon > --- > drivers/ptp/ptp_ocp.c | 257 ++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 247 insertions(+), 10 deletions(-) > > diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c > index 4021d3d325f9..73e91b8a2887 100644 > --- a/drivers/ptp/ptp_ocp.c > +++ b/drivers/ptp/ptp_ocp.c > @@ -34,6 +34,9 @@ > #define PCI_VENDOR_ID_OROLIA 0x1ad7 > #define PCI_DEVICE_ID_OROLIA_ARTCARD 0xa000 > > +#define PCI_VENDOR_ID_ADVA 0xad5a > +#define PCI_DEVICE_ID_ADVA_TIMECARD 0x0400 > + > static struct class timecard_class = { > .name = "timecard", > }; > @@ -63,6 +66,13 @@ struct ocp_reg { > u32 status_drift; > }; > > +struct servo_val { > + u32 servo_offset_p_val; > + u32 servo_offset_i_val; > + u32 servo_drift_p_val; > + u32 servo_drift_i_val; > +}; > + I don't really like naming here. Let's go with ptp_ocp prefix first. Then it's more like configuration rather than actual values, so I would say ptp_ocp_servo_conf is better here. And let's remove "_val" - no real need for this suffix. > #define OCP_CTRL_ENABLE BIT(0) > #define OCP_CTRL_ADJUST_TIME BIT(1) > #define OCP_CTRL_ADJUST_OFFSET BIT(2) > @@ -401,6 +411,12 @@ static const struct ocp_attr_group fb_timecard_groups[]; > > static const struct ocp_attr_group art_timecard_groups[]; > > +static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r); > + > +static const struct ocp_attr_group adva_timecard_groups[]; > + > +static const struct ocp_sma_op ocp_adva_sma_op; > + > struct ptp_ocp_eeprom_map { > u16 off; > u16 len; > @@ -835,10 +851,122 @@ static struct ocp_resource ocp_art_resource[] = { > { } > }; > > +static struct ocp_resource ocp_adva_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, > + }, > + }, > + /* 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_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(gnss_port), > + .offset = 0x00160000 + 0x1000, .irq_vec = 3, > + .extra = &(struct ptp_ocp_serial_port) { > + .baud = 9600, > + }, > + }, > + { > + OCP_MEM_RESOURCE(freq_in[0]), > + .offset = 0x01200000, .size = 0x10000, > + }, > + { > + OCP_SPI_RESOURCE(spi_flash), > + .offset = 0x00310400, .size = 0x10000, .irq_vec = 9, > + .extra = &(struct ptp_ocp_flash_info) { > + .name = "spi_altera", .pci_offset = 0, > + .data_size = sizeof(struct altera_spi_platform_data), > + .data = &(struct altera_spi_platform_data) { > + .num_chipselect = 1, > + .num_devices = 1, > + .devices = &(struct spi_board_info) { > + .modalias = "spi-nor", > + }, > + }, > + }, > + }, > + { > + .setup = ptp_ocp_adva_board_init, > + }, > + { } > +}; > + > static const struct pci_device_id ptp_ocp_pcidev_id[] = { > { PCI_DEVICE_DATA(FACEBOOK, 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) }, > { } > }; > MODULE_DEVICE_TABLE(pci, ptp_ocp_pcidev_id); > @@ -917,6 +1045,27 @@ static const struct ocp_selector ptp_ocp_art_sma_out[] = { > { } > }; > > +static const struct ocp_selector ptp_ocp_adva_sma_in[] = { > + { .name = "10Mhz", .value = 0x0000, .frequency = 10000000}, > + { .name = "PPS1", .value = 0x0001, .frequency = 1 }, > + { .name = "PPS2", .value = 0x0002, .frequency = 1 }, > + { .name = "TS1", .value = 0x0004, .frequency = 0 }, > + { .name = "TS2", .value = 0x0008, .frequency = 0 }, > + { .name = "FREQ1", .value = 0x0100, .frequency = 0 }, > + { .name = "None", .value = SMA_DISABLE, .frequency = 0 }, > + { } > +}; > + > +static const struct ocp_selector ptp_ocp_adva_sma_out[] = { > + { .name = "10Mhz", .value = 0x0000, .frequency = 10000000}, > + { .name = "PHC", .value = 0x0001, .frequency = 1 }, > + { .name = "GNSS1", .value = 0x0004, .frequency = 1 }, > + { .name = "GEN1", .value = 0x0040 }, > + { .name = "GND", .value = 0x2000 }, > + { .name = "VCC", .value = 0x4000 }, > + { } > +}; > + > struct ocp_sma_op { > const struct ocp_selector *tbl[2]; > void (*init)(struct ptp_ocp *bp); > @@ -1363,20 +1512,20 @@ ptp_ocp_estimate_pci_timing(struct ptp_ocp *bp) > } > > static int > -ptp_ocp_init_clock(struct ptp_ocp *bp) > +ptp_ocp_init_clock(struct ptp_ocp *bp, struct servo_val *servo_vals) > { > struct timespec64 ts; > u32 ctrl; > > + no need for the second empty line > ctrl = OCP_CTRL_ENABLE; > iowrite32(ctrl, &bp->reg->ctrl); > > - /* NO DRIFT Correction */ > - /* offset_p:i 1/8, offset_i: 1/16, drift_p: 0, drift_i: 0 */ > - iowrite32(0x2000, &bp->reg->servo_offset_p); > - iowrite32(0x1000, &bp->reg->servo_offset_i); > - iowrite32(0, &bp->reg->servo_drift_p); > - iowrite32(0, &bp->reg->servo_drift_i); > + /* servo configuration */ > + iowrite32(servo_vals->servo_offset_p_val, &bp->reg->servo_offset_p); > + iowrite32(servo_vals->servo_offset_i_val, &bp->reg->servo_offset_i); > + iowrite32(servo_vals->servo_drift_p_val, &bp->reg->servo_drift_p); > + iowrite32(servo_vals->servo_drift_p_val, &bp->reg->servo_drift_i); > > /* latch servo values */ > ctrl |= OCP_CTRL_ADJUST_SERVO; > @@ -2362,6 +2511,14 @@ static const struct ocp_sma_op ocp_fb_sma_op = { > .set_output = ptp_ocp_sma_fb_set_output, > }; > > +static const struct ocp_sma_op ocp_adva_sma_op = { > + .tbl = { ptp_ocp_adva_sma_in, ptp_ocp_adva_sma_out }, > + .init = ptp_ocp_sma_fb_init, > + .get = ptp_ocp_sma_fb_get, > + .set_inputs = ptp_ocp_sma_fb_set_inputs, > + .set_output = ptp_ocp_sma_fb_set_output, > +}; > + > static int > ptp_ocp_set_pins(struct ptp_ocp *bp) > { > @@ -2420,6 +2577,7 @@ static int > ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r) > { > int err; > + struct servo_val servo_vals; > > bp->flash_start = 1024 * 4096; > bp->eeprom_map = fb_eeprom_map; > @@ -2441,7 +2599,14 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r) > return err; > ptp_ocp_sma_init(bp); > > - return ptp_ocp_init_clock(bp); > + /* NO DRIFT Correction */ > + /* offset_p:i 1/8, offset_i: 1/16, drift_p: 0, drift_i: 0 */ > + servo_vals.servo_offset_p_val = 0x2000; > + servo_vals.servo_offset_i_val = 0x1000; > + servo_vals.servo_drift_p_val = 0; > + servo_vals.servo_drift_p_val = 0; instead of adding this to every particular initialization function, struct ptp_ocp_servo_conf can be put to .extra field of the resource holding init function. This will move all configuration points to the list of card-specific resources, the place to have differences of cards and will make the code cleaner and eliminate all these local structs. We can potentially create another static function to configure servo part, but it's up to you. > + > + return ptp_ocp_init_clock(bp, &servo_vals); > } > > static bool > @@ -2583,6 +2748,7 @@ static int > ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r) > { > int err; > + struct servo_val servo_vals; > > bp->flash_start = 0x1000000; > bp->eeprom_map = art_eeprom_map; > @@ -2603,7 +2769,49 @@ ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r) > if (err) > return err; > > - return ptp_ocp_init_clock(bp); > + /* NO DRIFT Correction */ > + /* offset_p:i 1/8, offset_i: 1/16, drift_p: 0, drift_i: 0 */ > + servo_vals.servo_offset_p_val = 0x2000; > + servo_vals.servo_offset_i_val = 0x1000; > + servo_vals.servo_drift_p_val = 0; > + servo_vals.servo_drift_p_val = 0; > + > + return ptp_ocp_init_clock(bp, &servo_vals); > +} > + > +/* ADVA specific board initializers; last "resource" registered. */ > +static int > +ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r) > +{ > + int err; > + struct servo_val servo_vals; > + > + bp->flash_start = 0xA00000; > + bp->fw_version = ioread32(&bp->image->version); > + bp->sma_op = &ocp_adva_sma_op; > + > + ptp_ocp_fb_set_version(bp); > + > + 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); > + if (err) > + return err; > + > + err = ptp_ocp_set_pins(bp); > + if (err) > + return err; > + ptp_ocp_sma_init(bp); > + > + /* offset_p:i 3/4, offset_i: 1/16, drift_p: 0, drift_i: 0 */ > + servo_vals.servo_offset_p_val = 0xc000; > + servo_vals.servo_offset_i_val = 0x1000; > + servo_vals.servo_drift_p_val = 0; > + servo_vals.servo_drift_p_val = 0; > + > + return ptp_ocp_init_clock(bp, &servo_vals); > } > > static ssize_t > @@ -3578,6 +3786,35 @@ static const struct ocp_attr_group art_timecard_groups[] = { > { }, > }; > > +static struct attribute *adva_timecard_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_tod_correction.attr, > + NULL, > +}; > + > +static const struct attribute_group adva_timecard_group = { > + .attrs = adva_timecard_attrs, > +}; > + > +static const struct ocp_attr_group adva_timecard_groups[] = { > + { .cap = OCP_CAP_BASIC, .group = &adva_timecard_group }, > + { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group }, > + { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group }, > + { }, > +}; > + > static void > gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit, > const char *def) starting from here ... > @@ -4492,7 +4729,7 @@ ptp_ocp_remove(struct pci_dev *pdev) > cancel_delayed_work_sync(&bp->sync_work); > for (i = 0; i < OCP_SMA_NUM; i++) { > if (bp->sma[i].dpll_pin) { > - dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, bp); > + dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]); > dpll_pin_put(bp->sma[i].dpll_pin); > } > } the chuck is already in a different patch and is reviewed actually, no need to post it again.