From patchwork Wed Jul 29 14:51:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 1338362 X-Patchwork-Delegate: eugen.hristev@microchip.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=microchip.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=microchip.com header.i=@microchip.com header.a=rsa-sha256 header.s=mchp header.b=nqbRw85j; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BGxQR30jBz9sSt for ; Thu, 30 Jul 2020 00:54:23 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 25EB18261C; Wed, 29 Jul 2020 16:53:01 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=quarantine dis=none) header.from=microchip.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=microchip.com header.i=@microchip.com header.b="nqbRw85j"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 03799825CD; Wed, 29 Jul 2020 16:52:22 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from esa1.microchip.iphmx.com (esa1.microchip.iphmx.com [68.232.147.91]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9B92A825EE for ; Wed, 29 Jul 2020 16:52:15 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=microchip.com Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=Claudiu.Beznea@microchip.com DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1596034335; x=1627570335; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=4w5muiMyO4cxp0GUZCUU8jUr6kRGhPVTr8yAba49k8I=; b=nqbRw85j4vEZL33OaekJeOIalrOV/YU6EkK3cjlgiaaQ8I2DfDeFp/ru 0HP6so3Agx1qTSjW2Gbrj0z8C+gywVue236H3Sz4kHNZdKvpCdaTHldWF mjh2UpdoVcI83z+WFkYcP4qw2TiC/vnpm7ujtbRayx2riSpRGW1CB3Nc+ u0noRCPZX9R1sGuQzGbcgL74hiJMgfukzIpqMm8OTseFQaIwnvzFXkyLE 4z8MYlBEWULiG3yDA3kEg1173efGnrcWvcThYeymvIQs0u+pAHJ8tYy17 eFnTbEM+VAbNFMdUBI8EA4NtLAZQzSk9uUXL6WH/UWMKn/a3lR2dxj8Iq Q==; IronPort-SDR: lbkwFWWKncpENkRsIjY50wT8pXSLED8ke8KfpW2E5jPH7oarL8i6GCDcE2w+443O9hbMlchv/F CixfML9eLqHY4kRLRJH6yqqIirP91CGLlTlepJwiAB75yer3szgXc02Zc0HGQcjRyd/e7I4N9D XVstj2LPKOC0iB+FY9XNDC9DPQOepr5lqE3hDCan/XmLoxk0nVpDohU6kFwDxFgW4RZJQOmx9y oN7D9o9HIsUZ5YkScnqlvw18+BAXQpJwkp7SHVzHTzYPav+WCoh/fcRZb4wNdDEIt3EBNFnbtH Gt0= X-IronPort-AV: E=Sophos;i="5.75,410,1589266800"; d="scan'208";a="89603769" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa1.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 29 Jul 2020 07:52:13 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1979.3; Wed, 29 Jul 2020 07:52:12 -0700 Received: from m18063-ThinkPad-T460p.microchip.com (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1979.3 via Frontend Transport; Wed, 29 Jul 2020 07:52:10 -0700 From: Claudiu Beznea To: , CC: , Subject: [PATCH 13/22] clk: at91: clk-master: add driver compatible with ccf Date: Wed, 29 Jul 2020 17:51:32 +0300 Message-ID: <1596034301-5428-14-git-send-email-claudiu.beznea@microchip.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1596034301-5428-1-git-send-email-claudiu.beznea@microchip.com> References: <1596034301-5428-1-git-send-email-claudiu.beznea@microchip.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean Add clk-master driver compatible with common clock framework. Signed-off-by: Claudiu Beznea --- drivers/clk/at91/Makefile | 2 +- drivers/clk/at91/clk-master.c | 156 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.h | 21 ++++++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-master.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 338582b88aee..a4e397066e1e 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,7 +3,7 @@ # ifdef CONFIG_CLK_CCF -obj-y += pmc.o sckc.o clk-main.o +obj-y += pmc.o sckc.o clk-main.o clk-master.o obj-$(CONFIG_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o else obj-y += compat.o diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c new file mode 100644 index 000000000000..1d388b6b2519 --- /dev/null +++ b/drivers/clk/at91/clk-master.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Master clock support for AT91 architectures. + * + * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries + * + * Author: Claudiu Beznea + * + * Based on drivers/clk/at91/clk-master.c from Linux. + */ + +#include +#include +#include +#include +#include +#include + +#include "pmc.h" + +#define UBOOT_DM_CLK_AT91_MASTER "at91-master-clk" + +#define MASTER_PRES_MASK 0x7 +#define MASTER_PRES_MAX MASTER_PRES_MASK +#define MASTER_DIV_SHIFT 8 +#define MASTER_DIV_MASK 0x3 + +struct clk_master { + void __iomem *base; + const struct clk_master_layout *layout; + const struct clk_master_characteristics *characteristics; + const u32 *mux_table; + const u32 *clk_mux_table; + u32 num_parents; + struct clk clk; + u8 id; +}; + +#define to_clk_master(_clk) container_of(_clk, struct clk_master, clk) + +static inline bool clk_master_ready(struct clk_master *master) +{ + unsigned int status; + + pmc_read(master->base, AT91_PMC_SR, &status); + + return !!(status & AT91_PMC_MCKRDY); +} + +static int clk_master_enable(struct clk *clk) +{ + struct clk_master *master = to_clk_master(clk); + + while (!clk_master_ready(master)) { + debug("waiting for mck %d\n", master->id); + cpu_relax(); + } + + return 0; +} + +static ulong clk_master_get_rate(struct clk *clk) +{ + struct clk_master *master = to_clk_master(clk); + const struct clk_master_layout *layout = master->layout; + const struct clk_master_characteristics *characteristics = + master->characteristics; + ulong rate = clk_get_parent_rate(clk); + unsigned int mckr; + u8 pres, div; + + if (!rate) + return 0; + + pmc_read(master->base, master->layout->offset, &mckr); + mckr &= layout->mask; + + pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK; + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; + + if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX) + rate /= 3; + else + rate >>= pres; + + rate /= characteristics->divisors[div]; + + if (rate < characteristics->output.min) + pr_warn("master clk is underclocked"); + else if (rate > characteristics->output.max) + pr_warn("master clk is overclocked"); + + return rate; +} + +static const struct clk_ops master_ops = { + .enable = clk_master_enable, + .get_rate = clk_master_get_rate, +}; + +struct clk *at91_clk_register_master(void __iomem *base, + const char *name, const char * const *parent_names, + int num_parents, const struct clk_master_layout *layout, + const struct clk_master_characteristics *characteristics, + const u32 *mux_table) +{ + struct clk_master *master; + struct clk *clk; + unsigned int val; + int ret; + + if (!base || !name || !num_parents || !parent_names || + !layout || !characteristics || !mux_table) + return ERR_PTR(-EINVAL); + + master = kzalloc(sizeof(*master), GFP_KERNEL); + if (!master) + return ERR_PTR(-ENOMEM); + + master->layout = layout; + master->characteristics = characteristics; + master->base = base; + master->num_parents = num_parents; + master->mux_table = mux_table; + + pmc_read(master->base, master->layout->offset, &val); + clk = &master->clk; + clk->flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL; + ret = clk_register(clk, UBOOT_DM_CLK_AT91_MASTER, name, + parent_names[val & AT91_PMC_CSS]); + if (ret) { + kfree(master); + clk = ERR_PTR(ret); + } + + return clk; +} + +U_BOOT_DRIVER(at91_master_clk) = { + .name = UBOOT_DM_CLK_AT91_MASTER, + .id = UCLASS_CLK, + .ops = &master_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +const struct clk_master_layout at91rm9200_master_layout = { + .mask = 0x31F, + .pres_shift = 2, + .offset = AT91_PMC_MCKR, +}; + +const struct clk_master_layout at91sam9x5_master_layout = { + .mask = 0x373, + .pres_shift = 4, + .offset = AT91_PMC_MCKR, +}; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index b24d2d89903d..33c7a66e84b5 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -19,6 +19,21 @@ struct clk_range { unsigned long max; }; +struct clk_master_layout { + u32 offset; + u32 mask; + u8 pres_shift; +}; + +extern const struct clk_master_layout at91rm9200_master_layout; +extern const struct clk_master_layout at91sam9x5_master_layout; + +struct clk_master_characteristics { + struct clk_range output; + u32 divisors[4]; + u8 have_div3_pres; +}; + struct clk_pll_characteristics { struct clk_range input; int num_output; @@ -59,6 +74,12 @@ sam9x60_clk_register_frac_pll(void __iomem *base, const char *name, const char *parent_name, u8 id, const struct clk_pll_characteristics *characteristics, const struct clk_pll_layout *layout, bool critical); +struct clk * +at91_clk_register_master(void __iomem *base, const char *name, + const char * const *parent_names, int num_parents, + const struct clk_master_layout *layout, + const struct clk_master_characteristics *characteristics, + const u32 *mux_table); int at91_clk_mux_val_to_index(const u32 *table, u32 num_parents, u32 val); int at91_clk_mux_index_to_val(const u32 *table, u32 num_parents, u32 index);