From patchwork Fri Jun 11 04:16:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490721 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=uKRTzuZw; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SGS2sQLz9sVb for ; Fri, 11 Jun 2021 14:16:48 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4D42C82EDE; Fri, 11 Jun 2021 06:16:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uKRTzuZw"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3119182F24; Fri, 11 Jun 2021 06:16:35 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x733.google.com (mail-qk1-x733.google.com [IPv6:2607:f8b0:4864:20::733]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id AF3F482ECD for ; Fri, 11 Jun 2021 06:16:30 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x733.google.com with SMTP id i67so29714214qkc.4 for ; Thu, 10 Jun 2021 21:16:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rLc1x5e5QvB0uXTpel4PXHIgyU1vBEP5uexZBfC4+Io=; b=uKRTzuZwLZu6DEK2fi7f92lvF21zp4097hPdho+hlW13sHhfhChguFKUZ+lj9Ti2QD 2v1nxCre+A6p3eiy4IhL6PXF1zPApKh/LPccJPsDKmwxcBwraWISVD0r6WXcZ/BEKcfP a07Bx1uTQHmfft3N7Uc+ZwPGMO6M+3VPDtVLNWpFBXtzRnD4fzOjfqvpbhjKXmwRi6xq abl/ukP81v0Leg0kfFQUvLbITYIJpGsPl2NPsu6HxjwlEFW8OEPgSjBgPnku+Ojh8n4D zmYOSo7brqCePDHEpxjuMmbVrndPCI9oS3j76nbJ2kKyfY9PraKdgx/o/HbB+SN2x/C3 10dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rLc1x5e5QvB0uXTpel4PXHIgyU1vBEP5uexZBfC4+Io=; b=cY0vRQe2B/J4dbyeu333BCE6mbckemHhlXeX3H/157j/8Ym4ayULJzoFfniIqmLFPS SW8vlUC+Em9rXPzJDjujwWaswWMRCno0oxfiSrl4+9cN4lFMlsbjMnyQ2ilVa+fNikse +UL/BDsfhVj2UTne7OeTazOiuQn80KlfjloLNUXNSVNtuPdI3PFUMTYrrwBxv+T8Yhb+ OEvDx41KIHUKu3fVR0m7lT1mOg781fY4EHKFQkjgD3BZ/r24Dt6ScuURqAScKtGG6Isa kHqMi2BP6PM0SsocQgxJyTHbUpIvlgs05PTbwG5kLE5Muk9/sr3vICwreXNOBJVCCn/r 6tXA== X-Gm-Message-State: AOAM532l9v+JbyF8MZ0ikAsrBXAb3UaBMzyPTfyzaxrO9GY0ET35gGgh sAtyllImHpF5pD2yBJ919tQ9Hqn3tAE= X-Google-Smtp-Source: ABdhPJyL3P0Z59jDNBd+J4HnFVUCTAK5fJTYqOH+k8ItZ2deBCkyxBZdErO3qpqPeOoZc275GeBWow== X-Received: by 2002:a37:454a:: with SMTP id s71mr2035773qka.88.1623384988032; Thu, 10 Jun 2021 21:16:28 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:27 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson , Simon Glass , Andreas Dannenberg , Lokesh Vutla , Philipp Tomsich Subject: [PATCH v3 01/11] clk: Allow force setting clock defaults before relocation Date: Fri, 11 Jun 2021 00:16:07 -0400 Message-Id: <20210611041617.1665833-2-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Since 291da96b8e ("clk: Allow clock defaults to be set during re-reloc state for SPL only") it has been impossible to set clock defaults before relocation. This is annoying on boards without SPL, since there is no way to set clock defaults before U-Boot proper. In particular, the aisram rate must be changed before relocation on the K210, since U-Boot will hang if we try and change the rate while we are using aisram. To get around this, extend the stage parameter to allow force setting defaults, even if they would be otherwise postponed for later. A device tree property was decided against because of the concerns in the original commit thread about the overhead of repeatedly parsing the device tree. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- Changes in v3: - Always define clk_defaults_stage, even if clk_set_defaults is a dummy Changes in v2: - Convert stage to enum drivers/clk/clk-uclass.c | 27 +++++++++++++++++---------- drivers/clk/rockchip/clk_rk3308.c | 2 +- drivers/core/device.c | 2 +- drivers/net/gmac_rockchip.c | 2 +- include/clk.h | 30 ++++++++++++++++++++++++++---- 5 files changed, 46 insertions(+), 17 deletions(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 53e7be764d..25b6a41855 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -207,7 +207,8 @@ static struct clk *clk_set_default_get_by_id(struct clk *clk) return c; } -static int clk_set_default_parents(struct udevice *dev, int stage) +static int clk_set_default_parents(struct udevice *dev, + enum clk_defaults_stage stage) { struct clk clk, parent_clk, *c, *p; int index; @@ -251,10 +252,10 @@ static int clk_set_default_parents(struct udevice *dev, int stage) * It cannot be done right now but need to wait after the * device is probed */ - if (stage == 0 && clk.dev == dev) + if (stage == CLK_DEFAULTS_PRE && clk.dev == dev) continue; - if (stage > 0 && clk.dev != dev) + if (stage != CLK_DEFAULTS_PRE && clk.dev != dev) /* do not setup twice the parent clocks */ continue; @@ -280,7 +281,8 @@ static int clk_set_default_parents(struct udevice *dev, int stage) return 0; } -static int clk_set_default_rates(struct udevice *dev, int stage) +static int clk_set_default_rates(struct udevice *dev, + enum clk_defaults_stage stage) { struct clk clk, *c; int index; @@ -320,10 +322,10 @@ static int clk_set_default_rates(struct udevice *dev, int stage) * It cannot be done right now but need to wait after the * device is probed */ - if (stage == 0 && clk.dev == dev) + if (stage == CLK_DEFAULTS_PRE && clk.dev == dev) continue; - if (stage > 0 && clk.dev != dev) + if (stage != CLK_DEFAULTS_PRE && clk.dev != dev) /* do not setup twice the parent clocks */ continue; @@ -346,16 +348,21 @@ fail: return ret; } -int clk_set_defaults(struct udevice *dev, int stage) +int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage) { int ret; if (!dev_has_ofnode(dev)) return 0; - /* If this not in SPL and pre-reloc state, don't take any action. */ + /* + * To avoid setting defaults twice, don't set them before relocation. + * However, still set them for SPL. And still set them if explicitly + * asked. + */ if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC))) - return 0; + if (stage != CLK_DEFAULTS_POST_FORCE) + return 0; debug("%s(%s)\n", __func__, dev_read_name(dev)); @@ -805,7 +812,7 @@ int clk_uclass_post_probe(struct udevice *dev) * where the DT is used to setup default parents and rates * using assigned-clocks */ - clk_set_defaults(dev, 1); + clk_set_defaults(dev, CLK_DEFAULTS_POST); return 0; } diff --git a/drivers/clk/rockchip/clk_rk3308.c b/drivers/clk/rockchip/clk_rk3308.c index 5a838b9e9a..5248e59685 100644 --- a/drivers/clk/rockchip/clk_rk3308.c +++ b/drivers/clk/rockchip/clk_rk3308.c @@ -1014,7 +1014,7 @@ static int rk3308_clk_probe(struct udevice *dev) rk3308_clk_init(dev); /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ - ret = clk_set_defaults(dev, 1); + ret = clk_set_defaults(dev, CLK_DEFAULTS_POST); if (ret) debug("%s clk_set_defaults failed %d\n", __func__, ret); diff --git a/drivers/core/device.c b/drivers/core/device.c index cb960f8ec4..9f1400768d 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -561,7 +561,7 @@ int device_probe(struct udevice *dev) * Process 'assigned-{clocks/clock-parents/clock-rates}' * properties */ - ret = clk_set_defaults(dev, 0); + ret = clk_set_defaults(dev, CLK_DEFAULTS_PRE); if (ret) goto fail; } diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index f909660484..04008d2b19 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -565,7 +565,7 @@ static int gmac_rockchip_probe(struct udevice *dev) ulong rate; int ret; - ret = clk_set_defaults(dev, 0); + ret = clk_set_defaults(dev, CLK_DEFAULTS_PRE); if (ret) debug("%s clk_set_defaults failed %d\n", __func__, ret); diff --git a/include/clk.h b/include/clk.h index ca6b85fa6f..f3c88fe68a 100644 --- a/include/clk.h +++ b/include/clk.h @@ -277,19 +277,41 @@ static inline int clk_release_all(struct clk *clk, int count) } #endif +/** + * enum clk_defaults_stage - What stage clk_set_defaults() is called at + * @CLK_DEFAULTS_PRE: Called before probe. Setting of defaults for clocks owned + * by this clock driver will be defered until after probing. + * @CLK_DEFAULTS_POST: Called after probe. Only defaults for clocks owned by + * this clock driver will be set. + * @CLK_DEFAULTS_POST_FORCE: Called after probe, and always set defaults, even + * before relocation. Usually, defaults are not set + * pre-relocation to avoid setting them twice (when + * the device is probed again post-relocation). This + * may incur a performance cost as device tree + * properties must be parsed for a second time. + * However, when not using SPL, pre-relocation may be + * the only time we can set defaults for some clocks + * (such as those used for the RAM we will relocate + * into). + */ +enum clk_defaults_stage { + CLK_DEFAULTS_PRE = 0, + CLK_DEFAULTS_POST = 1, + CLK_DEFAULTS_POST_FORCE, +}; + #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ CONFIG_IS_ENABLED(CLK) + /** * clk_set_defaults - Process 'assigned-{clocks/clock-parents/clock-rates}' * properties to configure clocks * * @dev: A device to process (the ofnode associated with this device * will be processed). - * @stage: A integer. 0 indicates that this is called before the device - * is probed. 1 indicates that this is called just after the - * device has been probed + * @stage: The stage of the probing process this function is called during. */ -int clk_set_defaults(struct udevice *dev, int stage); +int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage); #else static inline int clk_set_defaults(struct udevice *dev, int stage) { From patchwork Fri Jun 11 04:16:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490722 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=DzFGkv6b; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SGg3QDXz9sW4 for ; Fri, 11 Jun 2021 14:16:59 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E281082052; Fri, 11 Jun 2021 06:16:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="DzFGkv6b"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BFE2282F38; Fri, 11 Jun 2021 06:16:38 +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,FREEMAIL_FROM,SPF_HELO_NONE, T_FILL_THIS_FORM_SHORT autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [IPv6:2607:f8b0:4864:20::730]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DDA6F82EDB for ; Fri, 11 Jun 2021 06:16:30 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x730.google.com with SMTP id c124so29732273qkd.8 for ; Thu, 10 Jun 2021 21:16:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+BHWqKIS5NZBBjr3iF7xutEujyogiZoNylt0QRR0PyI=; b=DzFGkv6btfxQ2ywJ2s3WIitlhm/VhqNtM+GEFwM8t4qUjlQxoZ0qHldkZs+LXTy7Hw fXcaI8+tLN2mSvEoAoLoECGU6hnnivVLNvAnZ+6cr2/zBSv6UVe2T8e5CIdOmwW+bJM1 WLDNo5mN1f/0Dd8ac+jnVDSFb0jrYFIPmprndk9sZpMNj4p/+8Fkr6WwMH4SGF2ZWf00 vKHg4A1OO6B7j+VJEboU6y44z6XDeH9kx2RqFLSrV39pU1MOuGs/G6mZ46BZB3fZ8NgE z4judz81Um9w0iwdnHRCUk/mH9vOqQRm0bOdCiD+WgYnN9a4SzDyr/eoxEpqA605NFgd 4nUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+BHWqKIS5NZBBjr3iF7xutEujyogiZoNylt0QRR0PyI=; b=f92SspNe6KINpWTRAEE4AtsvlEWop5v1yWf+eOKZVtt24tMo0uSWpf7nbEXmEsujut OlSZjFPZrfpDBNZL9zOazCWwOr5hKFNso5sUCZfqhSv8/SnDQwnNxJP6OEjWKe/4eSpl 6f/vBVoIKQA2ezPm2KPFWmI4hDtcd2IhMTG9e3FNVIC0rfi9P7bK6WLcmoMjOIY4zSkr rXy7wCsw+lL7OOq19Vp1ZtKzZoInC5DEGtTYelrq6BRIxH9ukbAgu/KgL71+T+vC52Vf VhTZsRTtQ5QB8sTYpNq0ZSdFqE7Wxr3kfCSGHa8H+msugraM/ubJv4oVFlHu31gOqaMy TqtQ== X-Gm-Message-State: AOAM532zku+ZUkMCJmdnCgeBPbnlc2KzI8FVabgJT4kwqgFhOAhrll4q v/dAUXbgZiK9MF01QJZczX2C/3Xns/U= X-Google-Smtp-Source: ABdhPJx+NJj8MNDAUsaXtohESzBMKVy92TSZ3jOMWyda3pFf7wYxgFK3f739YVZ7z4mLT0ZI9EWWYw== X-Received: by 2002:a37:642:: with SMTP id 63mr1951428qkg.400.1623384988829; Thu, 10 Jun 2021 21:16:28 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:28 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 02/11] clk: k210: Rewrite to remove CCF Date: Fri, 11 Jun 2021 00:16:08 -0400 Message-Id: <20210611041617.1665833-3-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean This is effectively a complete rewrite to remove all dependency on CCF. The code is now smaller, and so is the binary. It also takes up less memory at runtime (since we don't have to create 40 udevices). In general, I am much happier with this driver as much of the complexity and late binding has been removed. The k210_*_params structs which were previously used to initialize CCF clocks are now used as the complete configuration. Since we can write our own division logic, we can now do away with several "half" clocks which only existed to provide constant factors of two. The clock IDs have been renumbered to remove unused clocks. This may not be the last time they are renumbered, since we have diverged with Linux. There are also still a few clocks left out which may need to be added back in. In general, I have tried to leave out behavioral changes. However, there is a small bugfix regarding ACLK. According to the technical reference manual, its mux comes *after* its divider (which is present only for PLL0). This would have required yet another intermediate clock to fix with CCF, but with the new driver it is just 2 lines of code :) Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) drivers/clk/kendryte/Kconfig | 2 +- drivers/clk/kendryte/clk.c | 848 +++++++++++------------- drivers/clk/kendryte/pll.c | 114 ++-- include/dt-bindings/clock/k210-sysctl.h | 94 ++- include/kendryte/pll.h | 26 +- 5 files changed, 499 insertions(+), 585 deletions(-) diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig index 073fca0781..0dc8e3f889 100644 --- a/drivers/clk/kendryte/Kconfig +++ b/drivers/clk/kendryte/Kconfig @@ -1,6 +1,6 @@ config CLK_K210 bool "Clock support for Kendryte K210" - depends on CLK && CLK_CCF && CLK_COMPOSITE_CCF + depends on CLK help This enables support clock driver for Kendryte K210 platforms. diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index 41c712e03f..34e8e742a6 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include @@ -14,77 +14,6 @@ #include #include -/* All methods are delegated to CCF clocks */ - -static ulong k210_clk_get_rate(struct clk *clk) -{ - struct clk *c; - int err = clk_get_by_id(clk->id, &c); - - if (err) - return err; - return clk_get_rate(c); -} - -static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *c; - int err = clk_get_by_id(clk->id, &c); - - if (err) - return err; - return clk_set_rate(c, rate); -} - -static int k210_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *c, *p; - int err = clk_get_by_id(clk->id, &c); - - if (err) - return err; - - err = clk_get_by_id(parent->id, &p); - if (err) - return err; - - return clk_set_parent(c, p); -} - -static int k210_clk_endisable(struct clk *clk, bool enable) -{ - struct clk *c; - int err = clk_get_by_id(clk->id, &c); - - if (err) - return err; - return enable ? clk_enable(c) : clk_disable(c); -} - -static int k210_clk_enable(struct clk *clk) -{ - return k210_clk_endisable(clk, true); -} - -static int k210_clk_disable(struct clk *clk) -{ - return k210_clk_endisable(clk, false); -} - -static const struct clk_ops k210_clk_ops = { - .set_rate = k210_clk_set_rate, - .get_rate = k210_clk_get_rate, - .set_parent = k210_clk_set_parent, - .enable = k210_clk_enable, - .disable = k210_clk_disable, -}; - -/* Parents for muxed clocks */ -static const char * const generic_sels[] = { "in0_half", "pll0_half" }; -/* The first clock is in0, which is filled in by k210_clk_probe */ -static const char *aclk_sels[] = { NULL, "pll0_half" }; -static const char *pll2_sels[] = { NULL, "pll0", "pll1" }; - /* * All parameters for different sub-clocks are collected into parameter arrays. * These parameters are then initialized by the clock which uses them during @@ -97,68 +26,113 @@ static const char *pll2_sels[] = { NULL, "pll0", "pll1" }; * easy to find bugs in the code. */ -#define DIV(id, off, shift, width) DIV_FLAGS(id, off, shift, width, 0) +/** + * enum k210_clk_div_type - The type of divider + * @K210_DIV_ONE: freq = parent / (reg + 1) + * @K210_DIV_EVEN: freq = parent / 2 / (reg + 1) + * @K210_DIV_POWER: freq = parent / (2 << reg) + * @K210_DIV_FIXED: freq = parent / factor + */ +enum k210_clk_div_type { + K210_DIV_ONE, + K210_DIV_EVEN, + K210_DIV_POWER, + K210_DIV_FIXED, +}; + +/** + * struct k210_div_params - Parameters for dividing clocks + * @type: An &enum k210_clk_div_type specifying the dividing formula + * @off: The offset of the divider from the sysctl base address + * @shift: The offset of the LSB of the divider + * @width: The number of bits in the divider + * @div: The fixed divisor for this divider + */ +struct k210_div_params { + u8 type; + union { + struct { + u8 off; + u8 shift; + u8 width; + }; + u8 div; + }; +}; + #define DIV_LIST \ - DIV_FLAGS(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, \ - CLK_DIVIDER_POWER_OF_TWO) \ - DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3) \ - DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3) \ - DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3) \ - DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4) \ - DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4) \ - DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4) \ - DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4) \ - DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4) \ - DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8) \ - DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8) \ - DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8) \ - DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8) \ - DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8) \ - DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8) \ - DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8) \ - DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16) \ - DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16) \ - DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16) \ - DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8) \ - DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8) \ - DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8) \ - DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8) \ - DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8) \ - DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8) \ - DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8) \ - DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8) + DIV(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, K210_DIV_POWER) \ + DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3, K210_DIV_ONE) \ + DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3, K210_DIV_ONE) \ + DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3, K210_DIV_ONE) \ + DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4, K210_DIV_ONE) \ + DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4, K210_DIV_ONE) \ + DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4, K210_DIV_ONE) \ + DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4, K210_DIV_ONE) \ + DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4, K210_DIV_ONE) \ + DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8, K210_DIV_EVEN) \ + DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8, K210_DIV_EVEN) \ + DIV_FIXED(K210_CLK_CLINT, 50) \ #define _DIVIFY(id) K210_CLK_DIV_##id #define DIVIFY(id) _DIVIFY(id) -enum k210_div_ids { -#define DIV_FLAGS(id, ...) DIVIFY(id), +enum k210_div_id { +#define DIV(id, ...) DIVIFY(id), +#define DIV_FIXED DIV DIV_LIST -#undef DIV_FLAGS -}; - -struct k210_div_params { - u8 off; - u8 shift; - u8 width; - u8 flags; +#undef DIV +#undef DIV_FIXED + K210_CLK_DIV_NONE, }; static const struct k210_div_params k210_divs[] = { -#define DIV_FLAGS(id, _off, _shift, _width, _flags) \ +#define DIV(id, _off, _shift, _width, _type) \ [DIVIFY(id)] = { \ + .type = (_type), \ .off = (_off), \ .shift = (_shift), \ .width = (_width), \ - .flags = (_flags), \ + }, +#define DIV_FIXED(id, _div) \ + [DIVIFY(id)] = { \ + .type = K210_DIV_FIXED, \ + .div = (_div) \ }, DIV_LIST -#undef DIV_FLAGS +#undef DIV +#undef DIV_FIXED }; #undef DIV #undef DIV_LIST +/** + * struct k210_gate_params - Parameters for gated clocks + * @off: The offset of the gate from the sysctl base address + * @bit_idx: The index of the bit within the register + */ +struct k210_gate_params { + u8 off; + u8 bit_idx; +}; + #define GATE_LIST \ GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \ GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \ @@ -199,15 +173,11 @@ static const struct k210_div_params k210_divs[] = { #define _GATEIFY(id) K210_CLK_GATE_##id #define GATEIFY(id) _GATEIFY(id) -enum k210_gate_ids { +enum k210_gate_id { #define GATE(id, ...) GATEIFY(id), GATE_LIST #undef GATE -}; - -struct k210_gate_params { - u8 off; - u8 bit_idx; + K210_CLK_GATE_NONE, }; static const struct k210_gate_params k210_gates[] = { @@ -222,11 +192,31 @@ static const struct k210_gate_params k210_gates[] = { #undef GATE_LIST +/* The most parents is PLL2 */ +#define K210_CLK_MAX_PARENTS 3 + +/** + * struct k210_mux_params - Parameters for muxed clocks + * @parents: A list of parent clock ids + * @num_parents: The number of parent clocks + * @off: The offset of the mux from the base sysctl address + * @shift: The offset of the LSB of the mux selector + * @width: The number of bits in the mux selector + */ +struct k210_mux_params { + u8 parents[K210_CLK_MAX_PARENTS]; + u8 num_parents; + u8 off; + u8 shift; + u8 width; +}; + #define MUX(id, reg, shift, width) \ - MUX_PARENTS(id, generic_sels, reg, shift, width) + MUX_PARENTS(id, reg, shift, width, K210_CLK_IN0, K210_CLK_PLL0) #define MUX_LIST \ - MUX_PARENTS(K210_CLK_PLL2, pll2_sels, K210_SYSCTL_PLL2, 26, 2) \ - MUX_PARENTS(K210_CLK_ACLK, aclk_sels, K210_SYSCTL_SEL0, 0, 1) \ + MUX_PARENTS(K210_CLK_PLL2, K210_SYSCTL_PLL2, 26, 2, \ + K210_CLK_IN0, K210_CLK_PLL0, K210_CLK_PLL1) \ + MUX(K210_CLK_ACLK, K210_SYSCTL_SEL0, 0, 1) \ MUX(K210_CLK_SPI3, K210_SYSCTL_SEL0, 12, 1) \ MUX(K210_CLK_TIMER0, K210_SYSCTL_SEL0, 13, 1) \ MUX(K210_CLK_TIMER1, K210_SYSCTL_SEL0, 14, 1) \ @@ -235,26 +225,18 @@ static const struct k210_gate_params k210_gates[] = { #define _MUXIFY(id) K210_CLK_MUX_##id #define MUXIFY(id) _MUXIFY(id) -enum k210_mux_ids { +enum k210_mux_id { #define MUX_PARENTS(id, ...) MUXIFY(id), MUX_LIST #undef MUX_PARENTS K210_CLK_MUX_NONE, }; -struct k210_mux_params { - const char *const *parent_names; - u8 num_parents; - u8 off; - u8 shift; - u8 width; -}; - static const struct k210_mux_params k210_muxes[] = { -#define MUX_PARENTS(id, parents, _off, _shift, _width) \ +#define MUX_PARENTS(id, _off, _shift, _width, ...) \ [MUXIFY(id)] = { \ - .parent_names = (const char * const *)(parents), \ - .num_parents = ARRAY_SIZE(parents), \ + .parents = { __VA_ARGS__ }, \ + .num_parents = __count_args(__VA_ARGS__), \ .off = (_off), \ .shift = (_shift), \ .width = (_width), \ @@ -266,389 +248,321 @@ static const struct k210_mux_params k210_muxes[] = { #undef MUX #undef MUX_LIST -struct k210_pll_params { - u8 off; - u8 lock_off; - u8 shift; - u8 width; +/** + * enum k210_clk_flags - The type of a K210 clock + * @K210_CLKF_MUX: This clock has a mux and not a static parent + * @K210_CLKF_PLL: This clock is a PLL + */ +enum k210_clk_flags { + K210_CLKF_MUX = BIT(0), + K210_CLKF_PLL = BIT(1), }; -static const struct k210_pll_params k210_plls[] = { -#define PLL(_off, _shift, _width) { \ - .off = (_off), \ - .lock_off = K210_SYSCTL_PLL_LOCK, \ - .shift = (_shift), \ - .width = (_width), \ -} - [0] = PLL(K210_SYSCTL_PLL0, 0, 2), - [1] = PLL(K210_SYSCTL_PLL1, 8, 1), - [2] = PLL(K210_SYSCTL_PLL2, 16, 1), -#undef PLL +/** + * struct k210_clk_params - The parameters defining a K210 clock + * @name: The name of the clock + * @flags: A set of &enum k210_clk_flags defining which fields are valid + * @mux: An &enum k210_mux_id of this clock's mux + * @parent: The clock id of this clock's parent + * @pll: The id of the PLL (if this clock is a PLL) + * @div: An &enum k210_div_id of this clock's divider + * @gate: An &enum k210_gate_id of this clock's gate + */ +struct k210_clk_params { +#if CONFIG_IS_ENABLED(CMD_CLK) + const char *name; +#endif + u8 flags; + union { + u8 parent; + u8 mux; + }; + union { + u8 pll; + struct { + u8 div; + u8 gate; + }; + }; }; -#define COMP(id) \ - COMP_FULL(id, MUXIFY(id), DIVIFY(id), GATEIFY(id)) -#define COMP_NOMUX(id) \ - COMP_FULL(id, K210_CLK_MUX_NONE, DIVIFY(id), GATEIFY(id)) -#define COMP_LIST \ - COMP(K210_CLK_SPI3) \ - COMP(K210_CLK_TIMER0) \ - COMP(K210_CLK_TIMER1) \ - COMP(K210_CLK_TIMER2) \ - COMP_NOMUX(K210_CLK_SRAM0) \ - COMP_NOMUX(K210_CLK_SRAM1) \ - COMP_NOMUX(K210_CLK_ROM) \ - COMP_NOMUX(K210_CLK_DVP) \ - COMP_NOMUX(K210_CLK_APB0) \ - COMP_NOMUX(K210_CLK_APB1) \ - COMP_NOMUX(K210_CLK_APB2) \ - COMP_NOMUX(K210_CLK_AI) \ - COMP_NOMUX(K210_CLK_I2S0) \ - COMP_NOMUX(K210_CLK_I2S1) \ - COMP_NOMUX(K210_CLK_I2S2) \ - COMP_NOMUX(K210_CLK_WDT0) \ - COMP_NOMUX(K210_CLK_WDT1) \ - COMP_NOMUX(K210_CLK_SPI0) \ - COMP_NOMUX(K210_CLK_SPI1) \ - COMP_NOMUX(K210_CLK_SPI2) \ - COMP_NOMUX(K210_CLK_I2C0) \ - COMP_NOMUX(K210_CLK_I2C1) \ - COMP_NOMUX(K210_CLK_I2C2) -#define _COMPIFY(id) K210_CLK_COMP_##id -#define COMPIFY(id) _COMPIFY(id) - -enum k210_comp_ids { -#define COMP_FULL(id, ...) COMPIFY(id), - COMP_LIST -#undef COMP_FULL -}; - -struct k210_comp_params { - u8 mux; - u8 div; - u8 gate; -}; - -static const struct k210_comp_params k210_comps[] = { -#define COMP_FULL(id, _mux, _div, _gate) \ - [COMPIFY(id)] = { \ +static const struct k210_clk_params k210_clks[] = { +#if CONFIG_IS_ENABLED(CMD_CLK) +#define NAME(_name) .name = (_name), +#else +#define NAME(name) +#endif +#define CLK(id, _name, _parent, _div, _gate) \ + [id] = { \ + NAME(_name) \ + .parent = (_parent), \ + .div = (_div), \ + .gate = (_gate), \ + } +#define CLK_MUX(id, _name, _mux, _div, _gate) \ + [id] = { \ + NAME(_name) \ + .flags = K210_CLKF_MUX, \ .mux = (_mux), \ .div = (_div), \ .gate = (_gate), \ + } +#define CLK_PLL(id, _pll, _parent) \ + [id] = { \ + NAME("pll" #_pll) \ + .flags = K210_CLKF_PLL, \ + .parent = (_parent), \ + .pll = (_pll), \ + } +#define CLK_FULL(id, name) \ + CLK_MUX(id, name, MUXIFY(id), DIVIFY(id), GATEIFY(id)) +#define CLK_NOMUX(id, name, parent) \ + CLK(id, name, parent, DIVIFY(id), GATEIFY(id)) +#define CLK_DIV(id, name, parent) \ + CLK(id, name, parent, DIVIFY(id), K210_CLK_GATE_NONE) +#define CLK_GATE(id, name, parent) \ + CLK(id, name, parent, K210_CLK_DIV_NONE, GATEIFY(id)) + CLK_PLL(K210_CLK_PLL0, 0, K210_CLK_IN0), + CLK_PLL(K210_CLK_PLL1, 1, K210_CLK_IN0), + [K210_CLK_PLL2] = { + NAME("pll2") + .flags = K210_CLKF_MUX | K210_CLKF_PLL, + .mux = MUXIFY(K210_CLK_PLL2), + .pll = 2, }, - COMP_LIST -#undef COMP_FULL + CLK_MUX(K210_CLK_ACLK, "aclk", MUXIFY(K210_CLK_ACLK), + DIVIFY(K210_CLK_ACLK), K210_CLK_GATE_NONE), + CLK_FULL(K210_CLK_SPI3, "spi3"), + CLK_FULL(K210_CLK_TIMER0, "timer0"), + CLK_FULL(K210_CLK_TIMER1, "timer1"), + CLK_FULL(K210_CLK_TIMER2, "timer2"), + CLK_NOMUX(K210_CLK_SRAM0, "sram0", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_SRAM1, "sram1", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_ROM, "rom", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_DVP, "dvp", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_APB0, "apb0", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_APB1, "apb1", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_APB2, "apb2", K210_CLK_ACLK), + CLK_NOMUX(K210_CLK_AI, "ai", K210_CLK_PLL1), + CLK_NOMUX(K210_CLK_I2S0, "i2s0", K210_CLK_PLL2), + CLK_NOMUX(K210_CLK_I2S1, "i2s1", K210_CLK_PLL2), + CLK_NOMUX(K210_CLK_I2S2, "i2s2", K210_CLK_PLL2), + CLK_NOMUX(K210_CLK_WDT0, "wdt0", K210_CLK_IN0), + CLK_NOMUX(K210_CLK_WDT1, "wdt1", K210_CLK_IN0), + CLK_NOMUX(K210_CLK_SPI0, "spi0", K210_CLK_PLL0), + CLK_NOMUX(K210_CLK_SPI1, "spi1", K210_CLK_PLL0), + CLK_NOMUX(K210_CLK_SPI2, "spi2", K210_CLK_PLL0), + CLK_NOMUX(K210_CLK_I2C0, "i2c0", K210_CLK_PLL0), + CLK_NOMUX(K210_CLK_I2C1, "i2c1", K210_CLK_PLL0), + CLK_NOMUX(K210_CLK_I2C2, "i2c2", K210_CLK_PLL0), + CLK_DIV(K210_CLK_I2S0_M, "i2s0_m", K210_CLK_PLL2), + CLK_DIV(K210_CLK_I2S1_M, "i2s1_m", K210_CLK_PLL2), + CLK_DIV(K210_CLK_I2S2_M, "i2s2_m", K210_CLK_PLL2), + CLK_DIV(K210_CLK_CLINT, "clint", K210_CLK_ACLK), + CLK_GATE(K210_CLK_CPU, "cpu", K210_CLK_ACLK), + CLK_GATE(K210_CLK_DMA, "dma", K210_CLK_ACLK), + CLK_GATE(K210_CLK_FFT, "fft", K210_CLK_ACLK), + CLK_GATE(K210_CLK_GPIO, "gpio", K210_CLK_APB0), + CLK_GATE(K210_CLK_UART1, "uart1", K210_CLK_APB0), + CLK_GATE(K210_CLK_UART2, "uart2", K210_CLK_APB0), + CLK_GATE(K210_CLK_UART3, "uart3", K210_CLK_APB0), + CLK_GATE(K210_CLK_FPIOA, "fpioa", K210_CLK_APB0), + CLK_GATE(K210_CLK_SHA, "sha", K210_CLK_APB0), + CLK_GATE(K210_CLK_AES, "aes", K210_CLK_APB1), + CLK_GATE(K210_CLK_OTP, "otp", K210_CLK_APB1), + CLK_GATE(K210_CLK_RTC, "rtc", K210_CLK_IN0), +#undef NAME +#undef CLK_PLL +#undef CLK +#undef CLK_FULL +#undef CLK_NOMUX +#undef CLK_DIV +#undef CLK_GATE +#undef CLK_LIST }; -#undef COMP -#undef COMP_ID -#undef COMP_NOMUX -#undef COMP_NOMUX_ID -#undef COMP_LIST - -static struct clk *k210_bypass_children __section(".data"); - -/* Helper functions to create sub-clocks */ -static struct clk_mux *k210_create_mux(const struct k210_mux_params *params, - void *base) +static u32 k210_clk_readl(struct k210_clk_priv *priv, u8 off, u8 shift, + u8 width) { - struct clk_mux *mux = kzalloc(sizeof(*mux), GFP_KERNEL); + u32 reg = readl(priv->base + off); - if (!mux) - return mux; - - mux->reg = base + params->off; - mux->mask = BIT(params->width) - 1; - mux->shift = params->shift; - mux->parent_names = params->parent_names; - mux->num_parents = params->num_parents; - - return mux; + return (reg >> shift) & (BIT(width) - 1); } -static struct clk_divider *k210_create_div(const struct k210_div_params *params, - void *base) +static void k210_clk_writel(struct k210_clk_priv *priv, u8 off, u8 shift, + u8 width, u32 val) { - struct clk_divider *div = kzalloc(sizeof(*div), GFP_KERNEL); + u32 reg = readl(priv->base + off); + u32 mask = (BIT(width) - 1) << shift; - if (!div) - return div; - - div->reg = base + params->off; - div->shift = params->shift; - div->width = params->width; - div->flags = params->flags; - - return div; + reg &= ~mask; + reg |= mask & (val << shift); + writel(reg, priv->base + off); } -static struct clk_gate *k210_create_gate(const struct k210_gate_params *params, - void *base) +static int k210_clk_get_parent(struct k210_clk_priv *priv, int id) { - struct clk_gate *gate = kzalloc(sizeof(*gate), GFP_KERNEL); + u32 sel; + const struct k210_mux_params *mux; - if (!gate) - return gate; + if (!(k210_clks[id].flags & K210_CLKF_MUX)) + return k210_clks[id].parent; + mux = &k210_muxes[k210_clks[id].mux]; - gate->reg = base + params->off; - gate->bit_idx = params->bit_idx; - - return gate; + sel = k210_clk_readl(priv, mux->off, mux->shift, mux->width); + assert(sel < mux->num_parents); + return mux->parents[sel]; } -static struct k210_pll *k210_create_pll(const struct k210_pll_params *params, - void *base) +static ulong do_k210_clk_get_rate(struct k210_clk_priv *priv, int id) { - struct k210_pll *pll = kzalloc(sizeof(*pll), GFP_KERNEL); + int parent; + u32 val; + ulong parent_rate; + const struct k210_div_params *div; - if (!pll) - return pll; + if (id == K210_CLK_IN0) + return clk_get_rate(&priv->in0); - pll->reg = base + params->off; - pll->lock = base + params->lock_off; - pll->shift = params->shift; - pll->width = params->width; + parent = k210_clk_get_parent(priv, id); + parent_rate = do_k210_clk_get_rate(priv, parent); - return pll; + if (k210_clks[id].flags & K210_CLKF_PLL) + return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate); + + if (k210_clks[id].div == K210_CLK_DIV_NONE) + return parent_rate; + div = &k210_divs[k210_clks[id].div]; + + if (div->type == K210_DIV_FIXED) + return parent_rate / div->div; + + val = k210_clk_readl(priv, div->off, div->shift, div->width); + switch (div->type) { + case K210_DIV_ONE: + return parent_rate / (val + 1); + case K210_DIV_EVEN: + return parent_rate / 2 / (val + 1); + case K210_DIV_POWER: + /* This is ACLK, which has no divider on IN0 */ + if (parent == K210_CLK_IN0) + return parent_rate; + return parent_rate / (2 << val); + default: + assert(false); + return -EINVAL; + }; } -/* Create all sub-clocks, and then register the composite clock */ -static struct clk *k210_register_comp(const struct k210_comp_params *params, - void *base, const char *name, - const char *parent) +static ulong k210_clk_get_rate(struct clk *clk) { - const char *const *parent_names; - int num_parents; - struct clk *comp; - const struct clk_ops *mux_ops; - struct clk_mux *mux; - struct clk_divider *div; - struct clk_gate *gate; + return do_k210_clk_get_rate(dev_get_priv(clk->dev), clk->id); +} - if (params->mux == K210_CLK_MUX_NONE) { - if (!parent) - return ERR_PTR(-EINVAL); +static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate) +{ + return -ENOSYS; +} - mux_ops = NULL; - mux = NULL; - parent_names = &parent; - num_parents = 1; - } else { - mux_ops = &clk_mux_ops; - mux = k210_create_mux(&k210_muxes[params->mux], base); - if (!mux) - return ERR_PTR(-ENOMEM); +static int do_k210_clk_set_parent(struct k210_clk_priv *priv, int id, int new) +{ + int i; + const struct k210_mux_params *mux; - parent_names = mux->parent_names; - num_parents = mux->num_parents; + if (!(k210_clks[id].flags & K210_CLKF_MUX)) + return -ENOSYS; + mux = &k210_muxes[k210_clks[id].mux]; + + for (i = 0; i < mux->num_parents; i++) { + if (mux->parents[i] == new) { + k210_clk_writel(priv, mux->off, mux->shift, mux->width, + i); + return 0; + } + } + return -EINVAL; +} + +static int k210_clk_set_parent(struct clk *clk, struct clk *parent) +{ + return do_k210_clk_set_parent(dev_get_priv(clk->dev), clk->id, + parent->id); +} + +static int k210_clk_endisable(struct k210_clk_priv *priv, int id, bool enable) +{ + int parent = k210_clk_get_parent(priv, id); + const struct k210_gate_params *gate; + + if (id == K210_CLK_IN0) { + if (enable) + return clk_enable(&priv->in0); + else + return clk_disable(&priv->in0); } - div = k210_create_div(&k210_divs[params->div], base); - if (!div) { - comp = ERR_PTR(-ENOMEM); - goto cleanup_mux; + /* Only recursively enable clocks since we don't track refcounts */ + if (enable) { + int ret = k210_clk_endisable(priv, parent, true); + + if (ret && ret != -ENOSYS) + return ret; } - gate = k210_create_gate(&k210_gates[params->gate], base); - if (!gate) { - comp = ERR_PTR(-ENOMEM); - goto cleanup_div; + if (k210_clks[id].flags & K210_CLKF_PLL) { + if (enable) + return k210_pll_enable(priv, k210_clks[id].pll); + else + return k210_pll_disable(priv, k210_clks[id].pll); } - comp = clk_register_composite(NULL, name, parent_names, num_parents, - &mux->clk, mux_ops, - &div->clk, &clk_divider_ops, - &gate->clk, &clk_gate_ops, 0); - if (IS_ERR(comp)) - goto cleanup_gate; - return comp; + if (k210_clks[id].gate == K210_CLK_GATE_NONE) + return -ENOSYS; + gate = &k210_gates[k210_clks[id].gate]; -cleanup_gate: - free(gate); -cleanup_div: - free(div); -cleanup_mux: - free(mux); - return comp; -} - -static bool __section(".data") probed; - -/* reset probed so we will probe again post-relocation */ -static int k210_clk_bind(struct udevice *dev) -{ - probed = false; + k210_clk_writel(priv, gate->off, gate->bit_idx, 1, enable); return 0; } +static int k210_clk_enable(struct clk *clk) +{ + return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, true); +} + +static int k210_clk_disable(struct clk *clk) +{ + return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, false); +} + +static int k210_clk_request(struct clk *clk) +{ + if (clk->id >= ARRAY_SIZE(k210_clks)) + return -EINVAL; + return 0; +} + +static const struct clk_ops k210_clk_ops = { + .request = k210_clk_request, + .set_rate = k210_clk_set_rate, + .get_rate = k210_clk_get_rate, + .set_parent = k210_clk_set_parent, + .enable = k210_clk_enable, + .disable = k210_clk_disable, +}; + static int k210_clk_probe(struct udevice *dev) { int ret; - const char *in0; - struct clk *in0_clk, *bypass; - struct clk_mux *mux; - struct clk_divider *div; - struct k210_pll *pll; - void *base; + struct k210_clk_priv *priv = dev_get_priv(dev); - /* - * Only one instance of this driver allowed. This prevents weird bugs - * when the driver fails part-way through probing. Some clocks will - * already have been registered, and re-probing will register them - * again, creating a bunch of duplicates. Better error-handling/cleanup - * could fix this, but it's Probably Not Worth It (TM). - */ - if (probed) + priv->base = dev_read_addr_ptr(dev_get_parent(dev)); + if (!priv->base) return -EINVAL; - base = dev_read_addr_ptr(dev_get_parent(dev)); - if (!base) - return -EINVAL; - - in0_clk = kzalloc(sizeof(*in0_clk), GFP_KERNEL); - if (!in0_clk) - return -ENOMEM; - - ret = clk_get_by_index(dev, 0, in0_clk); + ret = clk_get_by_index(dev, 0, &priv->in0); if (ret) return ret; - in0 = in0_clk->dev->name; - - probed = true; - - aclk_sels[0] = in0; - pll2_sels[0] = in0; - - /* - * All PLLs have a broken bypass, but pll0 has the CPU downstream, so we - * need to manually reparent it whenever we configure pll0 - */ - pll = k210_create_pll(&k210_plls[0], base); - if (pll) { - bypass = k210_register_bypass("pll0", in0, &pll->clk, - &k210_pll_ops, in0_clk); - clk_dm(K210_CLK_PLL0, bypass); - } else { - return -ENOMEM; - } - - pll = k210_create_pll(&k210_plls[1], base); - if (pll) - clk_dm(K210_CLK_PLL1, - k210_register_pll_struct("pll1", in0, pll)); - - /* PLL2 is muxed, so set up a composite clock */ - mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_PLL2)], base); - pll = k210_create_pll(&k210_plls[2], base); - if (!mux || !pll) { - free(mux); - free(pll); - } else { - clk_dm(K210_CLK_PLL2, - clk_register_composite(NULL, "pll2", pll2_sels, - ARRAY_SIZE(pll2_sels), - &mux->clk, &clk_mux_ops, - &pll->clk, &k210_pll_ops, - &pll->clk, &k210_pll_ops, 0)); - } - - /* Half-frequency clocks for "even" dividers */ - clk_dm(K210_CLK_IN0_H, k210_clk_half("in0_half", in0)); - clk_dm(K210_CLK_PLL0_H, k210_clk_half("pll0_half", "pll0")); - clk_dm(K210_CLK_PLL2_H, k210_clk_half("pll2_half", "pll2")); - - /* ACLK has no gate */ - mux = k210_create_mux(&k210_muxes[MUXIFY(K210_CLK_ACLK)], base); - div = k210_create_div(&k210_divs[DIVIFY(K210_CLK_ACLK)], base); - if (!mux || !div) { - free(mux); - free(div); - } else { - struct clk *aclk = - clk_register_composite(NULL, "aclk", aclk_sels, - ARRAY_SIZE(aclk_sels), - &mux->clk, &clk_mux_ops, - &div->clk, &clk_divider_ops, - NULL, NULL, 0); - clk_dm(K210_CLK_ACLK, aclk); - if (!IS_ERR(aclk)) { - k210_bypass_children = aclk; - k210_bypass_set_children(bypass, - &k210_bypass_children, 1); - } - } - -#define REGISTER_COMP(id, name) \ - clk_dm(id, \ - k210_register_comp(&k210_comps[COMPIFY(id)], base, name, NULL)) - REGISTER_COMP(K210_CLK_SPI3, "spi3"); - REGISTER_COMP(K210_CLK_TIMER0, "timer0"); - REGISTER_COMP(K210_CLK_TIMER1, "timer1"); - REGISTER_COMP(K210_CLK_TIMER2, "timer2"); -#undef REGISTER_COMP - - /* Dividing clocks, no mux */ -#define REGISTER_COMP_NOMUX(id, name, parent) \ - clk_dm(id, \ - k210_register_comp(&k210_comps[COMPIFY(id)], base, name, parent)) - REGISTER_COMP_NOMUX(K210_CLK_SRAM0, "sram0", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_SRAM1, "sram1", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_ROM, "rom", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_DVP, "dvp", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_APB0, "apb0", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_APB1, "apb1", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_APB2, "apb2", "aclk"); - REGISTER_COMP_NOMUX(K210_CLK_AI, "ai", "pll1"); - REGISTER_COMP_NOMUX(K210_CLK_I2S0, "i2s0", "pll2_half"); - REGISTER_COMP_NOMUX(K210_CLK_I2S1, "i2s1", "pll2_half"); - REGISTER_COMP_NOMUX(K210_CLK_I2S2, "i2s2", "pll2_half"); - REGISTER_COMP_NOMUX(K210_CLK_WDT0, "wdt0", "in0_half"); - REGISTER_COMP_NOMUX(K210_CLK_WDT1, "wdt1", "in0_half"); - REGISTER_COMP_NOMUX(K210_CLK_SPI0, "spi0", "pll0_half"); - REGISTER_COMP_NOMUX(K210_CLK_SPI1, "spi1", "pll0_half"); - REGISTER_COMP_NOMUX(K210_CLK_SPI2, "spi2", "pll0_half"); - REGISTER_COMP_NOMUX(K210_CLK_I2C0, "i2c0", "pll0_half"); - REGISTER_COMP_NOMUX(K210_CLK_I2C1, "i2c1", "pll0_half"); - REGISTER_COMP_NOMUX(K210_CLK_I2C2, "i2c2", "pll0_half"); -#undef REGISTER_COMP_NOMUX - - /* Dividing clocks */ -#define REGISTER_DIV(id, name, parent) do {\ - const struct k210_div_params *params = &k210_divs[DIVIFY(id)]; \ - clk_dm(id, \ - clk_register_divider(NULL, name, parent, 0, base + params->off, \ - params->shift, params->width, 0)); \ -} while (false) - REGISTER_DIV(K210_CLK_I2S0_M, "i2s0_m", "pll2_half"); - REGISTER_DIV(K210_CLK_I2S1_M, "i2s1_m", "pll2_half"); - REGISTER_DIV(K210_CLK_I2S2_M, "i2s2_m", "pll2_half"); -#undef REGISTER_DIV - - /* Gated clocks */ -#define REGISTER_GATE(id, name, parent) do { \ - const struct k210_gate_params *params = &k210_gates[GATEIFY(id)]; \ - clk_dm(id, \ - clk_register_gate(NULL, name, parent, 0, base + params->off, \ - params->bit_idx, 0, NULL)); \ -} while (false) - REGISTER_GATE(K210_CLK_CPU, "cpu", "aclk"); - REGISTER_GATE(K210_CLK_DMA, "dma", "aclk"); - REGISTER_GATE(K210_CLK_FFT, "fft", "aclk"); - REGISTER_GATE(K210_CLK_GPIO, "gpio", "apb0"); - REGISTER_GATE(K210_CLK_UART1, "uart1", "apb0"); - REGISTER_GATE(K210_CLK_UART2, "uart2", "apb0"); - REGISTER_GATE(K210_CLK_UART3, "uart3", "apb0"); - REGISTER_GATE(K210_CLK_FPIOA, "fpioa", "apb0"); - REGISTER_GATE(K210_CLK_SHA, "sha", "apb0"); - REGISTER_GATE(K210_CLK_AES, "aes", "apb1"); - REGISTER_GATE(K210_CLK_OTP, "otp", "apb1"); - REGISTER_GATE(K210_CLK_RTC, "rtc", in0); -#undef REGISTER_GATE - - /* The MTIME register in CLINT runs at one 50th the CPU clock speed */ - clk_dm(K210_CLK_CLINT, - clk_register_fixed_factor(NULL, "clint", "aclk", 0, 1, 50)); return 0; } @@ -663,6 +577,6 @@ U_BOOT_DRIVER(k210_clk) = { .id = UCLASS_CLK, .of_match = k210_clk_ids, .ops = &k210_clk_ops, - .bind = k210_clk_bind, .probe = k210_clk_probe, + .priv_auto = sizeof(struct k210_clk_priv), }; diff --git a/drivers/clk/kendryte/pll.c b/drivers/clk/kendryte/pll.c index 184f37aaf2..1f0275c83f 100644 --- a/drivers/clk/kendryte/pll.c +++ b/drivers/clk/kendryte/pll.c @@ -12,17 +12,41 @@ #include #include #include +#include #include #include #include #include #include -#define CLK_K210_PLL "k210_clk_pll" +/** + * struct k210_pll_params - K210 PLL parameters + * @off: The offset of the PLL from the base sysctl address + * @shift: The offset of the LSB of the lock status + * @width: The number of bits in the lock status + */ +struct k210_pll_params { + u8 off; + u8 shift; + u8 width; +}; + +static const struct k210_pll_params k210_plls[] = { +#define PLL(_off, _shift, _width) { \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ +} + [0] = PLL(K210_SYSCTL_PLL0, 0, 2), + [1] = PLL(K210_SYSCTL_PLL1, 8, 1), + [2] = PLL(K210_SYSCTL_PLL2, 16, 1), +#undef PLL +}; #ifdef CONFIG_CLK_K210_SET_RATE -static int k210_pll_enable(struct clk *clk); -static int k210_pll_disable(struct clk *clk); +int k210_pll_enable(struct k210_clk_priv *priv, int id); +int k210_pll_disable(struct k210_clk_priv *priv, int id); +ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); /* * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc. @@ -423,12 +447,12 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, return 0; } -static ulong k210_pll_set_rate(struct clk *clk, ulong rate) +static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, + ulong rate_in) { int err; - long long rate_in = clk_get_parent_rate(clk); + const struct k210_pll_params *pll = &k210_plls[id]; struct k210_pll_config config = {}; - struct k210_pll *pll = to_k210_pll(clk); u32 reg; if (rate_in < 0) @@ -447,7 +471,7 @@ static ulong k210_pll_set_rate(struct clk *clk, ulong rate) */ k210_pll_disable(clk); - reg = readl(pll->reg); + reg = readl(priv->base + pll->off); reg &= ~K210_PLL_CLKR & ~K210_PLL_CLKF & ~K210_PLL_CLKOD @@ -456,7 +480,7 @@ static ulong k210_pll_set_rate(struct clk *clk, ulong rate) | FIELD_PREP(K210_PLL_CLKF, config.f - 1) | FIELD_PREP(K210_PLL_CLKOD, config.od - 1) | FIELD_PREP(K210_PLL_BWADJ, config.f - 1); - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); err = k210_pll_enable(clk); if (err) @@ -465,14 +489,18 @@ static ulong k210_pll_set_rate(struct clk *clk, ulong rate) serial_setbrg(); return clk_get_rate(clk); } +#else +ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, + ulong rate_in) +{ + return -ENOSYS; +} #endif /* CONFIG_CLK_K210_SET_RATE */ -static ulong k210_pll_get_rate(struct clk *clk) +ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in) { - long long rate_in = clk_get_parent_rate(clk); - struct k210_pll *pll = to_k210_pll(clk); u64 r, f, od; - u32 reg = readl(pll->reg); + u32 reg = readl(priv->base + k210_plls[id].off); if (rate_in < 0 || (reg & K210_PLL_BYPASS)) return rate_in; @@ -491,57 +519,58 @@ static ulong k210_pll_get_rate(struct clk *clk) * Wait for the PLL to be locked. If the PLL is not locked, try clearing the * slip before retrying */ -static void k210_pll_waitfor_lock(struct k210_pll *pll) +void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id) { + const struct k210_pll_params *pll = &k210_plls[id]; u32 mask = GENMASK(pll->width - 1, 0) << pll->shift; while (true) { - u32 reg = readl(pll->lock); + u32 reg = readl(priv->base + K210_SYSCTL_PLL_LOCK); if ((reg & mask) == mask) break; reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP); - writel(reg, pll->lock); + writel(reg, priv->base + K210_SYSCTL_PLL_LOCK); } } /* Adapted from sysctl_pll_enable */ -static int k210_pll_enable(struct clk *clk) +int k210_pll_enable(struct k210_clk_priv *priv, int id) { - struct k210_pll *pll = to_k210_pll(clk); - u32 reg = readl(pll->reg); + const struct k210_pll_params *pll = &k210_plls[id]; + u32 reg = readl(priv->base + pll->off); if ((reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) && !(reg & K210_PLL_RESET)) return 0; reg |= K210_PLL_PWRD; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); /* Ensure reset is low before asserting it */ reg &= ~K210_PLL_RESET; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); reg |= K210_PLL_RESET; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); nop(); nop(); reg &= ~K210_PLL_RESET; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); - k210_pll_waitfor_lock(pll); + k210_pll_waitfor_lock(priv, id); reg &= ~K210_PLL_BYPASS; reg |= K210_PLL_EN; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); return 0; } -static int k210_pll_disable(struct clk *clk) +int k210_pll_disable(struct k210_clk_priv *priv, int id) { - struct k210_pll *pll = to_k210_pll(clk); - u32 reg = readl(pll->reg); + const struct k210_pll_params *pll = &k210_plls[id]; + u32 reg = readl(priv->base + pll->off); /* * Bypassing before powering off is important so child clocks don't stop @@ -549,37 +578,10 @@ static int k210_pll_disable(struct clk *clk) * of the cpu clock. */ reg |= K210_PLL_BYPASS; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); reg &= ~K210_PLL_PWRD; reg &= ~K210_PLL_EN; - writel(reg, pll->reg); + writel(reg, priv->base + pll->off); return 0; } - -const struct clk_ops k210_pll_ops = { - .get_rate = k210_pll_get_rate, -#ifdef CONFIG_CLK_K210_SET_RATE - .set_rate = k210_pll_set_rate, -#endif - .enable = k210_pll_enable, - .disable = k210_pll_disable, -}; - -struct clk *k210_register_pll_struct(const char *name, const char *parent_name, - struct k210_pll *pll) -{ - int ret; - struct clk *clk = &pll->clk; - - ret = clk_register(clk, CLK_K210_PLL, name, parent_name); - if (ret) - return ERR_PTR(ret); - return clk; -} - -U_BOOT_DRIVER(k210_pll) = { - .name = CLK_K210_PLL, - .id = UCLASS_CLK, - .ops = &k210_pll_ops, -}; diff --git a/include/dt-bindings/clock/k210-sysctl.h b/include/dt-bindings/clock/k210-sysctl.h index fe852bbd92..6b0d5b46f8 100644 --- a/include/dt-bindings/clock/k210-sysctl.h +++ b/include/dt-bindings/clock/k210-sysctl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright (C) 2019-20 Sean Anderson + * Copyright (C) 2019-21 Sean Anderson */ #ifndef CLOCK_K210_SYSCTL_H @@ -9,52 +9,50 @@ /* * Arbitrary identifiers for clocks. */ -#define K210_CLK_NONE 0 -#define K210_CLK_IN0_H 1 -#define K210_CLK_PLL0_H 2 -#define K210_CLK_PLL0 3 -#define K210_CLK_PLL1 4 -#define K210_CLK_PLL2 5 -#define K210_CLK_PLL2_H 6 -#define K210_CLK_CPU 7 -#define K210_CLK_SRAM0 8 -#define K210_CLK_SRAM1 9 -#define K210_CLK_APB0 10 -#define K210_CLK_APB1 11 -#define K210_CLK_APB2 12 -#define K210_CLK_ROM 13 -#define K210_CLK_DMA 14 -#define K210_CLK_AI 15 -#define K210_CLK_DVP 16 -#define K210_CLK_FFT 17 -#define K210_CLK_GPIO 18 -#define K210_CLK_SPI0 19 -#define K210_CLK_SPI1 20 -#define K210_CLK_SPI2 21 -#define K210_CLK_SPI3 22 -#define K210_CLK_I2S0 23 -#define K210_CLK_I2S1 24 -#define K210_CLK_I2S2 25 -#define K210_CLK_I2S0_M 26 -#define K210_CLK_I2S1_M 27 -#define K210_CLK_I2S2_M 28 -#define K210_CLK_I2C0 29 -#define K210_CLK_I2C1 30 -#define K210_CLK_I2C2 31 -#define K210_CLK_UART1 32 -#define K210_CLK_UART2 33 -#define K210_CLK_UART3 34 -#define K210_CLK_AES 35 -#define K210_CLK_FPIOA 36 -#define K210_CLK_TIMER0 37 -#define K210_CLK_TIMER1 38 -#define K210_CLK_TIMER2 39 -#define K210_CLK_WDT0 40 -#define K210_CLK_WDT1 41 -#define K210_CLK_SHA 42 -#define K210_CLK_OTP 43 -#define K210_CLK_RTC 44 -#define K210_CLK_ACLK 45 -#define K210_CLK_CLINT 46 + +#define K210_CLK_PLL0 0 +#define K210_CLK_PLL1 1 +#define K210_CLK_PLL2 2 +#define K210_CLK_CPU 3 +#define K210_CLK_SRAM0 4 +#define K210_CLK_SRAM1 5 +#define K210_CLK_ACLK 6 +#define K210_CLK_CLINT 7 +#define K210_CLK_APB0 8 +#define K210_CLK_APB1 9 +#define K210_CLK_APB2 10 +#define K210_CLK_ROM 11 +#define K210_CLK_DMA 12 +#define K210_CLK_AI 13 +#define K210_CLK_DVP 14 +#define K210_CLK_FFT 15 +#define K210_CLK_GPIO 16 +#define K210_CLK_SPI0 17 +#define K210_CLK_SPI1 18 +#define K210_CLK_SPI2 19 +#define K210_CLK_SPI3 20 +#define K210_CLK_I2S0 21 +#define K210_CLK_I2S1 22 +#define K210_CLK_I2S2 23 +#define K210_CLK_I2S0_M 24 +#define K210_CLK_I2S1_M 25 +#define K210_CLK_I2S2_M 26 +#define K210_CLK_I2C0 27 +#define K210_CLK_I2C1 28 +#define K210_CLK_I2C2 29 +#define K210_CLK_UART1 30 +#define K210_CLK_UART2 31 +#define K210_CLK_UART3 32 +#define K210_CLK_AES 33 +#define K210_CLK_FPIOA 34 +#define K210_CLK_TIMER0 35 +#define K210_CLK_TIMER1 36 +#define K210_CLK_TIMER2 37 +#define K210_CLK_WDT0 38 +#define K210_CLK_WDT1 39 +#define K210_CLK_SHA 40 +#define K210_CLK_OTP 41 +#define K210_CLK_RTC 42 +#define K210_CLK_IN0 43 #endif /* CLOCK_K210_SYSCTL_H */ diff --git a/include/kendryte/pll.h b/include/kendryte/pll.h index 95b8494f40..16fd5a5b68 100644 --- a/include/kendryte/pll.h +++ b/include/kendryte/pll.h @@ -25,16 +25,6 @@ #define K210_PLL_CLEAR_SLIP 2 #define K210_PLL_TEST_OUT 3 -struct k210_pll { - struct clk clk; - void __iomem *reg; /* Base PLL register */ - void __iomem *lock; /* Common PLL lock register */ - u8 shift; /* Offset of bits in lock register */ - u8 width; /* Width of lock bits to test against */ -}; - -#define to_k210_pll(_clk) container_of(_clk, struct k210_pll, clk) - struct k210_pll_config { u8 r; u8 f; @@ -51,8 +41,18 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, #endif -extern const struct clk_ops k210_pll_ops; +/** + * struct k210_clk_priv - K210 clock driver private data + * @base: The base address of the sysctl device + * @in0: The "in0" external oscillator + */ +struct k210_clk_priv { + void __iomem *base; + struct clk in0; +}; -struct clk *k210_register_pll_struct(const char *name, const char *parent_name, - struct k210_pll *pll); +ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, ulong rate_in); +ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); +int k210_pll_enable(struct k210_clk_priv *priv, int id); +int k210_pll_disable(struct k210_clk_priv *priv, int id); #endif /* K210_PLL_H */ From patchwork Fri Jun 11 04:16:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490724 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=pI49FuFE; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SH51lwTz9sVb for ; Fri, 11 Jun 2021 14:17:21 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9F99582F19; Fri, 11 Jun 2021 06:16:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="pI49FuFE"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DAF5882F3A; Fri, 11 Jun 2021 06:16:41 +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,FREEMAIL_FROM,SPF_HELO_NONE, T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x82a.google.com (mail-qt1-x82a.google.com [IPv6:2607:f8b0:4864:20::82a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id AB88D82052 for ; Fri, 11 Jun 2021 06:16:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x82a.google.com with SMTP id g12so1681446qtb.2 for ; Thu, 10 Jun 2021 21:16:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nyIJl2RG1bWlDQk/hLWuWSWP/6PDti/nzHnGiGSZA3U=; b=pI49FuFEO/5AFjplHPzgARu6M/eHzo7Jy8MtqjIr1e4ogUpcQFUdn2RaXuDq1ykC4T 1ZSo8Eswp4NLX5qUO/JAN55qNi/WIqE8iQfh0OfIoM39Fa7VsAKPnzdZXJ3t7YEafPXY m0eKUUyGiOb0a2zxZPpRAc1CVzNYp34PiZFiP75El6pvnq7rvZG7r9tr8V51veuY4Iyq M37NasY9ASnoLF/krg3qxQvhxtvhXR/v9HXruwpRCshGjo7u6Zj64AEGIOrvgQcRlCCX EE9bdflHqf9WD7mO1nLBiV/Cnj8cG1Sw2uc1DSmb5Bk0wZv6G/H2M0P3pwzmT1CGUsmk jGZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nyIJl2RG1bWlDQk/hLWuWSWP/6PDti/nzHnGiGSZA3U=; b=qSGMADDvdojWnBA/k1htHXyS2b6WWnXJQhygBRz/4VWClfzHl6FcdDNEUpkugsixxT vrIin/OYwMcl8vJ9KOgh4l0ANo40dMlv9mqNLJpOM4xgPILO7U4nupP+fGdi5Ri6Rauo isA1lnqQ6BsPb093FY4f61gu+GgzJud4hpVufvE1WsgYbJDCX+4sqHIOknzVZnoHVfXc 8fQSlL9Pa/A7qdRw/bP9jImlEf5wJ+xXylyxK/X/xdbyRlxJ5sEaUEMcTM4qnbgZgeLO kBOVnuq9fHndhunNtucw5HTL5SvBMu30ZD2HfbVEjGS0jb++3HKR2dBHp2QtF6DJ3Uj0 qWtA== X-Gm-Message-State: AOAM533xeYY+OEOyNWk+9aFanMhDuTCg+fRJyCpDdcC/AACuvtmKEoT+ 47Kf7/D0ApvLhyR36ezYYL1oe5vvV14= X-Google-Smtp-Source: ABdhPJzDFWmnxGmcfLk6HGrhmss9buq1NIBw/uBj8kri/hyLQek+D3+fV1L7ivU8dkpCbPNI6H2SGA== X-Received: by 2002:a05:622a:40b:: with SMTP id n11mr2136002qtx.60.1623384989577; Thu, 10 Jun 2021 21:16:29 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:29 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 03/11] clk: k210: Move pll into the rest of the driver Date: Fri, 11 Jun 2021 00:16:09 -0400 Message-Id: <20210611041617.1665833-4-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Now that there no separate PLL driver, we can no longer make the PLL functions static. By moving the PLL driver in with the rest of the clock code, we can make these functions static again. We still keep the pll header for unit testing, but it is pretty reduced. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/clk.c | 606 +++++++++++++++++++++++++++++++++- drivers/clk/kendryte/pll.c | 587 -------------------------------- include/kendryte/clk.h | 35 -- include/kendryte/pll.h | 34 -- 5 files changed, 601 insertions(+), 663 deletions(-) delete mode 100644 drivers/clk/kendryte/pll.c delete mode 100644 include/kendryte/clk.h diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index 6fb68253ae..6710a1db72 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += bypass.o clk.o pll.o +obj-y += bypass.o clk.o diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index 34e8e742a6..de9db84361 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -2,17 +2,30 @@ /* * Copyright (C) 2019-20 Sean Anderson */ -#include +#define LOG_CATEGORY UCLASS_CLK #include -#include -#include +#include +#include +#include #include #include #include - -#include +#include +#include +#include #include +#include + +/** + * struct k210_clk_priv - K210 clock driver private data + * @base: The base address of the sysctl device + * @in0: The "in0" external oscillator + */ +struct k210_clk_priv { + void __iomem *base; + struct clk in0; +}; /* * All parameters for different sub-clocks are collected into parameter arrays. @@ -248,6 +261,30 @@ static const struct k210_mux_params k210_muxes[] = { #undef MUX #undef MUX_LIST +/** + * struct k210_pll_params - K210 PLL parameters + * @off: The offset of the PLL from the base sysctl address + * @shift: The offset of the LSB of the lock status + * @width: The number of bits in the lock status + */ +struct k210_pll_params { + u8 off; + u8 shift; + u8 width; +}; + +static const struct k210_pll_params k210_plls[] = { +#define PLL(_off, _shift, _width) { \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ +} + [0] = PLL(K210_SYSCTL_PLL0, 0, 2), + [1] = PLL(K210_SYSCTL_PLL1, 8, 1), + [2] = PLL(K210_SYSCTL_PLL2, 16, 1), +#undef PLL +}; + /** * enum k210_clk_flags - The type of a K210 clock * @K210_CLKF_MUX: This clock has a mux and not a static parent @@ -286,7 +323,6 @@ struct k210_clk_params { }; }; - static const struct k210_clk_params k210_clks[] = { #if CONFIG_IS_ENABLED(CMD_CLK) #define NAME(_name) .name = (_name), @@ -382,6 +418,564 @@ static const struct k210_clk_params k210_clks[] = { #undef CLK_LIST }; +#define K210_PLL_CLKR GENMASK(3, 0) +#define K210_PLL_CLKF GENMASK(9, 4) +#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */ +#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */ +#define K210_PLL_RESET BIT(20) +#define K210_PLL_PWRD BIT(21) /* PoWeReD */ +#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */ +#define K210_PLL_BYPASS BIT(23) +#define K210_PLL_TEST BIT(24) +#define K210_PLL_EN BIT(25) +#define K210_PLL_TEST_EN BIT(26) + +#define K210_PLL_LOCK 0 +#define K210_PLL_CLEAR_SLIP 2 +#define K210_PLL_TEST_OUT 3 + +#ifdef CONFIG_CLK_K210_SET_RATE +static int k210_pll_enable(struct k210_clk_priv *priv, int id); +static int k210_pll_disable(struct k210_clk_priv *priv, int id); +static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); + +/* + * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc. + * General-Purpose PLL. The logical layout of the PLL with internal feedback is + * approximately the following: + * + * +---------------+ + * |reference clock| + * +---------------+ + * | + * v + * +--+ + * |/r| + * +--+ + * | + * v + * +-------------+ + * |divided clock| + * +-------------+ + * | + * v + * +--------------+ + * |phase detector|<---+ + * +--------------+ | + * | | + * v +--------------+ + * +---+ |feedback clock| + * |VCO| +--------------+ + * +---+ ^ + * | +--+ | + * +--->|/f|---+ + * | +--+ + * v + * +---+ + * |/od| + * +---+ + * | + * v + * +------+ + * |output| + * +------+ + * + * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode, + * the effect of the division by f is to multiply the input frequency. The + * equation for the output rate is + * rate = (rate_in * f) / (r * od). + * Moving knowns to one side of the equation, we get + * rate / rate_in = f / (r * od) + * Rearranging slightly, + * abs_error = abs((rate / rate_in) - (f / (r * od))). + * To get relative, error, we divide by the expected ratio + * error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in). + * Simplifying, + * error = abs(1 - f / (r * od)) / (rate / rate_in) + * error = abs(1 - (f * rate_in) / (r * od * rate)) + * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate, + * error = abs((f * inv_ratio) / (r * od) - 1) + * This is the error used in evaluating parameters. + * + * r and od are four bits each, while f is six bits. Because r and od are + * multiplied together, instead of the full 256 values possible if both bits + * were used fully, there are only 97 distinct products. Combined with f, there + * are 6208 theoretical settings for the PLL. However, most of these settings + * can be ruled out immediately because they do not have the correct ratio. + * + * In addition to the constraint of approximating the desired ratio, parameters + * must also keep internal pll frequencies within acceptable ranges. The divided + * clock's minimum and maximum frequencies have a ratio of around 128. This + * leaves fairly substantial room to work with, especially since the only + * affected parameter is r. The VCO's minimum and maximum frequency have a ratio + * of 5, which is considerably more restrictive. + * + * The r and od factors are stored in a table. This is to make it easy to find + * the next-largest product. Some products have multiple factorizations, but + * only when one factor has at least a 2.5x ratio to the factors of the other + * factorization. This is because any smaller ratio would not make a difference + * when ensuring the VCO's frequency is within spec. + * + * Throughout the calculation function, fixed point arithmetic is used. Because + * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit + * 32.32 fixed-point numbers are used to represent ratios. In general, to + * implement division, the numerator is first multiplied by 2^32. This gives a + * result where the whole number part is in the upper 32 bits, and the fraction + * is in the lower 32 bits. + * + * In general, rounding is done to the closest integer. This helps find the best + * approximation for the ratio. Rounding in one direction (e.g down) could cause + * the function to miss a better ratio with one of the parameters increased by + * one. + */ + +/* + * The factors table was generated with the following python code: + * + * def p(x, y): + * return (1.0*x/y > 2.5) or (1.0*y/x > 2.5) + * + * factors = {} + * for i in range(1, 17): + * for j in range(1, 17): + * fs = factors.get(i*j) or [] + * if fs == [] or all([ + * (p(i, x) and p(i, y)) or (p(j, x) and p(j, y)) + * for (x, y) in fs]): + * fs.append((i, j)) + * factors[i*j] = fs + * + * for k, l in sorted(factors.items()): + * for v in l: + * print("PACK(%s, %s)," % v) + */ +#define PACK(r, od) (((((r) - 1) & 0xF) << 4) | (((od) - 1) & 0xF)) +#define UNPACK_R(val) ((((val) >> 4) & 0xF) + 1) +#define UNPACK_OD(val) (((val) & 0xF) + 1) +static const u8 factors[] = { + PACK(1, 1), + PACK(1, 2), + PACK(1, 3), + PACK(1, 4), + PACK(1, 5), + PACK(1, 6), + PACK(1, 7), + PACK(1, 8), + PACK(1, 9), + PACK(3, 3), + PACK(1, 10), + PACK(1, 11), + PACK(1, 12), + PACK(3, 4), + PACK(1, 13), + PACK(1, 14), + PACK(1, 15), + PACK(3, 5), + PACK(1, 16), + PACK(4, 4), + PACK(2, 9), + PACK(2, 10), + PACK(3, 7), + PACK(2, 11), + PACK(2, 12), + PACK(5, 5), + PACK(2, 13), + PACK(3, 9), + PACK(2, 14), + PACK(2, 15), + PACK(2, 16), + PACK(3, 11), + PACK(5, 7), + PACK(3, 12), + PACK(3, 13), + PACK(4, 10), + PACK(3, 14), + PACK(4, 11), + PACK(3, 15), + PACK(3, 16), + PACK(7, 7), + PACK(5, 10), + PACK(4, 13), + PACK(6, 9), + PACK(5, 11), + PACK(4, 14), + PACK(4, 15), + PACK(7, 9), + PACK(4, 16), + PACK(5, 13), + PACK(6, 11), + PACK(5, 14), + PACK(6, 12), + PACK(5, 15), + PACK(7, 11), + PACK(6, 13), + PACK(5, 16), + PACK(9, 9), + PACK(6, 14), + PACK(8, 11), + PACK(6, 15), + PACK(7, 13), + PACK(6, 16), + PACK(7, 14), + PACK(9, 11), + PACK(10, 10), + PACK(8, 13), + PACK(7, 15), + PACK(9, 12), + PACK(10, 11), + PACK(7, 16), + PACK(9, 13), + PACK(8, 15), + PACK(11, 11), + PACK(9, 14), + PACK(8, 16), + PACK(10, 13), + PACK(11, 12), + PACK(9, 15), + PACK(10, 14), + PACK(11, 13), + PACK(9, 16), + PACK(10, 15), + PACK(11, 14), + PACK(12, 13), + PACK(10, 16), + PACK(11, 15), + PACK(12, 14), + PACK(13, 13), + PACK(11, 16), + PACK(12, 15), + PACK(13, 14), + PACK(12, 16), + PACK(13, 15), + PACK(14, 14), + PACK(13, 16), + PACK(14, 15), + PACK(14, 16), + PACK(15, 15), + PACK(15, 16), + PACK(16, 16), +}; + +TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, + struct k210_pll_config *best) +{ + int i; + s64 error, best_error; + u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */ + u64 max_r; + u64 r, f, od; + + /* + * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the + * VCO frequency. These are not the same limits as below because od can + * reduce the output frequency by 16. + */ + if (rate > 1750000000 || rate < 21250000) + return -EINVAL; + + /* Similar restrictions on the input rate */ + if (rate_in > 1750000000 || rate_in < 13300000) + return -EINVAL; + + ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in); + inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate); + /* Can't increase by more than 64 or reduce by more than 256 */ + if (rate > rate_in && ratio > (64ULL << 32)) + return -EINVAL; + else if (rate <= rate_in && inv_ratio > (256ULL << 32)) + return -EINVAL; + + /* + * The divided clock (rate_in / r) must stay between 1.75 GHz and 13.3 + * MHz. There is no minimum, since the only way to get a higher input + * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs + * cannot output frequencies greater than 1.75 GHz, the minimum would + * never be greater than one. + */ + max_r = DIV_ROUND_DOWN_ULL(rate_in, 13300000); + + /* Variables get immediately incremented, so start at -1th iteration */ + i = -1; + f = 0; + r = 0; + od = 0; + best_error = S64_MAX; + error = best_error; + /* do-while here so we always try at least one ratio */ + do { + /* + * Whether we swapped r and od while enforcing frequency limits + */ + bool swapped = false; + u64 last_od = od; + u64 last_r = r; + + /* + * Try the next largest value for f (or r and od) and + * recalculate the other parameters based on that + */ + if (rate > rate_in) { + /* + * Skip factors of the same product if we already tried + * out that product + */ + do { + i++; + r = UNPACK_R(factors[i]); + od = UNPACK_OD(factors[i]); + } while (i + 1 < ARRAY_SIZE(factors) && + r * od == last_r * last_od); + + /* Round close */ + f = (r * od * ratio + BIT(31)) >> 32; + if (f > 64) + f = 64; + } else { + u64 tmp = ++f * inv_ratio; + bool round_up = !!(tmp & BIT(31)); + u32 goal = (tmp >> 32) + round_up; + u32 err, last_err; + + /* Get the next r/od pair in factors */ + while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) { + i++; + r = UNPACK_R(factors[i]); + od = UNPACK_OD(factors[i]); + } + + /* + * This is a case of double rounding. If we rounded up + * above, we need to round down (in cases of ties) here. + * This prevents off-by-one errors resulting from + * choosing X+2 over X when X.Y rounds up to X+1 and + * there is no r * od = X+1. For the converse, when X.Y + * is rounded down to X, we should choose X+1 over X-1. + */ + err = abs(r * od - goal); + last_err = abs(last_r * last_od - goal); + if (last_err < err || (round_up && last_err == err)) { + i--; + r = last_r; + od = last_od; + } + } + + /* + * Enforce limits on internal clock frequencies. If we + * aren't in spec, try swapping r and od. If everything is + * in-spec, calculate the relative error. + */ + while (true) { + /* + * Whether the intermediate frequencies are out-of-spec + */ + bool out_of_spec = false; + + if (r > max_r) { + out_of_spec = true; + } else { + /* + * There is no way to only divide once; we need + * to examine the frequency with and without the + * effect of od. + */ + u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r); + + if (vco > 1750000000 || vco < 340000000) + out_of_spec = true; + } + + if (out_of_spec) { + if (!swapped) { + u64 tmp = r; + + r = od; + od = tmp; + swapped = true; + continue; + } else { + /* + * Try looking ahead to see if there are + * additional factors for the same + * product. + */ + if (i + 1 < ARRAY_SIZE(factors)) { + u64 new_r, new_od; + + i++; + new_r = UNPACK_R(factors[i]); + new_od = UNPACK_OD(factors[i]); + if (r * od == new_r * new_od) { + r = new_r; + od = new_od; + swapped = false; + continue; + } + i--; + } + break; + } + } + + error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od); + /* The lower 16 bits are spurious */ + error = abs((error - BIT(32))) >> 16; + + if (error < best_error) { + best->r = r; + best->f = f; + best->od = od; + best_error = error; + } + break; + } + } while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0); + + if (best_error == S64_MAX) + return -EINVAL; + + log_debug("best error %lld\n", best_error); + return 0; +} + +static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, + ulong rate_in) +{ + int err; + const struct k210_pll_params *pll = &k210_plls[id]; + struct k210_pll_config config = {}; + u32 reg; + + if (rate_in < 0) + return rate_in; + + log_debug("Calculating parameters with rate=%lu and rate_in=%lu\n", + rate, rate_in); + err = k210_pll_calc_config(rate, rate_in, &config); + if (err) + return err; + log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od); + + /* + * Don't use clk_disable as it might not actually disable the pll due to + * refcounting + */ + k210_pll_disable(priv, id); + + reg = readl(priv->base + pll->off); + reg &= ~K210_PLL_CLKR + & ~K210_PLL_CLKF + & ~K210_PLL_CLKOD + & ~K210_PLL_BWADJ; + reg |= FIELD_PREP(K210_PLL_CLKR, config.r - 1) + | FIELD_PREP(K210_PLL_CLKF, config.f - 1) + | FIELD_PREP(K210_PLL_CLKOD, config.od - 1) + | FIELD_PREP(K210_PLL_BWADJ, config.f - 1); + writel(reg, priv->base + pll->off); + + err = k210_pll_enable(priv, id); + + serial_setbrg(); + return k210_pll_get_rate(priv, id, rate); +} +#else +static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, + ulong rate_in) +{ + return -ENOSYS; +} +#endif /* CONFIG_CLK_K210_SET_RATE */ + +static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, + ulong rate_in) +{ + u64 r, f, od; + u32 reg = readl(priv->base + k210_plls[id].off); + + if (rate_in < 0 || (reg & K210_PLL_BYPASS)) + return rate_in; + + if (!(reg & K210_PLL_PWRD)) + return 0; + + r = FIELD_GET(K210_PLL_CLKR, reg) + 1; + f = FIELD_GET(K210_PLL_CLKF, reg) + 1; + od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; + + return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od); +} + +/* + * Wait for the PLL to be locked. If the PLL is not locked, try clearing the + * slip before retrying + */ +static void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id) +{ + const struct k210_pll_params *pll = &k210_plls[id]; + u32 mask = (BIT(pll->width) - 1) << pll->shift; + + while (true) { + u32 reg = readl(priv->base + K210_SYSCTL_PLL_LOCK); + + if ((reg & mask) == mask) + break; + + reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP); + writel(reg, priv->base + K210_SYSCTL_PLL_LOCK); + } +} + +/* Adapted from sysctl_pll_enable */ +static int k210_pll_enable(struct k210_clk_priv *priv, int id) +{ + const struct k210_pll_params *pll = &k210_plls[id]; + u32 reg = readl(priv->base + pll->off); + + if ((reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) && + !(reg & K210_PLL_RESET)) + return 0; + + reg |= K210_PLL_PWRD; + writel(reg, priv->base + pll->off); + + /* Ensure reset is low before asserting it */ + reg &= ~K210_PLL_RESET; + writel(reg, priv->base + pll->off); + reg |= K210_PLL_RESET; + writel(reg, priv->base + pll->off); + nop(); + nop(); + reg &= ~K210_PLL_RESET; + writel(reg, priv->base + pll->off); + + k210_pll_waitfor_lock(priv, id); + + reg &= ~K210_PLL_BYPASS; + reg |= K210_PLL_EN; + writel(reg, priv->base + pll->off); + + return 0; +} + +static int k210_pll_disable(struct k210_clk_priv *priv, int id) +{ + const struct k210_pll_params *pll = &k210_plls[id]; + u32 reg = readl(priv->base + pll->off); + + /* + * Bypassing before powering off is important so child clocks don't stop + * working. This is especially important for pll0, the indirect parent + * of the cpu clock. + */ + reg |= K210_PLL_BYPASS; + writel(reg, priv->base + pll->off); + + reg &= ~K210_PLL_PWRD; + reg &= ~K210_PLL_EN; + writel(reg, priv->base + pll->off); + return 0; +} + static u32 k210_clk_readl(struct k210_clk_priv *priv, u8 off, u8 shift, u8 width) { diff --git a/drivers/clk/kendryte/pll.c b/drivers/clk/kendryte/pll.c deleted file mode 100644 index 1f0275c83f..0000000000 --- a/drivers/clk/kendryte/pll.c +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2019-20 Sean Anderson - */ -#define LOG_CATEGORY UCLASS_CLK - -#include -#include -/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct k210_pll_params - K210 PLL parameters - * @off: The offset of the PLL from the base sysctl address - * @shift: The offset of the LSB of the lock status - * @width: The number of bits in the lock status - */ -struct k210_pll_params { - u8 off; - u8 shift; - u8 width; -}; - -static const struct k210_pll_params k210_plls[] = { -#define PLL(_off, _shift, _width) { \ - .off = (_off), \ - .shift = (_shift), \ - .width = (_width), \ -} - [0] = PLL(K210_SYSCTL_PLL0, 0, 2), - [1] = PLL(K210_SYSCTL_PLL1, 8, 1), - [2] = PLL(K210_SYSCTL_PLL2, 16, 1), -#undef PLL -}; - -#ifdef CONFIG_CLK_K210_SET_RATE -int k210_pll_enable(struct k210_clk_priv *priv, int id); -int k210_pll_disable(struct k210_clk_priv *priv, int id); -ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); - -/* - * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc. - * General-Purpose PLL. The logical layout of the PLL with internal feedback is - * approximately the following: - * - * +---------------+ - * |reference clock| - * +---------------+ - * | - * v - * +--+ - * |/r| - * +--+ - * | - * v - * +-------------+ - * |divided clock| - * +-------------+ - * | - * v - * +--------------+ - * |phase detector|<---+ - * +--------------+ | - * | | - * v +--------------+ - * +---+ |feedback clock| - * |VCO| +--------------+ - * +---+ ^ - * | +--+ | - * +--->|/f|---+ - * | +--+ - * v - * +---+ - * |/od| - * +---+ - * | - * v - * +------+ - * |output| - * +------+ - * - * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode, - * the effect of the division by f is to multiply the input frequency. The - * equation for the output rate is - * rate = (rate_in * f) / (r * od). - * Moving knowns to one side of the equation, we get - * rate / rate_in = f / (r * od) - * Rearranging slightly, - * abs_error = abs((rate / rate_in) - (f / (r * od))). - * To get relative, error, we divide by the expected ratio - * error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in). - * Simplifying, - * error = abs(1 - f / (r * od)) / (rate / rate_in) - * error = abs(1 - (f * rate_in) / (r * od * rate)) - * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate, - * error = abs((f * inv_ratio) / (r * od) - 1) - * This is the error used in evaluating parameters. - * - * r and od are four bits each, while f is six bits. Because r and od are - * multiplied together, instead of the full 256 values possible if both bits - * were used fully, there are only 97 distinct products. Combined with f, there - * are 6208 theoretical settings for the PLL. However, most of these settings - * can be ruled out immediately because they do not have the correct ratio. - * - * In addition to the constraint of approximating the desired ratio, parameters - * must also keep internal pll frequencies within acceptable ranges. The divided - * clock's minimum and maximum frequencies have a ratio of around 128. This - * leaves fairly substantial room to work with, especially since the only - * affected parameter is r. The VCO's minimum and maximum frequency have a ratio - * of 5, which is considerably more restrictive. - * - * The r and od factors are stored in a table. This is to make it easy to find - * the next-largest product. Some products have multiple factorizations, but - * only when one factor has at least a 2.5x ratio to the factors of the other - * factorization. This is because any smaller ratio would not make a difference - * when ensuring the VCO's frequency is within spec. - * - * Throughout the calculation function, fixed point arithmetic is used. Because - * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit - * 32.32 fixed-point numbers are used to represent ratios. In general, to - * implement division, the numerator is first multiplied by 2^32. This gives a - * result where the whole number part is in the upper 32 bits, and the fraction - * is in the lower 32 bits. - * - * In general, rounding is done to the closest integer. This helps find the best - * approximation for the ratio. Rounding in one direction (e.g down) could cause - * the function to miss a better ratio with one of the parameters increased by - * one. - */ - -/* - * The factors table was generated with the following python code: - * - * def p(x, y): - * return (1.0*x/y > 2.5) or (1.0*y/x > 2.5) - * - * factors = {} - * for i in range(1, 17): - * for j in range(1, 17): - * fs = factors.get(i*j) or [] - * if fs == [] or all([ - * (p(i, x) and p(i, y)) or (p(j, x) and p(j, y)) - * for (x, y) in fs]): - * fs.append((i, j)) - * factors[i*j] = fs - * - * for k, l in sorted(factors.items()): - * for v in l: - * print("PACK(%s, %s)," % v) - */ -#define PACK(r, od) (((((r) - 1) & 0xF) << 4) | (((od) - 1) & 0xF)) -#define UNPACK_R(val) ((((val) >> 4) & 0xF) + 1) -#define UNPACK_OD(val) (((val) & 0xF) + 1) -static const u8 factors[] = { - PACK(1, 1), - PACK(1, 2), - PACK(1, 3), - PACK(1, 4), - PACK(1, 5), - PACK(1, 6), - PACK(1, 7), - PACK(1, 8), - PACK(1, 9), - PACK(3, 3), - PACK(1, 10), - PACK(1, 11), - PACK(1, 12), - PACK(3, 4), - PACK(1, 13), - PACK(1, 14), - PACK(1, 15), - PACK(3, 5), - PACK(1, 16), - PACK(4, 4), - PACK(2, 9), - PACK(2, 10), - PACK(3, 7), - PACK(2, 11), - PACK(2, 12), - PACK(5, 5), - PACK(2, 13), - PACK(3, 9), - PACK(2, 14), - PACK(2, 15), - PACK(2, 16), - PACK(3, 11), - PACK(5, 7), - PACK(3, 12), - PACK(3, 13), - PACK(4, 10), - PACK(3, 14), - PACK(4, 11), - PACK(3, 15), - PACK(3, 16), - PACK(7, 7), - PACK(5, 10), - PACK(4, 13), - PACK(6, 9), - PACK(5, 11), - PACK(4, 14), - PACK(4, 15), - PACK(7, 9), - PACK(4, 16), - PACK(5, 13), - PACK(6, 11), - PACK(5, 14), - PACK(6, 12), - PACK(5, 15), - PACK(7, 11), - PACK(6, 13), - PACK(5, 16), - PACK(9, 9), - PACK(6, 14), - PACK(8, 11), - PACK(6, 15), - PACK(7, 13), - PACK(6, 16), - PACK(7, 14), - PACK(9, 11), - PACK(10, 10), - PACK(8, 13), - PACK(7, 15), - PACK(9, 12), - PACK(10, 11), - PACK(7, 16), - PACK(9, 13), - PACK(8, 15), - PACK(11, 11), - PACK(9, 14), - PACK(8, 16), - PACK(10, 13), - PACK(11, 12), - PACK(9, 15), - PACK(10, 14), - PACK(11, 13), - PACK(9, 16), - PACK(10, 15), - PACK(11, 14), - PACK(12, 13), - PACK(10, 16), - PACK(11, 15), - PACK(12, 14), - PACK(13, 13), - PACK(11, 16), - PACK(12, 15), - PACK(13, 14), - PACK(12, 16), - PACK(13, 15), - PACK(14, 14), - PACK(13, 16), - PACK(14, 15), - PACK(14, 16), - PACK(15, 15), - PACK(15, 16), - PACK(16, 16), -}; - -TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, - struct k210_pll_config *best) -{ - int i; - s64 error, best_error; - u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */ - u64 max_r; - u64 r, f, od; - - /* - * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the - * VCO frequency. These are not the same limits as below because od can - * reduce the output frequency by 16. - */ - if (rate > 1750000000 || rate < 21250000) - return -EINVAL; - - /* Similar restrictions on the input rate */ - if (rate_in > 1750000000 || rate_in < 13300000) - return -EINVAL; - - ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in); - inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate); - /* Can't increase by more than 64 or reduce by more than 256 */ - if (rate > rate_in && ratio > (64ULL << 32)) - return -EINVAL; - else if (rate <= rate_in && inv_ratio > (256ULL << 32)) - return -EINVAL; - - /* - * The divided clock (rate_in / r) must stay between 1.75 GHz and 13.3 - * MHz. There is no minimum, since the only way to get a higher input - * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs - * cannot output frequencies greater than 1.75 GHz, the minimum would - * never be greater than one. - */ - max_r = DIV_ROUND_DOWN_ULL(rate_in, 13300000); - - /* Variables get immediately incremented, so start at -1th iteration */ - i = -1; - f = 0; - r = 0; - od = 0; - best_error = S64_MAX; - error = best_error; - /* do-while here so we always try at least one ratio */ - do { - /* - * Whether we swapped r and od while enforcing frequency limits - */ - bool swapped = false; - u64 last_od = od; - u64 last_r = r; - - /* - * Try the next largest value for f (or r and od) and - * recalculate the other parameters based on that - */ - if (rate > rate_in) { - /* - * Skip factors of the same product if we already tried - * out that product - */ - do { - i++; - r = UNPACK_R(factors[i]); - od = UNPACK_OD(factors[i]); - } while (i + 1 < ARRAY_SIZE(factors) && - r * od == last_r * last_od); - - /* Round close */ - f = (r * od * ratio + BIT(31)) >> 32; - if (f > 64) - f = 64; - } else { - u64 tmp = ++f * inv_ratio; - bool round_up = !!(tmp & BIT(31)); - u32 goal = (tmp >> 32) + round_up; - u32 err, last_err; - - /* Get the next r/od pair in factors */ - while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) { - i++; - r = UNPACK_R(factors[i]); - od = UNPACK_OD(factors[i]); - } - - /* - * This is a case of double rounding. If we rounded up - * above, we need to round down (in cases of ties) here. - * This prevents off-by-one errors resulting from - * choosing X+2 over X when X.Y rounds up to X+1 and - * there is no r * od = X+1. For the converse, when X.Y - * is rounded down to X, we should choose X+1 over X-1. - */ - err = abs(r * od - goal); - last_err = abs(last_r * last_od - goal); - if (last_err < err || (round_up && last_err == err)) { - i--; - r = last_r; - od = last_od; - } - } - - /* - * Enforce limits on internal clock frequencies. If we - * aren't in spec, try swapping r and od. If everything is - * in-spec, calculate the relative error. - */ - while (true) { - /* - * Whether the intermediate frequencies are out-of-spec - */ - bool out_of_spec = false; - - if (r > max_r) { - out_of_spec = true; - } else { - /* - * There is no way to only divide once; we need - * to examine the frequency with and without the - * effect of od. - */ - u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r); - - if (vco > 1750000000 || vco < 340000000) - out_of_spec = true; - } - - if (out_of_spec) { - if (!swapped) { - u64 tmp = r; - - r = od; - od = tmp; - swapped = true; - continue; - } else { - /* - * Try looking ahead to see if there are - * additional factors for the same - * product. - */ - if (i + 1 < ARRAY_SIZE(factors)) { - u64 new_r, new_od; - - i++; - new_r = UNPACK_R(factors[i]); - new_od = UNPACK_OD(factors[i]); - if (r * od == new_r * new_od) { - r = new_r; - od = new_od; - swapped = false; - continue; - } - i--; - } - break; - } - } - - error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od); - /* The lower 16 bits are spurious */ - error = abs((error - BIT(32))) >> 16; - - if (error < best_error) { - best->r = r; - best->f = f; - best->od = od; - best_error = error; - } - break; - } - } while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0); - - if (best_error == S64_MAX) - return -EINVAL; - - log_debug("best error %lld\n", best_error); - return 0; -} - -static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, - ulong rate_in) -{ - int err; - const struct k210_pll_params *pll = &k210_plls[id]; - struct k210_pll_config config = {}; - u32 reg; - - if (rate_in < 0) - return rate_in; - - log_debug("Calculating parameters with rate=%lu and rate_in=%lld\n", - rate, rate_in); - err = k210_pll_calc_config(rate, rate_in, &config); - if (err) - return err; - log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od); - - /* - * Don't use clk_disable as it might not actually disable the pll due to - * refcounting - */ - k210_pll_disable(clk); - - reg = readl(priv->base + pll->off); - reg &= ~K210_PLL_CLKR - & ~K210_PLL_CLKF - & ~K210_PLL_CLKOD - & ~K210_PLL_BWADJ; - reg |= FIELD_PREP(K210_PLL_CLKR, config.r - 1) - | FIELD_PREP(K210_PLL_CLKF, config.f - 1) - | FIELD_PREP(K210_PLL_CLKOD, config.od - 1) - | FIELD_PREP(K210_PLL_BWADJ, config.f - 1); - writel(reg, priv->base + pll->off); - - err = k210_pll_enable(clk); - if (err) - return err; - - serial_setbrg(); - return clk_get_rate(clk); -} -#else -ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, - ulong rate_in) -{ - return -ENOSYS; -} -#endif /* CONFIG_CLK_K210_SET_RATE */ - -ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in) -{ - u64 r, f, od; - u32 reg = readl(priv->base + k210_plls[id].off); - - if (rate_in < 0 || (reg & K210_PLL_BYPASS)) - return rate_in; - - if (!(reg & K210_PLL_PWRD)) - return 0; - - r = FIELD_GET(K210_PLL_CLKR, reg) + 1; - f = FIELD_GET(K210_PLL_CLKF, reg) + 1; - od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; - - return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od); -} - -/* - * Wait for the PLL to be locked. If the PLL is not locked, try clearing the - * slip before retrying - */ -void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id) -{ - const struct k210_pll_params *pll = &k210_plls[id]; - u32 mask = GENMASK(pll->width - 1, 0) << pll->shift; - - while (true) { - u32 reg = readl(priv->base + K210_SYSCTL_PLL_LOCK); - - if ((reg & mask) == mask) - break; - - reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP); - writel(reg, priv->base + K210_SYSCTL_PLL_LOCK); - } -} - -/* Adapted from sysctl_pll_enable */ -int k210_pll_enable(struct k210_clk_priv *priv, int id) -{ - const struct k210_pll_params *pll = &k210_plls[id]; - u32 reg = readl(priv->base + pll->off); - - if ((reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) && - !(reg & K210_PLL_RESET)) - return 0; - - reg |= K210_PLL_PWRD; - writel(reg, priv->base + pll->off); - - /* Ensure reset is low before asserting it */ - reg &= ~K210_PLL_RESET; - writel(reg, priv->base + pll->off); - reg |= K210_PLL_RESET; - writel(reg, priv->base + pll->off); - nop(); - nop(); - reg &= ~K210_PLL_RESET; - writel(reg, priv->base + pll->off); - - k210_pll_waitfor_lock(priv, id); - - reg &= ~K210_PLL_BYPASS; - reg |= K210_PLL_EN; - writel(reg, priv->base + pll->off); - - return 0; -} - -int k210_pll_disable(struct k210_clk_priv *priv, int id) -{ - const struct k210_pll_params *pll = &k210_plls[id]; - u32 reg = readl(priv->base + pll->off); - - /* - * Bypassing before powering off is important so child clocks don't stop - * working. This is especially important for pll0, the indirect parent - * of the cpu clock. - */ - reg |= K210_PLL_BYPASS; - writel(reg, priv->base + pll->off); - - reg &= ~K210_PLL_PWRD; - reg &= ~K210_PLL_EN; - writel(reg, priv->base + pll->off); - return 0; -} diff --git a/include/kendryte/clk.h b/include/kendryte/clk.h deleted file mode 100644 index 9c6245d468..0000000000 --- a/include/kendryte/clk.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2019-20 Sean Anderson - */ - -#ifndef K210_CLK_H -#define K210_CLK_H - -#define LOG_CATEGORY UCLASS_CLK -#include -#include - -static inline struct clk *k210_clk_gate(const char *name, - const char *parent_name, - void __iomem *reg, u8 bit_idx) -{ - return clk_register_gate(NULL, name, parent_name, 0, reg, bit_idx, 0, - NULL); -} - -static inline struct clk *k210_clk_half(const char *name, - const char *parent_name) -{ - return clk_register_fixed_factor(NULL, name, parent_name, 0, 1, 2); -} - -static inline struct clk *k210_clk_div(const char *name, - const char *parent_name, - void __iomem *reg, u8 shift, u8 width) -{ - return clk_register_divider(NULL, name, parent_name, 0, reg, shift, - width, 0); -} - -#endif /* K210_CLK_H */ diff --git a/include/kendryte/pll.h b/include/kendryte/pll.h index 16fd5a5b68..fd16a89cb2 100644 --- a/include/kendryte/pll.h +++ b/include/kendryte/pll.h @@ -5,25 +5,7 @@ #ifndef K210_PLL_H #define K210_PLL_H -#include #include -#include - -#define K210_PLL_CLKR GENMASK(3, 0) -#define K210_PLL_CLKF GENMASK(9, 4) -#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */ -#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */ -#define K210_PLL_RESET BIT(20) -#define K210_PLL_PWRD BIT(21) /* PoWeReD */ -#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */ -#define K210_PLL_BYPASS BIT(23) -#define K210_PLL_TEST BIT(24) -#define K210_PLL_EN BIT(25) -#define K210_PLL_TEST_EN BIT(26) - -#define K210_PLL_LOCK 0 -#define K210_PLL_CLEAR_SLIP 2 -#define K210_PLL_TEST_OUT 3 struct k210_pll_config { u8 r; @@ -34,25 +16,9 @@ struct k210_pll_config { #ifdef CONFIG_UNIT_TEST TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, struct k210_pll_config *best); - #ifndef nop #define nop() #endif #endif - -/** - * struct k210_clk_priv - K210 clock driver private data - * @base: The base address of the sysctl device - * @in0: The "in0" external oscillator - */ -struct k210_clk_priv { - void __iomem *base; - struct clk in0; -}; - -ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, ulong rate_in); -ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); -int k210_pll_enable(struct k210_clk_priv *priv, int id); -int k210_pll_disable(struct k210_clk_priv *priv, int id); #endif /* K210_PLL_H */ From patchwork Fri Jun 11 04:16:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490723 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=G5EeGSFM; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SGt3rRnz9sVb for ; Fri, 11 Jun 2021 14:17:10 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id ABB9982F1A; Fri, 11 Jun 2021 06:16:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="G5EeGSFM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 32DF882F34; Fri, 11 Jun 2021 06:16:38 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id AD6AC82EDE for ; Fri, 11 Jun 2021 06:16:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x830.google.com with SMTP id p21so1663586qtw.6 for ; Thu, 10 Jun 2021 21:16:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xtb4SC3CY2Ol4pgdO58JOnNw1oJxooX8e9xtFrnFpyE=; b=G5EeGSFMkNHtF+MFVJtZ91gCIGNYA6u3Dxi+E05uYkLLCigW8aqYo2PzR1Xq1uGo9u JJ4SPqmxS31GOLwhbSLYIbr+dXSAkCDeuM/y39m/QLmGc1OiNe0TLCiQnPOlyJx8JFB1 IOG3tLuq68bJTYTXtGsZt8adF0jYdpiu2Cd/KB7kEe4DQXfG+h+D9Euf9J7xyjimEwtI a2bg9qOwIgEAY3VP2XnIfVuZ/988wn4PSNrf5zsNtMcc58ukIj7br1u47hEikqG3NK4M 1OllxtUne7JOlQV1ZWXvOyT1cmkz87/Duq8pmRu1BPYROkM6nvF1zM+6FUcoWLNoHoxM OKRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xtb4SC3CY2Ol4pgdO58JOnNw1oJxooX8e9xtFrnFpyE=; b=HqYtY58aS94NsDRPqDAWOTPYixydtxzrsqr4NeLL+JIazUHo3D/ixTixD4FvH3s6r4 6oPmAgI9EAJ9LjPALn6RYDmOrpBtUK3Uud/HYgPNPgGeX29PxzEJY/7jcb+GPBHV0Ih6 3YWFN9/jZXvDp6mZ+a4sJvJmN7htR3RYyOC0GA6nqOF5KiwdJoGiK3bVBAYPmPNylzTi H8Pe2pu8U51GtVb6RX+EICTksj8d96vvGbbx43pTQM7w4TOzuslzXFyGjLfssx3uodiD VOK0pTaBkn7BqXQmIbP/X3zhkTvgjEztYNQQ7+mll4ivVewKrQLm8YkC8+Tt49pegSRM ShgA== X-Gm-Message-State: AOAM5317vC2KcXYNbYm7puOeybfXNEM8AIVd838G50HnRRM3rMM57ayp V/zBSp9H5MoEBlBXogSnWahpMGc1Ghg= X-Google-Smtp-Source: ABdhPJyWJg8kjCFhVzmigw+HfM8umFGtcplNRWm4mQ7K625eK3GOIM4R522LAiawKXKudyau8qXcMg== X-Received: by 2002:ac8:7ed8:: with SMTP id x24mr2153613qtj.148.1623384990223; Thu, 10 Jun 2021 21:16:30 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:29 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 04/11] clk: k210: Implement soc_clk_dump Date: Fri, 11 Jun 2021 00:16:10 -0400 Message-Id: <20210611041617.1665833-5-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Since we are no longer using CCF we cannot use the default soc_clk_dump. Instead, implement our own. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) drivers/clk/kendryte/clk.c | 68 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index de9db84361..203d5f741c 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -925,14 +925,19 @@ static void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id) } } +static bool k210_pll_enabled(u32 reg) +{ + return (reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) && + !(reg & K210_PLL_RESET); +} + /* Adapted from sysctl_pll_enable */ static int k210_pll_enable(struct k210_clk_priv *priv, int id) { const struct k210_pll_params *pll = &k210_plls[id]; u32 reg = readl(priv->base + pll->off); - if ((reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) && - !(reg & K210_PLL_RESET)) + if (k210_pll_enabled(reg)) return 0; reg |= K210_PLL_PWRD; @@ -1174,3 +1179,62 @@ U_BOOT_DRIVER(k210_clk) = { .probe = k210_clk_probe, .priv_auto = sizeof(struct k210_clk_priv), }; + +#if CONFIG_IS_ENABLED(CMD_CLK) +static char show_enabled(struct k210_clk_priv *priv, int id) +{ + bool enabled; + + if (k210_clks[id].flags & K210_CLKF_PLL) { + const struct k210_pll_params *pll = + &k210_plls[k210_clks[id].pll]; + + enabled = k210_pll_enabled(readl(priv->base + pll->off)); + } else if (k210_clks[id].gate == K210_CLK_GATE_NONE) { + return '-'; + } else { + const struct k210_gate_params *gate = + &k210_gates[k210_clks[id].gate]; + + enabled = k210_clk_readl(priv, gate->off, gate->bit_idx, 1); + } + + return enabled ? 'y' : 'n'; +} + +static void show_clks(struct k210_clk_priv *priv, int id, int depth) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(k210_clks); i++) { + if (k210_clk_get_parent(priv, i) != id) + continue; + + printf(" %-9lu %-7c %*s%s\n", do_k210_clk_get_rate(priv, i), + show_enabled(priv, i), depth * 4, "", + k210_clks[i].name); + + show_clks(priv, i, depth + 1); + } +} + +int soc_clk_dump(void) +{ + int ret; + struct udevice *dev; + struct k210_clk_priv *priv; + + ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(k210_clk), + &dev); + if (ret) + return ret; + priv = dev_get_priv(dev); + + puts(" Rate Enabled Name\n"); + puts("------------------------\n"); + printf(" %-9lu %-7c %*s%s\n", clk_get_rate(&priv->in0), 'y', 0, "", + priv->in0.dev->name); + show_clks(priv, K210_CLK_IN0, 1); + return 0; +} +#endif From patchwork Fri Jun 11 04:16:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490726 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=DtxUtGjP; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SHV2cpGz9sVb for ; Fri, 11 Jun 2021 14:17:42 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D827282F27; Fri, 11 Jun 2021 06:16:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="DtxUtGjP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 09DF282F24; Fri, 11 Jun 2021 06:16:46 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x72f.google.com (mail-qk1-x72f.google.com [IPv6:2607:f8b0:4864:20::72f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 749EC82F19 for ; Fri, 11 Jun 2021 06:16:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x72f.google.com with SMTP id f70so14515679qke.13 for ; Thu, 10 Jun 2021 21:16:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ST1NdDNlOtrZ7Pz3HjChb0bDZxW2/bQRkUdlh2CWt0U=; b=DtxUtGjPYTlqgRBS1H092omcdpFVAPonIzjZsfi8Niyy52kQcYpCt+LvZZB95AaeSD bgaFOrWO9BtB+i1cVzXGJHJpnxZxcprS8fnHTT8LbQy535MD722vL7B47GalL87fbfi6 vPeR8gcS1pb9eesljMlLKxD2Hdro3uRBAQ/pfseuQ5fzSR44exV1d6tYdvBA07mKE52V iyTYav68adQ1CSHa8kHFzcQ0SVx8HD0K+oWGWDwvIU/D29isDhTTFPKXb/DYiEfrnmJp 2V1BU/A99Qwy99HQdxDWO+VmpeBlDm4FjZLF6eilWIX5Acd/26vIjsQns0WzHmsoQisx d01g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ST1NdDNlOtrZ7Pz3HjChb0bDZxW2/bQRkUdlh2CWt0U=; b=p0YVSA32XZnLjwZnzdV25r2iuvxBBQuhPhsDovX537VYXeB44t8pEXTrZLTXgf3AjU zKet09i7bSdHvlB49ps8S6qBJNAoPYmYTLoc9Dcanhgb/QPe4nBlS28zb0T01RZBRcZH GSwpw3xAKJG5u+GJ3jddOW6IZ0TdVo9s1v3apWr5i338N1bjvvzgSHHEUACtAaH+HIrh XbV0uI9+YiK09voIXL68khXRAyBq2tRm6sdwGORtnwgixTRKe+jo23cQ4sCeh3h7aD45 xIjLjb3KCzdxN6WyRgQy9GDvWgohxgdwmKZOSYICMpcLzQeZf6NMZ1Dg2GuvNYybmslJ U4Ag== X-Gm-Message-State: AOAM530YNVlwGYYvCODpXcWN2j8/988joVXOra1fdWBYM/xecVa+Qr/Z fQD6bGRvrk0qJuWIRURVOvru3kA7QMQ= X-Google-Smtp-Source: ABdhPJwATs5l9H4WlwRYsBvDqJDlJsR0G5uAYpbxSwPPObXcLsSFsxPPgggjiz0UYoYZZqrmz1SnYA== X-Received: by 2002:a37:cc6:: with SMTP id 189mr2012191qkm.261.1623384991153; Thu, 10 Jun 2021 21:16:31 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:30 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 05/11] clk: k210: Re-add support for setting rate Date: Fri, 11 Jun 2021 00:16:11 -0400 Message-Id: <20210611041617.1665833-6-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean This adds support for setting clock rates, which was left out of the initial CCF expunging. There are several tricky bits here, mostly related to the PLLS: * The PLL's bypass is broken. If the PLL is reconfigured, any child clocks will be stopped. * PLL0 is the parent of ACLK which is the CPU and SRAM's clock. To prevent stopping the CPU while we configure PLL0's rate, ACLK is reparented to IN0 while PLL0 is disabled. * PLL1 is the parent of the AISRAM clock. This clock cannot be reparented, so we instead just disallow changing PLL1's rate after relocation (when we are using the AISRAM). Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- Changes in v3: - Fix inverted condition for setting defaults - Fix val not being set for K210_DIV_POWER Changes in v2: - Only force probe clocks pre-reloc drivers/clk/kendryte/clk.c | 89 +++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index 203d5f741c..a2901f9b96 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -17,6 +17,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /** * struct k210_clk_priv - K210 clock driver private data * @base: The base address of the sysctl device @@ -1059,11 +1061,6 @@ static ulong k210_clk_get_rate(struct clk *clk) return do_k210_clk_get_rate(dev_get_priv(clk->dev), clk->id); } -static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate) -{ - return -ENOSYS; -} - static int do_k210_clk_set_parent(struct k210_clk_priv *priv, int id, int new) { int i; @@ -1089,6 +1086,81 @@ static int k210_clk_set_parent(struct clk *clk, struct clk *parent) parent->id); } +static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate) +{ + int parent, ret, err; + ulong rate_in, val; + const struct k210_div_params *div; + struct k210_clk_priv *priv = dev_get_priv(clk->dev); + + if (clk->id == K210_CLK_IN0) + return clk_set_rate(&priv->in0, rate); + + parent = k210_clk_get_parent(priv, clk->id); + rate_in = do_k210_clk_get_rate(priv, parent); + + log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in); + + if (clk->id == K210_CLK_PLL0) { + /* Bypass ACLK so the CPU keeps going */ + ret = do_k210_clk_set_parent(priv, K210_CLK_ACLK, K210_CLK_IN0); + if (ret) + return ret; + } else if (clk->id == K210_CLK_PLL1 && gd->flags & GD_FLG_RELOC) { + /* + * We can't bypass the AI clock like we can ACLK, and after + * relocation we are using the AI ram. + */ + return -EPERM; + } + + if (k210_clks[clk->id].flags & K210_CLKF_PLL) { + ret = k210_pll_set_rate(priv, k210_clks[clk->id].pll, rate, + rate_in); + if (!IS_ERR_VALUE(ret) && clk->id == K210_CLK_PLL0) { + /* + * This may have the side effect of reparenting ACLK, + * but I don't really want to keep track of what the old + * parent was. + */ + err = do_k210_clk_set_parent(priv, K210_CLK_ACLK, + K210_CLK_PLL0); + if (err) + return err; + } + return ret; + } + + if (k210_clks[clk->id].div == K210_CLK_DIV_NONE) + return -ENOSYS; + div = &k210_divs[k210_clks[clk->id].div]; + + switch (div->type) { + case K210_DIV_ONE: + val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate); + val = val ? val - 1 : 0; + break; + case K210_DIV_EVEN: + val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, 2 * rate); + break; + case K210_DIV_POWER: + /* This is ACLK, which has no divider on IN0 */ + if (parent == K210_CLK_IN0) + return -ENOSYS; + + val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate); + val = __ffs(val); + break; + default: + assert(false); + return -EINVAL; + }; + + val = val ? val - 1 : 0; + k210_clk_writel(priv, div->off, div->shift, div->width, val); + return do_k210_clk_get_rate(priv, clk->id); +} + static int k210_clk_endisable(struct k210_clk_priv *priv, int id, bool enable) { int parent = k210_clk_get_parent(priv, id); @@ -1163,6 +1235,13 @@ static int k210_clk_probe(struct udevice *dev) if (ret) return ret; + /* + * Force setting defaults, even before relocation. This is so we can + * set the clock rate for PLL1 before we relocate into aisram. + */ + if (!(gd->flags & GD_FLG_RELOC)) + clk_set_defaults(dev, CLK_DEFAULTS_POST_FORCE); + return 0; } From patchwork Fri Jun 11 04:16:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490725 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=msmG5Ig9; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SHJ4BVBz9sVb for ; Fri, 11 Jun 2021 14:17:32 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B95B282F3B; Fri, 11 Jun 2021 06:16:48 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="msmG5Ig9"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8838782F24; Fri, 11 Jun 2021 06:16:45 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qt1-x82f.google.com (mail-qt1-x82f.google.com [IPv6:2607:f8b0:4864:20::82f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2D36982F15 for ; Fri, 11 Jun 2021 06:16:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x82f.google.com with SMTP id l17so1639925qtq.12 for ; Thu, 10 Jun 2021 21:16:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CWfh6RTqDxq8liIs2AMEd2GVF8MvDAX5ZGlb0Q9ypvI=; b=msmG5Ig9Sx1nRW+qKARm9eq+Jg0UIkjgBkmyXgck8RN4A7GEd2+SweYsYZuNnJpsO4 hDuVcW6RUdvsrwFofmsqB2TiHS7YrSVdZ4BENuQHBK8W/y4B/EgmXiFb8g8CCLdFAvnW eO/wbrrFTcJvZy4qte5uLF1oGT6Ov/SjBQiPffqp95sqjgXUpDDJ893c9TWlyMqasRWZ 3U1IDX6f9ZzkF0bUhrSU8XGLssFTRnB+e9tL9Cf7kKXaNwS6zR3e7Y/QAfIuM6qnvWnJ Lsiiquer4FHW8QUXZ7+3nUpZ7ILo5fYDztMPLQC74b0aSrWETz1DPh9fbXPgRIHG51qy DyAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CWfh6RTqDxq8liIs2AMEd2GVF8MvDAX5ZGlb0Q9ypvI=; b=Kz0J1dB5GvFhqEJa/yugl+mpvQFAJU7lbVYB4JciBZQTRZp55+QZafZIDlr+AgcjB3 C1VgK1MmQb3wZRpt7xN9DP3SEVzknAjgRY9i029PNwwoZQ3Pn7TCLaZWM1F4aaFhRabg m1+wrC7JB9EVorvaTAEgucbISB1K/Kaq4F4Fvj7ayROh3/BO2p5cNhK1kbrJJ34wHR3+ 7ZpdEqytQphlPX+a5FAouMFwal1+nnzTV6qZcoV1qAAPCZE9SCOvyaG2gup58W66csmT t5UUSnAPZ8OUB7WcGXkeJ+U4b/DywBVHdjOMEIltQ+H4xGH++8h53QzoYudb1A4T2Tvo XyRw== X-Gm-Message-State: AOAM530ZbVFJyn8DIhKMNtk1CnE70LdA1TYOH363EASLMuwnMppBt5Rn AhD7/osTyrIBhydC2xz1pkfPQew/LEk= X-Google-Smtp-Source: ABdhPJwoOlbFKqjKOik0TZWwudOr5KkwNcIqhbsP0Yj7ddaknri85DwkviV0zpJhPsHgLP2hXmGllg== X-Received: by 2002:ac8:5a44:: with SMTP id o4mr2136092qta.189.1623384991869; Thu, 10 Jun 2021 21:16:31 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:31 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 06/11] clk: k210: Don't set PLL rates if we are already at the correct rate Date: Fri, 11 Jun 2021 00:16:12 -0400 Message-Id: <20210611041617.1665833-7-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean This speeds up boot by preventing multiple reconfigurations of the PLLs. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) drivers/clk/kendryte/clk.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index a2901f9b96..3148756968 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -847,21 +847,22 @@ static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, const struct k210_pll_params *pll = &k210_plls[id]; struct k210_pll_config config = {}; u32 reg; + ulong calc_rate; if (rate_in < 0) return rate_in; - log_debug("Calculating parameters with rate=%lu and rate_in=%lu\n", - rate, rate_in); err = k210_pll_calc_config(rate, rate_in, &config); if (err) return err; log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od); - /* - * Don't use clk_disable as it might not actually disable the pll due to - * refcounting - */ + /* Don't bother setting the rate if we're already at that rate */ + calc_rate = DIV_ROUND_DOWN_ULL(((u64)rate_in) * config.f, + config.r * config.od); + if (calc_rate == k210_pll_get_rate(priv, id, rate)) + return calc_rate; + k210_pll_disable(priv, id); reg = readl(priv->base + pll->off); @@ -875,7 +876,7 @@ static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, | FIELD_PREP(K210_PLL_BWADJ, config.f - 1); writel(reg, priv->base + pll->off); - err = k210_pll_enable(priv, id); + k210_pll_enable(priv, id); serial_setbrg(); return k210_pll_get_rate(priv, id, rate); From patchwork Fri Jun 11 04:16:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490727 X-Patchwork-Delegate: uboot@andestech.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; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=S2sD+yk8; 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 4G1SHj0yr9z9sVb for ; Fri, 11 Jun 2021 14:17:53 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4EDC782F47; Fri, 11 Jun 2021 06:16:52 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S2sD+yk8"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5C54082F12; Fri, 11 Jun 2021 06:16:46 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qt1-x833.google.com (mail-qt1-x833.google.com [IPv6:2607:f8b0:4864:20::833]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id EA77782F27 for ; Fri, 11 Jun 2021 06:16:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x833.google.com with SMTP id p21so1663621qtw.6 for ; Thu, 10 Jun 2021 21:16:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pl+wEIceVKxUxNHRWxM4OyuSB2bocOIbFwcVQ+dFClc=; b=S2sD+yk8yf32SUwRqOweMfwqXBASlDew/wjygTb3cM7NjsF8+apBJ3jGo+E4cu1pFr T77K9gbLVcjCmMbgJi0DPFqFq391mEmNQRHqWXFNtFhbQaGdcFvrqkRWNpvlhXbtUJ/P VVHF+40vtZClPNHLzCJpQq3J6/n5mS9r1AwFBwb+J335qLldoPNMZZMwdM9+LkkgCqxi JqInfzr4UO5V4DQZFs2B2ajBeOueSMadb7rzQL+j28Ov6xdpYeDIgafwzGRt3BCQZbrC 0GlIMPEZ7+PlJ8S8YSj8gsH7vCqot3sbMxDsmURVUfYwJLdzybgbKoo2V/v71FGZTzS1 6DXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pl+wEIceVKxUxNHRWxM4OyuSB2bocOIbFwcVQ+dFClc=; b=YG999HVVka/NIzxXimVf7i7aATKRJ5z5jYgEVjd8fQFgLm2QvL0TjS0yWWmpEdtn+n 01ROyhQWTI/B4WLgiG5uxW51qsGsjxf7B92d2VNgfrcHsDSYXGkcnN93XUoWUrxAgkZ6 tt+rUNZT0Vwr5jUZ02JUXC7jBhqSNXSa7aS6jGGTgwkWJ3909+WXiNfZ/SEVgein9kAl UVa7Q6vUT0NFMP2LXLQsuf+8lvt5dsgv4OyJk8GgIeQN8Fi+k849hWJ2/KKI9gxWf8Hm 4qCyqPY0USMWIfNOFEK02WzslDCrTOHMvOQyHFhXFWwdLEU0gm+XcnZqS/0vjXBibKZK +Rlg== X-Gm-Message-State: AOAM531B1EuMjY3FZdmtZ5si++th2YjxDr5079l6wln5VjDY4BYwRQVK NcBEE6n6lWmZz/nTn0jdHVsD5s87Mys= X-Google-Smtp-Source: ABdhPJzXT15Xny66zm3vLDpOJOxhCsFCuQ7CrCfB8yLyS/nw6Mef4/OcBDIi6EHtWXco0H4atumwTQ== X-Received: by 2002:a05:622a:174f:: with SMTP id l15mr2109252qtk.141.1623384992601; Thu, 10 Jun 2021 21:16:32 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:32 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 07/11] clk: k210: Remove bypass driver Date: Fri, 11 Jun 2021 00:16:13 -0400 Message-Id: <20210611041617.1665833-8-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean This driver no longer serves a purpose now that we have moved away from CCF. Drop it. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/bypass.c | 273 ---------------------------------- include/kendryte/bypass.h | 31 ---- 3 files changed, 1 insertion(+), 305 deletions(-) delete mode 100644 drivers/clk/kendryte/bypass.c delete mode 100644 include/kendryte/bypass.h diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index 6710a1db72..0303c0b99c 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += bypass.o clk.o +obj-y += clk.o diff --git a/drivers/clk/kendryte/bypass.c b/drivers/clk/kendryte/bypass.c deleted file mode 100644 index bbdbd9a10d..0000000000 --- a/drivers/clk/kendryte/bypass.c +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2020 Sean Anderson - */ - -#define LOG_CATEGORY UCLASS_CLK - -#include -#include -#include -#include -#include -#include -#include -#include - -#define CLK_K210_BYPASS "k210_clk_bypass" - -/* - * This is a small driver to do a software bypass of a clock if hardware bypass - * is not working. I have tried to write this in a generic fashion, so that it - * could be potentially broken out of the kendryte code at some future date. - * - * Say you have the following clock configuration - * - * +---+ +---+ - * |osc| |pll| - * +---+ +---+ - * ^ - * /| - * / | - * / | - * / | - * / | - * +---+ +---+ - * |clk| |clk| - * +---+ +---+ - * - * But the pll does not have a bypass, so when you configure the pll, the - * configuration needs to change to look like - * - * +---+ +---+ - * |osc| |pll| - * +---+ +---+ - * ^ - * |\ - * | \ - * | \ - * | \ - * | \ - * +---+ +---+ - * |clk| |clk| - * +---+ +---+ - * - * To set this up, create a bypass clock with bypassee=pll and alt=osc. When - * creating the child clocks, set their parent to the bypass clock. After - * creating all the children, call k210_bypass_setchildren(). - */ - -static int k210_bypass_dobypass(struct k210_bypass *bypass) -{ - int ret, i; - - /* - * If we already have saved parents, then the children are already - * bypassed - */ - if (bypass->child_count && bypass->saved_parents[0]) - return 0; - - for (i = 0; i < bypass->child_count; i++) { - struct clk *child = bypass->children[i]; - struct clk *parent = clk_get_parent(child); - - if (IS_ERR(parent)) { - for (; i; i--) - bypass->saved_parents[i] = NULL; - return PTR_ERR(parent); - } - bypass->saved_parents[i] = parent; - } - - for (i = 0; i < bypass->child_count; i++) { - struct clk *child = bypass->children[i]; - - ret = clk_set_parent(child, bypass->alt); - if (ret) { - for (; i; i--) - clk_set_parent(bypass->children[i], - bypass->saved_parents[i]); - for (i = 0; i < bypass->child_count; i++) - bypass->saved_parents[i] = NULL; - return ret; - } - } - - return 0; -} - -static int k210_bypass_unbypass(struct k210_bypass *bypass) -{ - int err, ret, i; - - if (!bypass->child_count && !bypass->saved_parents[0]) { - log_warning("Cannot unbypass children; dobypass not called first\n"); - return 0; - } - - ret = 0; - for (i = 0; i < bypass->child_count; i++) { - err = clk_set_parent(bypass->children[i], - bypass->saved_parents[i]); - if (err) - ret = err; - bypass->saved_parents[i] = NULL; - } - return ret; -} - -static ulong k210_bypass_get_rate(struct clk *clk) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - if (ops->get_rate) - return ops->get_rate(bypass->bypassee); - else - return clk_get_parent_rate(bypass->bypassee); -} - -static ulong k210_bypass_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - /* Don't bother bypassing if we aren't going to set the rate */ - if (!ops->set_rate) - return k210_bypass_get_rate(clk); - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - ret = ops->set_rate(bypass->bypassee, rate); - if (ret < 0) - return ret; - - return k210_bypass_unbypass(bypass); -} - -static int k210_bypass_set_parent(struct clk *clk, struct clk *parent) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - if (ops->set_parent) - return ops->set_parent(bypass->bypassee, parent); - else - return -EINVAL; -} - -/* - * For these next two functions, do the bypassing even if there is no - * en-/-disable function, since the bypassing itself can be observed in between - * calls. - */ -static int k210_bypass_enable(struct clk *clk) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - if (ops->enable) - ret = ops->enable(bypass->bypassee); - else - ret = 0; - if (ret) - return ret; - - return k210_bypass_unbypass(bypass); -} - -static int k210_bypass_disable(struct clk *clk) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - if (ops->disable) - return ops->disable(bypass->bypassee); - else - return 0; -} - -static const struct clk_ops k210_bypass_ops = { - .get_rate = k210_bypass_get_rate, - .set_rate = k210_bypass_set_rate, - .set_parent = k210_bypass_set_parent, - .enable = k210_bypass_enable, - .disable = k210_bypass_disable, -}; - -int k210_bypass_set_children(struct clk *clk, struct clk **children, - size_t child_count) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - - kfree(bypass->saved_parents); - if (child_count) { - bypass->saved_parents = - kcalloc(child_count, sizeof(struct clk *), GFP_KERNEL); - if (!bypass->saved_parents) - return -ENOMEM; - } - bypass->child_count = child_count; - bypass->children = children; - - return 0; -} - -struct clk *k210_register_bypass_struct(const char *name, - const char *parent_name, - struct k210_bypass *bypass) -{ - int ret; - struct clk *clk; - - clk = &bypass->clk; - - ret = clk_register(clk, CLK_K210_BYPASS, name, parent_name); - if (ret) - return ERR_PTR(ret); - - bypass->bypassee->dev = clk->dev; - return clk; -} - -struct clk *k210_register_bypass(const char *name, const char *parent_name, - struct clk *bypassee, - const struct clk_ops *bypassee_ops, - struct clk *alt) -{ - struct clk *clk; - struct k210_bypass *bypass; - - bypass = kzalloc(sizeof(*bypass), GFP_KERNEL); - if (!bypass) - return ERR_PTR(-ENOMEM); - - bypass->bypassee = bypassee; - bypass->bypassee_ops = bypassee_ops; - bypass->alt = alt; - - clk = k210_register_bypass_struct(name, parent_name, bypass); - if (IS_ERR(clk)) - kfree(bypass); - return clk; -} - -U_BOOT_DRIVER(k210_bypass) = { - .name = CLK_K210_BYPASS, - .id = UCLASS_CLK, - .ops = &k210_bypass_ops, -}; diff --git a/include/kendryte/bypass.h b/include/kendryte/bypass.h deleted file mode 100644 index ab85bbcbfc..0000000000 --- a/include/kendryte/bypass.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2020 Sean Anderson - */ -#ifndef K210_BYPASS_H -#define K210_BYPASS_H - -struct clk; - -struct k210_bypass { - struct clk clk; - struct clk **children; /* Clocks to reparent */ - struct clk **saved_parents; /* Parents saved over en-/dis-able */ - struct clk *bypassee; /* Clock to bypass */ - const struct clk_ops *bypassee_ops; /* Ops of the bypass clock */ - struct clk *alt; /* Clock to set children to when bypassing */ - size_t child_count; -}; - -#define to_k210_bypass(_clk) container_of(_clk, struct k210_bypass, clk) - -int k210_bypass_set_children(struct clk *clk, struct clk **children, - size_t child_count); -struct clk *k210_register_bypass_struct(const char *name, - const char *parent_name, - struct k210_bypass *bypass); -struct clk *k210_register_bypass(const char *name, const char *parent_name, - struct clk *bypassee, - const struct clk_ops *bypassee_ops, - struct clk *alt); -#endif /* K210_BYPASS_H */ From patchwork Fri Jun 11 04:16:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490728 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Lot9j0b5; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SHv6bVDz9sVb for ; Fri, 11 Jun 2021 14:18:03 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E973082F54; Fri, 11 Jun 2021 06:16:53 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Lot9j0b5"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4272582F15; Fri, 11 Jun 2021 06:16:46 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qt1-x82d.google.com (mail-qt1-x82d.google.com [IPv6:2607:f8b0:4864:20::82d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A07C082F2A for ; Fri, 11 Jun 2021 06:16:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qt1-x82d.google.com with SMTP id 93so1646359qtc.10 for ; Thu, 10 Jun 2021 21:16:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fGq8e/rHl3lHef7angv4WElrXvFmrzSYrXLwLWZr8j8=; b=Lot9j0b51mDcsoTFobaTbkD0Zhm9xaI+Dkvu5LTs8LNrQY4ne53R3agdDiAjefydK5 0C2BODm6kpKM39TKCNvrRpZn1Kq/pEi8TkX3YsX+YxJf9Zd7BAfVx2UfMfuYZTL6nBcf wBPyfU5tZeipM2c4S2RlHm61FOqvqvp5ORBnPX2tV1SH97+tBzoiSiIT57wwajPMgMQ4 O+lfbjKTJYAyw+q0sIpgk3sXNqy94mC0sq5W+W11eXTUPkSD7NQbSrahdiEecQqRjotB UGCVkP7XZ0FVCjYUsG6QmqGstjljOh+zShQZEEayxKWo53y5qvwGFDNC301sScbHvj9v uTTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fGq8e/rHl3lHef7angv4WElrXvFmrzSYrXLwLWZr8j8=; b=jQ0oPaSOs2zMmFRhIgqqD5BQl4O18cTPFnPJUpYJtgJgLXB3Er9Xe9ayRf84nOAm7u HhWiu+AvXo0CJ436DttSLeg1ygtdxhGT/08MRderOPivwES22+C3dFPYG1AVNJbOdfgU 0wVdd8L1RD+BGzuSGliilb1VLZt2opc4Ku9AUoSfwuPPjmgs1UkJT0/4p3bLP9ZnQNEm Thsw7GPnUjvCkrMorHKajnh6udVUiPjNiX2ko+sJ8NQPdRV4Pawm4eP6fSCoJHFMlEXd +qz4M9yTxeKqf9/60+zn31KR4xX/JYUvXGXE/pEI5dHydg1WOkJmIS6fFYkUElLHgYB+ 3qGQ== X-Gm-Message-State: AOAM530CSkDfZ3G1urkq511ABhTK40Q2nXn1wN92SDjszl39HlzS0FzD P/HitIEiFj3pvCCN0SAJTj9q4XoPTKY= X-Google-Smtp-Source: ABdhPJwKmRmDBHYiR2mF9B/ozB2gtk9H/1PzqmYAEQ1OABwBDFy7Dpa4am/Mn5H/46GgjEJ/d4Ds5g== X-Received: by 2002:a05:622a:3cd:: with SMTP id k13mr2115547qtx.388.1623384993257; Thu, 10 Jun 2021 21:16:33 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:32 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 08/11] clk: k210: Move k210 clock out of its own subdirectory Date: Fri, 11 Jun 2021 00:16:14 -0400 Message-Id: <20210611041617.1665833-9-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Now that we have only one clock driver, we don't need to have our own subdirectory. Move the driver back with the rest of the clock drivers. The MAINTAINERS for kendryte pinctrl is also fixed since it has always been wrong. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) MAINTAINERS | 4 ++-- drivers/clk/Kconfig | 14 +++++++++++++- drivers/clk/Makefile | 2 +- drivers/clk/{kendryte/clk.c => clk_kendryte.c} | 0 drivers/clk/kendryte/Kconfig | 12 ------------ drivers/clk/kendryte/Makefile | 1 - 6 files changed, 16 insertions(+), 17 deletions(-) rename drivers/clk/{kendryte/clk.c => clk_kendryte.c} (100%) delete mode 100644 drivers/clk/kendryte/Kconfig delete mode 100644 drivers/clk/kendryte/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index 86ff5e04a6..effcf5469d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -999,8 +999,8 @@ M: Sean Anderson S: Maintained F: doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt F: doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt -F: drivers/clk/kendryte/ -F: drivers/pinctrl/kendryte/ +F: drivers/clk/clk_kendryte.c +F: drivers/pinctrl/pinctrl-kendryte.c F: include/kendryte/ RNG diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 40a5a5dd88..4bc6680121 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -159,11 +159,23 @@ config CLK_SCMI by a SCMI agent based on SCMI clock protocol communication with a SCMI server. +config CLK_K210 + bool "Clock support for Kendryte K210" + depends on CLK + help + This enables support clock driver for Kendryte K210 platforms. + +config CLK_K210_SET_RATE + bool "Enable setting the Kendryte K210 PLL rate" + depends on CLK_K210 + help + Add functionality to calculate new rates for K210 PLLs. Enabling this + feature adds around 1K to U-Boot's final size. + source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" source "drivers/clk/imx/Kconfig" -source "drivers/clk/kendryte/Kconfig" source "drivers/clk/meson/Kconfig" source "drivers/clk/microchip/Kconfig" source "drivers/clk/mvebu/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 645709b855..f06164bb49 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_CLK_BOSTON) += clk_boston.o obj-$(CONFIG_CLK_EXYNOS) += exynos/ obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o -obj-$(CONFIG_CLK_K210) += kendryte/ +obj-$(CONFIG_CLK_K210) += clk_kendryte.o obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_MPFS) += microchip/ obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/clk_kendryte.c similarity index 100% rename from drivers/clk/kendryte/clk.c rename to drivers/clk/clk_kendryte.c diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig deleted file mode 100644 index 0dc8e3f889..0000000000 --- a/drivers/clk/kendryte/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config CLK_K210 - bool "Clock support for Kendryte K210" - depends on CLK - help - This enables support clock driver for Kendryte K210 platforms. - -config CLK_K210_SET_RATE - bool "Enable setting the Kendryte K210 PLL rate" - depends on CLK_K210 - help - Add functionality to calculate new rates for K210 PLLs. Enabling this - feature adds around 1K to U-Boot's final size. diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile deleted file mode 100644 index 0303c0b99c..0000000000 --- a/drivers/clk/kendryte/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += clk.o From patchwork Fri Jun 11 04:16:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490730 X-Patchwork-Delegate: uboot@andestech.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; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=fTfwON9Q; 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 4G1SJG0k32z9sVb for ; Fri, 11 Jun 2021 14:18:22 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1320E82F63; Fri, 11 Jun 2021 06:16:58 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fTfwON9Q"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 162DB82F27; Fri, 11 Jun 2021 06:16:49 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x72a.google.com (mail-qk1-x72a.google.com [IPv6:2607:f8b0:4864:20::72a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1931A82F29 for ; Fri, 11 Jun 2021 06:16:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x72a.google.com with SMTP id j184so29728536qkd.6 for ; Thu, 10 Jun 2021 21:16:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NgZyIxtVD1DsQN4CoRQiDFuE+TFwA9mnOBQWvA3QiVM=; b=fTfwON9Q/zvFxSACs8CPobjh431cwpltxSMJ92seme5zm3m1Gjpr56pMc1bgNk6708 KkLbg4LvKvbX8Lkcdg/YthrvRZCGR/pamh7uEPn/UjgFocq+Wp4zqK1tfDgVeIGH+Cwc sDnu1MjXHUmmv6z9X9elf4QiFYoO6AtIpBHmLlJYl4Xzz7EWUOW1dDrFlKc3lW8pjrbM Z29YPTXTR4WgWWNkyZ2mM69RbYzr07l8Ez1LUbnH8HOsS1plY/hNXmW9XSPG2nYhyfPc qgfFeWTpFUkkAtzOREO+sbv8y/CMKtvGhuqKhiBba27GrPmHlqK6LQs7KlMxUmIlmy0l ZwQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NgZyIxtVD1DsQN4CoRQiDFuE+TFwA9mnOBQWvA3QiVM=; b=oLnYk5yi600FkLj2q4FzZcVDO/d3TMweLeglev71ojtQuTAccR5ZKzBRUgtC4a4+oX tHPeVnhCjNetW/c/WARtyZ517DOz/kQUSEcaHxvjFmnAN7fRTbjl5su/MVng+Zk1EyOQ cqlLZ4yNCO2T8Mv0TBaTuzRG23SbXlPvOSAIC9bVYOHd9b9NXGY2v9Fv7h82e7lQ1Xdm ao3I9fJWI79/aiQ7tLD7XA0GVL8Nyr5NDjUyj8uxEIss1tCmwWTW0Z4mNbP/EBWFAcpm I1rJ4dPo1J6iqd18PS0auZ2sXoMx/4H63wa6YOs2Td66WQq1EQWaxZPgCmRl0EWePORD VSjw== X-Gm-Message-State: AOAM531zp9+RMeteLTZOxtbdVtSqoPx6b4VH/F1ZqGwzfrefRIEyFQD0 iX4k5vLy6CW+qs2Xz7TcyOJxLZgYwGY= X-Google-Smtp-Source: ABdhPJwsEhbVH2ob96O2ftxvfSitN1fAU4s902nwHtaxVrFMRf7upNln3p4n86S/mryOerO4Xf16pA== X-Received: by 2002:a05:620a:130e:: with SMTP id o14mr1992869qkj.296.1623384993917; Thu, 10 Jun 2021 21:16:33 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:33 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 09/11] k210: dts: Set PLL1 to the same rate as PLL0 Date: Fri, 11 Jun 2021 00:16:15 -0400 Message-Id: <20210611041617.1665833-10-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Linux has had some stability issues when using AISRAM with a different frequency from SRAM. Mirror their change here now that we relocate into AISRAM. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- Changes in v3: - Add CLK_K210_SET_RATE to defconfig so these changes apply arch/riscv/dts/k210.dtsi | 2 ++ configs/sipeed_maix_bitm_defconfig | 1 + 2 files changed, 3 insertions(+) diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi index 2492af8038..8bcd3cebde 100644 --- a/arch/riscv/dts/k210.dtsi +++ b/arch/riscv/dts/k210.dtsi @@ -501,6 +501,8 @@ #clock-cells = <1>; compatible = "kendryte,k210-clk"; clocks = <&in0>; + assigned-clocks = <&sysclk K210_CLK_PLL1>; + assigned-clock-rates = <390000000>; u-boot,dm-pre-reloc; }; diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig index bd877cd055..6a06f650ea 100644 --- a/configs/sipeed_maix_bitm_defconfig +++ b/configs/sipeed_maix_bitm_defconfig @@ -13,6 +13,7 @@ CONFIG_HUSH_PARSER=y CONFIG_MTDIDS_DEFAULT="nor0=spi3:0" CONFIG_MTDPARTS_DEFAULT="nor0:1M(u-boot),0x1000@0xfff000(env)" # CONFIG_NET is not set +CONFIG_CLK_K210_SET_RATE=y # CONFIG_INPUT is not set CONFIG_SF_DEFAULT_BUS=3 # CONFIG_DM_ETH is not set From patchwork Fri Jun 11 04:16:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490729 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=AF/EA4pi; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SJ53VDQz9sVb for ; Fri, 11 Jun 2021 14:18:13 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3555982F5A; Fri, 11 Jun 2021 06:16:56 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="AF/EA4pi"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 12D2182F43; Fri, 11 Jun 2021 06:16:49 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E697182F26 for ; Fri, 11 Jun 2021 06:16:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x72d.google.com with SMTP id j184so29728565qkd.6 for ; Thu, 10 Jun 2021 21:16:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=05bkayVW0AHjC4UqQRpWXo1OHds9XLoxRnrqKSpcSnU=; b=AF/EA4piUxamIDj4uM1vm3NNlJcrJge35FZDeRKCpoOJC1ov0yzETYG+ohopulFPdi ++UH9a9DZt6GzbqzlsgBSVG+BoS/gsqPTSf8AMyNsfI+14b8q9ZQroVVk0Q2lZX4bkgV Auzkno8zzL9EuHIw/gqgn36m2Wju66ntmsSDxhx4MFRHIJHCilo3Q4VNJEHF4FWhx9Ux NoeqOvVCRY8njq1OU/gAmUXuC0b2JhvdGK88+nPuP93xZFPWX8eR4s/iNJ+rkpn7SeNU s5sxAIFs8GJx4hNJLZJej9AZILmVwY6E+uf5iYzlHnDcneCeINBYJQNMxy1uYukhfQxG 8PBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=05bkayVW0AHjC4UqQRpWXo1OHds9XLoxRnrqKSpcSnU=; b=YygAc0ZSCI5rmZzeZ9RnSOd2iVnBXli+ltLnt8ZqjESfn06YfAaPTZlmZQ+4n4UhHL z8p1RmeOR/HE3KSLF3YxFKTmCojTPjbD6xdtdbyEWPsWVGBniagF8Yv6jVYocVCpzGGa AjCqYc5KjpGOw01ymKtgeLnFaVaxf+P7xaVzK491GEFtNmtteEUls8rCN0HHHiljtoc2 LyBJTONkudOaHCu8F7CxBeiA2j7YT3tRJI4k825KOzIF4GYkHV+8Z1ABobL4GwhdNlTO gbYU3Iysqscu6uyuNk1Zu7qltHXTksGb92jf98ZMzqaoM413rbjsN4NBx7SuuylteL77 0UKA== X-Gm-Message-State: AOAM532IPwAUwoWGLs+i9Y+EnfS5UMFer1UlvRFuXe1gL/EZOezdgPgK kvDaXUzk7eRynOVjJ5FbQOUYP8FSCJA= X-Google-Smtp-Source: ABdhPJyz191/LHUMxN5lusck982MmJujM8FNhuG65piqGw6HltF40xuHVdDbguWiimNwpZcIFnnWpw== X-Received: by 2002:a05:620a:1643:: with SMTP id c3mr1951542qko.308.1623384994617; Thu, 10 Jun 2021 21:16:34 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:34 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson Subject: [PATCH v3 10/11] k210: Don't imply CCF Date: Fri, 11 Jun 2021 00:16:16 -0400 Message-Id: <20210611041617.1665833-11-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean Now that the k210 clock driver does not depend on CCF, we should no longer imply it (and probably should not have in the first place). We can also reduce the pre-relocation malloc arena back to something sensible. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- (no changes since v1) board/sipeed/maix/Kconfig | 2 -- configs/sipeed_maix_bitm_defconfig | 1 - 2 files changed, 3 deletions(-) diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig index adf6abb572..b1d7a7ad93 100644 --- a/board/sipeed/maix/Kconfig +++ b/board/sipeed/maix/Kconfig @@ -37,8 +37,6 @@ config BOARD_SPECIFIC_OPTIONS imply SIFIVE_CLINT imply POWER_DOMAIN imply SIMPLE_PM_BUS - imply CLK_CCF - imply CLK_COMPOSITE_CCF imply CLK_K210 imply DM_RESET imply RESET_SYSCON diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig index 6a06f650ea..33c67c0b54 100644 --- a/configs/sipeed_maix_bitm_defconfig +++ b/configs/sipeed_maix_bitm_defconfig @@ -1,5 +1,4 @@ CONFIG_RISCV=y -CONFIG_SYS_MALLOC_F_LEN=0x10000 CONFIG_ENV_SIZE=0x1000 CONFIG_ENV_OFFSET=0xfff000 CONFIG_ENV_SECT_SIZE=0x1000 From patchwork Fri Jun 11 04:16:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1490731 X-Patchwork-Delegate: uboot@andestech.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=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=P1SxLY9O; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (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 4G1SJR1l5kz9sW4 for ; Fri, 11 Jun 2021 14:18:31 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C481282F68; Fri, 11 Jun 2021 06:16:59 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="P1SxLY9O"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D939182F24; Fri, 11 Jun 2021 06:16:49 +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,FREEMAIL_FROM,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-qk1-x733.google.com (mail-qk1-x733.google.com [IPv6:2607:f8b0:4864:20::733]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 82D0F82F2F for ; Fri, 11 Jun 2021 06:16:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x733.google.com with SMTP id f70so14515790qke.13 for ; Thu, 10 Jun 2021 21:16:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0AD3bH7vdzJ0DxP9L2N8wwUC/vMKZsUBpH2QBQh4ih8=; b=P1SxLY9OEwp6E/q3tVRIiy2cQERxa58APkLCGLwLyp7H3LKeWB2AKzNqeXvcRDoD2R gilAGBf3+4U3arZkcprUFJD7TRgvunmzyj4wyr3VoQgIDbjvaPJabQRjzdUYpYBIBO7X DM+/sVZd1oXJu4ZxZdtTzkv0NtRlkOW2VEhnA66vQzVacyREQxpn5yPlV9cS932DpcPc rigKK5HUplnp/au1ybXSG7sBIyDpYVC922bdezPxe4V9gJkX1TSe1zIuD83eGCrWB5Bk R6FsqLJ8Ej8LyiBiZJLTidDoGKE75k9Lhz9LwLZNI2VhK1CnGBwwYPcvfjsUF5y3XtIN L3lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0AD3bH7vdzJ0DxP9L2N8wwUC/vMKZsUBpH2QBQh4ih8=; b=V927ZYTrylk05Mn/WyM5ZXTnIWSbJNMxAJJGrfxFMqRkwsCa/JjXvhUDezDXO8kFi2 c+lMB1dgPF8ZDHji4wAFHGklA1Zu2/Bap6e0M8R8nbrIT0yal9m8R9HAGmDc7TG/YbBA wqQyvFgHGpGzBw+/9YOZWwhgUP4V1cM6xzV2+kUkBRirA4Plae+lbVHFmMzwoHKTr+lp +geAea6rVDmDYwUXGrYQgL34KOXAlH6pXyJQqmcaOrip+b1sIH647RIe8ZKSTj0P22OY qoHXRBKBd4bTkB7NH7Xr7V1amFofRHT9f8Y7jl7tza6tfqIqNN+733dhG10vdp/QhCHI MyAA== X-Gm-Message-State: AOAM533dioF+LMYebQCBcoX2RWyGz1FeMKntGytAKt38yKosPIWoFshW rHpt+0Xt40RdPi9JXKw5AEBjQKKlUQw= X-Google-Smtp-Source: ABdhPJwfgBH4VZRI1rqFi1UYAEbk8Xvc5xq3qKxFhafM3UfdceC9Id3HhrfDJzQ1malgKM7n+LT4TQ== X-Received: by 2002:a05:620a:a85:: with SMTP id v5mr2042856qkg.285.1623384995327; Thu, 10 Jun 2021 21:16:35 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id d16sm3399033qtj.69.2021.06.10.21.16.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 21:16:35 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Damien Le Moal , Leo Liang , Lukasz Majewski , Sean Anderson , Simon Glass Subject: [PATCH v3 11/11] test: Add K210 PLL tests to sandbox defconfigs Date: Fri, 11 Jun 2021 00:16:17 -0400 Message-Id: <20210611041617.1665833-12-seanga2@gmail.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210611041617.1665833-1-seanga2@gmail.com> References: <20210611041617.1665833-1-seanga2@gmail.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.4 at phobos.denx.de X-Virus-Status: Clean This adds the unit test for the K210 PLL to the sandbox defconfigs. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- (no changes since v1) configs/sandbox64_defconfig | 2 ++ configs/sandbox_defconfig | 2 ++ configs/sandbox_flattree_defconfig | 2 ++ 3 files changed, 6 insertions(+) diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 9a373bab6f..9cd746107d 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -107,6 +107,8 @@ CONFIG_AXI_SANDBOX=y CONFIG_BUTTON=y CONFIG_BUTTON_GPIO=y CONFIG_CLK=y +CONFIG_CLK_K210=y +CONFIG_CLK_K210_SET_RATE=y CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index bdbf714e2b..f9749dea61 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -130,6 +130,8 @@ CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y CONFIG_CLK_SCMI=y +CONFIG_CLK_K210=y +CONFIG_CLK_K210_SET_RATE=y CONFIG_SANDBOX_CLK_CCF=y CONFIG_CPU=y CONFIG_DM_DEMO=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 853c9440ea..772230ce47 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -86,6 +86,8 @@ CONFIG_AXI=y CONFIG_AXI_SANDBOX=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y +CONFIG_CLK_K210=y +CONFIG_CLK_K210_SET_RATE=y CONFIG_SANDBOX_CLK_CCF=y CONFIG_CPU=y CONFIG_DM_DEMO=y