All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
To: Sagi Maimon <maimon.sagi@gmail.com>,
	richardcochran@gmail.com, jonathan.lemon@gmail.com,
	vadfed@fb.com
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, kuba@kernel.org
Subject: Re: [PATCH v3] ptp: ocp: add Adva timecard support
Date: Thu, 4 Jan 2024 11:53:25 +0000	[thread overview]
Message-ID: <dd04a64c-9593-47cd-a3e2-b113b5ac2d86@linux.dev> (raw)
In-Reply-To: <20240103071039.94132-1-maimon.sagi@gmail.com>

On 03/01/2024 07:10, 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 <maimon.sagi@gmail.com>
> ---
> 
>   Addressed comments from:
>   - Jakub Kicinski : https://www.spinics.net/lists/netdev/msg962419.html
>            
>   Changes since version 2:
>   - reformat the commit message to separate the subject from the body of the message.
>   
>   
>   drivers/ptp/ptp_ocp.c | 247 ++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 238 insertions(+), 9 deletions(-)
> 

Hi Sagi!

Thanks for adjusting the code. It looks much better now.
But I still have some questions futher in the mail.

> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
> index 4021d3d325f9..96f2ab8a9d61 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 ptp_ocp_servo_conf {
> +	u32	servo_offset_p;
> +	u32	servo_offset_i;
> +	u32	servo_drift_p;
> +	u32	servo_drift_i;
> +};
> +
>   #define OCP_CTRL_ENABLE		BIT(0)
>   #define OCP_CTRL_ADJUST_TIME	BIT(1)
>   #define OCP_CTRL_ADJUST_OFFSET	BIT(2)
> @@ -397,10 +407,14 @@ static int ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr);
>   
>   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_attr_group fb_timecard_groups[];
>   
>   static const struct ocp_attr_group art_timecard_groups[];
>   
> +static const struct ocp_attr_group adva_timecard_groups[];
> +
>   struct ptp_ocp_eeprom_map {
>   	u16	off;
>   	u16	len;
> @@ -700,6 +714,12 @@ static struct ocp_resource ocp_fb_resource[] = {
>   	},
>   	{
>   		.setup = ptp_ocp_fb_board_init,
> +		.extra = &(struct ptp_ocp_servo_conf) {
> +			.servo_offset_p = 0x2000,
> +			.servo_offset_i = 0x1000,
> +			.servo_drift_p = 0,
> +			.servo_drift_i = 0,
> +		},
>   	},
>   	{ }
>   };
> @@ -831,6 +851,129 @@ static struct ocp_resource ocp_art_resource[] = {
>   	},
>   	{
>   		.setup = ptp_ocp_art_board_init,
> +		.extra = &(struct ptp_ocp_servo_conf) {
> +			.servo_offset_p = 0x2000,
> +			.servo_offset_i = 0x1000,
> +			.servo_drift_p = 0,
> +			.servo_drift_i = 0,
> +		},
> +	},
> +	{ }
> +};
> +
> +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,
			^^^
			wrong indentation
> +	},
> +	{
> +			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",
> +					},
> +				},
> +			},

			and this block too, wrong indentation

> +	},
> +	{
> +		.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,
> +		},
>   	},
>   	{ }
>   };
> @@ -839,6 +982,7 @@ 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 +1061,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,7 +1528,7 @@ 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 ptp_ocp_servo_conf *servo_conf)
>   {
>   	struct timespec64 ts;
>   	u32 ctrl;
> @@ -1371,12 +1536,11 @@ ptp_ocp_init_clock(struct ptp_ocp *bp)
>   	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_conf->servo_offset_p, &bp->reg->servo_offset_p);
> +	iowrite32(servo_conf->servo_offset_i, &bp->reg->servo_offset_i);
> +	iowrite32(servo_conf->servo_drift_p, &bp->reg->servo_drift_p);
> +	iowrite32(servo_conf->servo_drift_p, &bp->reg->servo_drift_i);
>   
>   	/* latch servo values */
>   	ctrl |= OCP_CTRL_ADJUST_SERVO;
> @@ -2362,6 +2526,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)
>   {
> @@ -2441,7 +2613,7 @@ 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);
> +	return ptp_ocp_init_clock(bp, r->extra);
>   }
>   
>   static bool
> @@ -2603,7 +2775,35 @@ ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
>   	if (err)
>   		return err;
>   
> -	return ptp_ocp_init_clock(bp);
> +	return ptp_ocp_init_clock(bp, r->extra);
> +}
> +
> +/* ADVA specific board initializers; last "resource" registered. */
> +static int
> +ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
> +{
> +	int err;
> +
> +	bp->flash_start = 0xA00000;
> +	bp->fw_version = ioread32(&bp->image->version);
> +	bp->sma_op = &ocp_adva_sma_op;
> +
> +	ptp_ocp_fb_set_version(bp);

I believe there is no need to call ptp_ocp_fb_set_version() because it
has very HW specific code which is probably applicable to your HW.
The only thing to add here is to initialize fw information better.
Take a look at ptp_ocp_art_board_init() function which does all the
fw configuration without calling any other function. Just be sure to
setup fw_tag to something unused.
	
> +
> +	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);
> +
> +	return ptp_ocp_init_clock(bp, r->extra);
>   }
>   
>   static ssize_t
> @@ -3578,6 +3778,35 @@ static const struct ocp_attr_group art_timecard_groups[] = {
>   	{ },
>   };
>   
> +static struct attribute *adva_timecard_attrs[] = {
> +	&dev_attr_serialnum.attr,

You export serialnum attribute here, but you niether configure any
eeprom HW nor filling "serial" for the board object. That is not good.
Do you have any board-specific information in the firmware or how do you
store board specific values?

I would like to have boards report board identifier and it's serial
number via devlink and sysfs to be sure that user-space software can
understand which firmware to use in case of FW upgrades.

> +	&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 },
> +	{ },
> +};
> +

Don't forget to configure fw_cap field correctly when you change init
function.

>   static void
>   gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit,
>   	       const char *def)

---
pw-bot: cr

      reply	other threads:[~2024-01-04 11:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-03  7:10 [PATCH v3] ptp: ocp: add Adva timecard support Sagi Maimon
2024-01-04 11:53 ` Vadim Fedorenko [this message]

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=dd04a64c-9593-47cd-a3e2-b113b5ac2d86@linux.dev \
    --to=vadim.fedorenko@linux.dev \
    --cc=jonathan.lemon@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maimon.sagi@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=richardcochran@gmail.com \
    --cc=vadfed@fb.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.