Skip to content

Commit 3f0457e

Browse files
committed
dpll: zl3073x: Refactor DPLL initialization
JIRA: https://issues.redhat.com/browse/RHEL-115367 commit ebb1031 Author: Ivan Vecera <ivecera@redhat.com> Date: Tue Sep 9 11:15:31 2025 +0200 dpll: zl3073x: Refactor DPLL initialization Refactor DPLL initialization and move DPLL (de)registration, monitoring control, fetching device invariant parameters and phase offset measurement block setup to separate functions. Use these new functions during device probe and teardown functions and during changes to the clock_id devlink parameter. These functions will also be used in the next patch implementing devlink flash, where this functionality is likewise required. Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Signed-off-by: Ivan Vecera <ivecera@redhat.com> Link: https://patch.msgid.link/20250909091532.11790-5-ivecera@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
1 parent 603f3d2 commit 3f0457e

File tree

3 files changed

+142
-86
lines changed

3 files changed

+142
-86
lines changed

drivers/dpll/zl3073x/core.c

Lines changed: 133 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -956,21 +956,142 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
956956
msecs_to_jiffies(500));
957957
}
958958

959+
/**
960+
* zl3073x_dev_phase_meas_setup - setup phase offset measurement
961+
* @zldev: pointer to zl3073x_dev structure
962+
*
963+
* Enable phase offset measurement block, set measurement averaging factor
964+
* and enable DPLL-to-its-ref phase measurement for all DPLLs.
965+
*
966+
* Returns: 0 on success, <0 on error
967+
*/
968+
static int
969+
zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev)
970+
{
971+
struct zl3073x_dpll *zldpll;
972+
u8 dpll_meas_ctrl, mask = 0;
973+
int rc;
974+
975+
/* Read DPLL phase measurement control register */
976+
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl);
977+
if (rc)
978+
return rc;
979+
980+
/* Setup phase measurement averaging factor */
981+
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
982+
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3);
983+
984+
/* Enable DPLL measurement block */
985+
dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN;
986+
987+
/* Update phase measurement control register */
988+
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
989+
if (rc)
990+
return rc;
991+
992+
/* Enable DPLL-to-connected-ref measurement for each channel */
993+
list_for_each_entry(zldpll, &zldev->dplls, list)
994+
mask |= BIT(zldpll->id);
995+
996+
return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask);
997+
}
998+
999+
/**
1000+
* zl3073x_dev_start - Start normal operation
1001+
* @zldev: zl3073x device pointer
1002+
* @full: perform full initialization
1003+
*
1004+
* The function starts normal operation, which means registering all DPLLs and
1005+
* their pins, and starting monitoring. If full initialization is requested,
1006+
* the function additionally initializes the phase offset measurement block and
1007+
* fetches hardware-invariant parameters.
1008+
*
1009+
* Return: 0 on success, <0 on error
1010+
*/
1011+
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full)
1012+
{
1013+
struct zl3073x_dpll *zldpll;
1014+
int rc;
1015+
1016+
if (full) {
1017+
/* Fetch device state */
1018+
rc = zl3073x_dev_state_fetch(zldev);
1019+
if (rc)
1020+
return rc;
1021+
1022+
/* Setup phase offset measurement block */
1023+
rc = zl3073x_dev_phase_meas_setup(zldev);
1024+
if (rc) {
1025+
dev_err(zldev->dev,
1026+
"Failed to setup phase measurement\n");
1027+
return rc;
1028+
}
1029+
}
1030+
1031+
/* Register all DPLLs */
1032+
list_for_each_entry(zldpll, &zldev->dplls, list) {
1033+
rc = zl3073x_dpll_register(zldpll);
1034+
if (rc) {
1035+
dev_err_probe(zldev->dev, rc,
1036+
"Failed to register DPLL%u\n",
1037+
zldpll->id);
1038+
return rc;
1039+
}
1040+
}
1041+
1042+
/* Perform initial firmware fine phase correction */
1043+
rc = zl3073x_dpll_init_fine_phase_adjust(zldev);
1044+
if (rc) {
1045+
dev_err_probe(zldev->dev, rc,
1046+
"Failed to init fine phase correction\n");
1047+
return rc;
1048+
}
1049+
1050+
/* Start monitoring */
1051+
kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0);
1052+
1053+
return 0;
1054+
}
1055+
1056+
/**
1057+
* zl3073x_dev_stop - Stop normal operation
1058+
* @zldev: zl3073x device pointer
1059+
*
1060+
* The function stops the normal operation that mean deregistration of all
1061+
* DPLLs and their pins and stop monitoring.
1062+
*
1063+
* Return: 0 on success, <0 on error
1064+
*/
1065+
void zl3073x_dev_stop(struct zl3073x_dev *zldev)
1066+
{
1067+
struct zl3073x_dpll *zldpll;
1068+
1069+
/* Stop monitoring */
1070+
kthread_cancel_delayed_work_sync(&zldev->work);
1071+
1072+
/* Unregister all DPLLs */
1073+
list_for_each_entry(zldpll, &zldev->dplls, list) {
1074+
if (zldpll->dpll_dev)
1075+
zl3073x_dpll_unregister(zldpll);
1076+
}
1077+
}
1078+
9591079
static void zl3073x_dev_dpll_fini(void *ptr)
9601080
{
9611081
struct zl3073x_dpll *zldpll, *next;
9621082
struct zl3073x_dev *zldev = ptr;
9631083

964-
/* Stop monitoring thread */
1084+
/* Stop monitoring and unregister DPLLs */
1085+
zl3073x_dev_stop(zldev);
1086+
1087+
/* Destroy monitoring thread */
9651088
if (zldev->kworker) {
966-
kthread_cancel_delayed_work_sync(&zldev->work);
9671089
kthread_destroy_worker(zldev->kworker);
9681090
zldev->kworker = NULL;
9691091
}
9701092

971-
/* Release DPLLs */
1093+
/* Free all DPLLs */
9721094
list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) {
973-
zl3073x_dpll_unregister(zldpll);
9741095
list_del(&zldpll->list);
9751096
zl3073x_dpll_free(zldpll);
9761097
}
@@ -986,7 +1107,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
9861107

