Skip to content

Commit ef61f55

Browse files
sagimaimonkuba-moo
authored andcommitted
ptp: ocp: add Adva timecard support
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 <[email protected]> Reviewed-by: Vadim Fedorenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4bea747 commit ef61f55

File tree

1 file changed

+293
-9
lines changed

1 file changed

+293
-9
lines changed

drivers/ptp/ptp_ocp.c

Lines changed: 293 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#define PCI_VENDOR_ID_OROLIA 0x1ad7
3535
#define PCI_DEVICE_ID_OROLIA_ARTCARD 0xa000
3636

37+
#define PCI_VENDOR_ID_ADVA 0xad5a
38+
#define PCI_DEVICE_ID_ADVA_TIMECARD 0x0400
39+
3740
static struct class timecard_class = {
3841
.name = "timecard",
3942
};
@@ -63,6 +66,13 @@ struct ocp_reg {
6366
u32 status_drift;
6467
};
6568

69+
struct ptp_ocp_servo_conf {
70+
u32 servo_offset_p;
71+
u32 servo_offset_i;
72+
u32 servo_drift_p;
73+
u32 servo_drift_i;
74+
};
75+
6676
#define OCP_CTRL_ENABLE BIT(0)
6777
#define OCP_CTRL_ADJUST_TIME BIT(1)
6878
#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);
397407

398408
static int ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
399409

410+
static int ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
411+
400412
static const struct ocp_attr_group fb_timecard_groups[];
401413

402414
static const struct ocp_attr_group art_timecard_groups[];
403415

