@@ -574,6 +574,85 @@ zl3073x_dpll_input_pin_phase_offset_get(const struct dpll_pin *dpll_pin,
574
574
return rc ;
575
575
}
576
576
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
+
577
656
/**
578
657
* zl3073x_dpll_ref_prio_get - get priority for given input pin
579
658
* @pin: pointer to pin
@@ -1284,6 +1363,114 @@ zl3073x_dpll_output_pin_frequency_set(const struct dpll_pin *dpll_pin,
1284
1363
ZL_REG_OUTPUT_MB_MASK , BIT (out ));
1285
1364
}
1286
1365
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
+
1287
1474
static int
1288
1475
zl3073x_dpll_output_pin_state_on_dpll_get (const struct dpll_pin * dpll_pin ,
1289
1476
void * pin_priv ,
@@ -1411,6 +1598,8 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
1411
1598
.frequency_get = zl3073x_dpll_input_pin_frequency_get ,
1412
1599
.frequency_set = zl3073x_dpll_input_pin_frequency_set ,
1413
1600
.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 ,
1414
1603
.prio_get = zl3073x_dpll_input_pin_prio_get ,
1415
1604
.prio_set = zl3073x_dpll_input_pin_prio_set ,
1416
1605
.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 = {
1423
1612
.esync_set = zl3073x_dpll_output_pin_esync_set ,
1424
1613
.frequency_get = zl3073x_dpll_output_pin_frequency_get ,
1425
1614
.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 ,
1426
1617
.state_on_dpll_get = zl3073x_dpll_output_pin_state_on_dpll_get ,
1427
1618
};
1428
1619
0 commit comments