From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
To: Serge Semin <Sergey.Semin@baikalelectronics.ru>,
Hans de Goede <hdegoede@redhat.com>, Jens Axboe <axboe@kernel.dk>
Cc: Serge Semin <fancer.lancer@gmail.com>,
Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>,
Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>,
Rob Herring <robh+dt@kernel.org>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH 05/21] ata: libahci_platform: Convert to using devm bulk clocks API
Date: Thu, 24 Mar 2022 10:29:01 +0900 [thread overview]
Message-ID: <603eb020-3f43-c193-b3f6-8ff697f845c8@opensource.wdc.com> (raw)
In-Reply-To: <20220324001628.13028-6-Sergey.Semin@baikalelectronics.ru>
On 3/24/22 09:16, Serge Semin wrote:
> In order to simplify the clock-related code there is a way to convert the
> current fixed clocks array into using the common bulk clocks kernel API
> with dynamic set of the clock handlers and device-managed clock-resource
> tracking. It's a bit tricky due to the complication coming from the
> requirement to support the platforms (da850, spear13xx) with the
> non-OF-based clock source, but still doable.
>
> Before this modification there are two methods have been used to get the
> clocks connected to an AHCI device: clk_get() - to get the very first
> clock in the list and of_clk_get() - to get the rest of them. Basically
> the platforms with non-OF-based clocks definition could specify only a
> single reference clock source. The platforms with OF-hw clocks have been
> luckier and could setup up to AHCI_MAX_CLKS clocks. Such semantic can be
> retained with using devm_clk_bulk_get_all() to retrieve the clocks defined
> via the DT firmware and devm_clk_get_optional() otherwise. In both cases
> using the device-managed version of the methods will cause the automatic
> resources deallocation on the AHCI device removal event. The only
> complicated part in the suggested approach is the explicit allocation and
> initialization of the clk_bulk_data structure instance for the non-OF
> reference clocks. It's required in order to use the Bulk Clocks API for
> the both denoted cases of the clocks definition.
>
> Note aside with the clock-related code reduction and natural
> simplification, there are several bonuses the suggested modification
> provides. First of all the limitation of having no greater than
> AHCI_MAX_CLKS clocks is now removed, since the devm_clk_bulk_get_all()
> method will allocate as many reference clocks data descriptors as there
> are clocks specified for the device. Secondly the clock names are
> auto-detected. So the glue drivers can make sure that the required clocks
> are specified just by checking the clock IDs in the clk_bulk_data array.
> Thirdly using the handy Bulk Clocks kernel API improves the
> clocks-handling code readability. And the last but not least this
> modification implements a true optional clocks support to the
> ahci_platform_get_resources() method. Indeed the previous clocks getting
> procedure just stopped getting the clocks on any errors (aside from
> non-critical -EPROBE_DEFER) in a way so the callee wasn't even informed
> about abnormal loop termination. The new implementation lacks of such
> problem. The ahci_platform_get_resources() will return an error code if
> the corresponding clocks getting method ends execution abnormally.
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> ---
> drivers/ata/ahci.h | 4 +-
> drivers/ata/libahci_platform.c | 82 +++++++++++++++-------------------
> 2 files changed, 37 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index eeac5482f1d1..1564c691094a 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -38,7 +38,6 @@
>
> enum {
> AHCI_MAX_PORTS = 32,
> - AHCI_MAX_CLKS = 5,
> AHCI_MAX_SG = 168, /* hardware max is 64K */
> AHCI_DMA_BOUNDARY = 0xffffffff,
> AHCI_MAX_CMDS = 32,
> @@ -341,7 +340,8 @@ struct ahci_host_priv {
> u32 em_msg_type; /* EM message type */
> u32 remapped_nvme; /* NVMe remapped device count */
> bool got_runtime_pm; /* Did we do pm_runtime_get? */
> - struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
> + unsigned int n_clks;
> + struct clk_bulk_data *clks; /* Optional */
> struct reset_control *rsts; /* Optional */
> struct regulator **target_pwrs; /* Optional */
> struct regulator *ahci_regulator;/* Optional */
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index 8eabbb5f208c..d805ddc3a024 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -8,6 +8,7 @@
> * Anton Vorontsov <avorontsov@ru.mvista.com>
> */
>
> +#include <linux/clk-provider.h>
> #include <linux/clk.h>
> #include <linux/kernel.h>
> #include <linux/gfp.h>
> @@ -97,28 +98,14 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
> * ahci_platform_enable_clks - Enable platform clocks
> * @hpriv: host private area to store config values
> *
> - * This function enables all the clks found in hpriv->clks, starting at
> - * index 0. If any clk fails to enable it disables all the clks already
> - * enabled in reverse order, and then returns an error.
> + * This function enables all the clks found for the AHCI device.
> *
> * RETURNS:
> * 0 on success otherwise a negative error code
> */
> int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
> {
> - int c, rc;
> -
> - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
> - rc = clk_prepare_enable(hpriv->clks[c]);
> - if (rc)
> - goto disable_unprepare_clk;
> - }
> - return 0;
> -
> -disable_unprepare_clk:
> - while (--c >= 0)
> - clk_disable_unprepare(hpriv->clks[c]);
> - return rc;
> + return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
> }
> EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
>
> @@ -126,16 +113,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
> * ahci_platform_disable_clks - Disable platform clocks
> * @hpriv: host private area to store config values
> *
> - * This function disables all the clks found in hpriv->clks, in reverse
> - * order of ahci_platform_enable_clks (starting at the end of the array).
> + * This function disables all the clocks enabled before
> + * (bulk-clocks-disable function is supposed to do that in reverse
> + * from the enabling procedure order).
> */
> void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
> {
> - int c;
> -
> - for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
> - if (hpriv->clks[c])
> - clk_disable_unprepare(hpriv->clks[c]);
> + clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
> }
> EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
>
> @@ -292,8 +276,6 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
> pm_runtime_disable(dev);
> }
>
> - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
> - clk_put(hpriv->clks[c]);
> /*
> * The regulators are tied to child node device and not to the
> * SATA device itself. So we can't use devm for automatically
> @@ -374,8 +356,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
> * 2) regulator for controlling the targets power (optional)
> * regulator for controlling the AHCI controller (optional)
> - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
> - * or for non devicetree enabled platforms a single clock
> + * 3) all clocks specified in the devicetree node, or a single
> + * clock for non-OF platforms (optional)
> * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
> * 5) phys (optional)
> *
> @@ -385,11 +367,10 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> unsigned int flags)
> {
> + int enabled_ports = 0, rc = 0, child_nodes;
> struct device *dev = &pdev->dev;
> struct ahci_host_priv *hpriv;
> - struct clk *clk;
> struct device_node *child;
> - int i, enabled_ports = 0, rc = 0, child_nodes;
> u32 mask_port_map = 0;
>
> if (!devres_open_group(dev, NULL, GFP_KERNEL))
> @@ -413,25 +394,32 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> }
> }
>
> - for (i = 0; i < AHCI_MAX_CLKS; i++) {
> - /*
> - * For now we must use clk_get(dev, NULL) for the first clock,
> - * because some platforms (da850, spear13xx) are not yet
> - * converted to use devicetree for clocks. For new platforms
> - * this is equivalent to of_clk_get(dev->of_node, 0).
> - */
> - if (i == 0)
> - clk = clk_get(dev, NULL);
> - else
> - clk = of_clk_get(dev->of_node, i);
> -
> - if (IS_ERR(clk)) {
> - rc = PTR_ERR(clk);
> - if (rc == -EPROBE_DEFER)
> - goto err_out;
> - break;
> + /*
> + * Bulk clock get procedure can fail to find any clock due to running
> + * an a non-OF platform or due to the clocks being defined in bypass
> + * from the DT firmware (like da850, spear13xx). In that case we
> + * fallback to getting a single clock source right from the dev clocks
> + * list.
> + */
> + rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
I would move the error check first here to make things more readable:
rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
if (rc < 0)
goto err_out;
if (rc) {
/* Got clocks in bulk */
hpriv->n_clks = rc;
} else {
/*
* No clock bulk found: fallback to manually getting
* the optional clock.
*/
hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks),
GFP_KERNEL);
...
}
And it may be cleaner to move this entire code hunk into a helper,
something like ahci_platform_get_clks() ?
> + if (rc > 0) {
> + hpriv->n_clks = rc;
> + } else if (!rc) {
> + hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
> + if (!hpriv->clks) {
> + rc = -ENOMEM;
> + goto err_out;
> }
> - hpriv->clks[i] = clk;
> + hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
> + if (IS_ERR(hpriv->clks->clk)) {
> + rc = PTR_ERR(hpriv->clks->clk);
> + goto err_out;
> + } else if (hpriv->clks->clk) {
> + hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
> + hpriv->n_clks = 1;
> + }
> + } else {
> + goto err_out;
> }
>
> hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
--
Damien Le Moal
Western Digital Research
next prev parent reply other threads:[~2022-03-24 1:29 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-24 0:16 [PATCH 00/21] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
2022-03-24 0:16 ` [PATCH 01/21] dt-bindings: ata: sata: Extend number of SATA ports Serge Semin
2022-03-29 8:15 ` Damien Le Moal
2022-04-11 19:25 ` Serge Semin
2022-03-24 0:16 ` [PATCH 02/21] dt-bindings: ata: Convert AHCI-bindings to DT schema Serge Semin
2022-03-28 19:32 ` Rob Herring
2022-04-11 19:34 ` Serge Semin
2022-03-24 0:16 ` [PATCH 03/21] ata: libahci_platform: Explicitly set rc on devres_alloc failure Serge Semin
2022-03-24 0:58 ` Damien Le Moal
2022-03-24 21:37 ` Serge Semin
2022-03-25 1:56 ` Damien Le Moal
2022-04-06 20:03 ` Serge Semin
2022-03-29 8:20 ` Damien Le Moal
2022-03-24 0:16 ` [PATCH 04/21] ata: libahci_platform: Convert to using handy devm-ioremap methods Serge Semin
2022-03-24 1:11 ` Damien Le Moal
2022-04-06 20:42 ` Serge Semin
2022-03-24 0:16 ` [PATCH 05/21] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
2022-03-24 1:29 ` Damien Le Moal [this message]
2022-04-09 4:59 ` Serge Semin
2022-03-28 22:36 ` kernel test robot
2022-03-28 23:42 ` kernel test robot
2022-03-29 0:03 ` kernel test robot
2022-03-24 0:16 ` [PATCH 06/21] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
2022-03-24 1:36 ` Damien Le Moal
2022-04-11 6:02 ` Serge Semin
2022-03-24 0:16 ` [PATCH 07/21] ata: libahci_platform: Sanity check the DT child nodes number Serge Semin
2022-03-24 1:40 ` Damien Le Moal
2022-03-24 8:12 ` Sergey Shtylyov
2022-03-24 8:13 ` Damien Le Moal
2022-04-11 13:10 ` Serge Semin
2022-03-24 0:16 ` [PATCH 08/21] ata: libahci_platform: Parse ports-implemented property in resources getter Serge Semin
2022-03-24 0:16 ` [PATCH 09/21] ata: libahci_platform: Introduce reset assertion/deassertion methods Serge Semin
2022-03-24 1:52 ` Damien Le Moal
2022-04-11 10:57 ` Serge Semin
2022-03-24 0:16 ` [PATCH 10/21] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
2022-03-24 0:16 ` [PATCH 11/21] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
2022-03-24 0:16 ` [PATCH 12/21] ata: libahci: Discard redundant force_port_map parameter Serge Semin
2022-03-24 2:05 ` Damien Le Moal
2022-04-11 12:11 ` Serge Semin
2022-04-11 12:25 ` Damien Le Moal
2022-04-11 20:52 ` Serge Semin
2022-04-11 22:48 ` Damien Le Moal
2022-04-12 12:29 ` Serge Semin
2022-03-24 0:16 ` [PATCH 13/21] ata: libahci: Don't read AHCI version twice in the save-config method Serge Semin
2022-03-24 0:16 ` [PATCH 14/21] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
2022-03-24 0:16 ` [PATCH 15/21] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
2022-03-24 0:16 ` [PATCH 16/21] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
2022-04-01 0:06 ` Rob Herring
2022-04-11 20:00 ` Serge Semin
2022-03-24 0:16 ` [PATCH 17/21] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
2022-03-24 2:21 ` Damien Le Moal
2022-04-11 12:41 ` Serge Semin
2022-04-11 13:03 ` Damien Le Moal
2022-04-11 20:41 ` Serge Semin
2022-03-24 0:16 ` [PATCH 18/21] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
2022-03-24 0:16 ` [PATCH 19/21] ata: ahci-dwc: Add platform-specific quirks support Serge Semin
2022-03-24 0:16 ` [PATCH 20/21] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support Serge Semin
2022-03-24 0:16 ` [PATCH 21/21] MAINTAINERS: Add maintainers for DWC AHCI SATA driver Serge Semin
2022-03-24 2:17 ` Damien Le Moal
2022-04-11 12:16 ` Serge Semin
2022-03-28 20:06 ` [PATCH 00/21] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Damien Le Moal
2022-03-29 8:30 ` Damien Le Moal
2022-04-06 19:54 ` Serge Semin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=603eb020-3f43-c193-b3f6-8ff697f845c8@opensource.wdc.com \
--to=damien.lemoal@opensource.wdc.com \
--cc=Alexey.Malahov@baikalelectronics.ru \
--cc=Pavel.Parkhomenko@baikalelectronics.ru \
--cc=Sergey.Semin@baikalelectronics.ru \
--cc=axboe@kernel.dk \
--cc=devicetree@vger.kernel.org \
--cc=fancer.lancer@gmail.com \
--cc=hdegoede@redhat.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).