9871108
INIT_LIST_HEAD(&zldev->dplls);
9881109

989-
/* Initialize all DPLLs */
1110+
/* Allocate all DPLLs */
9901111
for (i = 0; i < num_dplls; i++) {
9911112
zldpll = zl3073x_dpll_alloc(zldev, i);
9921113
if (IS_ERR(zldpll)) {
@@ -996,35 +1117,24 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
9961117
goto error;
9971118
}
9981119

999-
rc = zl3073x_dpll_register(zldpll);
1000-
if (rc) {
1001-
dev_err_probe(zldev->dev, rc,
1002-
"Failed to register DPLL%u\n", i);
1003-
zl3073x_dpll_free(zldpll);
1004-
goto error;
1005-
}
1006-
10071120
list_add_tail(&zldpll->list, &zldev->dplls);
10081121
}
10091122

1010-
/* Perform initial firmware fine phase correction */
1011-
rc = zl3073x_dpll_init_fine_phase_adjust(zldev);
1012-
if (rc) {
1013-
dev_err_probe(zldev->dev, rc,
1014-
"Failed to init fine phase correction\n");
1015-
goto error;
1016-
}
1017-
10181123
/* Initialize monitoring thread */
10191124
kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work);
10201125
kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev));
10211126
if (IS_ERR(kworker)) {
10221127
rc = PTR_ERR(kworker);
10231128
goto error;
10241129
}
1025-
10261130
zldev->kworker = kworker;
1027-
kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0);
1131+
1132+
/* Start normal operation */
1133+
rc = zl3073x_dev_start(zldev, true);
1134+
if (rc) {
1135+
dev_err_probe(zldev->dev, rc, "Failed to start device\n");
1136+
goto error;
1137+
}
10281138

10291139
/* Add devres action to release DPLL related resources */
10301140
rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
@@ -1039,46 +1149,6 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
10391149
return rc;
10401150
}
10411151

