From patchwork Tue Apr 30 10:19:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Fan X-Patchwork-Id: 1093162 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=nxp.com header.i=@nxp.com header.b="cOkCwzRr"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 44td9t4S1Zz9sBV for ; Tue, 30 Apr 2019 20:31:46 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 275A1C21E18; Tue, 30 Apr 2019 10:28:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id C02C6C21EC3; Tue, 30 Apr 2019 10:20:56 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 8BF1FC21DD7; Tue, 30 Apr 2019 10:19:51 +0000 (UTC) Received: from EUR01-DB5-obe.outbound.protection.outlook.com (mail-eopbgr150082.outbound.protection.outlook.com [40.107.15.82]) by lists.denx.de (Postfix) with ESMTPS id 230D4C21DF9 for ; Tue, 30 Apr 2019 10:19:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xBYJw+SvSDOnkWybEkMsAt8kcijnOJcG90w+HZwRiBc=; b=cOkCwzRrzEf3NZFNDFmWbWgHNu8Z7n6iG2c7ML8llr8/oGa+vM5JYGYEJLL4k92FetTxIVZhnvjo5bPFo1eDFxbjS2PRRXuLHiU1bh8nVVWyHi4BtSYZ49FGMG+uMce/udS/N4kwGFWlcNOKKeyOaH6VkZ/X5v1DSJZGrsjQZWQ= Received: from AM0PR04MB4481.eurprd04.prod.outlook.com (52.135.147.15) by AM0PR04MB4593.eurprd04.prod.outlook.com (52.135.150.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1835.13; Tue, 30 Apr 2019 10:19:46 +0000 Received: from AM0PR04MB4481.eurprd04.prod.outlook.com ([fe80::3173:24:d401:2378]) by AM0PR04MB4481.eurprd04.prod.outlook.com ([fe80::3173:24:d401:2378%6]) with mapi id 15.20.1835.018; Tue, 30 Apr 2019 10:19:46 +0000 From: Peng Fan To: "sbabic@denx.de" , "festevam@gmail.com" , "lukma@denx.de" Thread-Topic: [i.MX8MM+CCF 38/41] clk: add composite clk support Thread-Index: AQHU/z48kv4ACLjLu02IdQYvy4UaFQ== Date: Tue, 30 Apr 2019 10:19:46 +0000 Message-ID: <20190430103056.32537-39-peng.fan@nxp.com> References: <20190430103056.32537-1-peng.fan@nxp.com> In-Reply-To: <20190430103056.32537-1-peng.fan@nxp.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.16.4 x-clientproxiedby: HK0PR03CA0057.apcprd03.prod.outlook.com (2603:1096:203:52::21) To AM0PR04MB4481.eurprd04.prod.outlook.com (2603:10a6:208:70::15) authentication-results: spf=none (sender IP is ) smtp.mailfrom=peng.fan@nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [119.31.174.71] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 5a8d7a9b-2da1-4526-4665-08d6cd555e9b x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600141)(711020)(4605104)(4618075)(2017052603328)(7193020); SRVR:AM0PR04MB4593; x-ms-traffictypediagnostic: AM0PR04MB4593: x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:6430; x-forefront-prvs: 00235A1EEF x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(376002)(366004)(136003)(346002)(39860400002)(396003)(199004)(189003)(5660300002)(256004)(36756003)(478600001)(53936002)(4326008)(54906003)(97736004)(316002)(6512007)(6506007)(102836004)(386003)(86362001)(73956011)(66946007)(66476007)(66556008)(2201001)(2501003)(64756008)(186003)(26005)(66446008)(6436002)(110136005)(305945005)(7736002)(71190400001)(71200400001)(2616005)(2906002)(50226002)(6116002)(8676002)(3846002)(1076003)(476003)(52116002)(25786009)(11346002)(44832011)(68736007)(446003)(76176011)(8936002)(6486002)(81156014)(81166006)(486006)(99286004)(14454004)(66066001); DIR:OUT; SFP:1101; SCL:1; SRVR:AM0PR04MB4593; H:AM0PR04MB4481.eurprd04.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: Af1CJIrIwQAD5eJEo9JuAiorgrTBg6C7YyzVsyywcalHw8yneV9kEKuxvUhy5YU/GHFjX3zMFt/mu42uvHOBz2BjelZuO0iOJ92XqLWQG+jvzsB41vTPrYoNqJdvXjSQjicEiqFNqG0FTx4H8v8jOzay4pggweeUCPiwBxDN21tjcCMBpk84x4VBFaI3ZisvuKheM93kVh776/sU9RRrg0bxDHQyYCW9wy8jqtCeKNKaBbhsapUi/FkrcwsWNNPR9AanqydwCoL60vUKWaDENt7TL0TfwwiRkppSiwO3pUVIV2IU1r/PEuQ4W6ygwnCUtXOSBhOLaUDEgnUscF9tOLOvxLASn9TIOjyTJjMmVUyjOdS/gXWlFkpKq0Oj0uttHyoeFZveSpEnqHoGzKUzaEXNvRHDnnr1TxkxlRNoiYE= MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5a8d7a9b-2da1-4526-4665-08d6cd555e9b X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Apr 2019 10:19:46.5011 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR04MB4593 Cc: "trini@konsulko.com" , "u-boot@lists.denx.de" , dl-uboot-imx , "sr@denx.de" Subject: [U-Boot] [i.MX8MM+CCF 38/41] clk: add composite clk support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Import clk composite clk support from Linux Kernel 5.1-rc5 Signed-off-by: Peng Fan --- drivers/clk/Kconfig | 14 ++++ drivers/clk/Makefile | 1 + drivers/clk/clk-composite.c | 165 +++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 22 ++++++ 4 files changed, 202 insertions(+) create mode 100644 drivers/clk/clk-composite.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9df3bc731a..3735e235f5 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -53,6 +53,13 @@ config SPL_CLK_CCF Enable this option if you want to (re-)use the Linux kernel's Common Clock Framework [CCF] code in U-Boot's SPL. +config SPL_CLK_COMPOSITE_CCF + bool "SPL Common Clock Framework [CCF] composite clk support " + depends on SPL_CLK_CCF + help + Enable this option if you want to (re-)use the Linux kernel's Common + Clock Framework [CCF] composite code in U-Boot's SPL. + config CLK_CCF bool "Common Clock Framework [CCF] support " depends on CLK @@ -60,6 +67,13 @@ config CLK_CCF Enable this option if you want to (re-)use the Linux kernel's Common Clock Framework [CCF] code in U-Boot's clock driver. +config CLK_COMPOSITE_CCF + bool "Common Clock Framework [CCF] composite clk support " + depends on CLK_CCF + help + Enable this option if you want to (re-)use the Linux kernel's Common + Clock Framework [CCF] composite code in U-Boot's clock driver. + config CLK_STM32F bool "Enable clock driver support for STM32F family" depends on CLK && (STM32F7 || STM32F4) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 0bc8f7e5ce..6c71b0fc16 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o +obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o obj-y += imx/ obj-y += tegra/ diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 0000000000..18adfd9850 --- /dev/null +++ b/drivers/clk/clk-composite.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. + * Copyright 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +#define UBOOT_DM_CLK_COMPOSITE "clk_composite" + +static u8 clk_composite_get_parent(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + struct clk *mux = composite->mux; + + return clk_mux_get_parent(mux); +} + +static int clk_composite_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + const struct clk_ops *mux_ops = composite->mux_ops; + struct clk *mux = composite->mux; + + return mux_ops->set_parent(mux, parent); +} + +static unsigned long clk_composite_recalc_rate(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + const struct clk_ops *rate_ops = composite->rate_ops; + struct clk *rate = composite->rate; + + return rate_ops->get_rate(rate); +} + +static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + const struct clk_ops *rate_ops = composite->rate_ops; + struct clk *clk_rate = composite->rate; + + return rate_ops->set_rate(clk_rate, rate); +} + +static int clk_composite_enable(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + const struct clk_ops *gate_ops = composite->gate_ops; + struct clk *gate = composite->gate; + + return gate_ops->enable(gate); +} + +static int clk_composite_disable(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite( + clk_dev_binded(clk) ? + (struct clk *)dev_get_driver_data(clk->dev) : clk); + const struct clk_ops *gate_ops = composite->gate_ops; + struct clk *gate = composite->gate; + + gate_ops->disable(gate); + + return 0; +} + +struct clk_ops clk_composite_ops = { + /* This will be set according to clk_register_composite */ +}; + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + struct clk *mux, const struct clk_ops *mux_ops, + struct clk *rate, const struct clk_ops *rate_ops, + struct clk *gate, const struct clk_ops *gate_ops, + unsigned long flags) +{ + struct clk *clk; + struct clk_composite *composite; + int ret; + struct clk_ops *composite_ops = &clk_composite_ops; + + composite = kzalloc(sizeof(*composite), GFP_KERNEL); + if (!composite) + return ERR_PTR(-ENOMEM); + + if (mux && mux_ops) { + composite->mux = mux; + composite->mux_ops = mux_ops; + if (mux_ops->set_parent) + composite_ops->set_parent = clk_composite_set_parent; + mux->data = (ulong)composite; + } + + if (rate && rate_ops) { + if (!rate_ops->get_rate) { + clk = ERR_PTR(-EINVAL); + goto err; + } + composite_ops->get_rate = clk_composite_recalc_rate; + + /* .set_rate requires either .round_rate or .determine_rate */ + if (rate_ops->set_rate) { + composite_ops->set_rate = + clk_composite_set_rate; + } + + composite->rate = rate; + composite->rate_ops = rate_ops; + rate->data = (ulong)composite; + } + + if (gate && gate_ops) { + if (!gate_ops->enable || !gate_ops->disable) { + clk = ERR_PTR(-EINVAL); + goto err; + } + + composite->gate = gate; + composite->gate_ops = gate_ops; + composite_ops->enable = clk_composite_enable; + composite_ops->disable = clk_composite_disable; + gate->data = (ulong)composite; + } + + clk = &composite->clk; + ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, (ulong)clk, + name, parent_names[clk_composite_get_parent(clk)]); + if (ret) { + clk = ERR_PTR(ret); + goto err; + } + + return clk; + +err: + kfree(composite); + return clk; +} + +U_BOOT_DRIVER(clk_composite) = { + .name = UBOOT_DM_CLK_COMPOSITE, + .id = UCLASS_CLK, + .ops = &clk_composite_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index b2bed768b6..490713adb6 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -119,6 +119,28 @@ struct clk_fixed_rate { #define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev)) +struct clk_composite { + struct clk clk; + struct clk_ops ops; + + struct clk *mux; + struct clk *rate; + struct clk *gate; + + const struct clk_ops *mux_ops; + const struct clk_ops *rate_ops; + const struct clk_ops *gate_ops; +}; + +#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk) + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + struct clk *mux_clk, const struct clk_ops *mux_ops, + struct clk *rate_clk, const struct clk_ops *rate_ops, + struct clk *gate_clk, const struct clk_ops *gate_ops, + unsigned long flags); + int clk_register(struct clk *clk, const char *drv_name, ulong drv_data, const char *name, const char *parent_name);