@@ -574,6 +574,85 @@ zl3073x_dpll_input_pin_phase_offset_get(const struct dpll_pin *dpll_pin,
574574 return rc ;
575575}
576576
577+ static int
578+ zl3073x_dpll_input_pin_phase_adjust_get (const struct dpll_pin * dpll_pin ,
579+ void * pin_priv ,
580+ const struct dpll_device * dpll ,
581+ void * dpll_priv ,
582+ s32 * phase_adjust ,
583+ struct netlink_ext_ack * extack )
584+ {
585+ struct zl3073x_dpll * zldpll = dpll_priv ;
586+ struct zl3073x_dev * zldev = zldpll -> dev ;
587+ struct zl3073x_dpll_pin * pin = pin_priv ;
588+ s64 phase_comp ;
589+ u8 ref ;
590+ int rc ;
591+
592+ guard (mutex )(& zldev -> multiop_lock );
593+
594+ /* Read reference configuration */
595+ ref = zl3073x_input_pin_ref_get (pin -> id );
596+ rc = zl3073x_mb_op (zldev , ZL_REG_REF_MB_SEM , ZL_REF_MB_SEM_RD ,
597+ ZL_REG_REF_MB_MASK , BIT (ref ));
598+ if (rc )
599+ return rc ;
600+
601+ /* Read current phase offset compensation */
602+ rc = zl3073x_read_u48 (zldev , ZL_REG_REF_PHASE_OFFSET_COMP , & phase_comp );
603+ if (rc )
604+ return rc ;
605+
606+ /* Perform sign extension for 48bit signed value */
607+ phase_comp = sign_extend64 (phase_comp , 47 );
608+
609+ /* Reverse two's complement negation applied during set and convert
610+ * to 32bit signed int
611+ */
612+ * phase_adjust = (s32 )- phase_comp ;
613+
614+ return rc ;
615+ }
616+
617+ static int
618+ zl3073x_dpll_input_pin_phase_adjust_set (const struct dpll_pin * dpll_pin ,
619+ void * pin_priv ,
620+ const struct dpll_device * dpll ,
621+ void * dpll_priv ,
622+ s32 phase_adjust ,
623+ struct netlink_ext_ack * extack )
624+ {
625+ struct zl3073x_dpll * zldpll = dpll_priv ;
626+ struct zl3073x_dev * zldev = zldpll -> dev ;
627+ struct zl3073x_dpll_pin * pin = pin_priv ;
628+ s64 phase_comp ;
629+ u8 ref ;
630+ int rc ;
631+
632+ /* The value in the register is stored as two's complement negation
633+ * of requested value.
634+ */
635+ phase_comp = - phase_adjust ;
636+
637+ guard (mutex )(& zldev -> multiop_lock );
638+
639+ /* Read reference configuration */
640+ ref = zl3073x_input_pin_ref_get (pin -> id );
641+ rc = zl3073x_mb_op (zldev , ZL_REG_REF_MB_SEM , ZL_REF_MB_SEM_RD ,
642+ ZL_REG_REF_MB_MASK , BIT (ref ));
643+ if (rc )
644+ return rc ;
645+
646+ /* Write the requested value into the compensation register */
647+ rc = zl3073x_write_u48 (zldev , ZL_REG_REF_PHASE_OFFSET_COMP , phase_comp );
648+ if (rc )
649+ return rc ;
650+
651+ /* Commit reference configuration */
652+ return zl3073x_mb_op (zldev , ZL_REG_REF_MB_SEM , ZL_REF_MB_SEM_WR ,
653+ ZL_REG_REF_MB_MASK , BIT (ref ));
654+ }
655+
577656/**
578657 * zl3073x_dpll_ref_prio_get - get priority for given input pin
579658 * @pin: pointer to pin
@@ -1284,6 +1363,114 @@ zl3073x_dpll_output_pin_frequency_set(const struct dpll_pin *dpll_pin,
12841363 ZL_REG_OUTPUT_MB_MASK , BIT (out ));
12851364}
12861365
1366+ static int
1367+ zl3073x_dpll_output_pin_phase_adjust_get (const struct dpll_pin * dpll_pin ,
1368+ void * pin_priv ,
1369+ const struct dpll_device * dpll ,
1370+ void * dpll_priv ,
1371+ s32 * phase_adjust ,
1372+ struct netlink_ext_ack * extack )
1373+ {
1374+ struct zl3073x_dpll * zldpll = dpll_priv ;
1375+ struct zl3073x_dev * zldev = zldpll -> dev ;
1376+ struct zl3073x_dpll_pin * pin = pin_priv ;
1377+ u32 synth_freq ;
1378+ s32 phase_comp ;
1379+ u8 out , synth ;
1380+ int rc ;
1381+
1382+ out = zl3073x_output_pin_out_get (pin -> id );
1383+ synth = zl3073x_out_synth_get (zldev , out );
1384+ synth_freq = zl3073x_synth_freq_get (zldev , synth );
1385+
1386+ /* Check synth freq for zero */
1387+ if (!synth_freq ) {
1388+ dev_err (zldev -> dev , "Got zero synth frequency for output %u\n" ,
1389+ out );
1390+ return - EINVAL ;
1391+ }
1392+
1393+ guard (mutex )(& zldev -> multiop_lock );
1394+
1395+ /* Read output configuration */
1396+ rc = zl3073x_mb_op (zldev , ZL_REG_OUTPUT_MB_SEM , ZL_OUTPUT_MB_SEM_RD ,
1397+ ZL_REG_OUTPUT_MB_MASK , BIT (out ));
1398+ if (rc )
1399+ return rc ;
1400+
1401+ /* Read current output phase compensation */
1402+ rc = zl3073x_read_u32 (zldev , ZL_REG_OUTPUT_PHASE_COMP , & phase_comp );
1403+ if (rc )
1404+ return rc ;
1405+
1406+ /* Value in register is expressed in half synth clock cycles */
1407+ phase_comp *= (int )div_u64 (PSEC_PER_SEC , 2 * synth_freq );
1408+
1409+ /* Reverse two's complement negation applied during 'set' */
1410+ * phase_adjust = - phase_comp ;
1411+
1412+ return rc ;
1413+ }
1414+
1415+ static int
1416+ zl3073x_dpll_output_pin_phase_adjust_set (const struct dpll_pin * dpll_pin ,
1417+ void * pin_priv ,
1418+ const struct dpll_device * dpll ,
1419+ void * dpll_priv ,
1420+ s32 phase_adjust ,
1421+ struct netlink_ext_ack * extack )
1422+ {
1423+ struct zl3073x_dpll * zldpll = dpll_priv ;
1424+ struct zl3073x_dev * zldev = zldpll -> dev ;
1425+ struct zl3073x_dpll_pin * pin = pin_priv ;
1426+ int half_synth_cycle ;
1427+ u32 synth_freq ;
1428+ u8 out , synth ;
1429+ int rc ;
1430+
1431+ /* Get attached synth */
1432+ out = zl3073x_output_pin_out_get (pin -> id );
1433+ synth = zl3073x_out_synth_get (zldev , out );
1434+
1435+ /* Get synth's frequency */
1436+ synth_freq = zl3073x_synth_freq_get (zldev , synth );
1437+
1438+ /* Value in register is expressed in half synth clock cycles so
1439+ * the given phase adjustment a multiple of half synth clock.
1440+ */
1441+ half_synth_cycle = (int )div_u64 (PSEC_PER_SEC , 2 * synth_freq );
1442+
1443+ if ((phase_adjust % half_synth_cycle ) != 0 ) {
1444+ NL_SET_ERR_MSG_FMT (extack ,
1445+ "Phase adjustment value has to be multiple of %d" ,
1446+ half_synth_cycle );
1447+ return - EINVAL ;
1448+ }
1449+ phase_adjust /= half_synth_cycle ;
1450+
1451+ /* The value in the register is stored as two's complement negation
1452+ * of requested value.
1453+ */
1454+ phase_adjust = - phase_adjust ;
1455+
1456+ guard (mutex )(& zldev -> multiop_lock );
1457+
1458+ /* Read output configuration */
1459+ rc = zl3073x_mb_op (zldev , ZL_REG_OUTPUT_MB_SEM , ZL_OUTPUT_MB_SEM_RD ,
1460+ ZL_REG_OUTPUT_MB_MASK , BIT (out ));
1461+ if (rc )
1462+ return rc ;
1463+
1464+ /* Write the requested value into the compensation register */
1465+ rc = zl3073x_write_u32 (zldev , ZL_REG_OUTPUT_PHASE_COMP , phase_adjust );
1466+ if (rc )
1467+ return rc ;
1468+
1469+ /* Update output configuration from mailbox */
1470+ return zl3073x_mb_op (zldev , ZL_REG_OUTPUT_MB_SEM , ZL_OUTPUT_MB_SEM_WR ,
1471+ ZL_REG_OUTPUT_MB_MASK , BIT (out ));
1472+ }
1473+
12871474static int
12881475zl3073x_dpll_output_pin_state_on_dpll_get (const struct dpll_pin * dpll_pin ,
12891476 void * pin_priv ,
@@ -1411,6 +1598,8 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
14111598 .frequency_get = zl3073x_dpll_input_pin_frequency_get ,
14121599 .frequency_set = zl3073x_dpll_input_pin_frequency_set ,
14131600 .phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get ,
1601+ .phase_adjust_get = zl3073x_dpll_input_pin_phase_adjust_get ,
1602+ .phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set ,
14141603 .prio_get = zl3073x_dpll_input_pin_prio_get ,
14151604 .prio_set = zl3073x_dpll_input_pin_prio_set ,
14161605 .state_on_dpll_get = zl3073x_dpll_input_pin_state_on_dpll_get ,
@@ -1423,6 +1612,8 @@ static const struct dpll_pin_ops zl3073x_dpll_output_pin_ops = {
14231612 .esync_set = zl3073x_dpll_output_pin_esync_set ,
14241613 .frequency_get = zl3073x_dpll_output_pin_frequency_get ,
14251614 .frequency_set = zl3073x_dpll_output_pin_frequency_set ,
1615+ .phase_adjust_get = zl3073x_dpll_output_pin_phase_adjust_get ,
1616+ .phase_adjust_set = zl3073x_dpll_output_pin_phase_adjust_set ,
14261617 .state_on_dpll_get = zl3073x_dpll_output_pin_state_on_dpll_get ,
14271618};
14281619
0 commit comments