From nobody Mon Oct 6 04:59:36 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36ED32EF675 for ; Fri, 25 Jul 2025 15:42:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753458129; cv=none; b=CEAAy3+Tb+D5Sko0Gr7y05MTQKgqULA/bEtI7DM/YED6nFwzNBArjqd1rF3GduWZ/GX8W3+CA6nanfuxkotI8C57VOjeSS02j4ojovF/6EqTY7gaWn511q8rQZXn6ARKFL6WxvX1t63M8QoxOgcqNkRLKhPq63mCngmWEuSwLII= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753458129; c=relaxed/simple; bh=AMtecukD+c7HRnKNJMkxLchm4exdtOVKEDOuiQe340Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HM9oHCkxn3c0pVWSXofzvMmg7WnwrZv4A0LSUcew/JJk8m+haCAwoF9hU11kV/Gw9VdXgDIavOVIffGivTW/RPFU1LhkFrSLNUMo/xoW0Q9pWEaW/7YQyoO0oYm4U3yC5JIzO+Zg6gmUmkDBAC0b+lGU7Ag7pJrEMfjy2H0SxwY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=PHq/EcYq; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="PHq/EcYq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1753458126; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wtCbzuYWLe0Jy2fUsoiE0Q0JrQHtuM5Ho73ZqD3AqIo=; b=PHq/EcYqrOvI3ftLR8KFvF3Eq0LQiI37FMZWaFJyQnAMrJ9//gUkqc4czgWJJTsDmFb2e7 4Ew54GVItzq8RVfAVH4nTIruF6kU+q7okFKOKoRAIVq1CztdqO5zg1unu2N0A6fNQHMmrg nUZuZ9cpTBQn2EN/Ux8831TtEXxXSL0= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-282-iVvjoTV1MlWgbWQsvxgDaQ-1; Fri, 25 Jul 2025 11:42:02 -0400 X-MC-Unique: iVvjoTV1MlWgbWQsvxgDaQ-1 X-Mimecast-MFC-AGG-ID: iVvjoTV1MlWgbWQsvxgDaQ_1753458119 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C7E2E19560A3; Fri, 25 Jul 2025 15:41:58 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.45.224.176]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 24B5119560AA; Fri, 25 Jul 2025 15:41:54 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Jiri Pirko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Prathosh Satish , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Michal Schmidt , Petr Oros Subject: [PATCH net-next 4/5] dpll: zl3073x: Refactor DPLL initialization Date: Fri, 25 Jul 2025 17:41:35 +0200 Message-ID: <20250725154136.1008132-5-ivecera@redhat.com> In-Reply-To: <20250725154136.1008132-1-ivecera@redhat.com> References: <20250725154136.1008132-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Ivan Vecera --- drivers/dpll/zl3073x/core.c | 207 +++++++++++++++++++++------------ drivers/dpll/zl3073x/core.h | 3 + drivers/dpll/zl3073x/devlink.c | 18 +-- 3 files changed, 142 insertions(+), 86 deletions(-) diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c index 86c26edc90462..b3015173d9f63 100644 --- a/drivers/dpll/zl3073x/core.c +++ b/drivers/dpll/zl3073x/core.c @@ -956,21 +956,142 @@ zl3073x_dev_periodic_work(struct kthread_work *work) msecs_to_jiffies(500)); } =20 +/** + * zl3073x_dev_phase_meas_setup - setup phase offset measurement + * @zldev: pointer to zl3073x_dev structure + * + * Enable phase offset measurement block, set measurement averaging factor + * and enable DPLL-to-its-ref phase measurement for all DPLLs. + * + * Returns: 0 on success, <0 on error + */ +static int +zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev) +{ + struct zl3073x_dpll *zldpll; + u8 dpll_meas_ctrl, mask; + int rc; + + /* Read DPLL phase measurement control register */ + rc =3D zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl); + if (rc) + return rc; + + /* Setup phase measurement averaging factor */ + dpll_meas_ctrl &=3D ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR; + dpll_meas_ctrl |=3D FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3); + + /* Enable DPLL measurement block */ + dpll_meas_ctrl |=3D ZL_DPLL_MEAS_CTRL_EN; + + /* Update phase measurement control register */ + rc =3D zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl); + if (rc) + return rc; + + /* Enable DPLL-to-connected-ref measurement for each channel */ + list_for_each_entry(zldpll, &zldev->dplls, list) + mask |=3D BIT(zldpll->id); + + return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask); +} + +/** + * zl3073x_dev_start - Start normal operation + * @zldev: zl3073x device pointer + * @full: perform full initialization + * + * The function starts normal operation, which means registering all DPLLs= and + * their pins, and starting monitoring. If full initialization is requeste= d, + * the function additionally initializes the phase offset measurement bloc= k and + * fetches hardware-invariant parameters. + * + * Return: 0 on success, <0 on error + */ +int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full) +{ + struct zl3073x_dpll *zldpll; + int rc; + + if (full) { + /* Fetch device state */ + rc =3D zl3073x_dev_state_fetch(zldev); + if (rc) + return rc; + + /* Setup phase offset measurement block */ + rc =3D zl3073x_dev_phase_meas_setup(zldev); + if (rc) { + dev_err(zldev->dev, + "Failed to setup phase measurement\n"); + return rc; + } + } + + /* Register all DPLLs */ + list_for_each_entry(zldpll, &zldev->dplls, list) { + rc =3D zl3073x_dpll_register(zldpll); + if (rc) { + dev_err_probe(zldev->dev, rc, + "Failed to register DPLL%u\n", + zldpll->id); + return rc; + } + } + + /* Perform initial firmware fine phase correction */ + rc =3D zl3073x_dpll_init_fine_phase_adjust(zldev); + if (rc) { + dev_err_probe(zldev->dev, rc, + "Failed to init fine phase correction\n"); + return rc; + } + + /* Start monitoring */ + kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); + + return 0; +} + +/** + * zl3073x_dev_stop - Stop normal operation + * @zldev: zl3073x device pointer + * + * The function stops the normal operation that mean deregistration of all + * DPLLs and their pins and stop monitoring. + * + * Return: 0 on success, <0 on error + */ +void zl3073x_dev_stop(struct zl3073x_dev *zldev) +{ + struct zl3073x_dpll *zldpll; + + /* Stop monitoring */ + kthread_cancel_delayed_work_sync(&zldev->work); + + /* Unregister all DPLLs */ + list_for_each_entry(zldpll, &zldev->dplls, list) { + if (zldpll->dpll_dev) + zl3073x_dpll_unregister(zldpll); + } +} + static void zl3073x_dev_dpll_fini(void *ptr) { struct zl3073x_dpll *zldpll, *next; struct zl3073x_dev *zldev =3D ptr; =20 - /* Stop monitoring thread */ + /* Stop monitoring and unregister DPLLs */ + zl3073x_dev_stop(zldev); + + /* Destroy monitoring thread */ if (zldev->kworker) { - kthread_cancel_delayed_work_sync(&zldev->work); kthread_destroy_worker(zldev->kworker); zldev->kworker =3D NULL; } =20 - /* Release DPLLs */ + /* Free all DPLLs */ list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { - zl3073x_dpll_unregister(zldpll); list_del(&zldpll->list); zl3073x_dpll_free(zldpll); } @@ -986,7 +1107,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 n= um_dplls) =20 INIT_LIST_HEAD(&zldev->dplls); =20 - /* Initialize all DPLLs */ + /* Allocate all DPLLs */ for (i =3D 0; i < num_dplls; i++) { zldpll =3D zl3073x_dpll_alloc(zldev, i); if (IS_ERR(zldpll)) { @@ -996,25 +1117,9 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 = num_dplls) goto error; } =20 - rc =3D zl3073x_dpll_register(zldpll); - if (rc) { - dev_err_probe(zldev->dev, rc, - "Failed to register DPLL%u\n", i); - zl3073x_dpll_free(zldpll); - goto error; - } - list_add_tail(&zldpll->list, &zldev->dplls); } =20 - /* Perform initial firmware fine phase correction */ - rc =3D zl3073x_dpll_init_fine_phase_adjust(zldev); - if (rc) { - dev_err_probe(zldev->dev, rc, - "Failed to init fine phase correction\n"); - goto error; - } - /* Initialize monitoring thread */ kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); kworker =3D kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); @@ -1022,9 +1127,14 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8= num_dplls) rc =3D PTR_ERR(kworker); goto error; } - zldev->kworker =3D kworker; - kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); + + /* Start normal operation */ + rc =3D zl3073x_dev_start(zldev, true); + if (rc) { + dev_err_probe(zldev->dev, rc, "Failed to start device\n"); + goto error; + } =20 /* Add devres action to release DPLL related resources */ rc =3D 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) return rc; } =20 -/** - * zl3073x_dev_phase_meas_setup - setup phase offset measurement - * @zldev: pointer to zl3073x_dev structure - * @num_channels: number of DPLL channels - * - * Enable phase offset measurement block, set measurement averaging factor - * and enable DPLL-to-its-ref phase measurement for all DPLLs. - * - * Returns: 0 on success, <0 on error - */ -static int -zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels) -{ - u8 dpll_meas_ctrl, mask; - int i, rc; - - /* Read DPLL phase measurement control register */ - rc =3D zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl); - if (rc) - return rc; - - /* Setup phase measurement averaging factor */ - dpll_meas_ctrl &=3D ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR; - dpll_meas_ctrl |=3D FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3); - - /* Enable DPLL measurement block */ - dpll_meas_ctrl |=3D ZL_DPLL_MEAS_CTRL_EN; - - /* Update phase measurement control register */ - rc =3D zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl); - if (rc) - return rc; - - /* Enable DPLL-to-connected-ref measurement for each channel */ - for (i =3D 0, mask =3D 0; i < num_channels; i++) - mask |=3D BIT(i); - - return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask); -} - /** * zl3073x_dev_probe - initialize zl3073x device * @zldev: pointer to zl3073x device @@ -1146,17 +1216,6 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, return dev_err_probe(zldev->dev, rc, "Failed to initialize mutex\n"); =20 - /* Fetch device state */ - rc =3D zl3073x_dev_state_fetch(zldev); - if (rc) - return rc; - - /* Setup phase offset measurement block */ - rc =3D zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels); - if (rc) - return dev_err_probe(zldev->dev, rc, - "Failed to setup phase measurement\n"); - /* Register DPLL channels */ rc =3D zl3073x_devm_dpll_init(zldev, chip_info->num_channels); if (rc) diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h index a9c098dd6d5a2..f4a6cecbbba7e 100644 --- a/drivers/dpll/zl3073x/core.h +++ b/drivers/dpll/zl3073x/core.h @@ -111,6 +111,9 @@ struct zl3073x_dev *zl3073x_devm_alloc(struct device *d= ev); int zl3073x_dev_probe(struct zl3073x_dev *zldev, const struct zl3073x_chip_info *chip_info); =20 +int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full); +void zl3073x_dev_stop(struct zl3073x_dev *zldev); + /********************** * Registers operations **********************/ diff --git a/drivers/dpll/zl3073x/devlink.c b/drivers/dpll/zl3073x/devlink.c index f3ca973a4d416..d0f6d9cd4a68e 100644 --- a/drivers/dpll/zl3073x/devlink.c +++ b/drivers/dpll/zl3073x/devlink.c @@ -86,14 +86,12 @@ zl3073x_devlink_reload_down(struct devlink *devlink, bo= ol netns_change, struct netlink_ext_ack *extack) { struct zl3073x_dev *zldev =3D devlink_priv(devlink); - struct zl3073x_dpll *zldpll; =20 if (action !=3D DEVLINK_RELOAD_ACTION_DRIVER_REINIT) return -EOPNOTSUPP; =20 - /* Unregister all DPLLs */ - list_for_each_entry(zldpll, &zldev->dplls, list) - zl3073x_dpll_unregister(zldpll); + /* Stop normal operation */ + zl3073x_dev_stop(zldev); =20 return 0; } @@ -107,7 +105,6 @@ zl3073x_devlink_reload_up(struct devlink *devlink, { struct zl3073x_dev *zldev =3D devlink_priv(devlink); union devlink_param_value val; - struct zl3073x_dpll *zldpll; int rc; =20 if (action !=3D DEVLINK_RELOAD_ACTION_DRIVER_REINIT) @@ -125,13 +122,10 @@ zl3073x_devlink_reload_up(struct devlink *devlink, zldev->clock_id =3D val.vu64; } =20 - /* Re-register all DPLLs */ - list_for_each_entry(zldpll, &zldev->dplls, list) { - rc =3D zl3073x_dpll_register(zldpll); - if (rc) - dev_warn(zldev->dev, - "Failed to re-register DPLL%u\n", zldpll->id); - } + /* Restart normal operation */ + rc =3D zl3073x_dev_start(zldev, false); + if (rc) + dev_warn(zldev->dev, "Failed to re-start normal operation\n"); =20 *actions_performed =3D BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); =20 --=20 2.49.1