1042-
/**
1043-
* zl3073x_dev_phase_meas_setup - setup phase offset measurement
1044-
* @zldev: pointer to zl3073x_dev structure
1045-
* @num_channels: number of DPLL channels
1046-
*
1047-
* Enable phase offset measurement block, set measurement averaging factor
1048-
* and enable DPLL-to-its-ref phase measurement for all DPLLs.
1049-
*
1050-
* Returns: 0 on success, <0 on error
1051-
*/
1052-
static int
1053-
zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels)
1054-
{
1055-
u8 dpll_meas_ctrl, mask;
1056-
int i, rc;
1057-
1058-
/* Read DPLL phase measurement control register */
1059-
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl);
1060-
if (rc)
1061-
return rc;
1062-
1063-
/* Setup phase measurement averaging factor */
1064-
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
1065-
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3);
1066-
1067-
/* Enable DPLL measurement block */
1068-
dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN;
1069-
1070-
/* Update phase measurement control register */
1071-
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
1072-
if (rc)
1073-
return rc;
1074-
1075-
/* Enable DPLL-to-connected-ref measurement for each channel */
1076-
for (i = 0, mask = 0; i < num_channels; i++)
1077-
mask |= BIT(i);
1078-
1079-
return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask);
1080-
}
1081-
10821152
/**
10831153
* zl3073x_dev_probe - initialize zl3073x device
10841154
* @zldev: pointer to zl3073x device
@@ -1146,17 +1216,6 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
11461216
return dev_err_probe(zldev->dev, rc,
11471217
"Failed to initialize mutex\n");
11481218

1149-
/* Fetch device state */
1150-
rc = zl3073x_dev_state_fetch(zldev);
1151-
if (rc)
1152-
return rc;
1153-
1154-
/* Setup phase offset measurement block */
1155-
rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels);
1156-
if (rc)
1157-
return dev_err_probe(zldev->dev, rc,
1158-
"Failed to setup phase measurement\n");
1159-
11601219
/* Register DPLL channels */
11611220
rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
11621221
if (rc)

drivers/dpll/zl3073x/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
112112
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
113113
const struct zl3073x_chip_info *chip_info);
114114

115+
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
116+
void zl3073x_dev_stop(struct zl3073x_dev *zldev);
117+
115118
/**********************
116119
* Registers operations
117120
**********************/

drivers/dpll/zl3073x/devlink.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,12 @@ zl3073x_devlink_reload_down(struct devlink *devlink, bool netns_change,
8686
struct netlink_ext_ack *extack)
8787
{
8888
struct zl3073x_dev *zldev = devlink_priv(devlink);
89-
struct zl3073x_dpll *zldpll;
9089

9190
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
9291
return -EOPNOTSUPP;
9392

94-
/* Unregister all DPLLs */
95-
list_for_each_entry(zldpll, &zldev->dplls, list)
96-
zl3073x_dpll_unregister(zldpll);
93+
/* Stop normal operation */
94+
zl3073x_dev_stop(zldev);
9795

9896
return 0;
9997
}
@@ -107,7 +105,6 @@ zl3073x_devlink_reload_up(struct devlink *devlink,
107105
{
108106
struct zl3073x_dev *zldev = devlink_priv(devlink);
109107
union devlink_param_value val;
110-
struct zl3073x_dpll *zldpll;
111108
int rc;
112109

113110
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
@@ -125,13 +122,10 @@ zl3073x_devlink_reload_up(struct devlink *devlink,
125122
zldev->clock_id = val.vu64;
126123
}
127124

128-
/* Re-register all DPLLs */
129-
list_for_each_entry(zldpll, &zldev->dplls, list) {
130-
rc = zl3073x_dpll_register(zldpll);
131-
if (rc)
132-
dev_warn(zldev->dev,
133-
"Failed to re-register DPLL%u\n", zldpll->id);
134-
}
125+
/* Restart normal operation */
126+
rc = zl3073x_dev_start(zldev, false);
127+
if (rc)
128+
dev_warn(zldev->dev, "Failed to re-start normal operation\n");
135129

136130
*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
137131

0 commit comments

Comments
 (0)