416+
static const struct ocp_attr_group adva_timecard_groups[];
417+
404418
struct ptp_ocp_eeprom_map {
405419
u16 off;
406420
u16 len;
@@ -700,6 +714,12 @@ static struct ocp_resource ocp_fb_resource[] = {
700714
},
701715
{
702716
.setup = ptp_ocp_fb_board_init,
717+
.extra = &(struct ptp_ocp_servo_conf) {
718+
.servo_offset_p = 0x2000,
719+
.servo_offset_i = 0x1000,
720+
.servo_drift_p = 0,
721+
.servo_drift_i = 0,
722+
},
703723
},
704724
{ }
705725
};
@@ -831,6 +851,170 @@ static struct ocp_resource ocp_art_resource[] = {
831851
},
832852
{
833853
.setup = ptp_ocp_art_board_init,
854+
.extra = &(struct ptp_ocp_servo_conf) {
855+
.servo_offset_p = 0x2000,
856+
.servo_offset_i = 0x1000,
857+
.servo_drift_p = 0,
858+
.servo_drift_i = 0,
859+
},
860+
},
861+
{ }
862+
};
863+
864+
static struct ocp_resource ocp_adva_resource[] = {
865+
{
866+
OCP_MEM_RESOURCE(reg),
867+
.offset = 0x01000000, .size = 0x10000,
868+
},
869+
{
870+
OCP_EXT_RESOURCE(ts0),
871+
.offset = 0x01010000, .size = 0x10000, .irq_vec = 1,
872+
.extra = &(struct ptp_ocp_ext_info) {
873+
.index = 0,
874+
.irq_fcn = ptp_ocp_ts_irq,
875+
.enable = ptp_ocp_ts_enable,
876+
},
877+
},
878+
{
879+
OCP_EXT_RESOURCE(ts1),
880+
.offset = 0x01020000, .size = 0x10000, .irq_vec = 2,
881+
.extra = &(struct ptp_ocp_ext_info) {
882+
.index = 1,
883+
.irq_fcn = ptp_ocp_ts_irq,
884+
.enable = ptp_ocp_ts_enable,
885+
},
886+
},
887+
{
888+
OCP_EXT_RESOURCE(ts2),
889+
.offset = 0x01060000, .size = 0x10000, .irq_vec = 6,
890+
.extra = &(struct ptp_ocp_ext_info) {
891+
.index = 2,
892+
.irq_fcn = ptp_ocp_ts_irq,
893+
.enable = ptp_ocp_ts_enable,
894+
},
895+
},
896+
/* Timestamp for PHC and/or PPS generator */
897+
{
898+
OCP_EXT_RESOURCE(pps),
899+
.offset = 0x010C0000, .size = 0x10000, .irq_vec = 0,
900+
.extra = &(struct ptp_ocp_ext_info) {
901+
.index = 5,
902+
.irq_fcn = ptp_ocp_ts_irq,
903+
.enable = ptp_ocp_ts_enable,
904+
},
905+
},
906+
{
907+
OCP_EXT_RESOURCE(signal_out[0]),
908+
.offset = 0x010D0000, .size = 0x10000, .irq_vec = 11,
909+
.extra = &(struct ptp_ocp_ext_info) {
910+
.index = 1,
911+
.irq_fcn = ptp_ocp_signal_irq,
912+
.enable = ptp_ocp_signal_enable,
913+
},
914+
},
915+
{
916+
OCP_EXT_RESOURCE(signal_out[1]),
917+
.offset = 0x010E0000, .size = 0x10000, .irq_vec = 12,
918+
.extra = &(struct ptp_ocp_ext_info) {
919+
.index = 2,
920+
.irq_fcn = ptp_ocp_signal_irq,
921+
.enable = ptp_ocp_signal_enable,
922+
},
923+
},
924+
{
925+
OCP_MEM_RESOURCE(pps_to_ext),
926+
.offset = 0x01030000, .size = 0x10000,
927+
},
928+
{
929+
OCP_MEM_RESOURCE(pps_to_clk),
930+
.offset = 0x01040000, .size = 0x10000,
931+
},
932+
{
933+
OCP_MEM_RESOURCE(tod),
934+
.offset = 0x01050000, .size = 0x10000,
935+
},
936+
{
937+
OCP_MEM_RESOURCE(image),
938+
.offset = 0x00020000, .size = 0x1000,
939+
},
940+
{
941+
OCP_MEM_RESOURCE(pps_select),
942+
.offset = 0x00130000, .size = 0x1000,
943+
},
944+
{
945+
OCP_MEM_RESOURCE(sma_map1),
946+
.offset = 0x00140000, .size = 0x1000,
947+
},
948+
{
949+
OCP_MEM_RESOURCE(sma_map2),
950+
.offset = 0x00220000, .size = 0x1000,
951+
},
952+
{
953+
OCP_SERIAL_RESOURCE(gnss_port),
954+
.offset = 0x00160000 + 0x1000, .irq_vec = 3,
955+
.extra = &(struct ptp_ocp_serial_port) {
956+
.baud = 9600,
957+
},
958+
},
959+
{
960+
OCP_SERIAL_RESOURCE(mac_port),
961+
.offset = 0x00180000 + 0x1000, .irq_vec = 5,
962+
.extra = &(struct ptp_ocp_serial_port) {
963+
.baud = 115200,
964+
},
965+
},
966+
{
967+
OCP_MEM_RESOURCE(freq_in[0]),
968+
.offset = 0x01200000, .size = 0x10000,
969+
},
970+
{
971+
OCP_MEM_RESOURCE(freq_in[1]),
972+
.offset = 0x01210000, .size = 0x10000,
973+
},
974+
{
975+
OCP_SPI_RESOURCE(spi_flash),
976+
.offset = 0x00310400, .size = 0x10000, .irq_vec = 9,
977+
.extra = &(struct ptp_ocp_flash_info) {
978+
.name = "spi_altera", .pci_offset = 0,
979+
.data_size = sizeof(struct altera_spi_platform_data),
980+
.data = &(struct altera_spi_platform_data) {
981+
.num_chipselect = 1,
982+
.num_devices = 1,
983+
.devices = &(struct spi_board_info) {
984+
.modalias = "spi-nor",
985+
},
986+
},
987+
},
988+
},
989+
{
990+
OCP_I2C_RESOURCE(i2c_ctrl),
991+
.offset = 0x150000, .size = 0x100, .irq_vec = 7,
992+
.extra = &(struct ptp_ocp_i2c_info) {
993+
.name = "ocores-i2c",
994+
.fixed_rate = 50000000,
995+
.data_size = sizeof(struct ocores_i2c_platform_data),
996+
.data = &(struct ocores_i2c_platform_data) {
997+
.clock_khz = 50000,
998+
.bus_khz = 100,
999+
.reg_io_width = 4, // 32-bit/4-byte
1000+
.reg_shift = 2, // 32-bit addressing
1001+
.num_devices = 2,
1002+
.devices = (struct i2c_board_info[]) {
1003+
{ I2C_BOARD_INFO("24c02", 0x50) },
1004+
{ I2C_BOARD_INFO("24mac402", 0x58),
1005+
.platform_data = "mac" },
1006+
},
1007+
},
1008+
},
1009+
},
1010+
{
1011+
.setup = ptp_ocp_adva_board_init,
1012+
.extra = &(struct ptp_ocp_servo_conf) {
1013+
.servo_offset_p = 0xc000,
1014+
.servo_offset_i = 0x1000,
1015+
.servo_drift_p = 0,
1016+
.servo_drift_i = 0,
1017+
},
8341018
},
8351019
{ }
8361020
};
@@ -839,6 +1023,7 @@ static const struct pci_device_id ptp_ocp_pcidev_id[] = {
8391023
{ PCI_DEVICE_DATA(FACEBOOK, TIMECARD, &ocp_fb_resource) },
8401024
{ PCI_DEVICE_DATA(CELESTICA, TIMECARD, &ocp_fb_resource) },
8411025
{ PCI_DEVICE_DATA(OROLIA, ARTCARD, &ocp_art_resource) },
1026+
{ PCI_DEVICE_DATA(ADVA, TIMECARD, &ocp_adva_resource) },
8421027
{ }
8431028
};
8441029
MODULE_DEVICE_TABLE(pci, ptp_ocp_pcidev_id);
@@ -917,6 +1102,30 @@ static const struct ocp_selector ptp_ocp_art_sma_out[] = {
9171102
{ }
9181103
};
9191104

