From nobody Sat Sep 21 17:12:17 2024 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 B435BECAAD1 for ; Wed, 31 Aug 2022 12:49:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231449AbiHaMtJ (ORCPT ); Wed, 31 Aug 2022 08:49:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231400AbiHaMtE (ORCPT ); Wed, 31 Aug 2022 08:49:04 -0400 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64CA19D660; Wed, 31 Aug 2022 05:48:59 -0700 (PDT) X-UUID: 4fd42144ad174eab84c1252172da8949-20220831 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=39ebN8yN46vkEhOfN7WVyLWWk/+c6irLgIToD0MrqLc=; b=Zxd5gc2KlSGY7obT6RhwdhAQ/lXqDC8AQYi3IagVMMEHE8nSX1eMYMpoW3fA7o+Jl6QAr0NvwcF7JF/BWHe3YE0yLDT1ArMI3xqWaPwRVqi+6sBt9JFK8JzaT2TAzu8R5vHpDPL2mUz6iAGtNLYYjXC1S64lUEt6bOD9uZoqiwU=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.10,REQID:1b554c54-c76f-481a-8c4c-f333a85c3690,OB:0,L OB:10,IP:0,URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:95,FILE:0,BULK:0,RULE:Rele ase_Ham,ACTION:release,TS:70 X-CID-INFO: VERSION:1.1.10,REQID:1b554c54-c76f-481a-8c4c-f333a85c3690,OB:0,LOB :10,IP:0,URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:95,FILE:0,BULK:0,RULE:Spam_G S981B3D,ACTION:quarantine,TS:70 X-CID-META: VersionHash:84eae18,CLOUDID:d86832d0-20bd-4e5e-ace8-00692b7ab380,C OID:e61777ea110b,Recheck:0,SF:28|17|19|48,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,Bulk:nil,QS:nil,BEC:nil,COL:0 X-UUID: 4fd42144ad174eab84c1252172da8949-20220831 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 662536373; Wed, 31 Aug 2022 20:48:53 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.792.15; Wed, 31 Aug 2022 20:48:52 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.792.15 via Frontend Transport; Wed, 31 Aug 2022 20:48:52 +0800 From: Johnson Wang To: , , , CC: , , , , , , Johnson Wang , Edward-JW Yang Subject: [PATCH 1/4] clk: mediatek: Export PLL operations symbols Date: Wed, 31 Aug 2022 20:48:47 +0800 Message-ID: <20220831124850.7748-2-johnson.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220831124850.7748-1-johnson.wang@mediatek.com> References: <20220831124850.7748-1-johnson.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Export PLL operations and register functions for different type of clock driver used. Co-developed-by: Edward-JW Yang Signed-off-by: Edward-JW Yang Signed-off-by: Johnson Wang --- drivers/clk/mediatek/clk-pll.c | 84 ++++++++++++++-------------------- drivers/clk/mediatek/clk-pll.h | 56 +++++++++++++++++++++++ 2 files changed, 90 insertions(+), 50 deletions(-) diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 54e6cfd29dfc..a4eca5fd539c 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -27,37 +27,10 @@ =20 #define AUDPLL_TUNER_EN BIT(31) =20 -#define POSTDIV_MASK 0x7 - /* default 7 bits integer, can be overridden with pcwibits. */ #define INTEGER_BITS 7 =20 -/* - * MediaTek PLLs are configured through their pcw value. The pcw value des= cribes - * a divider in the PLL feedback loop which consists of 7 bits for the int= eger - * part and the remaining bits (if present) for the fractional part. Also = they - * have a 3 bit power-of-two post divider. - */ - -struct mtk_clk_pll { - struct clk_hw hw; - void __iomem *base_addr; - void __iomem *pd_addr; - void __iomem *pwr_addr; - void __iomem *tuner_addr; - void __iomem *tuner_en_addr; - void __iomem *pcw_addr; - void __iomem *pcw_chg_addr; - void __iomem *en_addr; - const struct mtk_pll_data *data; -}; - -static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) -{ - return container_of(hw, struct mtk_clk_pll, hw); -} - -static int mtk_pll_is_prepared(struct clk_hw *hw) +int mtk_pll_is_prepared(struct clk_hw *hw) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); =20 @@ -161,8 +134,8 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *p= ll, u32 pcw, * @fin: The input frequency * */ -static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *po= stdiv, - u32 freq, u32 fin) +void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, + u32 freq, u32 fin) { unsigned long fmin =3D pll->data->fmin ? pll->data->fmin : (1000 * MHZ); const struct mtk_pll_div_table *div_table =3D pll->data->div_table; @@ -198,8 +171,8 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll= , u32 *pcw, u32 *postdiv, *pcw =3D (u32)_pcw; } =20 -static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); u32 pcw =3D 0; @@ -211,8 +184,7 @@ static int mtk_pll_set_rate(struct clk_hw *hw, unsigned= long rate, return 0; } =20 -static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_= rate) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); u32 postdiv; @@ -227,8 +199,8 @@ static unsigned long mtk_pll_recalc_rate(struct clk_hw = *hw, return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv); } =20 -static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); u32 pcw =3D 0; @@ -239,7 +211,7 @@ static long mtk_pll_round_rate(struct clk_hw *hw, unsig= ned long rate, return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv); } =20 -static int mtk_pll_prepare(struct clk_hw *hw) +int mtk_pll_prepare(struct clk_hw *hw) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); u32 r; @@ -273,7 +245,7 @@ static int mtk_pll_prepare(struct clk_hw *hw) return 0; } =20 -static void mtk_pll_unprepare(struct clk_hw *hw) +void mtk_pll_unprepare(struct clk_hw *hw) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); u32 r; @@ -301,7 +273,7 @@ static void mtk_pll_unprepare(struct clk_hw *hw) writel(r, pll->pwr_addr); } =20 -static const struct clk_ops mtk_pll_ops =3D { +const struct clk_ops mtk_pll_ops =3D { .is_prepared =3D mtk_pll_is_prepared, .prepare =3D mtk_pll_prepare, .unprepare =3D mtk_pll_unprepare, @@ -310,18 +282,15 @@ static const struct clk_ops mtk_pll_ops =3D { .set_rate =3D mtk_pll_set_rate, }; =20 -static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, - void __iomem *base) +struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, + const struct mtk_pll_data *data, + void __iomem *base, + const struct clk_ops *pll_ops) { - struct mtk_clk_pll *pll; struct clk_init_data init =3D {}; int ret; const char *parent_name =3D "clk26m"; =20 - pll =3D kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) - return ERR_PTR(-ENOMEM); - pll->base_addr =3D base + data->reg; pll->pwr_addr =3D base + data->pwr_reg; pll->pd_addr =3D base + data->pd_reg; @@ -343,7 +312,7 @@ static struct clk_hw *mtk_clk_register_pll(const struct= mtk_pll_data *data, =20 init.name =3D data->name; init.flags =3D (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; - init.ops =3D &mtk_pll_ops; + init.ops =3D pll_ops; if (data->parent_name) init.parent_names =3D &data->parent_name; else @@ -360,7 +329,22 @@ static struct clk_hw *mtk_clk_register_pll(const struc= t mtk_pll_data *data, return &pll->hw; } =20 -static void mtk_clk_unregister_pll(struct clk_hw *hw) +struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, + void __iomem *base) +{ + struct mtk_clk_pll *pll; + struct clk_hw *hw; + + pll =3D kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + hw =3D mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); + + return hw; +} + +void mtk_clk_unregister_pll(struct clk_hw *hw) { struct mtk_clk_pll *pll; =20 @@ -423,8 +407,8 @@ int mtk_clk_register_plls(struct device_node *node, } EXPORT_SYMBOL_GPL(mtk_clk_register_plls); =20 -static __iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, - const struct mtk_pll_data *data) +__iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, + const struct mtk_pll_data *data) { struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); =20 diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h index fe3199715688..e87ab08eea9b 100644 --- a/drivers/clk/mediatek/clk-pll.h +++ b/drivers/clk/mediatek/clk-pll.h @@ -7,6 +7,7 @@ #ifndef __DRV_CLK_MTK_PLL_H #define __DRV_CLK_MTK_PLL_H =20 +#include #include =20 struct clk_ops; @@ -20,6 +21,7 @@ struct mtk_pll_div_table { =20 #define HAVE_RST_BAR BIT(0) #define PLL_AO BIT(1) +#define POSTDIV_MASK 0x7 =20 struct mtk_pll_data { int id; @@ -48,10 +50,64 @@ struct mtk_pll_data { u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ }; =20 +/* + * MediaTek PLLs are configured through their pcw value. The pcw value des= cribes + * a divider in the PLL feedback loop which consists of 7 bits for the int= eger + * part and the remaining bits (if present) for the fractional part. Also = they + * have a 3 bit power-of-two post divider. + */ + +struct mtk_clk_pll { + struct clk_hw hw; + void __iomem *base_addr; + void __iomem *pd_addr; + void __iomem *pwr_addr; + void __iomem *tuner_addr; + void __iomem *tuner_en_addr; + void __iomem *pcw_addr; + void __iomem *pcw_chg_addr; + void __iomem *en_addr; + const struct mtk_pll_data *data; +}; + + int mtk_clk_register_plls(struct device_node *node, const struct mtk_pll_data *plls, int num_plls, struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, struct clk_hw_onecell_data *clk_data); =20 +extern const struct clk_ops mtk_pll_ops; + +static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_pll, hw); +} + +int mtk_pll_is_prepared(struct clk_hw *hw); + +int mtk_pll_prepare(struct clk_hw *hw); + +void mtk_pll_unprepare(struct clk_hw *hw); + +unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_= rate); + +void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, + u32 freq, u32 fin); +int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); +long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate); + +struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, + const struct mtk_pll_data *data, + void __iomem *base, + const struct clk_ops *pll_ops); +struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, + void __iomem *base); +void mtk_clk_unregister_pll(struct clk_hw *hw); + +__iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, + const struct mtk_pll_data *data); + #endif /* __DRV_CLK_MTK_PLL_H */ --=20 2.18.0 From nobody Sat Sep 21 17:12:17 2024 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 B109EECAAD4 for ; Wed, 31 Aug 2022 12:49:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231466AbiHaMtT (ORCPT ); Wed, 31 Aug 2022 08:49:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231405AbiHaMtE (ORCPT ); Wed, 31 Aug 2022 08:49:04 -0400 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7B59A0606; Wed, 31 Aug 2022 05:49:00 -0700 (PDT) X-UUID: 8686b52b92c842e29da994014b9ee2ca-20220831 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=WQK1AyNx0JLk94WzgAavNJ5OIP6EmsCAETgWNY7s0Ns=; b=JPaXXtY5MT4GUStUHVDL4pTzWuGA+yirB/+kCz+Tg+KpNMhVzSkYgvSJpwQ4rYTQnRSygdqX4JP2AGDi2Q9buR5p4eL8YLQUnPU4NupeMXgJkt7XPcQJARpcC1ZdY4EQQ7+MRz602/q6yvGt39LyHtURBGlGwznCyGOQ7dyEJNs=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.10,REQID:7411a64f-eeb4-45a4-b94d-fbabbbb6c81a,OB:0,L OB:0,IP:0,URL:25,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release _Ham,ACTION:release,TS:25 X-CID-META: VersionHash:84eae18,CLOUDID:28752856-e800-47dc-8adf-0c936acf4f1b,C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:11|1,File: nil,Bulk:nil,QS:nil,BEC:nil,COL:0 X-UUID: 8686b52b92c842e29da994014b9ee2ca-20220831 Received: from mtkmbs11n1.mediatek.inc [(172.21.101.185)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1847041876; Wed, 31 Aug 2022 20:48:53 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.792.15; Wed, 31 Aug 2022 20:48:52 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.792.15 via Frontend Transport; Wed, 31 Aug 2022 20:48:52 +0800 From: Johnson Wang To: , , , CC: , , , , , , Johnson Wang , Edward-JW Yang Subject: [PATCH 2/4] dt-bindings: arm: mediatek: Add new bindings of MediaTek frequency hopping Date: Wed, 31 Aug 2022 20:48:48 +0800 Message-ID: <20220831124850.7748-3-johnson.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220831124850.7748-1-johnson.wang@mediatek.com> References: <20220831124850.7748-1-johnson.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the new binding documentation for MediaTek frequency hopping and spread spectrum clocking control. Co-developed-by: Edward-JW Yang Signed-off-by: Edward-JW Yang Signed-off-by: Johnson Wang --- .../bindings/arm/mediatek/mediatek,fhctl.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek= ,fhctl.yaml diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,fhctl.= yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,fhctl.yaml new file mode 100644 index 000000000000..c5d76410538b --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,fhctl.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/mediatek/mediatek,fhctl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek frequency hopping and spread spectrum clocking control + +maintainers: + - Edward-JW Yang + +description: | + Frequency hopping control (FHCTL) is a piece of hardware that control + some PLLs to adopt "hopping" mechanism to adjust their frequency. + Spread spectrum clocking (SSC) is another function provided by this hard= ware. + +properties: + compatible: + const: mediatek,fhctl + + reg: + maxItems: 1 + + mediatek,hopping-ssc-percents: + description: | + Determine the enablement of frequency hopping feature and the percen= tage + of spread spectrum clocking for PLLs. + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + items: + - description: PLL id that is expected to enable frequency hopping. + - description: The percentage of spread spectrum clocking for one = PLL. + minimum: 0 + maximum: 8 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + fhctl: fhctl@1000ce00 { + compatible =3D "mediatek,fhctl"; + reg =3D <0x1000c000 0xe00>; + mediatek,hopping-ssc-percents =3D ; + }; --=20 2.18.0 From nobody Sat Sep 21 17:12:17 2024 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 BE1C9ECAAD1 for ; Wed, 31 Aug 2022 12:49:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231442AbiHaMtV (ORCPT ); Wed, 31 Aug 2022 08:49:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231411AbiHaMtF (ORCPT ); Wed, 31 Aug 2022 08:49:05 -0400 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 63C0495E6F; Wed, 31 Aug 2022 05:49:00 -0700 (PDT) X-UUID: 59a288ed26774c679e222b2e4ba78ac7-20220831 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=9hwZ5lokIYKOlXJxV8Ro2SwVnjuNQzTSxW79IdGZ/zI=; b=IZYLpmpyZZ6n2ogx6ETo+TUSFtg7Y4aj0nl1V0C40Si6yA/O49421kFGwiMWSLVcM8ECYJ6/J7FFz4BsuOcfwhMWxwQX60vh1MsH4iq80MXU+FfxLrrug6WxGufnM6QRoYziVOOs11cMlX1oH9fxocKyLZEgDiA2JrM6naSx6Bg=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.10,REQID:778c9595-0d21-4c3e-bcbd-77190ace3919,OB:0,L OB:20,IP:0,URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:95,FILE:0,BULK:0,RULE:Rele ase_Ham,ACTION:release,TS:70 X-CID-INFO: VERSION:1.1.10,REQID:778c9595-0d21-4c3e-bcbd-77190ace3919,OB:0,LOB :20,IP:0,URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:95,FILE:0,BULK:0,RULE:Spam_G S981B3D,ACTION:quarantine,TS:70 X-CID-META: VersionHash:84eae18,CLOUDID:da6832d0-20bd-4e5e-ace8-00692b7ab380,C OID:9ac40243fccf,Recheck:0,SF:28|17|19|48,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,Bulk:nil,QS:nil,BEC:nil,COL:0 X-UUID: 59a288ed26774c679e222b2e4ba78ac7-20220831 Received: from mtkcas11.mediatek.inc [(172.21.101.40)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 825050367; Wed, 31 Aug 2022 20:48:53 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.792.15; Wed, 31 Aug 2022 20:48:52 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.792.15 via Frontend Transport; Wed, 31 Aug 2022 20:48:52 +0800 From: Johnson Wang To: , , , CC: , , , , , , Johnson Wang , Edward-JW Yang Subject: [PATCH 3/4] clk: mediatek: Add new clock driver to handle FHCTL hardware Date: Wed, 31 Aug 2022 20:48:49 +0800 Message-ID: <20220831124850.7748-4-johnson.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220831124850.7748-1-johnson.wang@mediatek.com> References: <20220831124850.7748-1-johnson.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To implement frequency hopping and spread spectrum clocking function, we introduce new clock type and APIs to handle FHCTL hardware. Co-developed-by: Edward-JW Yang Signed-off-by: Edward-JW Yang Signed-off-by: Johnson Wang --- drivers/clk/mediatek/Makefile | 2 +- drivers/clk/mediatek/clk-fhctl.c | 258 +++++++++++++++++++++++++++++ drivers/clk/mediatek/clk-fhctl.h | 27 +++ drivers/clk/mediatek/clk-pllfh.c | 271 +++++++++++++++++++++++++++++++ drivers/clk/mediatek/clk-pllfh.h | 81 +++++++++ 5 files changed, 638 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/mediatek/clk-fhctl.c create mode 100644 drivers/clk/mediatek/clk-fhctl.h create mode 100644 drivers/clk/mediatek/clk-pllfh.c create mode 100644 drivers/clk/mediatek/clk-pllfh.h diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index caf2ce93d666..0e674a55e51e 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_COMMON_CLK_MEDIATEK) +=3D clk-mtk.o clk-pll.o clk-gate.o clk-= apmixed.o clk-cpumux.o reset.o clk-mux.o +obj-$(CONFIG_COMMON_CLK_MEDIATEK) +=3D clk-mtk.o clk-pll.o clk-gate.o clk-= apmixed.o clk-cpumux.o reset.o clk-mux.o clk-fhctl.o clk-pllfh.o =20 obj-$(CONFIG_COMMON_CLK_MT6765) +=3D clk-mt6765.o obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) +=3D clk-mt6765-audio.o diff --git a/drivers/clk/mediatek/clk-fhctl.c b/drivers/clk/mediatek/clk-fh= ctl.c new file mode 100644 index 000000000000..69bd4ce2bc72 --- /dev/null +++ b/drivers/clk/mediatek/clk-fhctl.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Edward-JW Yang + */ + +#include + +#include "clk-mtk.h" +#include "clk-pllfh.h" +#include "clk-fhctl.h" + +#define PERCENT_TO_DDSLMT(dds, percent_m10) \ + ((((dds) * (percent_m10)) >> 5) / 100) + +static const struct fhctl_offset fhctl_offset =3D { + .offset_hp_en =3D 0x0, + .offset_clk_con =3D 0x8, + .offset_rst_con =3D 0xc, + .offset_slope0 =3D 0x10, + .offset_slope1 =3D 0x14, + .offset_cfg =3D 0x0, + .offset_updnlmt =3D 0x4, + .offset_dds =3D 0x8, + .offset_dvfs =3D 0xc, + .offset_mon =3D 0x10, +}; + +const struct fhctl_offset *fhctl_get_offset_table(void) +{ + return &fhctl_offset; +} + +static void dump_hw(struct mtk_clk_pll *pll, struct fh_pll_regs *regs, + const struct fh_pll_data *data) +{ + pr_info("hp_en<%x>,clk_con<%x>,slope0<%x>,slope1<%x>\n", + readl(regs->reg_hp_en), readl(regs->reg_clk_con), + readl(regs->reg_slope0), readl(regs->reg_slope1)); + pr_info("cfg<%x>,lmt<%x>,dds<%x>,dvfs<%x>,mon<%x>\n", + readl(regs->reg_cfg), readl(regs->reg_updnlmt), + readl(regs->reg_dds), readl(regs->reg_dvfs), + readl(regs->reg_mon)); + pr_info("pcw<%x>\n", readl(pll->pcw_addr)); +} + +static int fhctl_set_ssc_regs(struct mtk_clk_pll *pll, struct fh_pll_regs = *regs, + const struct fh_pll_data *data, u32 rate) +{ + u32 updnlmt_val, r; + + writel((readl(regs->reg_cfg) & ~(data->frddsx_en)), regs->reg_cfg); + writel((readl(regs->reg_cfg) & ~(data->sfstrx_en)), regs->reg_cfg); + writel((readl(regs->reg_cfg) & ~(data->fhctlx_en)), regs->reg_cfg); + + if (rate > 0) { + /* Set the relative parameter registers (dt/df/upbnd/downbnd) */ + r =3D readl(regs->reg_cfg); + r &=3D ~(data->msk_frddsx_dys); + r |=3D (data->df_val << (ffs(data->msk_frddsx_dys) - 1)); + writel(r, regs->reg_cfg); + + r =3D readl(regs->reg_cfg); + r &=3D ~(data->msk_frddsx_dts); + r |=3D (data->dt_val << (ffs(data->msk_frddsx_dts) - 1)); + writel(r, regs->reg_cfg); + + writel((readl(pll->pcw_addr) & data->dds_mask) | data->tgl_org, + regs->reg_dds); + + /* Calculate UPDNLMT */ + updnlmt_val =3D PERCENT_TO_DDSLMT((readl(regs->reg_dds) & + data->dds_mask), rate) << + data->updnlmt_shft; + + writel(updnlmt_val, regs->reg_updnlmt); + writel(readl(regs->reg_hp_en) | BIT(data->fh_id), + regs->reg_hp_en); + /* Enable SSC */ + writel(readl(regs->reg_cfg) | data->frddsx_en, regs->reg_cfg); + /* Enable Hopping control */ + writel(readl(regs->reg_cfg) | data->fhctlx_en, regs->reg_cfg); + + } else { + /* Switch to APMIXEDSYS control */ + writel(readl(regs->reg_hp_en) & ~BIT(data->fh_id), + regs->reg_hp_en); + /* Wait for DDS to be stable */ + udelay(30); + } + + return 0; +} + +static int hopping_hw_flow(struct mtk_clk_pll *pll, struct fh_pll_regs *re= gs, + const struct fh_pll_data *data, + struct fh_pll_state *state, unsigned int new_dds) +{ + u32 dds_mask =3D data->dds_mask; + u32 mon_dds =3D 0; + u32 con_pcw_tmp; + int ret; + + if (state->ssc_rate) + fhctl_set_ssc_regs(pll, regs, data, 0); + + writel((readl(pll->pcw_addr) & dds_mask) | data->tgl_org, + regs->reg_dds); + + writel(readl(regs->reg_cfg) | data->sfstrx_en, regs->reg_cfg); + writel(readl(regs->reg_cfg) | data->fhctlx_en, regs->reg_cfg); + writel(data->slope0_value, regs->reg_slope0); + writel(data->slope1_value, regs->reg_slope1); + + writel(readl(regs->reg_hp_en) | BIT(data->fh_id), regs->reg_hp_en); + writel((new_dds) | (data->dvfs_tri), regs->reg_dvfs); + + /* Wait 1000 us until DDS stable */ + ret =3D readl_poll_timeout_atomic(regs->reg_mon, mon_dds, + (mon_dds & dds_mask) =3D=3D new_dds, + 10, 1000); + if (ret) { + pr_warn("%s: FHCTL hopping timeout\n", pll->data->name); + dump_hw(pll, regs, data); + } + + con_pcw_tmp =3D readl(pll->pcw_addr) & (~dds_mask); + con_pcw_tmp =3D (con_pcw_tmp | (readl(regs->reg_mon) & dds_mask) | + data->pcwchg); + + writel(con_pcw_tmp, pll->pcw_addr); + writel(readl(regs->reg_hp_en) & ~BIT(data->fh_id), regs->reg_hp_en); + + if (state->ssc_rate) + fhctl_set_ssc_regs(pll, regs, data, state->ssc_rate); + + return ret; +} + +static unsigned int __get_postdiv(struct mtk_clk_pll *pll, + struct fh_pll_regs *regs, + const struct fh_pll_data *fh_data) +{ + unsigned int regval; + + regval =3D readl(pll->pd_addr) >> pll->data->pd_shift; + regval &=3D POSTDIV_MASK; + + return (1 << regval); +} + +static void __set_postdiv(struct mtk_clk_pll *pll, struct fh_pll_regs *reg= s, + const struct fh_pll_data *data, int postdiv) +{ + unsigned int regval; + + regval =3D readl(pll->pd_addr); + regval &=3D ~(POSTDIV_MASK << pll->data->pd_shift); + regval |=3D (ffs(postdiv) - 1) << pll->data->pd_shift; + writel(regval, pll->pd_addr); +} + +static int fhctl_hopping(struct mtk_fh *fh, unsigned int new_dds, int post= div) +{ + const struct fh_pll_data *data =3D &fh->pllfh_data->data; + struct fh_pll_state *state =3D &fh->pllfh_data->state; + struct fh_pll_regs *regs =3D &fh->regs; + struct mtk_clk_pll *pll =3D &fh->clk_pll; + spinlock_t *lock =3D fh->lock; + unsigned int pll_postdiv; + unsigned long flags =3D 0; + int ret; + + if (postdiv > 0) { + pll_postdiv =3D __get_postdiv(pll, regs, data); + + if (postdiv > pll_postdiv) + __set_postdiv(pll, regs, data, postdiv); + } + + spin_lock_irqsave(lock, flags); + + ret =3D hopping_hw_flow(pll, regs, data, state, new_dds); + + spin_unlock_irqrestore(lock, flags); + + if (postdiv > 0) { + if (postdiv < pll_postdiv) + __set_postdiv(pll, regs, data, postdiv); + } + + return ret; +} + +static int __fhctl_ssc_enable(struct mtk_fh *fh, u32 rate) +{ + const struct fh_pll_data *data =3D &fh->pllfh_data->data; + struct fh_pll_state *state =3D &fh->pllfh_data->state; + struct fh_pll_regs *regs =3D &fh->regs; + struct mtk_clk_pll *pll =3D &fh->clk_pll; + spinlock_t *lock =3D fh->lock; + unsigned long flags =3D 0; + + spin_lock_irqsave(lock, flags); + + fhctl_set_ssc_regs(pll, regs, data, rate); + state->ssc_rate =3D rate; + + spin_unlock_irqrestore(lock, flags); + + return 0; +} + +static int fhctl_ssc_enable(struct mtk_fh *fh, u32 rate) +{ + return __fhctl_ssc_enable(fh, rate); +} + +static int fhctl_ssc_disable(struct mtk_fh *fh) +{ + return __fhctl_ssc_enable(fh, 0); +} + +static const struct fh_operation fhctl_ops =3D { + .hopping =3D fhctl_hopping, + .ssc_enable =3D fhctl_ssc_enable, + .ssc_disable =3D fhctl_ssc_disable, +}; + +const struct fh_operation *fhctl_get_ops(void) +{ + return &fhctl_ops; +} + +void fhctl_hw_init(struct mtk_fh *fh) +{ + const struct fh_pll_data data =3D fh->pllfh_data->data; + struct fh_pll_state state =3D fh->pllfh_data->state; + struct fh_pll_regs regs =3D fh->regs; + u32 val; + + /* initial hw register */ + val =3D readl(regs.reg_clk_con) | BIT(data.fh_id); + writel(val, regs.reg_clk_con); + + val =3D readl(regs.reg_rst_con) & ~BIT(data.fh_id); + writel(val, regs.reg_rst_con); + val =3D readl(regs.reg_rst_con) | BIT(data.fh_id); + writel(val, regs.reg_rst_con); + + writel(0x0, regs.reg_cfg); + writel(0x0, regs.reg_updnlmt); + writel(0x0, regs.reg_dds); + + /* enable ssc if needed */ + if (state.ssc_rate) + fh->ops->ssc_enable(fh, state.ssc_rate); +} diff --git a/drivers/clk/mediatek/clk-fhctl.h b/drivers/clk/mediatek/clk-fh= ctl.h new file mode 100644 index 000000000000..3cd4921c39e9 --- /dev/null +++ b/drivers/clk/mediatek/clk-fhctl.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Edward-JW Yang + */ + +#ifndef __CLK_FHCTL_H +#define __CLK_FHCTL_H + + +struct fhctl_offset { + u32 offset_hp_en; + u32 offset_clk_con; + u32 offset_rst_con; + u32 offset_slope0; + u32 offset_slope1; + u32 offset_cfg; + u32 offset_updnlmt; + u32 offset_dds; + u32 offset_dvfs; + u32 offset_mon; +}; +const struct fhctl_offset *fhctl_get_offset_table(void); +const struct fh_operation *fhctl_get_ops(void); +void fhctl_hw_init(struct mtk_fh *fh); + +#endif diff --git a/drivers/clk/mediatek/clk-pllfh.c b/drivers/clk/mediatek/clk-pl= lfh.c new file mode 100644 index 000000000000..71b35323b526 --- /dev/null +++ b/drivers/clk/mediatek/clk-pllfh.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Edward-JW Yang + */ + +#include +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-pllfh.h" +#include "clk-fhctl.h" + +static DEFINE_SPINLOCK(pllfh_lock); + +inline struct mtk_fh *to_mtk_fh(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); + + return container_of(pll, struct mtk_fh, clk_pll); +} + +static int mtk_fhctl_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll =3D to_mtk_clk_pll(hw); + struct mtk_fh *fh =3D to_mtk_fh(hw); + u32 pcw =3D 0; + u32 postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); + fh->ops->hopping(fh, pcw, postdiv); + + return 0; +} + +static const struct clk_ops mtk_pllfh_ops =3D { + .is_prepared =3D mtk_pll_is_prepared, + .prepare =3D mtk_pll_prepare, + .unprepare =3D mtk_pll_unprepare, + .recalc_rate =3D mtk_pll_recalc_rate, + .round_rate =3D mtk_pll_round_rate, + .set_rate =3D mtk_fhctl_set_rate, +}; + +static struct mtk_pllfh_data *get_pllfh_by_id(struct mtk_pllfh_data *pllfh= s, + int num_fhs, int pll_id) +{ + int i; + + for (i =3D 0; i < num_fhs; i++) + if (pllfhs[i].data.pll_id =3D=3D pll_id) + return &pllfhs[i]; + + return NULL; +} + +void fhctl_parse_dt(struct mtk_pllfh_data *pllfhs, int num_fhs) +{ + void __iomem *base; + struct device_node *node; + const u8 *compatible_node =3D "mediatek,fhctl"; + u32 tmp =3D 0; + u32 num_cells, pll_id, ssc_rate; + int offset, i; + + node =3D of_find_compatible_node(NULL, NULL, compatible_node); + if (!node) { + pr_err("cannot find \"%s\"\n", compatible_node); + return; + } + + base =3D of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + if (!of_get_property(node, "mediatek,hopping-ssc-percents", &tmp)) { + pr_err("%s(): failed get property\n", __func__); + return; + } + + num_cells =3D tmp / (sizeof(u32) * 2); + + for (i =3D 0; i < num_cells; i++) { + struct mtk_pllfh_data *pllfh; + + offset =3D i * 2; + of_property_read_u32_index(node, + "mediatek,hopping-ssc-percents", + offset, &pll_id); + of_property_read_u32_index(node, + "mediatek,hopping-ssc-percents", + offset + 1, &ssc_rate); + pllfh =3D get_pllfh_by_id(pllfhs, num_fhs, pll_id); + if (!pllfh) + continue; + + pllfh->state.fh_enable =3D 1; + pllfh->state.ssc_rate =3D ssc_rate; + pllfh->state.base =3D base; + } +} + +static void pllfh_init(struct mtk_fh *fh, struct mtk_pllfh_data *pllfh_dat= a) +{ + struct fh_pll_regs *regs =3D &fh->regs; + const struct fhctl_offset *offset; + void __iomem *base =3D pllfh_data->state.base; + void __iomem *fhx_base =3D base + pllfh_data->data.fhx_offset; + + offset =3D fhctl_get_offset_table(); + + regs->reg_hp_en =3D base + offset->offset_hp_en; + regs->reg_clk_con =3D base + offset->offset_clk_con; + regs->reg_rst_con =3D base + offset->offset_rst_con; + regs->reg_slope0 =3D base + offset->offset_slope0; + regs->reg_slope1 =3D base + offset->offset_slope1; + + regs->reg_cfg =3D fhx_base + offset->offset_cfg; + regs->reg_updnlmt =3D fhx_base + offset->offset_updnlmt; + regs->reg_dds =3D fhx_base + offset->offset_dds; + regs->reg_dvfs =3D fhx_base + offset->offset_dvfs; + regs->reg_mon =3D fhx_base + offset->offset_mon; + + fh->pllfh_data =3D pllfh_data; + fh->lock =3D &pllfh_lock; + + fh->ops =3D fhctl_get_ops(); +} + +static bool fhctl_is_supported_and_enabled(const struct mtk_pllfh_data *pl= lfh) +{ + return pllfh && (pllfh->state.fh_enable =3D=3D 1); +} + +static struct clk_hw * +mtk_clk_register_pllfh(const struct mtk_pll_data *pll_data, + struct mtk_pllfh_data *pllfh_data, void __iomem *base) +{ + struct clk_hw *hw; + struct mtk_fh *fh; + + fh =3D kzalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) + return ERR_PTR(-ENOMEM); + + pllfh_init(fh, pllfh_data); + + hw =3D mtk_clk_register_pll_ops(&fh->clk_pll, pll_data, base, + &mtk_pllfh_ops); + + if (IS_ERR(hw)) + kfree(fh); + else + fhctl_hw_init(fh); + + return hw; +} + +static void mtk_clk_unregister_pllfh(struct clk_hw *hw) +{ + struct mtk_fh *fh; + + if (!hw) + return; + + fh =3D to_mtk_fh(hw); + + clk_hw_unregister(hw); + kfree(fh); +} + +int mtk_clk_register_pllfhs(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct mtk_pllfh_data *pllfhs, int num_fhs, + struct clk_hw_onecell_data *clk_data) +{ + void __iomem *base; + int i; + struct clk_hw *hw; + + base =3D of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -EINVAL; + } + + for (i =3D 0; i < num_plls; i++) { + const struct mtk_pll_data *pll =3D &plls[i]; + struct mtk_pllfh_data *pllfh; + + pllfh =3D get_pllfh_by_id(pllfhs, num_fhs, pll->id); + + if (fhctl_is_supported_and_enabled(pllfh)) + hw =3D mtk_clk_register_pllfh(pll, pllfh, base); + else + hw =3D mtk_clk_register_pll(pll, base); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", pll->name, + hw); + goto err; + } + + clk_data->hws[pll->id] =3D hw; + } + + return 0; + +err: + while (--i >=3D 0) { + const struct mtk_pll_data *pll =3D &plls[i]; + struct mtk_pllfh_data *pllfh; + + pllfh =3D get_pllfh_by_id(pllfhs, num_fhs, pll->id); + + if (fhctl_is_supported_and_enabled(pllfh)) + mtk_clk_unregister_pllfh(clk_data->hws[pll->id]); + else + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + + clk_data->hws[pll->id] =3D ERR_PTR(-ENOENT); + } + + iounmap(base); + + return PTR_ERR(hw); +} + +void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_pl= ls, + struct mtk_pllfh_data *pllfhs, int num_fhs, + struct clk_hw_onecell_data *clk_data) +{ + void __iomem *base =3D NULL, *fhctl_base =3D NULL; + int i; + + if (!clk_data) + return; + + for (i =3D num_plls; i > 0; i--) { + const struct mtk_pll_data *pll =3D &plls[i - 1]; + struct mtk_pllfh_data *pllfh; + + if (IS_ERR_OR_NULL(clk_data->hws[pll->id])) + continue; + + pllfh =3D get_pllfh_by_id(pllfhs, num_fhs, pll->id); + + if (fhctl_is_supported_and_enabled(pllfh)) { + fhctl_base =3D pllfh->state.base; + mtk_clk_unregister_pllfh(clk_data->hws[pll->id]); + } else { + base =3D mtk_clk_pll_get_base(clk_data->hws[pll->id], + pll); + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + } + + clk_data->hws[pll->id] =3D ERR_PTR(-ENOENT); + } + + if (fhctl_base) + iounmap(fhctl_base); + + iounmap(base); +} diff --git a/drivers/clk/mediatek/clk-pllfh.h b/drivers/clk/mediatek/clk-pl= lfh.h new file mode 100644 index 000000000000..d9f7c8527548 --- /dev/null +++ b/drivers/clk/mediatek/clk-pllfh.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Edward-JW Yang + */ + +#ifndef __DRV_CLKFH_H +#define __DRV_CLKFH_H + +#include "clk-pll.h" + +struct fh_pll_state { + u32 fh_enable; + u32 ssc_rate; + void __iomem *base; +}; + +struct fh_pll_data { + int pll_id; + int fh_id; + u32 fhx_offset; + u32 dds_mask; + u32 slope0_value; + u32 slope1_value; + u32 sfstrx_en; + u32 frddsx_en; + u32 fhctlx_en; + u32 tgl_org; + u32 dvfs_tri; + u32 pcwchg; + u32 dt_val; + u32 df_val; + u32 updnlmt_shft; + u32 msk_frddsx_dys; + u32 msk_frddsx_dts; +}; + +struct mtk_pllfh_data { + struct fh_pll_state state; + const struct fh_pll_data data; +}; + +struct fh_pll_regs { + void __iomem *reg_hp_en; + void __iomem *reg_clk_con; + void __iomem *reg_rst_con; + void __iomem *reg_slope0; + void __iomem *reg_slope1; + void __iomem *reg_cfg; + void __iomem *reg_updnlmt; + void __iomem *reg_dds; + void __iomem *reg_dvfs; + void __iomem *reg_mon; +}; + +struct mtk_fh { + struct mtk_clk_pll clk_pll; + struct fh_pll_regs regs; + struct mtk_pllfh_data *pllfh_data; + const struct fh_operation *ops; + spinlock_t *lock; +}; + +struct fh_operation { + int (*hopping)(struct mtk_fh *fh, unsigned int new_dds, int postdiv); + int (*ssc_enable)(struct mtk_fh *fh, u32 rate); + int (*ssc_disable)(struct mtk_fh *fh); +}; + +int mtk_clk_register_pllfhs(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct mtk_pllfh_data *pllfhs, int num_pllfhs, + struct clk_hw_onecell_data *clk_data); + +void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_pl= ls, + struct mtk_pllfh_data *pllfhs, int num_fhs, + struct clk_hw_onecell_data *clk_data); + +void fhctl_parse_dt(struct mtk_pllfh_data *pllfhs, int num_pllfhs); + +#endif /* __DRV_CLKFH_H */ --=20 2.18.0 From nobody Sat Sep 21 17:12:17 2024 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 3C4D5ECAAD4 for ; Wed, 31 Aug 2022 12:49:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231461AbiHaMtO (ORCPT ); Wed, 31 Aug 2022 08:49:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231406AbiHaMtE (ORCPT ); Wed, 31 Aug 2022 08:49:04 -0400 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB30DA285D; Wed, 31 Aug 2022 05:49:00 -0700 (PDT) X-UUID: e27e82e87491446cbeb43a99c8f2d59e-20220831 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=8ApQ2luuPpMOpqxJ/C2pxjh6Z+2EEHX4gdM+RImixxA=; b=p2pEUCm20TmojPPxdYyEi+rjaGLnmLXsVpiQYyVsqJA9oQ24GkGfs6NQAXNMDzVPk4SUE90aBvdq09ei3WeGd9J9/MpuPybNARw3T080M2B4eodK+5mzdx6CEstzAJ7UOnUUAjJX2LbT1lDX4qvZpJjp9Zs7sCNjN3xS5CKY/bM=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.10,REQID:c204b884-e761-4317-97db-8b44ee2d64f6,OB:0,L OB:0,IP:0,URL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Releas e_Ham,ACTION:release,TS:-25 X-CID-META: VersionHash:84eae18,CLOUDID:29752856-e800-47dc-8adf-0c936acf4f1b,C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:11|1,File: nil,Bulk:nil,QS:nil,BEC:nil,COL:0 X-UUID: e27e82e87491446cbeb43a99c8f2d59e-20220831 Received: from mtkexhb01.mediatek.inc [(172.21.101.102)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 386875241; Wed, 31 Aug 2022 20:48:54 +0800 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.792.15; Wed, 31 Aug 2022 20:48:52 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.792.15 via Frontend Transport; Wed, 31 Aug 2022 20:48:52 +0800 From: Johnson Wang To: , , , CC: , , , , , , Johnson Wang , Edward-JW Yang Subject: [PATCH 4/4] clk: mediatek: Change PLL register API for MT8186 Date: Wed, 31 Aug 2022 20:48:50 +0800 Message-ID: <20220831124850.7748-5-johnson.wang@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220831124850.7748-1-johnson.wang@mediatek.com> References: <20220831124850.7748-1-johnson.wang@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use mtk_clk_register_pllfhs() to enhance frequency hopping and spread spectrum clocking control for MT8186. Co-developed-by: Edward-JW Yang Signed-off-by: Edward-JW Yang Signed-off-by: Johnson Wang --- drivers/clk/mediatek/clk-mt8186-apmixedsys.c | 65 +++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/med= iatek/clk-mt8186-apmixedsys.c index e692a2a67ce1..f4406d6ad4ea 100644 --- a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c @@ -9,6 +9,7 @@ =20 #include "clk-mtk.h" #include "clk-pll.h" +#include "clk-pllfh.h" =20 #define MT8186_PLL_FMAX (3800UL * MHZ) #define MT8186_PLL_FMIN (1500UL * MHZ) @@ -76,6 +77,59 @@ static const struct mtk_pll_data plls[] =3D { 0, 0, 32, 0x034C, 24, 0x0044, 0x000C, 5, 0x0350), }; =20 +enum fh_pll_id { + FH_ARMPLL_LL, + FH_ARMPLL_BL, + FH_CCIPLL, + FH_MAINPLL, + FH_MMPLL, + FH_TVDPLL, + FH_RESERVE6, + FH_ADSPPLL, + FH_MFGPLL, + FH_NNAPLL, + FH_NNA2PLL, + FH_MSDCPLL, + FH_RESERVE12, + FH_NR_FH, +}; + +#define FH(_pllid, _fhid, _offset) { \ + .data =3D { \ + .pll_id =3D _pllid, \ + .fh_id =3D _fhid, \ + .fhx_offset =3D _offset, \ + .dds_mask =3D GENMASK(21, 0), \ + .slope0_value =3D 0x6003c97, \ + .slope1_value =3D 0x6003c97, \ + .sfstrx_en =3D BIT(2), \ + .frddsx_en =3D BIT(1), \ + .fhctlx_en =3D BIT(0), \ + .tgl_org =3D BIT(31), \ + .dvfs_tri =3D BIT(31), \ + .pcwchg =3D BIT(31), \ + .dt_val =3D 0x0, \ + .df_val =3D 0x9, \ + .updnlmt_shft =3D 16, \ + .msk_frddsx_dys =3D GENMASK(23, 20), \ + .msk_frddsx_dts =3D GENMASK(19, 16), \ + }, \ + } + +static struct mtk_pllfh_data pllfhs[] =3D { + FH(CLK_APMIXED_ARMPLL_LL, FH_ARMPLL_LL, 0x003C), + FH(CLK_APMIXED_ARMPLL_BL, FH_ARMPLL_BL, 0x0050), + FH(CLK_APMIXED_CCIPLL, FH_CCIPLL, 0x0064), + FH(CLK_APMIXED_MAINPLL, FH_MAINPLL, 0x0078), + FH(CLK_APMIXED_MMPLL, FH_MMPLL, 0x008C), + FH(CLK_APMIXED_TVDPLL, FH_TVDPLL, 0x00A0), + FH(CLK_APMIXED_ADSPPLL, FH_ADSPPLL, 0x00C8), + FH(CLK_APMIXED_MFGPLL, FH_MFGPLL, 0x00DC), + FH(CLK_APMIXED_NNAPLL, FH_NNAPLL, 0x00F0), + FH(CLK_APMIXED_NNA2PLL, FH_NNA2PLL, 0x0104), + FH(CLK_APMIXED_MSDCPLL, FH_MSDCPLL, 0x0118), +}; + static const struct of_device_id of_match_clk_mt8186_apmixed[] =3D { { .compatible =3D "mediatek,mt8186-apmixedsys", }, {} @@ -91,7 +145,10 @@ static int clk_mt8186_apmixed_probe(struct platform_dev= ice *pdev) if (!clk_data) return -ENOMEM; =20 - r =3D mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + fhctl_parse_dt(pllfhs, ARRAY_SIZE(pllfhs)); + + r =3D mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls), + pllfhs, ARRAY_SIZE(pllfhs), clk_data); if (r) goto free_apmixed_data; =20 @@ -104,7 +161,8 @@ static int clk_mt8186_apmixed_probe(struct platform_dev= ice *pdev) return r; =20 unregister_plls: - mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, + ARRAY_SIZE(pllfhs), clk_data); free_apmixed_data: mtk_free_clk_data(clk_data); return r; @@ -116,7 +174,8 @@ static int clk_mt8186_apmixed_remove(struct platform_de= vice *pdev) struct clk_hw_onecell_data *clk_data =3D platform_get_drvdata(pdev); =20 of_clk_del_provider(node); - mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, + ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); =20 return 0; --=20 2.18.0