Skip to content

Commit 83d687b

Browse files
committed
dpll: zl3073x: Refactor DPLL initialization
jira KERNEL-318 Rebuild_History Non-Buildable kernel-6.12.0-124.20.1.el10_1 commit-author Ivan Vecera <ivecera@redhat.com> commit ebb1031 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> (cherry picked from commit ebb1031) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent a691afd commit 83d687b

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
@@ -809,21 +809,142 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
809809
msecs_to_jiffies(500));
810810
}
811811

812+
/**
813+
* zl3073x_dev_phase_meas_setup - setup phase offset measurement
814+
* @zldev: pointer to zl3073x_dev structure
815+
*
816+
* Enable phase offset measurement block, set measurement averaging factor
817+
* and enable DPLL-to-its-ref phase measurement for all DPLLs.
818+
*
819+
* Returns: 0 on success, <0 on error
820+
*/
821+
static int
822+
zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev)
823+
{
824+
struct zl3073x_dpll *zldpll;
825+
u8 dpll_meas_ctrl, mask = 0;
826+
int rc;
827+
828+
/* Read DPLL phase measurement control register */
829+
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl);
830+
if (rc)
831+
return rc;
832+
833+
/* Setup phase measurement averaging factor */
834+
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
835+
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3);
836+
837+
/* Enable DPLL measurement block */
838+
dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN;
839+
840+
/* Update phase measurement control register */
841+
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
842+
if (rc)
843+
return rc;
844+
845+
/* Enable DPLL-to-connected-ref measurement for each channel */
846+
list_for_each_entry(zldpll, &zldev->dplls, list)
847+
mask |= BIT(zldpll->id);
848+
849+
return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask);
850+
}
851+
852+
/**
853+
* zl3073x_dev_start - Start normal operation
854+
* @zldev: zl3073x device pointer
855+
* @full: perform full initialization
856+
*
857+
* The function starts normal operation, which means registering all DPLLs and
858+
* their pins, and starting monitoring. If full initialization is requested,
859+
* the function additionally initializes the phase offset measurement block and
860+
* fetches hardware-invariant parameters.
861+
*
862+
* Return: 0 on success, <0 on error
863+
*/
864+
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full)
865+
{
866+
struct zl3073x_dpll *zldpll;
867+
int rc;
868+
869+
if (full) {
870+
/* Fetch device state */
871+
rc = zl3073x_dev_state_fetch(zldev);
872+
if (rc)
873+
return rc;
874+
875+
/* Setup phase offset measurement block */
876+
rc = zl3073x_dev_phase_meas_setup(zldev);
877+
if (rc) {
878+
dev_err(zldev->dev,
879+
"Failed to setup phase measurement\n");
880+
return rc;
881+
}
882+
}
883+
884+
/* Register all DPLLs */
885+
list_for_each_entry(zldpll, &zldev->dplls, list) {
886+
rc = zl3073x_dpll_register(zldpll);
887+
if (rc) {
888+
dev_err_probe(zldev->dev, rc,
889+
"Failed to register DPLL%u\n",
890+
zldpll->id);
891+
return rc;
892+
}
893+
}
894+
895+
/* Perform initial firmware fine phase correction */
896+
rc = zl3073x_dpll_init_fine_phase_adjust(zldev);
897+
if (rc) {
898+
dev_err_probe(zldev->dev, rc,
899+
"Failed to init fine phase correction\n");
900+
return rc;
901+
}
902+
903+
/* Start monitoring */
904+
kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0);
905+
906+
return 0;
907+
}
908+
909+
/**
910+
* zl3073x_dev_stop - Stop normal operation
911+
* @zldev: zl3073x device pointer
912+
*
913+
* The function stops the normal operation that mean deregistration of all
914+
* DPLLs and their pins and stop monitoring.
915+
*
916+
* Return: 0 on success, <0 on error
917+
*/
918+
void zl3073x_dev_stop(struct zl3073x_dev *zldev)
919+
{
920+
struct zl3073x_dpll *zldpll;
921+
922+
/* Stop monitoring */
923+
kthread_cancel_delayed_work_sync(&zldev->work);
924+
925+
/* Unregister all DPLLs */
926+
list_for_each_entry(zldpll, &zldev->dplls, list) {
927+
if (zldpll->dpll_dev)
928+
zl3073x_dpll_unregister(zldpll);
929+
}
930+
}
931+
812932
static void zl3073x_dev_dpll_fini(void *ptr)
813933
{
814934
struct zl3073x_dpll *zldpll, *next;
815935
struct zl3073x_dev *zldev = ptr;
816936

817-
/* Stop monitoring thread */
937+
/* Stop monitoring and unregister DPLLs */
938+
zl3073x_dev_stop(zldev);
939+
940+
/* Destroy monitoring thread */
818941
if (zldev->kworker) {
819-
kthread_cancel_delayed_work_sync(&zldev->work);
820942
kthread_destroy_worker(zldev->kworker);
821943
zldev->kworker = NULL;
822944
}
823945

824-
/* Release DPLLs */
946+
/* Free all DPLLs */
825947
list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) {
826-
zl3073x_dpll_unregister(zldpll);
827948
list_del(&zldpll->list);
828949
zl3073x_dpll_free(zldpll);
829950
}
@@ -839,7 +960,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
839960

