Message ID | 20230506-msm8226-ocmem-v1-3-3e24e2724f01@z3ntu.xyz |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp1479445vqo; Sun, 7 May 2023 02:36:04 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5Do+NS10jdarUtcpjT146KatapEsevnKwoueGcMLPFDL0SrNapz69xtOokSYyyYD3sJMlp X-Received: by 2002:a17:902:e881:b0:1a6:b140:9d2 with SMTP id w1-20020a170902e88100b001a6b14009d2mr9033131plg.61.1683452164230; Sun, 07 May 2023 02:36:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683452164; cv=none; d=google.com; s=arc-20160816; b=g4NzlwqCsTFnsXBppCYq1CstLAdgE2xNX0bjfdZEsbvw1PHdBLwn7EDRa/HjJinHwn xTZsMU+BXqY3IZ6FWQvJaCzMJvkEPvlnNc0ZUwGHOKkVcqO8a+ecgf1LavBWTQ+m6o64 YLetbLulKUjK+7hi7zoL5Qx75XkS24ZHSa0a8cWCFCT3/qH7Aljlw20fSKWcmstAF9Ig 1f7p0Cj0OCRU7l3eUW8tu+llJQ2ZxPrlDAzi7dX3/Xgm4897w7MwARRJnCUD2t6o1/ur nJGoxk1jeL3OF1VXJJ9RJqisxEJJFbGtOIgIEWPLvMFauGWorx8kpW09VZ2Hfec6QP4o WH7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=KVAyWXKQTm85eDbseDXBLyEoX3J6d4BTqtCFZPGPGPQ=; b=KrgV716U+ipIUgfWhtoPI07rLth7zc+nW5YYKwKm2AGeGwanDfHj6AzfTgJ3FtKQFk Bva+Km1tWIUkpOtbxvxMz+1FEeUUoo13pHX9qKhKh7V1H+rNHLkiJsi5tAZPArnlrRmV 4INyJT8At/Al3uYyfSHZrPC1PmYwALbEfsGR6PKZdJS9mjXPm5EUkNmK53Hi2JIehN1h dCVxBaAkEM5uLySyevebrADLwT5Kpww8IOey1QF4JKou6xKpOv3MiGfeNdgvHAYBUE1r pqhXaRVvezTwGXDXcMUq1UHKkAC2YPILfnP6iS5xnblS/Y0M/BnJPOeiQfJt4VwQRbbB ZmbA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@z3ntu.xyz header.s=z3ntu header.b=oFZt2cFi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=z3ntu.xyz Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r21-20020a170902be1500b0019e6b2ed4basi5326629pls.483.2023.05.07.02.35.49; Sun, 07 May 2023 02:36:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@z3ntu.xyz header.s=z3ntu header.b=oFZt2cFi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=z3ntu.xyz Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231615AbjEGJOd (ORCPT <rfc822;baris.duru.linux@gmail.com> + 99 others); Sun, 7 May 2023 05:14:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43010 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231519AbjEGJOB (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sun, 7 May 2023 05:14:01 -0400 Received: from mail.z3ntu.xyz (mail.z3ntu.xyz [128.199.32.197]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F263E18DC5; Sun, 7 May 2023 02:13:45 -0700 (PDT) Received: from [192.168.178.23] (unknown [62.108.10.64]) by mail.z3ntu.xyz (Postfix) with ESMTPSA id 2CF0FCED42; Sun, 7 May 2023 09:13:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=z3ntu.xyz; s=z3ntu; t=1683450782; bh=7KtnS7Z+etOjmKrOyowpeMfEieUCur9/xBWzDiV//qM=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=oFZt2cFig6qgSnBk2+zaN8QNc6lgs1R7D3YHe8UoE7TMByAcU+R6mtQD8T3iKl9ss ROapqefpVN4YZq2D+QuotC0hTyHCWcBQTdLAeOS18M1rVUdjTwMOKOjDR0dTlpftwu On0CQT0ZR/DNypgZ3ZUgri0DCa44YDdN/gFKKhtA= From: Luca Weiss <luca@z3ntu.xyz> Date: Sun, 07 May 2023 11:12:20 +0200 Subject: [PATCH 3/6] soc: qcom: ocmem: make iface clock optional MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230506-msm8226-ocmem-v1-3-3e24e2724f01@z3ntu.xyz> References: <20230506-msm8226-ocmem-v1-0-3e24e2724f01@z3ntu.xyz> In-Reply-To: <20230506-msm8226-ocmem-v1-0-3e24e2724f01@z3ntu.xyz> To: ~postmarketos/upstreaming@lists.sr.ht, phone-devel@vger.kernel.org, Andy Gross <agross@kernel.org>, Bjorn Andersson <andersson@kernel.org>, Konrad Dybcio <konrad.dybcio@linaro.org>, Rob Clark <robdclark@gmail.com>, Brian Masney <masneyb@onstation.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Conor Dooley <conor+dt@kernel.org> Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Luca Weiss <luca@z3ntu.xyz> X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3377; i=luca@z3ntu.xyz; h=from:subject:message-id; bh=7KtnS7Z+etOjmKrOyowpeMfEieUCur9/xBWzDiV//qM=; b=owEBbQKS/ZANAwAIAXLYQ7idTddWAcsmYgBkV2uZ0+L8JdjISj+5P1ZXupY/dHokPjna72Ot7 sNVXd2PtB2JAjMEAAEIAB0WIQQ5utIvCCzakboVj/py2EO4nU3XVgUCZFdrmQAKCRBy2EO4nU3X VgcREACUq7S1p9RsFUHU5Iny4N3ctDjH3jdSBvkmpF2wkDw/Xq2iSwNxXyodKttmnjcGSxqXoDy R9Qq8VwEg2Rg8uClBJbxdwHUI/T1KM9+fJdvP8AwgyX9i6kgeBhlsmiRLEqs72zBkCf75vCfA+L B1toXx12VTlXCjJXBI84THzbD5dUASoh+Mh+z/EJyCJDwGm+PnAUoWot+fcJ5ImY/USMAD8Rs47 kUNA6P1agnLQcHcqzC3+3jFr/9Y9TEO40cUT2imaYLV/jx5YZ0K79JmKXiW04SaTyOSBAjb8rwY KRi5mj3c+UAIHY4PTFCHSrGBDBbjeePguWYmQCFGRrL38EoJnEHNhoKlPRCGpb16cUo55kYiWck k3mcr7sUZDMmLyLS2tbH36zFRtlx96NLM/Ppr1e4SmYAMThEMysQUsPv/P7rOb+hlBK7Ur64bSV 4qfOxf/rvCxK/inU8ejBKXzntXSEo88e+b4cQSLrbNyUCQPEBuLq/EUzD8ycn8HT2+en4q+qtHr nh+TMDQrsh1LgKYNHSXCyNs1fn6Jr6vjlrRCAChzJPc2XJfVTNfOmFXUJctUusv1RHu9DvuYE4A nEjd0qBRRo627Z9q5B4bevrGGXfVj2Jk5SQCnR3m2O1JYHH/J230pBu2wLvrUWVPeUA6OGLQhSx eFSIRAGajsBSQ7A== X-Developer-Key: i=luca@z3ntu.xyz; a=openpgp; fpr=BD04DA24C971B8D587B2B8D7FAF69CF6CD2D02CD X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765227536440907888?= X-GMAIL-MSGID: =?utf-8?q?1765227536440907888?= |
Series |
Add MSM8226 OCMEM support plus some extra OCMEM driver fixes
|
|
Commit Message
Luca Weiss
May 7, 2023, 9:12 a.m. UTC
Some platforms such as msm8226 do not have an iface clk. Since clk_bulk
APIs don't offer to a way to treat some clocks as optional simply add
core_clk and iface_clk members to our drvdata.
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 18 deletions(-)
Comments
On 7.05.2023 11:12, Luca Weiss wrote: > Some platforms such as msm8226 do not have an iface clk. Since clk_bulk > APIs don't offer to a way to treat some clocks as optional simply add > core_clk and iface_clk members to our drvdata. > > Signed-off-by: Luca Weiss <luca@z3ntu.xyz> > --- I think I don't see anything wrong in here! Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org> Konrad > drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------ > 1 file changed, 24 insertions(+), 18 deletions(-) > > diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c > index a11a955a1327..6235065d3bc9 100644 > --- a/drivers/soc/qcom/ocmem.c > +++ b/drivers/soc/qcom/ocmem.c > @@ -54,6 +54,8 @@ struct ocmem { > const struct ocmem_config *config; > struct resource *memory; > void __iomem *mmio; > + struct clk *core_clk; > + struct clk *iface_clk; > unsigned int num_ports; > unsigned int num_macros; > bool interleaved; > @@ -91,16 +93,6 @@ struct ocmem { > #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, (val)) > #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, (val)) > > -#define OCMEM_CLK_CORE_IDX 0 > -static struct clk_bulk_data ocmem_clks[] = { > - { > - .id = "core", > - }, > - { > - .id = "iface", > - }, > -}; > - > static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) > { > writel(data, ocmem->mmio + reg); > @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) > ocmem->dev = dev; > ocmem->config = device_get_match_data(dev); > > - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); > - if (ret) > - return dev_err_probe(dev, ret, "Unable to get clocks\n"); > + ocmem->core_clk = devm_clk_get(dev, "core"); > + if (IS_ERR(ocmem->core_clk)) > + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), > + "Unable to get core clock\n"); > + > + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); > + if (IS_ERR(ocmem->iface_clk)) > + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), > + "Unable to get iface clock\n"); > > ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); > if (IS_ERR(ocmem->mmio)) > @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) > } > > /* The core clock is synchronous with graphics */ > - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); > + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); > + > + ret = clk_prepare_enable(ocmem->core_clk); > + if (ret) > + return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); > > - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + ret = clk_prepare_enable(ocmem->iface_clk); > if (ret) > - return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); > + return dev_err_probe(ocmem->dev, ret, "Failed to enable iface clock\n"); > > if (qcom_scm_restore_sec_cfg_available()) { > dev_dbg(dev, "configuring scm\n"); > @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct platform_device *pdev) > return 0; > > err_clk_disable: > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + clk_disable_unprepare(ocmem->core_clk); > + clk_disable_unprepare(ocmem->iface_clk); > return ret; > } > > static int ocmem_dev_remove(struct platform_device *pdev) > { > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + struct ocmem *ocmem = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(ocmem->core_clk); > + clk_disable_unprepare(ocmem->iface_clk); > > return 0; > } >
On 07/05/2023 12:12, Luca Weiss wrote: > Some platforms such as msm8226 do not have an iface clk. Since clk_bulk > APIs don't offer to a way to treat some clocks as optional simply add > core_clk and iface_clk members to our drvdata. What about using devm_clk_bulk_get_optional()? I think it would be simpler this way. > > Signed-off-by: Luca Weiss <luca@z3ntu.xyz> > --- > drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------ > 1 file changed, 24 insertions(+), 18 deletions(-) > > diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c > index a11a955a1327..6235065d3bc9 100644 > --- a/drivers/soc/qcom/ocmem.c > +++ b/drivers/soc/qcom/ocmem.c > @@ -54,6 +54,8 @@ struct ocmem { > const struct ocmem_config *config; > struct resource *memory; > void __iomem *mmio; > + struct clk *core_clk; > + struct clk *iface_clk; > unsigned int num_ports; > unsigned int num_macros; > bool interleaved; > @@ -91,16 +93,6 @@ struct ocmem { > #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, (val)) > #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, (val)) > > -#define OCMEM_CLK_CORE_IDX 0 > -static struct clk_bulk_data ocmem_clks[] = { > - { > - .id = "core", > - }, > - { > - .id = "iface", > - }, > -}; > - > static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) > { > writel(data, ocmem->mmio + reg); > @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) > ocmem->dev = dev; > ocmem->config = device_get_match_data(dev); > > - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); > - if (ret) > - return dev_err_probe(dev, ret, "Unable to get clocks\n"); > + ocmem->core_clk = devm_clk_get(dev, "core"); > + if (IS_ERR(ocmem->core_clk)) > + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), > + "Unable to get core clock\n"); > + > + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); > + if (IS_ERR(ocmem->iface_clk)) > + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), > + "Unable to get iface clock\n"); > > ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); > if (IS_ERR(ocmem->mmio)) > @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) > } > > /* The core clock is synchronous with graphics */ > - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); > + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); > + > + ret = clk_prepare_enable(ocmem->core_clk); > + if (ret) > + return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); > > - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + ret = clk_prepare_enable(ocmem->iface_clk); > if (ret) > - return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); > + return dev_err_probe(ocmem->dev, ret, "Failed to enable iface clock\n"); > > if (qcom_scm_restore_sec_cfg_available()) { > dev_dbg(dev, "configuring scm\n"); > @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct platform_device *pdev) > return 0; > > err_clk_disable: > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + clk_disable_unprepare(ocmem->core_clk); > + clk_disable_unprepare(ocmem->iface_clk); > return ret; > } > > static int ocmem_dev_remove(struct platform_device *pdev) > { > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > + struct ocmem *ocmem = platform_get_drvdata(pdev); > + > + clk_disable_unprepare(ocmem->core_clk); > + clk_disable_unprepare(ocmem->iface_clk); > > return 0; > } >
On Montag, 8. Mai 2023 13:34:23 CEST Dmitry Baryshkov wrote: > On 07/05/2023 12:12, Luca Weiss wrote: > > Some platforms such as msm8226 do not have an iface clk. Since clk_bulk > > APIs don't offer to a way to treat some clocks as optional simply add > > core_clk and iface_clk members to our drvdata. > > What about using devm_clk_bulk_get_optional()? I think it would be > simpler this way. Using that function both clocks would be optional which may or may not be a bad idea. Not sure how much binding yaml and/or driver should try and catch bad usages of the driver. But honestly the current usage of the bulk API seems a bit clunky, we have a static array of clocks that we use (not in struct ocmem for some reason) and then we refer to the core clock by index? Feels better to just have the two clock references in the device struct and then we're good. Let me know. Regards Luca > > > Signed-off-by: Luca Weiss <luca@z3ntu.xyz> > > --- > > > > drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------ > > 1 file changed, 24 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c > > index a11a955a1327..6235065d3bc9 100644 > > --- a/drivers/soc/qcom/ocmem.c > > +++ b/drivers/soc/qcom/ocmem.c > > @@ -54,6 +54,8 @@ struct ocmem { > > > > const struct ocmem_config *config; > > struct resource *memory; > > void __iomem *mmio; > > > > + struct clk *core_clk; > > + struct clk *iface_clk; > > > > unsigned int num_ports; > > unsigned int num_macros; > > bool interleaved; > > > > @@ -91,16 +93,6 @@ struct ocmem { > > > > #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, (val)) > > #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, (val)) > > > > -#define OCMEM_CLK_CORE_IDX 0 > > -static struct clk_bulk_data ocmem_clks[] = { > > - { > > - .id = "core", > > - }, > > - { > > - .id = "iface", > > - }, > > -}; > > - > > > > static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) > > { > > > > writel(data, ocmem->mmio + reg); > > > > @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device > > *pdev)> > > ocmem->dev = dev; > > ocmem->config = device_get_match_data(dev); > > > > - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); > > - if (ret) > > - return dev_err_probe(dev, ret, "Unable to get clocks\n"); > > + ocmem->core_clk = devm_clk_get(dev, "core"); > > + if (IS_ERR(ocmem->core_clk)) > > + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), > > + "Unable to get core clock\n"); > > + > > + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); > > + if (IS_ERR(ocmem->iface_clk)) > > + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), > > + "Unable to get iface clock\n"); > > > > ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); > > if (IS_ERR(ocmem->mmio)) > > > > @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct platform_device > > *pdev)> > > } > > > > /* The core clock is synchronous with graphics */ > > > > - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); > > + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); > > + > > + ret = clk_prepare_enable(ocmem->core_clk); > > + if (ret) > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); > > > > - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > + ret = clk_prepare_enable(ocmem->iface_clk); > > > > if (ret) > > > > - return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable iface > > clock\n"); > > > > if (qcom_scm_restore_sec_cfg_available()) { > > > > dev_dbg(dev, "configuring scm\n"); > > > > @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct platform_device > > *pdev)> > > return 0; > > > > err_clk_disable: > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > + clk_disable_unprepare(ocmem->core_clk); > > + clk_disable_unprepare(ocmem->iface_clk); > > > > return ret; > > > > } > > > > static int ocmem_dev_remove(struct platform_device *pdev) > > { > > > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > + struct ocmem *ocmem = platform_get_drvdata(pdev); > > + > > + clk_disable_unprepare(ocmem->core_clk); > > + clk_disable_unprepare(ocmem->iface_clk); > > > > return 0; > > > > }
On Tue, 9 May 2023 at 19:47, Luca Weiss <luca@z3ntu.xyz> wrote: > > On Montag, 8. Mai 2023 13:34:23 CEST Dmitry Baryshkov wrote: > > On 07/05/2023 12:12, Luca Weiss wrote: > > > Some platforms such as msm8226 do not have an iface clk. Since clk_bulk > > > APIs don't offer to a way to treat some clocks as optional simply add > > > core_clk and iface_clk members to our drvdata. > > > > What about using devm_clk_bulk_get_optional()? I think it would be > > simpler this way. > > Using that function both clocks would be optional which may or may not be a > bad idea. Not sure how much binding yaml and/or driver should try and catch > bad usages of the driver. The generic rule is that we should not validate the DT unless required (e.g. because of the possibility of legacy DT which used other bindings or contained less information). > But honestly the current usage of the bulk API seems a bit clunky, we have a > static array of clocks that we use (not in struct ocmem for some reason) and > then we refer to the core clock by index? Feels better to just have the two > clock references in the device struct and then we're good. > > Let me know. > > Regards > Luca > > > > > > Signed-off-by: Luca Weiss <luca@z3ntu.xyz> > > > --- > > > > > > drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------ > > > 1 file changed, 24 insertions(+), 18 deletions(-) > > > > > > diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c > > > index a11a955a1327..6235065d3bc9 100644 > > > --- a/drivers/soc/qcom/ocmem.c > > > +++ b/drivers/soc/qcom/ocmem.c > > > @@ -54,6 +54,8 @@ struct ocmem { > > > > > > const struct ocmem_config *config; > > > struct resource *memory; > > > void __iomem *mmio; > > > > > > + struct clk *core_clk; > > > + struct clk *iface_clk; > > > > > > unsigned int num_ports; > > > unsigned int num_macros; > > > bool interleaved; > > > > > > @@ -91,16 +93,6 @@ struct ocmem { > > > > > > #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, > (val)) > > > #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, > (val)) > > > > > > -#define OCMEM_CLK_CORE_IDX 0 > > > -static struct clk_bulk_data ocmem_clks[] = { > > > - { > > > - .id = "core", > > > - }, > > > - { > > > - .id = "iface", > > > - }, > > > -}; > > > - > > > > > > static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) > > > { > > > > > > writel(data, ocmem->mmio + reg); > > > > > > @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device > > > *pdev)> > > > ocmem->dev = dev; > > > ocmem->config = device_get_match_data(dev); > > > > > > - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > - if (ret) > > > - return dev_err_probe(dev, ret, "Unable to get clocks\n"); > > > + ocmem->core_clk = devm_clk_get(dev, "core"); > > > + if (IS_ERR(ocmem->core_clk)) > > > + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), > > > + "Unable to get core clock\n"); > > > + > > > + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); > > > + if (IS_ERR(ocmem->iface_clk)) > > > + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), > > > + "Unable to get iface clock\n"); > > > > > > ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); > > > if (IS_ERR(ocmem->mmio)) > > > > > > @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct platform_device > > > *pdev)> > > > } > > > > > > /* The core clock is synchronous with graphics */ > > > > > > - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); > > > + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); > > > + > > > + ret = clk_prepare_enable(ocmem->core_clk); > > > + if (ret) > > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable > core clock\n"); > > > > > > - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > + ret = clk_prepare_enable(ocmem->iface_clk); > > > > > > if (ret) > > > > > > - return dev_err_probe(ocmem->dev, ret, "Failed to enable > clocks\n"); > > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable > iface > > > clock\n"); > > > > > > if (qcom_scm_restore_sec_cfg_available()) { > > > > > > dev_dbg(dev, "configuring scm\n"); > > > > > > @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct platform_device > > > *pdev)> > > > return 0; > > > > > > err_clk_disable: > > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > + clk_disable_unprepare(ocmem->core_clk); > > > + clk_disable_unprepare(ocmem->iface_clk); > > > > > > return ret; > > > > > > } > > > > > > static int ocmem_dev_remove(struct platform_device *pdev) > > > { > > > > > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > + struct ocmem *ocmem = platform_get_drvdata(pdev); > > > + > > > + clk_disable_unprepare(ocmem->core_clk); > > > + clk_disable_unprepare(ocmem->iface_clk); > > > > > > return 0; > > > > > > } > > > >
On Dienstag, 9. Mai 2023 19:08:50 CEST Dmitry Baryshkov wrote: > On Tue, 9 May 2023 at 19:47, Luca Weiss <luca@z3ntu.xyz> wrote: > > On Montag, 8. Mai 2023 13:34:23 CEST Dmitry Baryshkov wrote: > > > On 07/05/2023 12:12, Luca Weiss wrote: > > > > Some platforms such as msm8226 do not have an iface clk. Since > > > > clk_bulk > > > > APIs don't offer to a way to treat some clocks as optional simply add > > > > core_clk and iface_clk members to our drvdata. > > > > > > What about using devm_clk_bulk_get_optional()? I think it would be > > > simpler this way. > > > > Using that function both clocks would be optional which may or may not be > > a > > bad idea. Not sure how much binding yaml and/or driver should try and > > catch > > bad usages of the driver. > > The generic rule is that we should not validate the DT unless required > (e.g. because of the possibility of legacy DT which used other > bindings or contained less information). Got it. But since in this driver we use one of the clocks for setting clock rate I'd keep using the two separate struct clk as I've done in this patch if you don't mind too much. Regards Luca > > > But honestly the current usage of the bulk API seems a bit clunky, we have > > a static array of clocks that we use (not in struct ocmem for some > > reason) and then we refer to the core clock by index? Feels better to > > just have the two clock references in the device struct and then we're > > good. > > > > Let me know. > > > > Regards > > Luca > > > > > > Signed-off-by: Luca Weiss <luca@z3ntu.xyz> > > > > --- > > > > > > > > drivers/soc/qcom/ocmem.c | 42 > > > > ++++++++++++++++++++++++------------------ > > > > 1 file changed, 24 insertions(+), 18 deletions(-) > > > > > > > > diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c > > > > index a11a955a1327..6235065d3bc9 100644 > > > > --- a/drivers/soc/qcom/ocmem.c > > > > +++ b/drivers/soc/qcom/ocmem.c > > > > @@ -54,6 +54,8 @@ struct ocmem { > > > > > > > > const struct ocmem_config *config; > > > > struct resource *memory; > > > > void __iomem *mmio; > > > > > > > > + struct clk *core_clk; > > > > + struct clk *iface_clk; > > > > > > > > unsigned int num_ports; > > > > unsigned int num_macros; > > > > bool interleaved; > > > > > > > > @@ -91,16 +93,6 @@ struct ocmem { > > > > > > > > #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, > > > > (val)) > > > > > > #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, > > > > (val)) > > > > > > -#define OCMEM_CLK_CORE_IDX 0 > > > > -static struct clk_bulk_data ocmem_clks[] = { > > > > - { > > > > - .id = "core", > > > > - }, > > > > - { > > > > - .id = "iface", > > > > - }, > > > > -}; > > > > - > > > > > > > > static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 > > > > data) > > > > { > > > > > > > > writel(data, ocmem->mmio + reg); > > > > > > > > @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device > > > > *pdev)> > > > > > > > > ocmem->dev = dev; > > > > ocmem->config = device_get_match_data(dev); > > > > > > > > - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > > - if (ret) > > > > - return dev_err_probe(dev, ret, "Unable to get clocks\n"); > > > > + ocmem->core_clk = devm_clk_get(dev, "core"); > > > > + if (IS_ERR(ocmem->core_clk)) > > > > + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), > > > > + "Unable to get core clock\n"); > > > > + > > > > + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); > > > > + if (IS_ERR(ocmem->iface_clk)) > > > > + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), > > > > + "Unable to get iface clock\n"); > > > > > > > > ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); > > > > if (IS_ERR(ocmem->mmio)) > > > > > > > > @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct > > > > platform_device > > > > *pdev)> > > > > > > > > } > > > > > > > > /* The core clock is synchronous with graphics */ > > > > > > > > - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < > > > > 0); > > > > + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); > > > > + > > > > + ret = clk_prepare_enable(ocmem->core_clk); > > > > + if (ret) > > > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable > > > > core clock\n"); > > > > > > - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > > + ret = clk_prepare_enable(ocmem->iface_clk); > > > > > > > > if (ret) > > > > > > > > - return dev_err_probe(ocmem->dev, ret, "Failed to enable > > > > clocks\n"); > > > > > > + return dev_err_probe(ocmem->dev, ret, "Failed to enable > > > > iface > > > > > > clock\n"); > > > > > > > > if (qcom_scm_restore_sec_cfg_available()) { > > > > > > > > dev_dbg(dev, "configuring scm\n"); > > > > > > > > @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct > > > > platform_device > > > > *pdev)> > > > > > > > > return 0; > > > > > > > > err_clk_disable: > > > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > > + clk_disable_unprepare(ocmem->core_clk); > > > > + clk_disable_unprepare(ocmem->iface_clk); > > > > > > > > return ret; > > > > > > > > } > > > > > > > > static int ocmem_dev_remove(struct platform_device *pdev) > > > > { > > > > > > > > - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); > > > > + struct ocmem *ocmem = platform_get_drvdata(pdev); > > > > + > > > > + clk_disable_unprepare(ocmem->core_clk); > > > > + clk_disable_unprepare(ocmem->iface_clk); > > > > > > > > return 0; > > > > > > > > }
On 9.05.2023 23:41, Luca Weiss wrote: > On Dienstag, 9. Mai 2023 19:08:50 CEST Dmitry Baryshkov wrote: >> On Tue, 9 May 2023 at 19:47, Luca Weiss <luca@z3ntu.xyz> wrote: >>> On Montag, 8. Mai 2023 13:34:23 CEST Dmitry Baryshkov wrote: >>>> On 07/05/2023 12:12, Luca Weiss wrote: >>>>> Some platforms such as msm8226 do not have an iface clk. Since >>>>> clk_bulk >>>>> APIs don't offer to a way to treat some clocks as optional simply add >>>>> core_clk and iface_clk members to our drvdata. >>>> >>>> What about using devm_clk_bulk_get_optional()? I think it would be >>>> simpler this way. >>> >>> Using that function both clocks would be optional which may or may not be >>> a >>> bad idea. Not sure how much binding yaml and/or driver should try and >>> catch >>> bad usages of the driver. >> >> The generic rule is that we should not validate the DT unless required >> (e.g. because of the possibility of legacy DT which used other >> bindings or contained less information). > > Got it. > > But since in this driver we use one of the clocks for setting clock rate I'd > keep using the two separate struct clk as I've done in this patch if you don't > mind too much. I'd also advocate for 2x struct clk, using bulk here is like trying to spread butter with a fork, it works, but has holes.. Konrad > > Regards > Luca > >> >>> But honestly the current usage of the bulk API seems a bit clunky, we have >>> a static array of clocks that we use (not in struct ocmem for some >>> reason) and then we refer to the core clock by index? Feels better to >>> just have the two clock references in the device struct and then we're >>> good. >>> >>> Let me know. >>> >>> Regards >>> Luca >>> >>>>> Signed-off-by: Luca Weiss <luca@z3ntu.xyz> >>>>> --- >>>>> >>>>> drivers/soc/qcom/ocmem.c | 42 >>>>> ++++++++++++++++++++++++------------------ >>>>> 1 file changed, 24 insertions(+), 18 deletions(-) >>>>> >>>>> diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c >>>>> index a11a955a1327..6235065d3bc9 100644 >>>>> --- a/drivers/soc/qcom/ocmem.c >>>>> +++ b/drivers/soc/qcom/ocmem.c >>>>> @@ -54,6 +54,8 @@ struct ocmem { >>>>> >>>>> const struct ocmem_config *config; >>>>> struct resource *memory; >>>>> void __iomem *mmio; >>>>> >>>>> + struct clk *core_clk; >>>>> + struct clk *iface_clk; >>>>> >>>>> unsigned int num_ports; >>>>> unsigned int num_macros; >>>>> bool interleaved; >>>>> >>>>> @@ -91,16 +93,6 @@ struct ocmem { >>>>> >>>>> #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, >>> >>> (val)) >>> >>>>> #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, >>> >>> (val)) >>> >>>>> -#define OCMEM_CLK_CORE_IDX 0 >>>>> -static struct clk_bulk_data ocmem_clks[] = { >>>>> - { >>>>> - .id = "core", >>>>> - }, >>>>> - { >>>>> - .id = "iface", >>>>> - }, >>>>> -}; >>>>> - >>>>> >>>>> static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 >>>>> data) >>>>> { >>>>> >>>>> writel(data, ocmem->mmio + reg); >>>>> >>>>> @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device >>>>> *pdev)> >>>>> >>>>> ocmem->dev = dev; >>>>> ocmem->config = device_get_match_data(dev); >>>>> >>>>> - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); >>>>> - if (ret) >>>>> - return dev_err_probe(dev, ret, "Unable to get clocks\n"); >>>>> + ocmem->core_clk = devm_clk_get(dev, "core"); >>>>> + if (IS_ERR(ocmem->core_clk)) >>>>> + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), >>>>> + "Unable to get core clock\n"); >>>>> + >>>>> + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); >>>>> + if (IS_ERR(ocmem->iface_clk)) >>>>> + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), >>>>> + "Unable to get iface clock\n"); >>>>> >>>>> ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); >>>>> if (IS_ERR(ocmem->mmio)) >>>>> >>>>> @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct >>>>> platform_device >>>>> *pdev)> >>>>> >>>>> } >>>>> >>>>> /* The core clock is synchronous with graphics */ >>>>> >>>>> - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < >>>>> 0); >>>>> + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); >>>>> + >>>>> + ret = clk_prepare_enable(ocmem->core_clk); >>>>> + if (ret) >>>>> + return dev_err_probe(ocmem->dev, ret, "Failed to enable >>> >>> core clock\n"); >>> >>>>> - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); >>>>> + ret = clk_prepare_enable(ocmem->iface_clk); >>>>> >>>>> if (ret) >>>>> >>>>> - return dev_err_probe(ocmem->dev, ret, "Failed to enable >>> >>> clocks\n"); >>> >>>>> + return dev_err_probe(ocmem->dev, ret, "Failed to enable >>> >>> iface >>> >>>>> clock\n"); >>>>> >>>>> if (qcom_scm_restore_sec_cfg_available()) { >>>>> >>>>> dev_dbg(dev, "configuring scm\n"); >>>>> >>>>> @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct >>>>> platform_device >>>>> *pdev)> >>>>> >>>>> return 0; >>>>> >>>>> err_clk_disable: >>>>> - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); >>>>> + clk_disable_unprepare(ocmem->core_clk); >>>>> + clk_disable_unprepare(ocmem->iface_clk); >>>>> >>>>> return ret; >>>>> >>>>> } >>>>> >>>>> static int ocmem_dev_remove(struct platform_device *pdev) >>>>> { >>>>> >>>>> - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); >>>>> + struct ocmem *ocmem = platform_get_drvdata(pdev); >>>>> + >>>>> + clk_disable_unprepare(ocmem->core_clk); >>>>> + clk_disable_unprepare(ocmem->iface_clk); >>>>> >>>>> return 0; >>>>> >>>>> } > > > >
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index a11a955a1327..6235065d3bc9 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -54,6 +54,8 @@ struct ocmem { const struct ocmem_config *config; struct resource *memory; void __iomem *mmio; + struct clk *core_clk; + struct clk *iface_clk; unsigned int num_ports; unsigned int num_macros; bool interleaved; @@ -91,16 +93,6 @@ struct ocmem { #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, (val)) #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, (val)) -#define OCMEM_CLK_CORE_IDX 0 -static struct clk_bulk_data ocmem_clks[] = { - { - .id = "core", - }, - { - .id = "iface", - }, -}; - static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) { writel(data, ocmem->mmio + reg); @@ -316,9 +308,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) ocmem->dev = dev; ocmem->config = device_get_match_data(dev); - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); - if (ret) - return dev_err_probe(dev, ret, "Unable to get clocks\n"); + ocmem->core_clk = devm_clk_get(dev, "core"); + if (IS_ERR(ocmem->core_clk)) + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), + "Unable to get core clock\n"); + + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); + if (IS_ERR(ocmem->iface_clk)) + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), + "Unable to get iface clock\n"); ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); if (IS_ERR(ocmem->mmio)) @@ -333,11 +331,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) } /* The core clock is synchronous with graphics */ - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); + + ret = clk_prepare_enable(ocmem->core_clk); + if (ret) + return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); + ret = clk_prepare_enable(ocmem->iface_clk); if (ret) - return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); + return dev_err_probe(ocmem->dev, ret, "Failed to enable iface clock\n"); if (qcom_scm_restore_sec_cfg_available()) { dev_dbg(dev, "configuring scm\n"); @@ -396,13 +398,17 @@ static int ocmem_dev_probe(struct platform_device *pdev) return 0; err_clk_disable: - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); + clk_disable_unprepare(ocmem->core_clk); + clk_disable_unprepare(ocmem->iface_clk); return ret; } static int ocmem_dev_remove(struct platform_device *pdev) { - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); + struct ocmem *ocmem = platform_get_drvdata(pdev); + + clk_disable_unprepare(ocmem->core_clk); + clk_disable_unprepare(ocmem->iface_clk); return 0; }