Messages in this thread | | | Date | Thu, 8 Feb 2024 11:07:07 +0000 | Subject | Re: [PATCH net-next v6] ptp: ocp: add Adva timecard support | From | Vadim Fedorenko <> |
| |
On 05.02.2024 15:30, 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> > --- > Changes since version 5: > - set Adva fw_tag = 3, since other tags are for other vendors. > > drivers/ptp/ptp_ocp.c | 302 ++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 293 insertions(+), 9 deletions(-) >
Looks good, thanks!
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c > index 9507681e0d12..6506cfb89aa9 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,170 @@ 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_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_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_SERIAL_RESOURCE(mac_port), > + .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_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", > + }, > + }, > + }, > + }, > + { > + OCP_I2C_RESOURCE(i2c_ctrl), > + .offset = 0x150000, .size = 0x100, .irq_vec = 7, > + .extra = &(struct ptp_ocp_i2c_info) { > + .name = "ocores-i2c", > + .fixed_rate = 50000000, > + .data_size = sizeof(struct ocores_i2c_platform_data), > + .data = &(struct ocores_i2c_platform_data) { > + .clock_khz = 50000, > + .bus_khz = 100, > + .reg_io_width = 4, // 32-bit/4-byte > + .reg_shift = 2, // 32-bit addressing > + .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_servo_conf) { > + .servo_offset_p = 0xc000, > + .servo_offset_i = 0x1000, > + .servo_drift_p = 0, > + .servo_drift_i = 0, > + }, > }, > { } > }; > @@ -839,6 +1023,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 +1102,30 @@ 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 = "FREQ2", .value = 0x0200, .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 = "MAC", .value = 0x0002, .frequency = 1 }, > + { .name = "GNSS1", .value = 0x0004, .frequency = 1 }, > + { .name = "GEN1", .value = 0x0040 }, > + { .name = "GEN2", .value = 0x0080 }, > + { .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 +1572,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 +1580,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; > @@ -2348,6 +2556,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) > { > @@ -2427,7 +2643,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 > @@ -2589,7 +2805,44 @@ 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; > + u32 version; > + > + bp->flash_start = 0xA00000; > + bp->eeprom_map = fb_eeprom_map; > + bp->sma_op = &ocp_adva_sma_op; > + > + version = ioread32(&bp->image->version); > + /* if lower 16 bits are empty, this is the fw loader. */ > + if ((version & 0xffff) == 0) { > + version = version >> 16; > + bp->fw_loader = true; > + } > + bp->fw_tag = 3; > + bp->fw_version = version & 0xffff; > + 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); > + 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 > @@ -3564,6 +3817,37 @@ 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_SIGNAL, .group = &fb_timecard_signal1_group }, > + { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group }, > + { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq1_group }, > + { }, > +}; > + > static void > gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit, > const char *def)
| |