840961
INIT_LIST_HEAD(&zldev->dplls);
841962

842-
/* Initialize all DPLLs */
963+
/* Allocate all DPLLs */
843964
for (i = 0; i < num_dplls; i++) {
844965
zldpll = zl3073x_dpll_alloc(zldev, i);
845966
if (IS_ERR(zldpll)) {
@@ -849,35 +970,24 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
849970
goto error;
850971
}
851972

852-
rc = zl3073x_dpll_register(zldpll);
853-
if (rc) {
854-
dev_err_probe(zldev->dev, rc,
855-
"Failed to register DPLL%u\n", i);
856-
zl3073x_dpll_free(zldpll);
857-
goto error;
858-
}
859-
860973
list_add_tail(&zldpll->list, &zldev->dplls);
861974
}
862975

863-
/* Perform initial firmware fine phase correction */
864-
rc = zl3073x_dpll_init_fine_phase_adjust(zldev);
865-
if (rc) {
866-
dev_err_probe(zldev->dev, rc,
867-
"Failed to init fine phase correction\n");
868-
goto error;
869-
}
870-
871976
/* Initialize monitoring thread */
872977
kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work);
873978
kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev));
874979
if (IS_ERR(kworker)) {
875980
rc = PTR_ERR(kworker);
876981
goto error;
877982
}
878-
879983
zldev->kworker = kworker;
880-
kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0);
984+
985+
/* Start normal operation */
986+
rc = zl3073x_dev_start(zldev, true);
987+
if (rc) {
988+
dev_err_probe(zldev->dev, rc, "Failed to start device\n");
989+
goto error;
990+
}
881991

882992
/* Add devres action to release DPLL related resources */
883993
rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
@@ -892,46 +1002,6 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
8921002
return rc;
8931003
}
8941004

895-
/**
896-
* zl3073x_dev_phase_meas_setup - setup phase offset measurement
897-
* @zldev: pointer to zl3073x_dev structure
898-
* @num_channels: number of DPLL channels
899-
*
900-
* Enable phase offset measurement block, set measurement averaging factor
901-
* and enable DPLL-to-its-ref phase measurement for all DPLLs.
902-
*
903-
* Returns: 0 on success, <0 on error
904-
*/
905-
static int
906-
zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels)
907-
{
908-
u8 dpll_meas_ctrl, mask;
909-
int i, rc;
910-
911-
/* Read DPLL phase measurement control register */
912-
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl);
913-
if (rc)
914-
return rc;
915-
916-
/* Setup phase measurement averaging factor */
917-
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
918-
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3);
919-
920-
/* Enable DPLL measurement block */
921-
dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN;
922-
923-
/* Update phase measurement control register */
924-
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
925-
if (rc)
926-
return rc;
927-
928-
/* Enable DPLL-to-connected-ref measurement for each channel */
929-
for (i = 0, mask = 0; i < num_channels; i++)
930-
mask |= BIT(i);
931-
932-
return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask);
933-
}
934-
9351005
/**
9361006
* zl3073x_dev_probe - initialize zl3073x device
9371007
* @zldev: pointer to zl3073x device
@@ -999,17 +1069,6 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
9991069
return dev_err_probe(zldev->dev, rc,
10001070
"Failed to initialize mutex\n");
10011071

1002-
/* Fetch device state */
1003-
rc = zl3073x_dev_state_fetch(zldev);
1004-
if (rc)
1005-
return rc;
1006-
1007-
/* Setup phase offset measurement block */
1008-
rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels);
1009-
if (rc)
1010-
return dev_err_probe(zldev->dev, rc,
1011-
"Failed to setup phase measurement\n");
1012-
10131072
/* Register DPLL channels */
10141073
rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
10151074
if (rc)

drivers/dpll/zl3073x/core.h

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

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

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)