1105+
static const struct ocp_selector ptp_ocp_adva_sma_in[] = {
1106+
{ .name = "10Mhz", .value = 0x0000, .frequency = 10000000},
1107+
{ .name = "PPS1", .value = 0x0001, .frequency = 1 },
1108+
{ .name = "PPS2", .value = 0x0002, .frequency = 1 },
1109+
{ .name = "TS1", .value = 0x0004, .frequency = 0 },
1110+
{ .name = "TS2", .value = 0x0008, .frequency = 0 },
1111+
{ .name = "FREQ1", .value = 0x0100, .frequency = 0 },
1112+
{ .name = "FREQ2", .value = 0x0200, .frequency = 0 },
1113+
{ .name = "None", .value = SMA_DISABLE, .frequency = 0 },
1114+
{ }
1115+
};
1116+
1117+
static const struct ocp_selector ptp_ocp_adva_sma_out[] = {
1118+
{ .name = "10Mhz", .value = 0x0000, .frequency = 10000000},
1119+
{ .name = "PHC", .value = 0x0001, .frequency = 1 },
1120+
{ .name = "MAC", .value = 0x0002, .frequency = 1 },
1121+
{ .name = "GNSS1", .value = 0x0004, .frequency = 1 },
1122+
{ .name = "GEN1", .value = 0x0040 },
1123+
{ .name = "GEN2", .value = 0x0080 },
1124+
{ .name = "GND", .value = 0x2000 },
1125+
{ .name = "VCC", .value = 0x4000 },
1126+
{ }
1127+
};
1128+
9201129
struct ocp_sma_op {
9211130
const struct ocp_selector *tbl[2];
9221131
void (*init)(struct ptp_ocp *bp);
@@ -1363,20 +1572,19 @@ ptp_ocp_estimate_pci_timing(struct ptp_ocp *bp)
13631572
}
13641573

