From nobody Fri Dec 19 07:49:28 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79DEAC761AF for ; Sun, 26 Mar 2023 05:29:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231922AbjCZF34 (ORCPT ); Sun, 26 Mar 2023 01:29:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231330AbjCZF3y (ORCPT ); Sun, 26 Mar 2023 01:29:54 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECB831FD6; Sat, 25 Mar 2023 22:29:31 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id e15-20020a17090ac20f00b0023d1b009f52so8906740pjt.2; Sat, 25 Mar 2023 22:29:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808571; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gQdxggrvOBdOzYAM+XEY+ITiNdb5smrybeGz1srgktI=; b=MTnFNwgSpPuTbk8QPRmyE9hcMzYwaOud2n9pG094UAGP+9OsANjagntB3tXtMxueBg 0NC9O61HUPj8LWsvNK1c6vW0moqKoER3Jk6EdGEQmXSVQ/onEeEYiDGX6WzFr4WaFIXG YQRf+JGvU2w+FJ+3cI82a4KOqCrbf5HDB6bEJU4MPdFDSvAsJ306f2pq1JGqffxa8WnL vZ/AL1QxdQrxsp63/020+E64v42ACUuF5GxAFh1kwXkBnMrpiJX74Lp+6CUcPTnAAFFL O3Ttj7NzFADrkyeHPJmLdffytF4zRIMFJ/klcGmmNL0co3FAYkg3Ud5YO06J4WhwC2D2 3+5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808571; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gQdxggrvOBdOzYAM+XEY+ITiNdb5smrybeGz1srgktI=; b=azc4syzH5SvSfzl7csv6M6IZ/5pbxJSvL7P6AYbM09+BTEbgYiVV00M6wbHEE9gIfg G38M6mxkhvqcJZG9pZ/i1oIfnsyx35eK0cEY06jUCfY2MXzAri1UwTjIHU8oEBwnIzDn Yu8CPUm5/S7r2c0/UuwIq0wsviWh3mWMEoeeXUNaFgpbWBs8fQC1SlMfd2tLMnx8okmc np3hbygUFz0S4oizDLOjMki+jp8KIkWkA6HGqhfM1/AsU3tdun9tdXzBOAxJyt+Yw5XY lUH//xwQwcuuun8UJNgNg1D50S/EKuQaTTxvSIZwmf336por2C+NAKPYwaLtapAjiXO4 wmNg== X-Gm-Message-State: AO0yUKVNaN8htkwiOa22Fc+o6uMh43BDnNWmfzfvacPslkUWUq7ZNNhy UOlejmJDJrqxe33OehfKYSbiZo66WKwtlx8kBlM= X-Google-Smtp-Source: AK7set8kcgeI7p6SPOohnsf8UIArLriGRQVOn9rrmM+kikHPHoj/ZS+TZaYXKOcBL8IB9+0jUU6WeQ== X-Received: by 2002:a05:6a20:92a0:b0:d9:f41c:33b0 with SMTP id q32-20020a056a2092a000b000d9f41c33b0mr7592878pzg.36.1679808571032; Sat, 25 Mar 2023 22:29:31 -0700 (PDT) Received: from d.home.yangfl.dn42 ([104.28.213.201]) by smtp.gmail.com with ESMTPSA id b14-20020a63eb4e000000b004fb5f4bf585sm15966915pgk.78.2023.03.25.22.29.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:29:30 -0700 (PDT) From: David Yang To: linux-clk@vger.kernel.org Cc: David Yang , Michael Turquette , Stephen Boyd , linux-kernel@vger.kernel.org, Conor Dooley , Nick Alcock Subject: [PATCH 4/4] clk: hisilicon: Migrate devm APIs Date: Sun, 26 Mar 2023 13:27:50 +0800 Message-Id: <20230326052757.297551-5-mmyangfl@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230326052757.297551-1-mmyangfl@gmail.com> References: <20230326052757.297551-1-mmyangfl@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Migrates devm APIs for HiSilicon clock drivers. Signed-off-by: David Yang --- drivers/clk/hisilicon/clk-hi3559a.c | 29 +- drivers/clk/hisilicon/clk-hi3620.c | 28 +- drivers/clk/hisilicon/clk-hi6220-stub.c | 9 +- drivers/clk/hisilicon/clk-hi6220.c | 13 +- drivers/clk/hisilicon/clk-hisi-phase.c | 13 +- drivers/clk/hisilicon/clk-hix5hd2.c | 12 +- drivers/clk/hisilicon/clk.c | 411 +++++++--------------- drivers/clk/hisilicon/clk.h | 97 ++--- drivers/clk/hisilicon/clkdivider-hi6220.c | 24 +- drivers/clk/hisilicon/clkgate-separated.c | 26 +- 10 files changed, 262 insertions(+), 400 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/cl= k-hi3559a.c index d641b2a759dd..926a7c211978 100644 --- a/drivers/clk/hisilicon/clk-hi3559a.c +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -457,17 +457,16 @@ hisi_clk_register_pll(struct device *dev, const void = *clocks, { const struct hi3559av100_pll_clock *clks =3D clocks; void __iomem *base =3D data->base; - struct hi3559av100_clk_pll *p_clk =3D NULL; - struct clk *clk =3D NULL; + struct hi3559av100_clk_pll *p_clk; struct clk_init_data init; int i; - - p_clk =3D devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL); - - if (!p_clk) - return -ENOMEM; + int ret; =20 for (i =3D 0; i < nums; i++) { + p_clk =3D devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL); + if (!p_clk) + return -ENOMEM; + init.name =3D clks[i].name; init.flags =3D 0; init.parent_names =3D @@ -490,16 +489,14 @@ hisi_clk_register_pll(struct device *dev, const void = *clocks, p_clk->refdiv_width =3D clks[i].refdiv_width; p_clk->hw.init =3D &init; =20 - clk =3D clk_register(NULL, &p_clk->hw); - if (IS_ERR(clk)) { - devm_kfree(dev, p_clk); + ret =3D devm_clk_hw_register(dev, &p_clk->hw); + if (ret) { dev_err(dev, "%s: failed to register clock %s\n", - __func__, clks[i].name); - return PTR_ERR(clk); + __func__, clks[i].name); + return ret; } =20 - data->clk_data.clks[clks[i].id] =3D clk; - p_clk++; + data->clk_data->hws[clks[i].id] =3D &p_clk->hw; } =20 return 0; @@ -628,7 +625,7 @@ static int hi3559av100_shub_default_clk_set(struct devi= ce *dev, struct hisi_cloc void __iomem *crg_base; unsigned int val; =20 - crg_base =3D ioremap(CRG_BASE_ADDR, SZ_4K); + crg_base =3D devm_ioremap(dev, CRG_BASE_ADDR, SZ_4K); =20 /* SSP: 192M/2 */ val =3D readl_relaxed(crg_base + 0x20); @@ -640,7 +637,7 @@ static int hi3559av100_shub_default_clk_set(struct devi= ce *dev, struct hisi_cloc val |=3D (0x1 << 28); writel_relaxed(val, crg_base + 0x1C); =20 - iounmap(crg_base); + devm_iounmap(dev, crg_base); crg_base =3D NULL; =20 return 0; diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk= -hi3620.c index 1eacf77b0d8c..6a6c482c87c6 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -11,12 +11,10 @@ =20 #include #include +#include #include #include -#include -#include #include -#include =20 #include =20 @@ -399,15 +397,15 @@ static const struct clk_ops clk_mmc_ops =3D { .recalc_rate =3D mmc_clk_recalc_rate, }; =20 -static struct clk * +static struct clk_hw * clk_register_hisi_mmc(struct device *dev, const struct hisi_mmc_clock *mmc= _clk, void __iomem *base) { struct clk_mmc *mclk; - struct clk *clk; struct clk_init_data init; + int ret; =20 - mclk =3D kzalloc(sizeof(*mclk), GFP_KERNEL); + mclk =3D devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL); if (!mclk) return ERR_PTR(-ENOMEM); =20 @@ -431,27 +429,31 @@ clk_register_hisi_mmc(struct device *dev, const struc= t hisi_mmc_clock *mmc_clk, mclk->sam_off =3D mmc_clk->sam_off; mclk->sam_bits =3D mmc_clk->sam_bits; =20 - clk =3D clk_register(NULL, &mclk->hw); - if (WARN_ON(IS_ERR(clk))) - kfree(mclk); - return clk; + ret =3D devm_clk_hw_register(dev, &mclk->hw); + if (ret) { + dev_err(dev, "%s: failed to register clock %s\n", + __func__, clks[i].name); + return ret; + } + + return &mclk->hw; } =20 static int hisi_register_clk_mmc(struct device *dev, const void *clocks, int nums, struct hisi_clock_data *data) { const struct hisi_mmc_clock *clks =3D clocks; - struct clk *clk; int i; =20 for (i =3D 0; i < nums; i++) { - clk =3D clk_register_hisi_mmc(dev, &clks[i], data->base); + struct clk_hw *clk =3D clk_register_hisi_mmc(dev, &clks[i], data->base); + if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); return PTR_ERR(clk); } - data->clk_data.clks[clks[i].id] =3D clk; + data->clk_data->hws[clks[i].id] =3D clk; } =20 return 0; diff --git a/drivers/clk/hisilicon/clk-hi6220-stub.c b/drivers/clk/hisilico= n/clk-hi6220-stub.c index 4fdee4424d82..dd996a43958e 100644 --- a/drivers/clk/hisilicon/clk-hi6220-stub.c +++ b/drivers/clk/hisilicon/clk-hi6220-stub.c @@ -195,7 +195,6 @@ static int hi6220_stub_clk_probe(struct platform_device= *pdev) struct device *dev =3D &pdev->dev; struct clk_init_data init; struct hi6220_stub_clk *stub_clk; - struct clk *clk; struct device_node *np =3D pdev->dev.of_node; int ret; =20 @@ -233,11 +232,11 @@ static int hi6220_stub_clk_probe(struct platform_devi= ce *pdev) init.num_parents =3D 0; init.flags =3D 0; =20 - clk =3D devm_clk_register(dev, &stub_clk->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret =3D devm_clk_hw_register(dev, &stub_clk->hw); + if (ret) + return ret; =20 - ret =3D of_clk_add_provider(np, of_clk_src_simple_get, clk); + ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &stub_clk-= >hw); if (ret) { dev_err(dev, "failed to register OF clock provider\n"); return ret; diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk= -hi6220.c index cdc17f82ce2d..d37a3633f8ae 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -16,6 +16,13 @@ =20 #include "clk.h" =20 +static int +hi6220_clk_register_divider_stub(struct device *dev, const void *clks, + int num, struct hisi_clock_data *data) +{ + return hi6220_clk_register_divider(dev, clks, num, data); +} + /* clocks in AO (always on) controller */ static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] =3D { { HI6220_REF32K, "ref32k", NULL, 0, 32764, }, @@ -176,7 +183,7 @@ static const struct hisi_clocks hi6220_sys_clks =3D { .gate_sep_clks_num =3D ARRAY_SIZE(hi6220_separated_gate_clks_sys), .customized_clks =3D hi6220_div_clks_sys, .customized_clks_num =3D ARRAY_SIZE(hi6220_div_clks_sys), - /* .clk_register_customized =3D hi6220_clk_register_divider, */ + .clk_register_customized =3D hi6220_clk_register_divider_stub, }; =20 /* clocks in media controller */ @@ -224,7 +231,7 @@ static const struct hisi_clocks hi6220_media_clks =3D { .gate_sep_clks_num =3D ARRAY_SIZE(hi6220_separated_gate_clks_media), .customized_clks =3D hi6220_div_clks_media, .customized_clks_num =3D ARRAY_SIZE(hi6220_div_clks_media), - /* .clk_register_customized =3D hi6220_clk_register_divider, */ + .clk_register_customized =3D hi6220_clk_register_divider_stub, }; =20 /* clocks in pmctrl */ @@ -247,7 +254,7 @@ static const struct hisi_clocks hi6220_power_clks =3D { .gate_clks_num =3D ARRAY_SIZE(hi6220_gate_clks_power), .customized_clks =3D hi6220_div_clks_power, .customized_clks_num =3D ARRAY_SIZE(hi6220_div_clks_power), - /* .clk_register_customized =3D hi6220_clk_register_divider, */ + .clk_register_customized =3D hi6220_clk_register_divider_stub, }; =20 /* clocks in acpu */ diff --git a/drivers/clk/hisilicon/clk-hisi-phase.c b/drivers/clk/hisilicon= /clk-hisi-phase.c index ba6afad66a2b..15a23dd6edb1 100644 --- a/drivers/clk/hisilicon/clk-hisi-phase.c +++ b/drivers/clk/hisilicon/clk-hisi-phase.c @@ -5,11 +5,11 @@ * Simple HiSilicon phase clock implementation. */ =20 +#include #include #include #include #include -#include =20 #include "clk.h" =20 @@ -90,12 +90,13 @@ static const struct clk_ops clk_phase_ops =3D { .set_phase =3D hisi_clk_set_phase, }; =20 -struct clk *clk_register_hisi_phase(struct device *dev, +struct clk_hw *devm_clk_hw_register_hisi_phase(struct device *dev, const struct hisi_phase_clock *clks, void __iomem *base, spinlock_t *lock) { struct clk_hisi_phase *phase; struct clk_init_data init; + int ret; =20 phase =3D devm_kzalloc(dev, sizeof(struct clk_hisi_phase), GFP_KERNEL); if (!phase) @@ -116,6 +117,10 @@ struct clk *clk_register_hisi_phase(struct device *dev, phase->phase_num =3D clks->phase_num; phase->hw.init =3D &init; =20 - return devm_clk_register(dev, &phase->hw); + ret =3D devm_clk_hw_register(dev, &phase->hw); + if (ret) + return ERR_PTR(ret); + + return &phase->hw; } -EXPORT_SYMBOL_GPL(clk_register_hisi_phase); +EXPORT_SYMBOL_GPL(devm_clk_hw_register_hisi_phase); diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/cl= k-hix5hd2.c index f37a17649d26..d838fbae39fd 100644 --- a/drivers/clk/hisilicon/clk-hix5hd2.c +++ b/drivers/clk/hisilicon/clk-hix5hd2.c @@ -6,7 +6,7 @@ =20 #include =20 -#include +#include #include #include #include @@ -260,13 +260,14 @@ hix5hd2_clk_register_complex(struct device *dev, cons= t void *clocks, int nums, const struct hix5hd2_complex_clock *clks =3D clocks; void __iomem *base =3D data->base; int i; + int ret; =20 for (i =3D 0; i < nums; i++) { struct hix5hd2_clk_complex *p_clk; struct clk *clk; struct clk_init_data init; =20 - p_clk =3D kzalloc(sizeof(*p_clk), GFP_KERNEL); + p_clk =3D devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL); if (!p_clk) return -ENOMEM; =20 @@ -289,12 +290,11 @@ hix5hd2_clk_register_complex(struct device *dev, cons= t void *clocks, int nums, p_clk->phy_rst_mask =3D clks[i].phy_rst_mask; p_clk->hw.init =3D &init; =20 - clk =3D clk_register(NULL, &p_clk->hw); - if (IS_ERR(clk)) { - kfree(p_clk); + ret =3D devm_clk_hw_register(dev, &p_clk->hw); + if (ret) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - return PTR_ERR(p_clk); + return ret; } =20 data->clk_data.clks[clks[i].id] =3D clk; diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 96bbc09e7d45..9a5d530c772b 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -4,6 +4,7 @@ * * Copyright (c) 2012-2013 Hisilicon Limited. * Copyright (c) 2012-2013 Linaro Limited. + * Copyright (c) 2023 David Yang * * Author: Haojian Zhuang * Xin Li @@ -13,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -23,67 +26,44 @@ =20 static DEFINE_SPINLOCK(hisi_clk_lock); =20 -struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev, - int nr_clks) +struct hisi_clock_data *hisi_clk_init(struct device_node *np, int nr) { - struct hisi_clock_data *clk_data; - struct resource *res; - struct clk **clk_table; - - clk_data =3D devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return NULL; - - res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return NULL; - clk_data->base =3D devm_ioremap(&pdev->dev, - res->start, resource_size(res)); - if (!clk_data->base) - return NULL; - - clk_table =3D devm_kmalloc_array(&pdev->dev, nr_clks, - sizeof(*clk_table), - GFP_KERNEL); - if (!clk_table) - return NULL; - - clk_data->clk_data.clks =3D clk_table; - clk_data->clk_data.clk_num =3D nr_clks; - - return clk_data; -} -EXPORT_SYMBOL_GPL(hisi_clk_alloc); - -struct hisi_clock_data *hisi_clk_init(struct device_node *np, - int nr_clks) -{ - struct hisi_clock_data *clk_data; - struct clk **clk_table; void __iomem *base; + struct hisi_clock_data *data; + int ret; + int i; =20 base =3D of_iomap(np, 0); if (!base) { pr_err("%s: failed to map clock registers\n", __func__); - goto err; + return NULL; } =20 - clk_data =3D kzalloc(sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - goto err; + data =3D kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; =20 - clk_data->base =3D base; - clk_table =3D kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL); - if (!clk_table) + data->clk_data =3D kzalloc(sizeof(*data->clk_data) + nr * sizeof(data->cl= k_data->hws[0]), + GFP_KERNEL); + if (!data->clk_data) goto err_data; =20 - clk_data->clk_data.clks =3D clk_table; - clk_data->clk_data.clk_num =3D nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data); - return clk_data; + ret =3D of_clk_add_hw_provider(np, of_clk_hw_onecell_get, data->clk_data); + if (ret) + goto err_clk; + + data->base =3D base; + data->clks =3D NULL; + data->clk_data->num =3D nr; + for (i =3D 0; i < nr; i++) + data->clk_data->hws[i] =3D ERR_PTR(-EPROBE_DEFER); + + return data; + +err_clk: + kfree(data->clk_data); err_data: - kfree(clk_data); -err: + kfree(data); return NULL; } EXPORT_SYMBOL_GPL(hisi_clk_init); @@ -92,312 +72,171 @@ void hisi_clk_free(struct device_node *np, struct his= i_clock_data *data) { if (data->clks) { if (data->clks->fixed_rate_clks_num) - hisi_clk_unregister_fixed_rate(data->clks->fixed_rate_clks, - data->clks->fixed_rate_clks_num, - data); + hisi_clk_unregister_fixed_rate(data); if (data->clks->fixed_factor_clks_num) - hisi_clk_unregister_fixed_factor(data->clks->fixed_factor_clks, - data->clks->fixed_factor_clks_num, - data); + hisi_clk_unregister_fixed_factor(data); } =20 of_clk_del_provider(np); - kfree(data->clk_data.clks); + kfree(data->clk_data); kfree(data); } EXPORT_SYMBOL_GPL(hisi_clk_free); =20 int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, - int nums, struct hisi_clock_data *data) + int num, struct hisi_clock_data *data) { - struct clk *clk; + struct clk_hw *clk; int i; =20 - for (i =3D 0; i < nums; i++) { - clk =3D clk_register_fixed_rate(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, - clks[i].fixed_rate); + for (i =3D 0; i < num; i++) { + const struct hisi_fixed_rate_clock *p_clk =3D &clks[i]; + + clk =3D clk_hw_register_fixed_rate(NULL, p_clk->name, p_clk->parent_name, + p_clk->flags, p_clk->fixed_rate); + if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); + __func__, p_clk->name); goto err; } - data->clk_data.clks[clks[i].id] =3D clk; + + data->clk_data->hws[p_clk->id] =3D clk; } =20 return 0; =20 err: while (i--) - clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]); - + clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]); return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate); =20 int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *c= lks, - int nums, - struct hisi_clock_data *data) + int num, struct hisi_clock_data *data) { - struct clk *clk; + struct clk_hw *clk; int i; =20 - for (i =3D 0; i < nums; i++) { - clk =3D clk_register_fixed_factor(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, clks[i].mult, - clks[i].div); - if (IS_ERR(clk)) { - pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); - goto err; - } - data->clk_data.clks[clks[i].id] =3D clk; - } - - return 0; + for (i =3D 0; i < num; i++) { + const struct hisi_fixed_factor_clock *p_clk =3D &clks[i]; =20 -err: - while (i--) - clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]); - - return PTR_ERR(clk); -} -EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor); + clk =3D clk_hw_register_fixed_factor(NULL, p_clk->name, p_clk->parent_na= me, + p_clk->flags, p_clk->mult, p_clk->div); =20 -int hisi_clk_register_mux(const struct hisi_mux_clock *clks, - int nums, struct hisi_clock_data *data) -{ - struct clk *clk; - void __iomem *base =3D data->base; - int i; - - for (i =3D 0; i < nums; i++) { - u32 mask =3D BIT(clks[i].width) - 1; - - clk =3D clk_register_mux_table(NULL, clks[i].name, - clks[i].parent_names, - clks[i].num_parents, clks[i].flags, - base + clks[i].offset, clks[i].shift, - mask, clks[i].mux_flags, - clks[i].table, &hisi_clk_lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); + __func__, p_clk->name); goto err; } =20 - if (clks[i].alias) - clk_register_clkdev(clk, clks[i].alias, NULL); - - data->clk_data.clks[clks[i].id] =3D clk; + data->clk_data->hws[p_clk->id] =3D clk; } =20 return 0; =20 err: while (i--) - clk_unregister_mux(data->clk_data.clks[clks[i].id]); - + clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]); return PTR_ERR(clk); } -EXPORT_SYMBOL_GPL(hisi_clk_register_mux); +EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor); + +#define hisi_clk_register_fn(fn, type, stmt) \ +int fn(struct device *dev, const struct type *clks, \ + int num, struct hisi_clock_data *data) \ +{ \ + void __iomem *base =3D data->base; \ + int i; \ +\ + for (i =3D 0; i < num; i++) { \ + const struct type *p_clk =3D &clks[i]; \ + struct clk_hw *clk =3D stmt; \ +\ + if (IS_ERR(clk)) { \ + pr_err("%s: failed to register clock %s\n", \ + __func__, p_clk->name); \ + return PTR_ERR(clk); \ + } \ +\ + if (p_clk->alias) \ + clk_hw_register_clkdev(clk, p_clk->alias, NULL); \ +\ + data->clk_data->hws[p_clk->id] =3D clk; \ + } \ +\ + return 0; \ +} \ +EXPORT_SYMBOL_GPL(fn); + +hisi_clk_register_fn(hisi_clk_register_mux, hisi_mux_clock, + __devm_clk_hw_register_mux(dev, NULL, p_clk->name, + p_clk->num_parents, p_clk->parent_names, NULL, NULL, + p_clk->flags, base + p_clk->offset, p_clk->shift, BIT(p_clk->width) - 1, + p_clk->mux_flags, p_clk->table, &hisi_clk_lock)) =20 int hisi_clk_register_phase(struct device *dev, const struct hisi_phase_clock *clks, - int nums, struct hisi_clock_data *data) + int num, struct hisi_clock_data *data) { void __iomem *base =3D data->base; - struct clk *clk; int i; =20 - for (i =3D 0; i < nums; i++) { - clk =3D clk_register_hisi_phase(dev, &clks[i], base, - &hisi_clk_lock); + for (i =3D 0; i < num; i++) { + const struct hisi_phase_clock *p_clk =3D &clks[i]; + struct clk_hw *clk =3D devm_clk_hw_register_hisi_phase(dev, + p_clk, base, &hisi_clk_lock); + if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, - clks[i].name); + p_clk->name); return PTR_ERR(clk); } =20 - data->clk_data.clks[clks[i].id] =3D clk; + data->clk_data->hws[p_clk->id] =3D clk; } =20 return 0; } EXPORT_SYMBOL_GPL(hisi_clk_register_phase); =20 -int hisi_clk_register_divider(const struct hisi_divider_clock *clks, - int nums, struct hisi_clock_data *data) -{ - struct clk *clk; - void __iomem *base =3D data->base; - int i; - - for (i =3D 0; i < nums; i++) { - clk =3D clk_register_divider_table(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, - base + clks[i].offset, - clks[i].shift, clks[i].width, - clks[i].div_flags, - clks[i].table, - &hisi_clk_lock); - if (IS_ERR(clk)) { - pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); - goto err; - } - - if (clks[i].alias) - clk_register_clkdev(clk, clks[i].alias, NULL); - - data->clk_data.clks[clks[i].id] =3D clk; - } - - return 0; - -err: - while (i--) - clk_unregister_divider(data->clk_data.clks[clks[i].id]); - - return PTR_ERR(clk); -} -EXPORT_SYMBOL_GPL(hisi_clk_register_divider); - -int hisi_clk_register_gate(const struct hisi_gate_clock *clks, - int nums, struct hisi_clock_data *data) -{ - struct clk *clk; - void __iomem *base =3D data->base; - int i; - - for (i =3D 0; i < nums; i++) { - clk =3D clk_register_gate(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, - base + clks[i].offset, - clks[i].bit_idx, - clks[i].gate_flags, - &hisi_clk_lock); - if (IS_ERR(clk)) { - pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); - goto err; - } - - if (clks[i].alias) - clk_register_clkdev(clk, clks[i].alias, NULL); - - data->clk_data.clks[clks[i].id] =3D clk; - } - - return 0; - -err: - while (i--) - clk_unregister_gate(data->clk_data.clks[clks[i].id]); - - return PTR_ERR(clk); -} -EXPORT_SYMBOL_GPL(hisi_clk_register_gate); - -void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks, - int nums, struct hisi_clock_data *data) -{ - struct clk *clk; - void __iomem *base =3D data->base; - int i; - - for (i =3D 0; i < nums; i++) { - clk =3D hisi_register_clkgate_sep(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, - base + clks[i].offset, - clks[i].bit_idx, - clks[i].gate_flags, - &hisi_clk_lock); - if (IS_ERR(clk)) { - pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); - continue; - } - - if (clks[i].alias) - clk_register_clkdev(clk, clks[i].alias, NULL); - - data->clk_data.clks[clks[i].id] =3D clk; - } -} -EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep); - -void __init hi6220_clk_register_divider(const struct hi6220_divider_clock = *clks, - int nums, struct hisi_clock_data *data) -{ - struct clk *clk; - void __iomem *base =3D data->base; - int i; - - for (i =3D 0; i < nums; i++) { - clk =3D hi6220_register_clkdiv(NULL, clks[i].name, - clks[i].parent_name, - clks[i].flags, - base + clks[i].offset, - clks[i].shift, - clks[i].width, - clks[i].mask_bit, - &hisi_clk_lock); - if (IS_ERR(clk)) { - pr_err("%s: failed to register clock %s\n", - __func__, clks[i].name); - continue; - } - - if (clks[i].alias) - clk_register_clkdev(clk, clks[i].alias, NULL); - - data->clk_data.clks[clks[i].id] =3D clk; - } -} +hisi_clk_register_fn(hisi_clk_register_divider, hisi_divider_clock, + devm_clk_hw_register_divider_table(dev, p_clk->name, p_clk->parent_name, + p_clk->flags, base + p_clk->offset, p_clk->shift, p_clk->width, + p_clk->div_flags, p_clk->table, &hisi_clk_lock)) +hisi_clk_register_fn(hisi_clk_register_gate, hisi_gate_clock, + devm_clk_hw_register_gate(dev, p_clk->name, p_clk->parent_name, + p_clk->flags, base + p_clk->offset, p_clk->bit_idx, + p_clk->gate_flags, &hisi_clk_lock)) +hisi_clk_register_fn(hisi_clk_register_gate_sep, hisi_gate_clock, + devm_clk_hw_register_hisi_gate_sep(dev, p_clk->name, p_clk->parent_name, + p_clk->flags, base + p_clk->offset, p_clk->bit_idx, + p_clk->gate_flags, &hisi_clk_lock)) +hisi_clk_register_fn(hi6220_clk_register_divider, hi6220_divider_clock, + devm_clk_hw_register_hi6220_divider(dev, p_clk->name, p_clk->parent_name, + p_clk->flags, base + p_clk->offset, p_clk->shift, p_clk->width, + p_clk->mask_bit, &hisi_clk_lock)) =20 int hisi_clk_register(struct device *dev, const struct hisi_clocks *clks, struct hisi_clock_data *data) { int ret; =20 - if (clks->mux_clks_num) { - ret =3D hisi_clk_register_mux(clks->mux_clks, - clks->mux_clks_num, data); - if (ret) - return ret; - } - - if (clks->phase_clks_num) { - ret =3D hisi_clk_register_phase(dev, clks->phase_clks, - clks->phase_clks_num, data); - if (ret) - return ret; - } - - if (clks->divider_clks_num) { - ret =3D hisi_clk_register_divider(clks->divider_clks, - clks->divider_clks_num, data); - if (ret) - return ret; - } - - if (clks->gate_clks_num) { - ret =3D hisi_clk_register_gate(clks->gate_clks, - clks->gate_clks_num, data); - if (ret) - return ret; - } - - if (clks->gate_sep_clks_num) { - hisi_clk_register_gate_sep(clks->gate_sep_clks, - clks->gate_sep_clks_num, data); - } +#define do_hisi_clk_register(type) do { \ + if (clks->type##_clks_num) { \ + ret =3D hisi_clk_register_##type(dev, clks->type##_clks, \ + clks->type##_clks_num, data); \ + if (ret) \ + return ret; \ + } \ +} while (0) + + do_hisi_clk_register(mux); + do_hisi_clk_register(phase); + do_hisi_clk_register(divider); + do_hisi_clk_register(gate); + do_hisi_clk_register(gate_sep); =20 if (clks->clk_register_customized && clks->customized_clks_num) { ret =3D clks->clk_register_customized(dev, clks->customized_clks, diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index def94498e14d..44fafab996bf 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -4,6 +4,7 @@ * * Copyright (c) 2012-2013 Hisilicon Limited. * Copyright (c) 2012-2013 Linaro Limited. + * Copyright (c) 2023 David Yang * * Author: Haojian Zhuang * Xin Li @@ -19,9 +20,19 @@ struct platform_device; struct hisi_clocks; =20 +/* + * (Virtual) fixed clocks, often depended by crucial peripherals, require + * early initialization before device probing, thus cannot use devm APIs. + * Otherwise, kernel will defer those peripherals, causing boot failure. + * + * fixed_rate and fixed_factor clocks are driver-managed. They are freed by + * `hisi_clk_free` altogether. + * + * Other clocks are devm-managed. + */ struct hisi_clock_data { - struct clk_onecell_data clk_data; - void __iomem *base; + struct clk_hw_onecell_data *clk_data; + void __iomem *base; const struct hisi_clocks *clks; }; =20 @@ -137,37 +148,46 @@ struct hisi_clocks { int num, struct hisi_clock_data *data); }; =20 -struct clk *hisi_register_clkgate_sep(struct device *, const char *, - const char *, unsigned long, - void __iomem *, u8, - u8, spinlock_t *); -struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, void __iomem *reg, - u8 shift, u8 width, u32 mask_bit, spinlock_t *lock); - -struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int); -struct hisi_clock_data *hisi_clk_init(struct device_node *, int); -void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data); -int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *, - int, struct hisi_clock_data *); -int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *, - int, struct hisi_clock_data *); -int hisi_clk_register_mux(const struct hisi_mux_clock *, int, - struct hisi_clock_data *); -struct clk *clk_register_hisi_phase(struct device *dev, - const struct hisi_phase_clock *clks, +struct clk_hw * +devm_clk_hw_register_hisi_phase(struct device *dev, const struct hisi_phas= e_clock *clks, void __iomem *base, spinlock_t *lock); +struct clk_hw * +devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); +struct clk_hw * +devm_clk_hw_register_hi6220_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, + u8 width, u32 mask_bit, spinlock_t *lock); + +struct hisi_clock_data *hisi_clk_init(struct device_node *np, int nr); +void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data); + +int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, + int num, struct hisi_clock_data *data); +int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *c= lks, + int num, struct hisi_clock_data *data); + +int hisi_clk_register_mux(struct device *dev, + const struct hisi_mux_clock *clks, int num, + struct hisi_clock_data *data); int hisi_clk_register_phase(struct device *dev, - const struct hisi_phase_clock *clks, - int nums, struct hisi_clock_data *data); -int hisi_clk_register_divider(const struct hisi_divider_clock *, - int, struct hisi_clock_data *); -int hisi_clk_register_gate(const struct hisi_gate_clock *, - int, struct hisi_clock_data *); -void hisi_clk_register_gate_sep(const struct hisi_gate_clock *, - int, struct hisi_clock_data *); -void hi6220_clk_register_divider(const struct hi6220_divider_clock *, - int, struct hisi_clock_data *); + const struct hisi_phase_clock *clks, + int num, struct hisi_clock_data *data); +int hisi_clk_register_divider(struct device *dev, + const struct hisi_divider_clock *clks, + int num, struct hisi_clock_data *data); +int hisi_clk_register_gate(struct device *dev, + const struct hisi_gate_clock *clks, + int num, struct hisi_clock_data *data); +int hisi_clk_register_gate_sep(struct device *dev, + const struct hisi_gate_clock *clks, + int num, struct hisi_clock_data *data); +int hi6220_clk_register_divider(struct device *dev, + const struct hi6220_divider_clock *clks, + int num, struct hisi_clock_data *data); =20 int hisi_clk_register(struct device *dev, const struct hisi_clocks *clks, struct hisi_clock_data *data); @@ -180,22 +200,17 @@ int hisi_clk_remove(struct platform_device *pdev); =20 #define hisi_clk_unregister_fn(type) \ static inline \ -void hisi_clk_unregister_##type(const struct hisi_##type##_clock *clks, \ - int nums, struct hisi_clock_data *data) \ +void hisi_clk_unregister_##type(struct hisi_clock_data *data) \ { \ - struct clk **clocks =3D data->clk_data.clks; \ int i; \ - for (i =3D 0; i < nums; i++) { \ - int id =3D clks[i].id; \ - if (clocks[id]) \ - clk_unregister_##type(clocks[id]); \ + for (i =3D 0; i < data->clks->type##_clks_num; i++) { \ + struct clk_hw *clk =3D data->clk_data->hws[data->clks->type##_clks[i].id= ]; \ + if (clk && !IS_ERR(clk)) \ + clk_hw_unregister_##type(clk); \ } \ } =20 hisi_clk_unregister_fn(fixed_rate) hisi_clk_unregister_fn(fixed_factor) -hisi_clk_unregister_fn(mux) -hisi_clk_unregister_fn(divider) -hisi_clk_unregister_fn(gate) =20 #endif /* __HISI_CLK_H */ diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisili= con/clkdivider-hi6220.c index 5348bafe694f..3c03b3e5b841 100644 --- a/drivers/clk/hisilicon/clkdivider-hi6220.c +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c @@ -9,7 +9,7 @@ =20 #include #include -#include +#include #include #include #include @@ -97,19 +97,19 @@ static const struct clk_ops hi6220_clkdiv_ops =3D { .set_rate =3D hi6220_clkdiv_set_rate, }; =20 -struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, +struct clk_hw *devm_clk_hw_register_hi6220_divider(struct device *dev, con= st char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u32 mask_bit, spinlock_t *lock) { struct hi6220_clk_divider *div; - struct clk *clk; struct clk_init_data init; struct clk_div_table *table; u32 max_div, min_div; int i; + int ret; =20 /* allocate the divider */ - div =3D kzalloc(sizeof(*div), GFP_KERNEL); + div =3D devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); if (!div) return ERR_PTR(-ENOMEM); =20 @@ -117,11 +117,9 @@ struct clk *hi6220_register_clkdiv(struct device *dev,= const char *name, max_div =3D div_mask(width) + 1; min_div =3D 1; =20 - table =3D kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL); - if (!table) { - kfree(div); + table =3D devm_kcalloc(dev, max_div + 1, sizeof(*table), GFP_KERNEL); + if (!table) return ERR_PTR(-ENOMEM); - } =20 for (i =3D 0; i < max_div; i++) { table[i].div =3D min_div + i; @@ -144,11 +142,9 @@ struct clk *hi6220_register_clkdiv(struct device *dev,= const char *name, div->table =3D table; =20 /* register the clock */ - clk =3D clk_register(dev, &div->hw); - if (IS_ERR(clk)) { - kfree(table); - kfree(div); - } + ret =3D devm_clk_hw_register(dev, &div->hw); + if (ret) + return ERR_PTR(ret); =20 - return clk; + return &div->hw; } diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisili= con/clkgate-separated.c index 90d858522967..dc64a8a0ab58 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -11,8 +11,8 @@ =20 #include #include +#include #include -#include =20 #include "clk.h" =20 @@ -80,17 +80,18 @@ static const struct clk_ops clkgate_separated_ops =3D { .is_enabled =3D clkgate_separated_is_enabled, }; =20 -struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name, - const char *parent_name, - unsigned long flags, - void __iomem *reg, u8 bit_idx, - u8 clk_gate_flags, spinlock_t *lock) +struct clk_hw * +devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) { struct clkgate_separated *sclk; - struct clk *clk; struct clk_init_data init; + int ret; =20 - sclk =3D kzalloc(sizeof(*sclk), GFP_KERNEL); + sclk =3D devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL); if (!sclk) return ERR_PTR(-ENOMEM); =20 @@ -106,8 +107,9 @@ struct clk *hisi_register_clkgate_sep(struct device *de= v, const char *name, sclk->hw.init =3D &init; sclk->lock =3D lock; =20 - clk =3D clk_register(dev, &sclk->hw); - if (IS_ERR(clk)) - kfree(sclk); - return clk; + ret =3D devm_clk_hw_register(dev, &sclk->hw); + if (ret) + return ERR_PTR(ret); + + return &sclk->hw; } --=20 2.39.2