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+
3740static 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
398408static 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+
400412static const struct ocp_attr_group fb_timecard_groups [];
401413
402414static const struct ocp_attr_group art_timecard_groups [];
403415
416+ static const struct ocp_attr_group adva_timecard_groups [];
417+
404418struct 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};
8441029MODULE_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+
9201129struct 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
13651574static 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+
23512567static int
23522568ptp_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
24332649static 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
25952848static 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+
35673851static void
35683852gpio_input_map (char * buf , struct ptp_ocp * bp , u16 map [][2 ], u16 bit ,
35693853 const char * def )
0 commit comments