13651574
static int
1366-
ptp_ocp_init_clock(struct ptp_ocp *bp)
1575+
ptp_ocp_init_clock(struct ptp_ocp *bp, struct ptp_ocp_servo_conf *servo_conf)
13671576
{
13681577
struct timespec64 ts;
13691578
u32 ctrl;
13701579

13711580
ctrl = OCP_CTRL_ENABLE;
13721581
iowrite32(ctrl, &bp->reg->ctrl);
13731582

1374-
/* NO DRIFT Correction */
1375-
/* offset_p:i 1/8, offset_i: 1/16, drift_p: 0, drift_i: 0 */
1376-
iowrite32(0x2000, &bp->reg->servo_offset_p);
1377-
iowrite32(0x1000, &bp->reg->servo_offset_i);
1378-
iowrite32(0, &bp->reg->servo_drift_p);
1379-
iowrite32(0, &bp->reg->servo_drift_i);
1583+
/* servo configuration */
1584+
iowrite32(servo_conf->servo_offset_p, &bp->reg->servo_offset_p);
1585+
iowrite32(servo_conf->servo_offset_i, &bp->reg->servo_offset_i);
1586+
iowrite32(servo_conf->servo_drift_p, &bp->reg->servo_drift_p);
1587+
iowrite32(servo_conf->servo_drift_p, &bp->reg->servo_drift_i);
13801588

13811589
/* latch servo values */
13821590
ctrl |= OCP_CTRL_ADJUST_SERVO;
@@ -2348,6 +2556,14 @@ static const struct ocp_sma_op ocp_fb_sma_op = {
23482556
.set_output = ptp_ocp_sma_fb_set_output,
23492557
};
23502558

2559+
static const struct ocp_sma_op ocp_adva_sma_op = {
2560+
.tbl = { ptp_ocp_adva_sma_in, ptp_ocp_adva_sma_out },
2561+
.init = ptp_ocp_sma_fb_init,
2562+
.get = ptp_ocp_sma_fb_get,
2563+
.set_inputs = ptp_ocp_sma_fb_set_inputs,
2564+
.set_output = ptp_ocp_sma_fb_set_output,
2565+
};
2566+
23512567
static int
23522568
ptp_ocp_set_pins(struct ptp_ocp *bp)
23532569
{
@@ -2427,7 +2643,7 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
24272643
return err;
24282644
ptp_ocp_sma_init(bp);
24292645

2430-
return ptp_ocp_init_clock(bp);
2646+
return ptp_ocp_init_clock(bp, r->extra);
24312647
}
24322648

24332649
static bool
@@ -2589,7 +2805,44 @@ ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
25892805
if (err)
25902806
return err;
25912807

2592-
return ptp_ocp_init_clock(bp);
2808+
return ptp_ocp_init_clock(bp, r->extra);
2809+
}
2810+
2811+
/* ADVA specific board initializers; last "resource" registered. */
2812+
static int
2813+
ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
2814+
{
2815+
int err;
2816+
u32 version;
2817+
2818+
bp->flash_start = 0xA00000;
2819+
bp->eeprom_map = fb_eeprom_map;
2820+
bp->sma_op = &ocp_adva_sma_op;
2821+
2822+
version = ioread32(&bp->image->version);
2823+
/* if lower 16 bits are empty, this is the fw loader. */
2824+
if ((version & 0xffff) == 0) {
2825+
version = version >> 16;
2826+
bp->fw_loader = true;
2827+
}
2828+
bp->fw_tag = 3;
2829+
bp->fw_version = version & 0xffff;
2830+
bp->fw_cap = OCP_CAP_BASIC | OCP_CAP_SIGNAL | OCP_CAP_FREQ;
2831+
2832+
ptp_ocp_tod_init(bp);
2833+
ptp_ocp_nmea_out_init(bp);
2834+
ptp_ocp_signal_init(bp);
2835+
2836+
err = ptp_ocp_attr_group_add(bp, adva_timecard_groups);
2837+
if (err)
2838+
return err;
2839+
2840+
err = ptp_ocp_set_pins(bp);
2841+
if (err)
2842+
return err;
2843+
ptp_ocp_sma_init(bp);
2844+
2845+
return ptp_ocp_init_clock(bp, r->extra);
25932846
}
25942847

25952848
static ssize_t
@@ -3564,6 +3817,37 @@ static const struct ocp_attr_group art_timecard_groups[] = {
35643817
{ },
35653818
};
35663819

3820+
static struct attribute *adva_timecard_attrs[] = {
3821+
&dev_attr_serialnum.attr,
3822+
&dev_attr_gnss_sync.attr,
3823+
&dev_attr_clock_source.attr,
3824+
&dev_attr_available_clock_sources.attr,
3825+
&dev_attr_sma1.attr,
3826+
&dev_attr_sma2.attr,
3827+
&dev_attr_sma3.attr,
3828+
&dev_attr_sma4.attr,
3829+
&dev_attr_available_sma_inputs.attr,
3830+
&dev_attr_available_sma_outputs.attr,
3831+
&dev_attr_clock_status_drift.attr,
3832+
&dev_attr_clock_status_offset.attr,
3833+
&dev_attr_ts_window_adjust.attr,
3834+
&dev_attr_tod_correction.attr,
3835+
NULL,
3836+
};
3837+
3838+
static const struct attribute_group adva_timecard_group = {
3839+
.attrs = adva_timecard_attrs,
3840+
};
3841+
3842+
static const struct ocp_attr_group adva_timecard_groups[] = {
3843+
{ .cap = OCP_CAP_BASIC, .group = &adva_timecard_group },
3844+
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group },
3845+
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group },
3846+
{ .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group },
3847+
{ .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq1_group },
3848+
{ },
3849+
};
3850+
35673851
static void
35683852
gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit,
35693853
const char *def)

0 commit comments

Comments
 (0)