diff options
Diffstat (limited to 'drivers/ptp/ptp_ocp.c')
-rw-r--r-- | drivers/ptp/ptp_ocp.c | 519 |
1 files changed, 420 insertions, 99 deletions
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index 5f858e426bbd..b651087f426f 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) @@ -306,6 +316,15 @@ struct ptp_ocp_serial_port { #define OCP_SERIAL_LEN 6 #define OCP_SMA_NUM 4 +enum { + PORT_GNSS, + PORT_GNSS2, + PORT_MAC, /* miniature atomic clock */ + PORT_NMEA, + + __PORT_COUNT, +}; + struct ptp_ocp { struct pci_dev *pdev; struct device dev; @@ -347,10 +366,7 @@ struct ptp_ocp { struct delayed_work sync_work; int id; int n_irqs; - struct ptp_ocp_serial_port gnss_port; - struct ptp_ocp_serial_port gnss2_port; - struct ptp_ocp_serial_port mac_port; /* miniature atomic clock */ - struct ptp_ocp_serial_port nmea_port; + struct ptp_ocp_serial_port port[__PORT_COUNT]; bool fw_loader; u8 fw_tag; u16 fw_version; @@ -397,10 +413,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; @@ -641,28 +661,28 @@ static struct ocp_resource ocp_fb_resource[] = { }, }, { - OCP_SERIAL_RESOURCE(gnss_port), + OCP_SERIAL_RESOURCE(port[PORT_GNSS]), .offset = 0x00160000 + 0x1000, .irq_vec = 3, .extra = &(struct ptp_ocp_serial_port) { .baud = 115200, }, }, { - OCP_SERIAL_RESOURCE(gnss2_port), + OCP_SERIAL_RESOURCE(port[PORT_GNSS2]), .offset = 0x00170000 + 0x1000, .irq_vec = 4, .extra = &(struct ptp_ocp_serial_port) { .baud = 115200, }, }, { - OCP_SERIAL_RESOURCE(mac_port), + OCP_SERIAL_RESOURCE(port[PORT_MAC]), .offset = 0x00180000 + 0x1000, .irq_vec = 5, .extra = &(struct ptp_ocp_serial_port) { .baud = 57600, }, }, { - OCP_SERIAL_RESOURCE(nmea_port), + OCP_SERIAL_RESOURCE(port[PORT_NMEA]), .offset = 0x00190000 + 0x1000, .irq_vec = 10, }, { @@ -700,6 +720,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, + }, }, { } }; @@ -720,7 +746,7 @@ static struct ocp_resource ocp_art_resource[] = { .offset = 0x01000000, .size = 0x10000, }, { - OCP_SERIAL_RESOURCE(gnss_port), + OCP_SERIAL_RESOURCE(port[PORT_GNSS]), .offset = 0x00160000 + 0x1000, .irq_vec = 3, .extra = &(struct ptp_ocp_serial_port) { .baud = 115200, @@ -819,7 +845,7 @@ static struct ocp_resource ocp_art_resource[] = { }, }, { - OCP_SERIAL_RESOURCE(mac_port), + OCP_SERIAL_RESOURCE(port[PORT_MAC]), .offset = 0x00190000, .irq_vec = 7, .extra = &(struct ptp_ocp_serial_port) { .baud = 9600, @@ -831,6 +857,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(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_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 +1029,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 +1108,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); @@ -1343,27 +1558,29 @@ ptp_ocp_watchdog(struct timer_list *t) static void ptp_ocp_estimate_pci_timing(struct ptp_ocp *bp) { - ktime_t start, end; - ktime_t delay; + ktime_t start, end, delay = U64_MAX; u32 ctrl; + int i; - ctrl = ioread32(&bp->reg->ctrl); - ctrl = OCP_CTRL_READ_TIME_REQ | OCP_CTRL_ENABLE; + for (i = 0; i < 3; i++) { + ctrl = ioread32(&bp->reg->ctrl); + ctrl = OCP_CTRL_READ_TIME_REQ | OCP_CTRL_ENABLE; - iowrite32(ctrl, &bp->reg->ctrl); + iowrite32(ctrl, &bp->reg->ctrl); - start = ktime_get_ns(); + start = ktime_get_raw_ns(); - ctrl = ioread32(&bp->reg->ctrl); + ctrl = ioread32(&bp->reg->ctrl); - end = ktime_get_ns(); + end = ktime_get_raw_ns(); - delay = end - start; + delay = min(delay, end - start); + } bp->ts_window_adjust = (delay >> 5) * 3; } 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 +1588,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; @@ -1441,6 +1657,15 @@ ptp_ocp_tod_gnss_name(int idx) return gnss_name[idx]; } +static const char * +ptp_ocp_tty_port_name(int idx) +{ + static const char * const tty_name[] = { + "GNSS", "GNSS2", "MAC", "NMEA" + }; + return tty_name[idx]; +} + struct ptp_ocp_nvmem_match_info { struct ptp_ocp *bp; const void * const tag; @@ -2348,6 +2573,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 +2660,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 +2822,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 @@ -3094,6 +3364,54 @@ static EXT_ATTR_RO(freq, frequency, 2); static EXT_ATTR_RO(freq, frequency, 3); static ssize_t +ptp_ocp_tty_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + struct ptp_ocp *bp = dev_get_drvdata(dev); + + return sysfs_emit(buf, "ttyS%d", bp->port[(uintptr_t)ea->var].line); +} + +static umode_t +ptp_ocp_timecard_tty_is_visible(struct kobject *kobj, struct attribute *attr, int n) +{ + struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj)); + struct ptp_ocp_serial_port *port; + struct device_attribute *dattr; + struct dev_ext_attribute *ea; + + if (strncmp(attr->name, "tty", 3)) + return attr->mode; + + dattr = container_of(attr, struct device_attribute, attr); + ea = container_of(dattr, struct dev_ext_attribute, attr); + port = &bp->port[(uintptr_t)ea->var]; + return port->line == -1 ? 0 : 0444; +} + +#define EXT_TTY_ATTR_RO(_name, _val) \ + struct dev_ext_attribute dev_attr_tty##_name = \ + { __ATTR(tty##_name, 0444, ptp_ocp_tty_show, NULL), (void *)_val } + +static EXT_TTY_ATTR_RO(GNSS, PORT_GNSS); +static EXT_TTY_ATTR_RO(GNSS2, PORT_GNSS2); +static EXT_TTY_ATTR_RO(MAC, PORT_MAC); +static EXT_TTY_ATTR_RO(NMEA, PORT_NMEA); +static struct attribute *ptp_ocp_timecard_tty_attrs[] = { + &dev_attr_ttyGNSS.attr.attr, + &dev_attr_ttyGNSS2.attr.attr, + &dev_attr_ttyMAC.attr.attr, + &dev_attr_ttyNMEA.attr.attr, + NULL, +}; + +static const struct attribute_group ptp_ocp_timecard_tty_group = { + .name = "tty", + .attrs = ptp_ocp_timecard_tty_attrs, + .is_visible = ptp_ocp_timecard_tty_is_visible, +}; + +static ssize_t serialnum_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ptp_ocp *bp = dev_get_drvdata(dev); @@ -3374,7 +3692,7 @@ DEVICE_FREQ_GROUP(freq4, 3); static ssize_t disciplining_config_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj)); @@ -3409,7 +3727,7 @@ out: static ssize_t disciplining_config_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj)); @@ -3432,11 +3750,11 @@ disciplining_config_write(struct file *filp, struct kobject *kobj, return err; } -static BIN_ATTR_RW(disciplining_config, OCP_ART_CONFIG_SIZE); +static const BIN_ATTR_RW(disciplining_config, OCP_ART_CONFIG_SIZE); static ssize_t temperature_table_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj)); @@ -3471,7 +3789,7 @@ out: static ssize_t temperature_table_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj)); @@ -3494,7 +3812,7 @@ temperature_table_write(struct file *filp, struct kobject *kobj, return err; } -static BIN_ATTR_RW(temperature_table, OCP_ART_TEMP_TABLE_SIZE); +static const BIN_ATTR_RW(temperature_table, OCP_ART_TEMP_TABLE_SIZE); static struct attribute *fb_timecard_attrs[] = { &dev_attr_serialnum.attr, @@ -3522,6 +3840,7 @@ static const struct attribute_group fb_timecard_group = { static const struct ocp_attr_group fb_timecard_groups[] = { { .cap = OCP_CAP_BASIC, .group = &fb_timecard_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 }, @@ -3548,7 +3867,7 @@ static struct attribute *art_timecard_attrs[] = { NULL, }; -static struct bin_attribute *bin_art_timecard_attrs[] = { +static const struct bin_attribute *const bin_art_timecard_attrs[] = { &bin_attr_disciplining_config, &bin_attr_temperature_table, NULL, @@ -3556,11 +3875,44 @@ static struct bin_attribute *bin_art_timecard_attrs[] = { static const struct attribute_group art_timecard_group = { .attrs = art_timecard_attrs, - .bin_attrs = bin_art_timecard_attrs, + .bin_attrs_new = bin_art_timecard_attrs, }; static const struct ocp_attr_group art_timecard_groups[] = { { .cap = OCP_CAP_BASIC, .group = &art_timecard_group }, + { .cap = OCP_CAP_BASIC, .group = &ptp_ocp_timecard_tty_group }, + { }, +}; + +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_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_FREQ, .group = &fb_timecard_freq0_group }, + { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq1_group }, { }, }; @@ -3676,16 +4028,11 @@ ptp_ocp_summary_show(struct seq_file *s, void *data) bp = dev_get_drvdata(dev); seq_printf(s, "%7s: /dev/ptp%d\n", "PTP", ptp_clock_index(bp->ptp)); - if (bp->gnss_port.line != -1) - seq_printf(s, "%7s: /dev/ttyS%d\n", "GNSS1", - bp->gnss_port.line); - if (bp->gnss2_port.line != -1) - seq_printf(s, "%7s: /dev/ttyS%d\n", "GNSS2", - bp->gnss2_port.line); - if (bp->mac_port.line != -1) - seq_printf(s, "%7s: /dev/ttyS%d\n", "MAC", bp->mac_port.line); - if (bp->nmea_port.line != -1) - seq_printf(s, "%7s: /dev/ttyS%d\n", "NMEA", bp->nmea_port.line); + for (i = 0; i < __PORT_COUNT; i++) { + if (bp->port[i].line != -1) + seq_printf(s, "%7s: /dev/ttyS%d\n", ptp_ocp_tty_port_name(i), + bp->port[i].line); + } memset(sma_val, 0xff, sizeof(sma_val)); if (bp->sma_map1) { @@ -3995,7 +4342,7 @@ ptp_ocp_dev_release(struct device *dev) static int ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) { - int err; + int i, err; mutex_lock(&ptp_ocp_lock); err = idr_alloc(&ptp_ocp_idr, bp, 0, 0, GFP_KERNEL); @@ -4008,10 +4355,10 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) bp->ptp_info = ptp_ocp_clock_info; spin_lock_init(&bp->lock); - bp->gnss_port.line = -1; - bp->gnss2_port.line = -1; - bp->mac_port.line = -1; - bp->nmea_port.line = -1; + + for (i = 0; i < __PORT_COUNT; i++) + bp->port[i].line = -1; + bp->pdev = pdev; device_initialize(&bp->dev); @@ -4068,28 +4415,12 @@ ptp_ocp_complete(struct ptp_ocp *bp) struct pps_device *pps; char buf[32]; - if (bp->gnss_port.line != -1) { - sprintf(buf, "ttyS%d", bp->gnss_port.line); - ptp_ocp_link_child(bp, buf, "ttyGNSS"); - } - if (bp->gnss2_port.line != -1) { - sprintf(buf, "ttyS%d", bp->gnss2_port.line); - ptp_ocp_link_child(bp, buf, "ttyGNSS2"); - } - if (bp->mac_port.line != -1) { - sprintf(buf, "ttyS%d", bp->mac_port.line); - ptp_ocp_link_child(bp, buf, "ttyMAC"); - } - if (bp->nmea_port.line != -1) { - sprintf(buf, "ttyS%d", bp->nmea_port.line); - ptp_ocp_link_child(bp, buf, "ttyNMEA"); - } sprintf(buf, "ptp%d", ptp_clock_index(bp->ptp)); ptp_ocp_link_child(bp, buf, "ptp"); pps = pps_lookup_dev(bp->ptp); if (pps) - ptp_ocp_symlink(bp, pps->dev, "pps"); + ptp_ocp_symlink(bp, &pps->dev, "pps"); ptp_ocp_debugfs_add_device(bp); @@ -4132,23 +4463,20 @@ ptp_ocp_info(struct ptp_ocp *bp) }; struct device *dev = &bp->pdev->dev; u32 reg; + int i; ptp_ocp_phc_info(bp); - ptp_ocp_serial_info(dev, "GNSS", bp->gnss_port.line, - bp->gnss_port.baud); - ptp_ocp_serial_info(dev, "GNSS2", bp->gnss2_port.line, - bp->gnss2_port.baud); - ptp_ocp_serial_info(dev, "MAC", bp->mac_port.line, bp->mac_port.baud); - if (bp->nmea_out && bp->nmea_port.line != -1) { - bp->nmea_port.baud = -1; + for (i = 0; i < __PORT_COUNT; i++) { + if (i == PORT_NMEA && bp->nmea_out && bp->port[PORT_NMEA].line != -1) { + bp->port[PORT_NMEA].baud = -1; - reg = ioread32(&bp->nmea_out->uart_baud); - if (reg < ARRAY_SIZE(nmea_baud)) - bp->nmea_port.baud = nmea_baud[reg]; - - ptp_ocp_serial_info(dev, "NMEA", bp->nmea_port.line, - bp->nmea_port.baud); + reg = ioread32(&bp->nmea_out->uart_baud); + if (reg < ARRAY_SIZE(nmea_baud)) + bp->port[PORT_NMEA].baud = nmea_baud[reg]; + } + ptp_ocp_serial_info(dev, ptp_ocp_tty_port_name(i), bp->port[i].line, + bp->port[i].baud); } } @@ -4157,9 +4485,6 @@ ptp_ocp_detach_sysfs(struct ptp_ocp *bp) { struct device *dev = &bp->dev; - sysfs_remove_link(&dev->kobj, "ttyGNSS"); - sysfs_remove_link(&dev->kobj, "ttyGNSS2"); - sysfs_remove_link(&dev->kobj, "ttyMAC"); sysfs_remove_link(&dev->kobj, "ptp"); sysfs_remove_link(&dev->kobj, "pps"); } @@ -4189,14 +4514,9 @@ ptp_ocp_detach(struct ptp_ocp *bp) for (i = 0; i < 4; i++) if (bp->signal_out[i]) ptp_ocp_unregister_ext(bp->signal_out[i]); - if (bp->gnss_port.line != -1) - serial8250_unregister_port(bp->gnss_port.line); - if (bp->gnss2_port.line != -1) - serial8250_unregister_port(bp->gnss2_port.line); - if (bp->mac_port.line != -1) - serial8250_unregister_port(bp->mac_port.line); - if (bp->nmea_port.line != -1) - serial8250_unregister_port(bp->nmea_port.line); + for (i = 0; i < __PORT_COUNT; i++) + if (bp->port[i].line != -1) + serial8250_unregister_port(bp->port[i].line); platform_device_unregister(bp->spi_flash); platform_device_unregister(bp->i2c_ctrl); if (bp->i2c_clk) @@ -4209,10 +4529,11 @@ ptp_ocp_detach(struct ptp_ocp *bp) device_unregister(&bp->dev); } -static int ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll, - void *priv, - enum dpll_lock_status *status, - struct netlink_ext_ack *extack) +static int +ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll, void *priv, + enum dpll_lock_status *status, + enum dpll_lock_status_error *status_error, + struct netlink_ext_ack *extack) { struct ptp_ocp *bp = priv; @@ -4277,7 +4598,7 @@ static int ptp_ocp_dpll_direction_set(const struct dpll_pin *pin, return -EOPNOTSUPP; mode = direction == DPLL_PIN_DIRECTION_INPUT ? SMA_MODE_IN : SMA_MODE_OUT; - return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr); + return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr + 1); } static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin, @@ -4298,7 +4619,7 @@ static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin, tbl = bp->sma_op->tbl[sma->mode]; for (i = 0; tbl[i].name; i++) if (tbl[i].frequency == frequency) - return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr); + return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr + 1); return -EINVAL; } @@ -4315,7 +4636,7 @@ static int ptp_ocp_dpll_frequency_get(const struct dpll_pin *pin, u32 val; int i; - val = bp->sma_op->get(bp, sma_nr); + val = bp->sma_op->get(bp, sma_nr + 1); tbl = bp->sma_op->tbl[sma->mode]; for (i = 0; tbl[i].name; i++) if (val == tbl[i].value) { |