From patchwork Sun May 3 02:46:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281836 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=caXu8gbC; 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 49F9PX3zxPz9sRf for ; Sun, 3 May 2020 12:47:12 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 93E4E81EBB; Sun, 3 May 2020 04:46:51 +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="caXu8gbC"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AE15B81E89; Sun, 3 May 2020 04:46:47 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x742.google.com (mail-qk1-x742.google.com [IPv6:2607:f8b0:4864:20::742]) (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 6C3D781E7B for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qk1-x742.google.com with SMTP id c10so2145262qka.4 for ; Sat, 02 May 2020 19:46:44 -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=q9VDn1dBupdt/oL/HsyO+ifo6zXySfW/knh0EkGghcY=; b=caXu8gbCdi6i25PtApXjD1b4sMOwvpTytTw5i0Z89eOOi+F3H39O2jcjvkgeu1qAcc pe1z/pQNEwaFY0xZe0/Nvc6xbkaeoK4MYBxGDNmtnr+pFRynVrdkUKYQTwfkUPwjMMFl 7fh2YuGzHoPWQ70bejEs/Cpb/rQob4K6kC+66YF06W/S2vpBwGg4NmWXmQM9uRreDUQS y3qV/75JfdaZiVuEtalZAm5yIcb3bHhpXTt+yFzVDoLd/VQWJ/X3XdZ4sS7yytR+D4C0 Tgb+6Q9MXU8mXNVjmBB5zYv6ZAymeeJK/Vz1yLIM3e2B96oXEk5sCbTv/PctB9CTXKj6 2SFA== 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=q9VDn1dBupdt/oL/HsyO+ifo6zXySfW/knh0EkGghcY=; b=SYWgRjqGJFpYr5tg+jtaA6WmtcLkOZ7xH7X5zTiKzZ5o7o5w/WBxBEv1FVaJUiv4vX ec1bk3LfZ2X+nMUN77lRxNJPwsPiL16mrl6lB0ppXkSLE2jxYLEjdgGjZVHERRCRCU1Y RTTbC1kj6bW8oAl5FRqBGyRc8zl+ECtYP/SJ3XVMKl7MtVg/6pc2TkyPKyD5c7RsBGOJ nOD5M5i7BCfOs7KlhfaGKPkH4j3oS7joi/wefsbGqXKa1yXMbacPhrdm9qRMtnRhy1Hb PFpeM29RDpBIMlvWhexz+XDXBXxjb6dixTs3RUNI9uqa1IXkMDrjsIo/kDi4GEbj5aVB w6AA== X-Gm-Message-State: AGi0Pua/ep/etEzfxfhJyMoqhKH6TBWeFOomDctlPvw+6G7G2sJxFp+7 ICLpca0ZayVBlAiGOd8V57pAXPk5vYE= X-Google-Smtp-Source: APiQypKrky0NVwWDx9lRZLjWFW48adr5aCe3gJxrRQTLufk4w02aEyXgHX1HHaQiVElXcmhR9izZ9w== X-Received: by 2002:a37:a753:: with SMTP id q80mr4001074qke.492.1588474002688; Sat, 02 May 2020 19:46:42 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:41 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 01/21] clk: Always use the supplied struct clk Date: Sat, 2 May 2020 22:46:17 -0400 Message-Id: <20200503024637.327733-2-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean CCF clocks should always use the struct clock passed to their methods for extracting the driver-specific clock information struct. Previously, many functions would use the clk->dev->priv if the device was bound. This could cause problems with composite clocks. The individual clocks in a composite clock did not have the ->dev field filled in. This was fine, because the device-specific clock information would be used. However, since there was no ->dev, there was no way to get the parent clock. This caused the recalc_rate method of the CCF divider clock to fail. One option would be to use the clk->priv field to get the composite clock and from there get the appropriate parent device. However, this would tie the implementation to the composite clock. In general, different devices should not rely on the contents of ->priv from another device. The simple solution to this problem is to just always use the supplied struct clock. The composite clock now fills in the ->dev pointer of its child clocks. This allows child clocks to make calls like clk_get_parent() without issue. imx avoided the above problem by using a custom get_rate function with composite clocks. Signed-off-by: Sean Anderson Acked-by: Lukasz Majewski --- Changes in v4: - Lint Changes in v3: - Documented new assumptions in the CCF - Wrapped docs to 80 columns doc/imx/clk/ccf.txt | 63 +++++++++++++++++----------------- drivers/clk/clk-composite.c | 7 ++++ drivers/clk/clk-divider.c | 6 ++-- drivers/clk/clk-fixed-factor.c | 3 +- drivers/clk/clk-gate.c | 6 ++-- drivers/clk/clk-mux.c | 12 +++---- drivers/clk/imx/clk-gate2.c | 4 +-- 7 files changed, 50 insertions(+), 51 deletions(-) diff --git a/doc/imx/clk/ccf.txt b/doc/imx/clk/ccf.txt index 36b60dc438..e40ac360e8 100644 --- a/doc/imx/clk/ccf.txt +++ b/doc/imx/clk/ccf.txt @@ -1,42 +1,37 @@ Introduction: ============= -This documentation entry describes the Common Clock Framework [CCF] -port from Linux kernel (v5.1.12) to U-Boot. +This documentation entry describes the Common Clock Framework [CCF] port from +Linux kernel (v5.1.12) to U-Boot. -This code is supposed to bring CCF to IMX based devices (imx6q, imx7 -imx8). Moreover, it also provides some common clock code, which would -allow easy porting of CCF Linux code to other platforms. +This code is supposed to bring CCF to IMX based devices (imx6q, imx7 imx8). +Moreover, it also provides some common clock code, which would allow easy +porting of CCF Linux code to other platforms. Design decisions: ================= -* U-Boot's driver model [DM] for clk differs from Linux CCF. The most - notably difference is the lack of support for hierarchical clocks and - "clock as a manager driver" (single clock DTS node acts as a starting - point for all other clocks). +* U-Boot's driver model [DM] for clk differs from Linux CCF. The most notably + difference is the lack of support for hierarchical clocks and "clock as a + manager driver" (single clock DTS node acts as a starting point for all other + clocks). -* The clk_get_rate() caches the previously read data if CLK_GET_RATE_NOCACHE - is not set (no need for recursive access). +* The clk_get_rate() caches the previously read data if CLK_GET_RATE_NOCACHE is + not set (no need for recursive access). -* On purpose the "manager" clk driver (clk-imx6q.c) is not using large - table to store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = .... - Instead we use udevice's linked list for the same class (UCLASS_CLK). +* On purpose the "manager" clk driver (clk-imx6q.c) is not using large table to + store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = .... Instead we + use udevice's linked list for the same class (UCLASS_CLK). Rationale: ---------- - When porting the code as is from Linux, one would need ~1KiB of RAM to - store it. This is way too much if we do plan to use this driver in SPL. + When porting the code as is from Linux, one would need ~1KiB of RAM to store + it. This is way too much if we do plan to use this driver in SPL. * The "central" structure of this patch series is struct udevice and its uclass_priv field contains the struct clk pointer (to the originally created one). -* Up till now U-Boot's driver model (DM) CLK operates on udevice (main - access to clock is by udevice ops) - In the CCF the access to struct clk (embodying pointer to *dev) is - possible via dev_get_clk_ptr() (it is a wrapper on dev_get_uclass_priv()). - * To keep things simple the struct udevice's uclass_priv pointer is used to store back pointer to corresponding struct clk. However, it is possible to modify clk-uclass.c file and add there struct uc_clk_priv, which would have @@ -45,13 +40,17 @@ Design decisions: setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv)) the uclass_priv stores the pointer to struct clk. +* Non-CCF clocks do not have a pointer to a clock in clk->dev->priv. In the case + of composite clocks, clk->dev->priv may not match clk. Drivers should always + use the struct clk which is passed to them, and not clk->dev->priv. + * It is advised to add common clock code (like already added rate and flags) to the struct clk, which is a top level description of the clock. * U-Boot's driver model already provides the facility to automatically allocate - (via private_alloc_size) device private data (accessible via dev->priv). - It may look appealing to use this feature to allocate private structures for - CCF clk devices e.g. divider (struct clk_divider *divider) for IMX6Q clock. + (via private_alloc_size) device private data (accessible via dev->priv). It + may look appealing to use this feature to allocate private structures for CCF + clk devices e.g. divider (struct clk_divider *divider) for IMX6Q clock. The above feature had not been used for following reasons: - The original CCF Linux kernel driver is the "manager" for clocks - it @@ -64,21 +63,23 @@ Design decisions: * I've added the clk_get_parent(), which reads parent's dev->uclass_priv to provide parent's struct clk pointer. This seems the easiest way to get - child/parent relationship for struct clk in U-Boot's udevice based clocks. + child/parent relationship for struct clk in U-Boot's udevice based clocks. In + the future arbitrary parents may be supported by adding a get_parent function + to clk_ops. * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in 'struct clk'. Clock IP block agnostic flags from 'struct clk_core' (e.g. NOCACHE) have been - moved from this struct one level up to 'struct clk'. + moved from this struct one level up to 'struct clk'. Many flags are + unimplemented at the moment. * For tests the new ./test/dm/clk_ccf.c and ./drivers/clk/clk_sandbox_ccf.c files have been introduced. The latter setups the CCF clock structure for - sandbox by reusing, if possible, generic clock primitives - like divier - and mux. The former file provides code to tests this setup. + sandbox by reusing, if possible, generic clock primitives - like divier and + mux. The former file provides code to tests this setup. For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been introduced. - All new primitives added for new architectures must have corresponding test - in the two aforementioned files. - + All new primitives added for new architectures must have corresponding test in + the two aforementioned files. Testing (sandbox): ================== diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 414185031e..2ff1d6b47f 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -147,6 +147,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name, goto err; } + if (composite->mux) + composite->mux->dev = clk->dev; + if (composite->rate) + composite->rate->dev = clk->dev; + if (composite->gate) + composite->gate->dev = clk->dev; + return clk; err: diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index d79ae367b8..5fe1c3941f 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -72,8 +72,7 @@ unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate, static ulong clk_divider_recalc_rate(struct clk *clk) { - struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_divider *divider = to_clk_divider(clk); unsigned long parent_rate = clk_get_parent_rate(clk); unsigned int val; @@ -152,8 +151,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, static ulong clk_divider_set_rate(struct clk *clk, unsigned long rate) { - struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_divider *divider = to_clk_divider(clk); unsigned long parent_rate = clk_get_parent_rate(clk); int value; u32 val; diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 2ceb6bb171..0eb24b87fc 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -20,8 +20,7 @@ static ulong clk_factor_recalc_rate(struct clk *clk) { - struct clk_fixed_factor *fix = - to_clk_fixed_factor(dev_get_clk_ptr(clk->dev)); + struct clk_fixed_factor *fix = to_clk_fixed_factor(clk); unsigned long parent_rate = clk_get_parent_rate(clk); unsigned long long int rate; diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 6415c2f1b9..b5827dced0 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -45,8 +45,7 @@ */ static void clk_gate_endisable(struct clk *clk, int enable) { - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_gate *gate = to_clk_gate(clk); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; u32 reg; @@ -88,8 +87,7 @@ static int clk_gate_disable(struct clk *clk) int clk_gate_is_enabled(struct clk *clk) { - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_gate *gate = to_clk_gate(clk); u32 reg; #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index b9d2ae6778..0502217dc4 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -37,8 +37,7 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags, unsigned int val) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int num_parents = mux->num_parents; if (table) { @@ -81,8 +80,7 @@ unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index) u8 clk_mux_get_parent(struct clk *clk) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); u32 val; #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) @@ -99,8 +97,7 @@ u8 clk_mux_get_parent(struct clk *clk) static int clk_fetch_parent_index(struct clk *clk, struct clk *parent) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int i; @@ -117,8 +114,7 @@ static int clk_fetch_parent_index(struct clk *clk, static int clk_mux_set_parent(struct clk *clk, struct clk *parent) { - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? - dev_get_clk_ptr(clk->dev) : clk); + struct clk_mux *mux = to_clk_mux(clk); int index; u32 val; u32 reg; diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index b38890d5ba..40b2d4caab 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -39,7 +39,7 @@ struct clk_gate2 { static int clk_gate2_enable(struct clk *clk) { - struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + struct clk_gate2 *gate = to_clk_gate2(clk); u32 reg; reg = readl(gate->reg); @@ -52,7 +52,7 @@ static int clk_gate2_enable(struct clk *clk) static int clk_gate2_disable(struct clk *clk) { - struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + struct clk_gate2 *gate = to_clk_gate2(clk); u32 reg; reg = readl(gate->reg); From patchwork Sun May 3 02:46:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281838 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=SPcrjHg+; 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 49F9Q210qqz9sRf for ; Sun, 3 May 2020 12:47:38 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 11E6381EDE; Sun, 3 May 2020 04:46:55 +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="SPcrjHg+"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 236AF81E7E; Sun, 3 May 2020 04:46: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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf43.google.com (mail-qv1-xf43.google.com [IPv6:2607:f8b0:4864:20::f43]) (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 05E9F81E7E for ; Sun, 3 May 2020 04:46:45 +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-qv1-xf43.google.com with SMTP id h6so6682529qvz.8 for ; Sat, 02 May 2020 19:46:44 -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=h1m4lfm+TPLVRlEXFPHzcDT1m/P/6o+J1vJWNNUETEA=; b=SPcrjHg+zIs6VnQBEKknKlAgXp49jAnzg9F98aMQ+oUUGqUJ5V09B7WEf4dw7kN10D F6VA46tQufqZF890SFzpvC0/CQ7jEMTfvslWZ6hLRPducK9E6MOlW+i7aQmWJgaUGg36 SXigOxqoIrvRFzdlhtegpdkfd/FpijyJi35t1wqg5yMTvLPlLhrye6K6pTeCNjNVQ2O6 SLnZvQpo8yruydb3S8rkplaCJXTDVbyFB1UJx+iNGt6q7W5LSn+jeKIOMw+QzywDDlQe WdHqUJFV8Z+xiH915Jj7ujqpqpw/a0/Zliha8UPJdQMEmOlH8tCxQmRiDTPQWSrP3r7t 9epw== 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=h1m4lfm+TPLVRlEXFPHzcDT1m/P/6o+J1vJWNNUETEA=; b=CUnvCEV0U3alZuijRY+Ttl6puIZxeeqGAgozBTNlcpPOuAbhVA2cadoDNPtgPMu3/y o6QbJNLa4+BitRejLBw9H7JLqSSi6P3H3AEWjYdBOQy3Axs3QTHRxTFcU2XmEse9dQY0 kuH0YjnMcwlFwKmKaD/9FJ7O3qXQKUoLIQvErv4YznkIhdh0JG+MzcJ6Q7lpgiekFXV/ 3xDC+874b0qVqPgX104aC+EwsW3aRy1FNxv2J+tDmtHP4nmbkBQ5vgXHaNVsAh3Q5ANX rlEuctLik1doQb6kxB7JIbxCWKMPoYOeue9GQv+PSsdOOz2vNR7CQhUljVxLYnFveBx+ dpnA== X-Gm-Message-State: AGi0PubTYsEEx3IUJx3KKGu6uVjzxZEdGdP8hfFllyXfZ6s+5f7bUXi5 l+Jz+D0QK0Cz1NZqqADGNrpEkSEFROo= X-Google-Smtp-Source: APiQypK8OOx5SHcs5DWk41WDORUY0dzrOlslD1RJtYYf3eTwFv/mLmoONhtw+ZAHOpaF3vXSm206Gw== X-Received: by 2002:a0c:ffc3:: with SMTP id h3mr11031110qvv.156.1588474003681; Sat, 02 May 2020 19:46:43 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:43 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 02/21] clk: Check that ops of composite clock components exist before calling Date: Sat, 2 May 2020 22:46:18 -0400 Message-Id: <20200503024637.327733-3-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean clk_composite_ops was shared between all devices in the composite clock driver. If one clock had a feature (such as supporting set_parent) which another clock did not, it could call a null pointer dereference. This patch does three things 1. It adds null-pointer checks to all composite clock functions. 2. It makes clk_composite_ops const and sets its functions at compile-time. 3. It adds some basic sanity checks to num_parents. The combined effect of these changes is that any of mux, rate, or gate can be NULL, and composite clocks will still function normally. Previously, at least mux had to exist, since clk_composite_get_parent was used to determine the parent for clk_register. Signed-off-by: Sean Anderson Acked-by: Lukasz Majewski --- Changes in v4: - Return ENOTSUPP not ENOSYS with no set_parent Changes in v3: - Don't return an error code where a no-op would be fine drivers/clk/clk-composite.c | 57 +++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 2ff1d6b47f..819bfca2fc 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -24,7 +24,10 @@ static u8 clk_composite_get_parent(struct clk *clk) (struct clk *)dev_get_clk_ptr(clk->dev) : clk); struct clk *mux = composite->mux; - return clk_mux_get_parent(mux); + if (mux) + return clk_mux_get_parent(mux); + else + return 0; } static int clk_composite_set_parent(struct clk *clk, struct clk *parent) @@ -34,7 +37,10 @@ static int clk_composite_set_parent(struct clk *clk, struct clk *parent) const struct clk_ops *mux_ops = composite->mux_ops; struct clk *mux = composite->mux; - return mux_ops->set_parent(mux, parent); + if (mux && mux_ops) + return mux_ops->set_parent(mux, parent); + else + return -ENOTSUPP; } static unsigned long clk_composite_recalc_rate(struct clk *clk) @@ -44,7 +50,10 @@ static unsigned long clk_composite_recalc_rate(struct clk *clk) const struct clk_ops *rate_ops = composite->rate_ops; struct clk *rate = composite->rate; - return rate_ops->get_rate(rate); + if (rate && rate_ops) + return rate_ops->get_rate(rate); + else + return clk_get_parent_rate(clk); } static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) @@ -54,7 +63,10 @@ static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) const struct clk_ops *rate_ops = composite->rate_ops; struct clk *clk_rate = composite->rate; - return rate_ops->set_rate(clk_rate, rate); + if (rate && rate_ops) + return rate_ops->set_rate(clk_rate, rate); + else + return clk_get_rate(clk); } static int clk_composite_enable(struct clk *clk) @@ -64,7 +76,10 @@ static int clk_composite_enable(struct clk *clk) const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; - return gate_ops->enable(gate); + if (gate && gate_ops) + return gate_ops->enable(gate); + else + return 0; } static int clk_composite_disable(struct clk *clk) @@ -74,15 +89,12 @@ static int clk_composite_disable(struct clk *clk) const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; - gate_ops->disable(gate); - - return 0; + if (gate && gate_ops) + return gate_ops->disable(gate); + else + return 0; } -struct clk_ops clk_composite_ops = { - /* This will be set according to clk_register_composite */ -}; - struct clk *clk_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk *mux, @@ -96,7 +108,9 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk *clk; struct clk_composite *composite; int ret; - struct clk_ops *composite_ops = &clk_composite_ops; + + if (!num_parents || (num_parents != 1 && !mux)) + return ERR_PTR(-EINVAL); composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) @@ -105,8 +119,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, if (mux && mux_ops) { composite->mux = mux; composite->mux_ops = mux_ops; - if (mux_ops->set_parent) - composite_ops->set_parent = clk_composite_set_parent; mux->data = (ulong)composite; } @@ -115,11 +127,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, clk = ERR_PTR(-EINVAL); goto err; } - composite_ops->get_rate = clk_composite_recalc_rate; - - /* .set_rate requires either .round_rate or .determine_rate */ - if (rate_ops->set_rate) - composite_ops->set_rate = clk_composite_set_rate; composite->rate = rate; composite->rate_ops = rate_ops; @@ -134,8 +141,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->gate = gate; composite->gate_ops = gate_ops; - composite_ops->enable = clk_composite_enable; - composite_ops->disable = clk_composite_disable; gate->data = (ulong)composite; } @@ -161,6 +166,14 @@ err: return clk; } +static const struct clk_ops clk_composite_ops = { + .set_parent = clk_composite_set_parent, + .get_rate = clk_composite_recalc_rate, + .set_rate = clk_composite_set_rate, + .enable = clk_composite_enable, + .disable = clk_composite_disable, +}; + U_BOOT_DRIVER(clk_composite) = { .name = UBOOT_DM_CLK_COMPOSITE, .id = UCLASS_CLK, From patchwork Sun May 3 02:46:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281837 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=kVhDW8ih; 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 49F9Pq02bXz9sRf for ; Sun, 3 May 2020 12:47:26 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8B9BF81ED6; Sun, 3 May 2020 04:46: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="kVhDW8ih"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0AEC381EA9; Sun, 3 May 2020 04:46: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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x741.google.com (mail-qk1-x741.google.com [IPv6:2607:f8b0:4864:20::741]) (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 08C1F81E87 for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qk1-x741.google.com with SMTP id 23so13226038qkf.0 for ; Sat, 02 May 2020 19:46:45 -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=KV+Wfmv8NzJ/8GiouN+mz/HR1iaw7p9vyCwoMp8TfOE=; b=kVhDW8ihMwsnStwnYanXPBKprv06VH+IWe0DLwZo+WfRI8RH5mHwMB+PcUUJKBYDTS lu/krCFhNBikq/CXyTvXb3IX00w5QRK5lCtXBEW5fbsWlIzPz1EzXAMlV8mVJSfc/Y23 NNuNwubtjv7cuFERcu8iLBnEdVmR9CA0+aLRLDsHjQxLZTzNUsIspbmRXklkVRPcowzl GZy7tAb4Bewo0IQ2u+HLuEDEPzlmEcPPyn0hXTES2f8TyinbyeMzOfzpzj3hdLCFM3d6 fWM87+PVIM07e7yKG+7xsDDcktfthDgQVfMabYwhuWa7wxD2ahiRm9oie4a9JErllF2G KF5A== 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=KV+Wfmv8NzJ/8GiouN+mz/HR1iaw7p9vyCwoMp8TfOE=; b=GrEWAIGdhhuCmAjT0+6pitZfz7jlSvG6U6KZFLLAkwjveAtCJ+2JPL2bchQt0wCGHJ V+gI3rKFH0Rkt+9o04ci05ETKTu7ySq+Vjiz7X+ceBMBWUWfGiyCD7tzrrezN2yNID9J 0YRVuPe0norxB9AbZZG+tyJR2r+FJEFekqV92QIe+7gtcrt8G8guwzlThk/f0YLGBwiC MKgURF0QjKC9wyrT/3YWVjutZcy/K5i/N2nCFNZknVGj+uMjMUYvRNbCjTlaGpN31Vx4 sci6a4xXYetAWfpkaSnJirGP9u2hDyFWmgVHTVJslBlnh0xuOmANXCxLCwBO8Kx7sWcI F9sQ== X-Gm-Message-State: AGi0Pub9TGnoBaJS4noNjxSkwouI/oe7effYBofmD3Yf6B+JNOLPtgop eTvWi/glksqHR2M2QHNvpph0LGN8z0M= X-Google-Smtp-Source: APiQypLOF7BqiX6iXlhaucXHqf1qrM71C9MFq7GlAW5tYKMU3PKNrSAcVJzXCwRZ87pGrBpCA7w2Zg== X-Received: by 2002:a05:620a:246:: with SMTP id q6mr10517459qkn.357.1588474004662; Sat, 02 May 2020 19:46:44 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:44 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 03/21] clk: Unconditionally recursively en-/dis-able clocks Date: Sat, 2 May 2020 22:46:19 -0400 Message-Id: <20200503024637.327733-4-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean For clocks not in the CCF, their parents will not have UCLASS_CLK, so we just enable them as normal. The enable count is local to the struct clk, but this will never result in the actual en-/dis-able op being called (unless the same struct clk is enabled twice). For clocks in the CCF, we always traverse up the tree when enabling. Previously, CCF clocks without id set would be skipped, stopping the traversal too early. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- Changes in v6: - Fix disable incorrectly recursing into non-clock devices Changes in v5: - Clear enable_count on request Changes in v4: - Lint Changes in v3: - New drivers/clk/clk-uclass.c | 60 ++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 71878474eb..aa8dd9d027 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -410,6 +410,7 @@ int clk_request(struct udevice *dev, struct clk *clk) ops = clk_dev_ops(dev); clk->dev = dev; + clk->enable_count = 0; if (!ops->request) return 0; @@ -521,7 +522,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent) int clk_enable(struct clk *clk) { const struct clk_ops *ops; - struct clk *clkp = NULL; int ret; debug("%s(clk=%p)\n", __func__, clk); @@ -530,32 +530,29 @@ int clk_enable(struct clk *clk) ops = clk_dev_ops(clk->dev); if (CONFIG_IS_ENABLED(CLK_CCF)) { - /* Take id 0 as a non-valid clk, such as dummy */ - if (clk->id && !clk_get_by_id(clk->id, &clkp)) { - if (clkp->enable_count) { - clkp->enable_count++; - return 0; - } - if (clkp->dev->parent && - device_get_uclass_id(clkp->dev) == UCLASS_CLK) { - ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent)); - if (ret) { - printf("Enable %s failed\n", - clkp->dev->parent->name); - return ret; - } + if (clk->enable_count) { + clk->enable_count++; + return 0; + } + if (clk->dev->parent && + device_get_uclass_id(clk->dev->parent) == UCLASS_CLK) { + ret = clk_enable(dev_get_clk_ptr(clk->dev->parent)); + if (ret) { + printf("Enable %s failed\n", + clk->dev->parent->name); + return ret; } } if (ops->enable) { ret = ops->enable(clk); if (ret) { - printf("Enable %s failed\n", clk->dev->name); + printf("Enable %s failed (error %d)\n", + clk->dev->name, ret); return ret; } } - if (clkp) - clkp->enable_count++; + clk->enable_count++; } else { if (!ops->enable) return -ENOSYS; @@ -581,7 +578,6 @@ int clk_enable_bulk(struct clk_bulk *bulk) int clk_disable(struct clk *clk) { const struct clk_ops *ops; - struct clk *clkp = NULL; int ret; debug("%s(clk=%p)\n", __func__, clk); @@ -590,29 +586,27 @@ int clk_disable(struct clk *clk) ops = clk_dev_ops(clk->dev); if (CONFIG_IS_ENABLED(CLK_CCF)) { - if (clk->id && !clk_get_by_id(clk->id, &clkp)) { - if (clkp->enable_count == 0) { - printf("clk %s already disabled\n", - clkp->dev->name); - return 0; - } - - if (--clkp->enable_count > 0) - return 0; + if (clk->enable_count == 0) { + printf("clk %s already disabled\n", + clk->dev->name); + return 0; } + if (--clk->enable_count > 0) + return 0; + if (ops->disable) { ret = ops->disable(clk); if (ret) return ret; } - if (clkp && clkp->dev->parent && - device_get_uclass_id(clkp->dev) == UCLASS_CLK) { - ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent)); + if (clk->dev->parent && + device_get_uclass_id(clk->dev->parent) == UCLASS_CLK) { + ret = clk_disable(dev_get_clk_ptr(clk->dev->parent)); if (ret) { - printf("Disable %s failed\n", - clkp->dev->parent->name); + printf("Disable %s failed (error %d)\n", + clk->dev->parent->name, ret); return ret; } } From patchwork Sun May 3 02:46:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281839 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=HlbqbPB+; 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 49F9QH4Fzmz9sRf for ; Sun, 3 May 2020 12:47:51 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A8D0F81ECA; Sun, 3 May 2020 04:46: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="HlbqbPB+"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5D53281EB6; Sun, 3 May 2020 04:46:51 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x743.google.com (mail-qk1-x743.google.com [IPv6:2607:f8b0:4864:20::743]) (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 ED78E81E5E for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qk1-x743.google.com with SMTP id s9so10486190qkm.6 for ; Sat, 02 May 2020 19:46:46 -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=CLWhTnOC6F/pCr0MIYGtWkOda3+fLc0UtvneJyYeI/k=; b=HlbqbPB+LETcOU9jInNpu+l8vnpmFnSg7FV6x2U0bwzr0WEJEi/YerhCknEK9r9LR2 vcYgbSTMwPq2iNBh66L2RUGg4pn2Lh36bkRmWpZVF9tZnYijN3knbQC7oSV+ihrooAxi 44fMV0/6k3W+83qdDqRyxwAzw+A+8D0QnG6/bDfqx4j9K1OJrx/1Nwt1yxHxTQyHfDVT fSTvCrM7nt6HCFKjDou28y6o6tGCKG96PRooPZQoZdiDMcI6T4SzlPlyVVlHvNtZS+MO PrFYXn24PWe75Qe6youpOZIv92Boes6dpQ5f0RQt6p6pfayOUquLOL/csAcOWF2Fb5LJ Em6Q== 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=CLWhTnOC6F/pCr0MIYGtWkOda3+fLc0UtvneJyYeI/k=; b=PJjbHHeHEKDfSovx9f0ng7K+A+ZYw9QxWQH/jFNguzSFC9b1v7hSb7vQJ7Ag4pWdTd MaNTVtaIpFvU2UvRL/WpdGnDjlzoOEFqMMIQvst/tJKjP33slH1sqYYZzrqM7TXDa1jW zhc6rDuiRYeOP7YxlExyk1yiEveWkbEl5LxNiaE8OUBGhMfNWgUCoZ3fRAONE/x5VobZ FUh7NJLSNFap9q2Q6XV2jbI3AV0bhv5hH6ZzQFyvAPFR/oAfDM60bEbgP18XPaUjzLRy KXeIZlFa5d9ZCVz57KOG/7ErufBqbJSgkRoiqlNdC+m/vStAvrsgivcwssKScv5IXj5T 4AQw== X-Gm-Message-State: AGi0Pub0gRNeSe+V+Z2rkB14wOMmSGCckad/sTIyMh9bJfaojHcXzuwJ 9Jp2xZXweaPwfZZIloy7W5m1rcrh26w= X-Google-Smtp-Source: APiQypILO3kZCpHeL7fVWpG8lN4xc54MDNjp2OJE7wQiX3oXiJFylFuigcYeWoX7l5lQ9rU0nzfnSA== X-Received: by 2002:ae9:c301:: with SMTP id n1mr8701163qkg.300.1588474005697; Sat, 02 May 2020 19:46:45 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:45 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 04/21] clk: Fix clk_get_by_* handling of index Date: Sat, 2 May 2020 22:46:20 -0400 Message-Id: <20200503024637.327733-5-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean clk_get_by_index_nodev only ever fetched clock 1, due to passing a boolean predicate instead of the index. Other clk_get_by_* functions got the clock correctly, but passed a predicate instead of the index to clk_get_by_tail. This could lead to confusing error messages. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- Changes in v7: - New drivers/clk/clk-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index aa8dd9d027..c082fe95ff 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -121,7 +121,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name, return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) @@ -133,7 +133,7 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) index, &args); return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk) @@ -142,10 +142,10 @@ int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk) int ret; ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0, - index > 0, &args); + index, &args); return clk_get_by_index_tail(ret, node, &args, "clocks", - index > 0, clk); + index, clk); } int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) From patchwork Sun May 3 02:46:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281841 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=Efv1o2QD; 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 49F9Qr5WL9z9sRf for ; Sun, 3 May 2020 12:48:20 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8315A81EBA; Sun, 3 May 2020 04:46: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="Efv1o2QD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CE47A81ED9; Sun, 3 May 2020 04:46:53 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) (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 0E1A281EF0 for ; Sun, 3 May 2020 04:46:49 +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-x744.google.com with SMTP id b188so13148457qkd.9 for ; Sat, 02 May 2020 19:46:49 -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=fYSbQovxmLzzBegW3n58MpSvvNuFpyJnGuUoSi1ZFRs=; b=Efv1o2QDxZIG3EoLfJc3uydcUqeRxZ994f1X9nkyPAzNkxQqk7s/s8+tt3DVX98//Q 9W6Z0v/6kyB32Ra+jAd20+FFdmDNntq0OilJ4px33PwVmNO1NV4KZHglTREK723x69ML BuOrHiZSO3Xrx7YMjPXnxq5utFXixtdiz21/B3PUuXJlukSfJi6X3WnCwhHEdgqM3W4b UphYbp/1j5k/ub6ruJY8VPwqdduKvWu0jcWCtR/R3puDtOZ+EyNippwTACSti9zjYWcz suvgPemUSE5rEPAtMs2QpjSTog5FjYe3gxzUtjR8ufQBTIasSRgnduvHqN/oKJf4PoaW CPUw== 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=fYSbQovxmLzzBegW3n58MpSvvNuFpyJnGuUoSi1ZFRs=; b=AM0nlwLUI93G1PRZIj3RUL6xLQaa02KKqVctzIv5Hu3eB9KK5Au3y73UJVwJvq07bs ZWHbj74QZ+hVVOuYtAmUbHRnLKlrHkAx5SB2qYv3pmvmAYkO2+Rnwa/Buh9L6rmmaGYW a4uExfOwjqGDVuOW0NAONo5CTShqvzuQ9h+uFgf4kFZlCtTF/i16LD2OmwA3nwHMB8em hdIKwjgPXa0WY2IePICfekaWRNM4Z7MQKEgQe1Y367OGI4RU6XI60yB0SLruE5d82s4z GNt03erEgdOBAShe+ieKhUtla9QvjzMaPZHaKuxAvPeV73XgO7Je4JeJGTWibpO9EQD4 U6bA== X-Gm-Message-State: AGi0PuYdPqxeeC+Ej8zskMny0F6nkncSLlj6fQVIW+7ccbsfYRgOdgvo r4MIEodRVmRL34d2Cz/At2iled8cJg8= X-Google-Smtp-Source: APiQypKlbQBp1uAW+V/zltEUDmkxE0c/AFv1T9yyCb22KCbuIHKawbYAOvj99JAIo8ScNEwtZ00v8g== X-Received: by 2002:a37:278c:: with SMTP id n134mr10685784qkn.348.1588474006771; Sat, 02 May 2020 19:46:46 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:46 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 05/21] clk: Add K210 pll support Date: Sat, 2 May 2020 22:46:21 -0400 Message-Id: <20200503024637.327733-6-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This pll code is primarily based on the code from the kendryte standalone sdk in lib/drivers/sysctl.c. k210_pll_calc_config is roughly analogous to the algorithm used to set the pll frequency, but it has been completely rewritten to be fixed-point based. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- Changes in v8: - Rename k210_pll_params to k210_pll_config to avoid a name conflict with the rest of the clock code Changes in v6: - Reformat code to reduce checkpatch errors Changes in v5: - Add function to register from a struct Changes in v4: - Rename the reference clock to "divider clock", and input clock to "reference clock" to match the upstream documentation. - Add a test for calc_params. This currently resides in test/dm, but perhaps it should be moved to its own directory. - Update MAINTAINERS - Update copyright - Lint Changes in v3: - Add an option to not include support for setting the pll rate. This saves around 1K in the final executable. - Remove udelays to suppress warnings - Bypass PLL after enabling, instead of before - Check if the PLL is enabled already before doing a reset - Fix bug with locked mask Changes in v2: - Rename driver to "k210_clk_pll" - Add additional in-line documentation on algorithm and PLLs - Restrict the range of internal VCO and reference frequencies - Don't load driver before relocation - Remove spurious references to mach-k210 drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/kendryte/Kconfig | 12 + drivers/clk/kendryte/Makefile | 1 + drivers/clk/kendryte/pll.c | 601 ++++++++++++++++++++++++++++++++++ include/kendryte/pll.h | 57 ++++ include/test/export.h | 16 + test/dm/Makefile | 1 + test/dm/k210_pll.c | 96 ++++++ 9 files changed, 786 insertions(+) create mode 100644 drivers/clk/kendryte/Kconfig create mode 100644 drivers/clk/kendryte/Makefile create mode 100644 drivers/clk/kendryte/pll.c create mode 100644 include/kendryte/pll.h create mode 100644 include/test/export.h create mode 100644 test/dm/k210_pll.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1992d4a4b4..fb8335267b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -155,6 +155,7 @@ 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/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e01783391d..d911954581 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,6 +27,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_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig new file mode 100644 index 0000000000..7b69c8afaf --- /dev/null +++ b/drivers/clk/kendryte/Kconfig @@ -0,0 +1,12 @@ +config CLK_K210 + bool "Clock support for Kendryte K210" + depends on CLK && CLK_CCF + 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 new file mode 100644 index 0000000000..c56d93ea1c --- /dev/null +++ b/drivers/clk/kendryte/Makefile @@ -0,0 +1 @@ +obj-y += pll.o diff --git a/drivers/clk/kendryte/pll.c b/drivers/clk/kendryte/pll.c new file mode 100644 index 0000000000..2c5d5b8857 --- /dev/null +++ b/drivers/clk/kendryte/pll.c @@ -0,0 +1,601 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ +#include + +#define LOG_CATEGORY UCLASS_CLK +#include +/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define CLK_K210_PLL "k210_clk_pll" + +#ifdef CONFIG_CLK_K210_SET_RATE +static int k210_pll_enable(struct clk *clk); +static int k210_pll_disable(struct clk *clk); + +/* + * 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 clk *clk, ulong rate) +{ + int err; + long long rate_in = clk_get_parent_rate(clk); + struct k210_pll_config config = {}; + struct k210_pll *pll = to_k210_pll(clk); + 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(pll->reg); + 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, pll->reg); + + err = k210_pll_enable(clk); + if (err) + return err; + + serial_setbrg(); + return clk_get_rate(clk); +} +#endif /* CONFIG_CLK_K210_SET_RATE */ + +static ulong k210_pll_get_rate(struct clk *clk) +{ + 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); + + 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_pll *pll) +{ + u32 mask = GENMASK(pll->width - 1, 0) << pll->shift; + + while (true) { + u32 reg = readl(pll->lock); + + if ((reg & mask) == mask) + break; + + reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP); + writel(reg, pll->lock); + } +} + +/* Adapted from sysctl_pll_enable */ +static int k210_pll_enable(struct clk *clk) +{ + struct k210_pll *pll = to_k210_pll(clk); + u32 reg = readl(pll->reg); + + if ((reg | K210_PLL_PWRD) && !(reg | K210_PLL_RESET)) + return 0; + + reg |= K210_PLL_PWRD; + writel(reg, pll->reg); + + /* Ensure reset is low before asserting it */ + reg &= ~K210_PLL_RESET; + writel(reg, pll->reg); + reg |= K210_PLL_RESET; + writel(reg, pll->reg); + nop(); + nop(); + reg &= ~K210_PLL_RESET; + writel(reg, pll->reg); + + k210_pll_waitfor_lock(pll); + + reg &= ~K210_PLL_BYPASS; + writel(reg, pll->reg); + + return 0; +} + +static int k210_pll_disable(struct clk *clk) +{ + struct k210_pll *pll = to_k210_pll(clk); + u32 reg = readl(pll->reg); + + /* + * 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, pll->reg); + + reg &= ~K210_PLL_PWRD; + writel(reg, pll->reg); + 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; +} + +struct clk *k210_register_pll(const char *name, const char *parent_name, + void __iomem *reg, void __iomem *lock, u8 shift, + u8 width) +{ + struct clk *clk; + struct k210_pll *pll; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + pll->reg = reg; + pll->lock = lock; + pll->shift = shift; + pll->width = width; + + clk = k210_register_pll_struct(name, parent_name, pll); + if (IS_ERR(clk)) + kfree(pll); + return clk; +} + +U_BOOT_DRIVER(k210_pll) = { + .name = CLK_K210_PLL, + .id = UCLASS_CLK, + .ops = &k210_pll_ops, +}; diff --git a/include/kendryte/pll.h b/include/kendryte/pll.h new file mode 100644 index 0000000000..c8e3200799 --- /dev/null +++ b/include/kendryte/pll.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019-20 Sean Anderson + */ +#ifndef K210_PLL_H +#define K210_PLL_H + +#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 { + 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; + u8 od; +}; + +#ifdef CONFIG_UNIT_TEST +TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, + struct k210_pll_config *best); +#define nop() +#endif + +extern const struct clk_ops k210_pll_ops; + +struct clk *k210_register_pll_struct(const char *name, const char *parent_name, + struct k210_pll *pll); +struct clk *k210_register_pll(const char *name, const char *parent_name, + void __iomem *reg, void __iomem *lock, u8 shift, + u8 width); + +#endif /* K210_PLL_H */ diff --git a/include/test/export.h b/include/test/export.h new file mode 100644 index 0000000000..afc755a8ff --- /dev/null +++ b/include/test/export.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#ifndef TEST_EXPORT_H +#define TEST_EXPORT_H + +/* Declare something static, unless we are doing unit tests */ +#ifdef CONFIG_UNIT_TEST +#define TEST_STATIC +#else +#define TEST_STATIC static +#endif + +#endif /* TEST_EXPORT_H */ diff --git a/test/dm/Makefile b/test/dm/Makefile index 6c18fd04ce..5094a7866a 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -73,4 +73,5 @@ obj-$(CONFIG_DMA) += dma.o obj-$(CONFIG_DM_MDIO) += mdio.o obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o obj-$(CONFIG_DM_RNG) += rng.o +obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o endif diff --git a/test/dm/k210_pll.c b/test/dm/k210_pll.c new file mode 100644 index 0000000000..54764f269c --- /dev/null +++ b/test/dm/k210_pll.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */ +#include +#include +#include +#include + +static int dm_test_k210_pll_calc_config(u32 rate, u32 rate_in, + struct k210_pll_config *best) +{ + u64 f, r, od, max_r, inv_ratio; + s64 error, best_error; + + best_error = S64_MAX; + error = best_error; + max_r = min(16ULL, DIV_ROUND_DOWN_ULL(rate_in, 13300000)); + inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate); + + /* Brute force it */ + for (r = 1; r <= max_r; r++) { + for (f = 1; f <= 64; f++) { + for (od = 1; od <= 16; od++) { + u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r); + + if (vco > 1750000000 || vco < 340000000) + continue; + + 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; + } + } + } + } + + if (best_error == S64_MAX) + return -EINVAL; + return 0; +} + +static int dm_test_k210_pll_compare(struct k210_pll_config *ours, + struct k210_pll_config *theirs) +{ + return (u32)ours->f * theirs->r * theirs->od != + (u32)theirs->f * ours->r * ours->od; +} + +static int dm_test_k210_pll(struct unit_test_state *uts) +{ + struct k210_pll_config ours, theirs; + + /* General range checks */ + ut_asserteq(-EINVAL, k210_pll_calc_config(0, 26000000, &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(390000000, 0, &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(2000000000, 26000000, + &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(390000000, 2000000000, + &theirs)); + ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000, + &theirs)); + + /* Verify we get the same output with brute-force */ + ut_assertok(dm_test_k210_pll_calc_config(390000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(390000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(26000000, 390000000, &ours)); + ut_assertok(k210_pll_calc_config(26000000, 390000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(400000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(400000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(27000000, 26000000, &ours)); + ut_assertok(k210_pll_calc_config(27000000, 26000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + ut_assertok(dm_test_k210_pll_calc_config(26000000, 27000000, &ours)); + ut_assertok(k210_pll_calc_config(26000000, 27000000, &theirs)); + ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); + + return 0; +} +DM_TEST(dm_test_k210_pll, 0); From patchwork Sun May 3 02:46:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281840 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=S9jnC2Am; 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 49F9QY5vdVz9sRf for ; Sun, 3 May 2020 12:48:05 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2FA0281EF1; Sun, 3 May 2020 04:46: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="S9jnC2Am"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CE8F281ECD; Sun, 3 May 2020 04:46:52 +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,URIBL_BLOCKED autolearn=ham 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 4D55781E87 for ; Sun, 3 May 2020 04:46:49 +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 c10so2145341qka.4 for ; Sat, 02 May 2020 19:46:49 -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=+mopnSlE9GdlUrj7fMHSzovN//o1UTPGAAqtKFs7g24=; b=S9jnC2AmR1vj/jN0JmDiCpM3uEQRIfIScA9f9lxk93Q4wRcWWjMaRZS3cc8DUr6JuP O1oQwfbVqN9xJGLsvWYBiGC3kfzq0YYUIx0P1HzYVDnMD712zk/m9EE1TxRpc8MZ6ECi QUxewBkgqrzVKkKJyYpi2JZkf3xGxx61PlC42NNMoX3nl5aKoGGUcyfbYNOGFaLWc6Q0 VarTk5cF6y13R3bpb8gk4lmeJJZAJyjFz13ikLKN3WdNJEuuH1Dnr5s1AexC0CpAv9+Z AHEnbKv6dUfJ44E6a3tfVRsMM4z0f9MOdY80e9HBlxx0cdgLRMOCcn0Qtkh2eAEVG4Xh zY3w== 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=+mopnSlE9GdlUrj7fMHSzovN//o1UTPGAAqtKFs7g24=; b=ESjI6DYrmkDdTD311QWJ5gP4VNYA1tDShR7glvOKhPdn5jI8/jaP6ZeTpUlxMF6bDZ LOf1hAvtauD4qC4lgbIaOwwvxI8uBbOVcAB615pDjUYDqSO9N+prwXAst8KIFWn73gX3 PiPfcqgx/QvDktEiFpaTfLYH28qxE/rhvMF8yOBpVATTlCE9UdDQYJwMmdpTMY3HKX9W 6EipI/vvCw6eYY6SrXC5kbXvDvU74bWwBOYFLA1KpXQ7FuFAmqq5IS+5vUGaAlWGvc0F VJH2MgbR6/9rUKMPUmYP4tlFLqoRw8UeRV91dKTx/Cvu4yEuHUmh1C818f/1HVlh09q5 zkxA== X-Gm-Message-State: AGi0PuZacqSuQPoIRwDdU0rsTc8DRurT1ZiATNcFwUPmw5NvVQi3wQn1 RMAtswU4BSGVP42yeFGuSnQlKRcuVDM= X-Google-Smtp-Source: APiQypKQ/T+iSm7XU3FevPtQkA1HZHl2+1YwtXupcFONo2hrBbr2yyLQ1KF61wDFIHml0CrCVNGjHg== X-Received: by 2002:ae9:ebc8:: with SMTP id b191mr9821794qkg.1.1588474007712; Sat, 02 May 2020 19:46:47 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:47 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 06/21] clk: Add a bypass clock for K210 Date: Sat, 2 May 2020 22:46:22 -0400 Message-Id: <20200503024637.327733-7-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean 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. For the K210, it is used to have aclk bypass pll0 and use in0 instead so that the CPU keeps on working. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- Changes in v5: - Add function to register from a struct bypass Changes in v4: - New drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/bypass.c | 270 ++++++++++++++++++++++++++++++++++ include/kendryte/bypass.h | 31 ++++ 3 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/kendryte/bypass.c create mode 100644 include/kendryte/bypass.h diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index c56d93ea1c..47f682fce3 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += pll.o +obj-y += bypass.o pll.o diff --git a/drivers/clk/kendryte/bypass.c b/drivers/clk/kendryte/bypass.c new file mode 100644 index 0000000000..eb3e27d055 --- /dev/null +++ b/drivers/clk/kendryte/bypass.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include + +#include +#include +#include +#define LOG_CATEGORY UCLASS_CLK +#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 -ENOTSUPP; +} + +/* + * 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 new file mode 100644 index 0000000000..a081cbd12f --- /dev/null +++ b/include/kendryte/bypass.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Sean Anderson + */ +#ifndef K210_BYPASS_H +#define K210_BYPASS_H + +#include + +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 Sun May 3 02:46:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281844 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=Hnel58Ex; 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 49F9Rf4hMnz9sRf for ; Sun, 3 May 2020 12:49:02 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A6FF681F1C; Sun, 3 May 2020 04:47:05 +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="Hnel58Ex"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1DD7881EE2; Sun, 3 May 2020 04:46:57 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x741.google.com (mail-qk1-x741.google.com [IPv6:2607:f8b0:4864:20::741]) (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 6308F81E5E for ; Sun, 3 May 2020 04:46:51 +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-x741.google.com with SMTP id i14so1944834qka.10 for ; Sat, 02 May 2020 19:46:51 -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=socExPDCZ54zaTj4ssmI8tay+yJPFwF/46Vnj37Cu4s=; b=Hnel58ExvGUkKGuXScO6UDbAd0yiLm2jGtEl93I/r+HjEMPb9ghb+isIl7fgQB8pMz +xWXT9XwEt76834EWyzsRxNJMf3wcOjUFuNxNb0HMU+O8rCVmTmOmbYFffc5eteZQAjq nWTUvernjOSl9tekkA5qM3Y/Vwh/8IiA6h6Y5YKELScTrqRFcw8+poNiKa4nGTKmwDW/ sdq15DAwmf5lll62qAt1PCd+91YOOuprUlbM2I3OoZLK49TJOpx9wr5v6o+7k+f2wQuC R211f4hYPSnHizyfp0zjmAKcc2+puM5PWchvd//M9C58MT0CYLWr+TfgbTI0zVktussA /bbA== 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=socExPDCZ54zaTj4ssmI8tay+yJPFwF/46Vnj37Cu4s=; b=C7PlmUJCf3U1gAg2fsh0iRrO0XsAP/zS3Y8RuYlmi8NvGURpvW7eNh45Q3INPE2W/P O30mMOTJJfyiohYAXCzssOjw7Wv3/N2rpu6/8khv+F6Dlg7dI8LjSIFfP9+P+y5gl+an KcB311DcoELup5w41BUKgSPmevMHEOhZkyxHS5n1celo4lrH65F8TxtncCaLCPj90BTw 7sRaZDJ7/8pt3/+KVr5Z7WK5uR19flORbhe4cAz15JwpL5fn4y403FfBOoICjRHMLPeg z9o0QBGxeHk4vsuLkYaSUAZf59306Fko+WjntdxWlE69E8VxF/rG186jkXBIMak+xfvm yXnw== X-Gm-Message-State: AGi0PuYakwj0MtcDR7vflRs7wxQAocxXxaSMC+XTfstOfKI1nxsn5+CB fFILLAxMix7H6AVYD9SCDJq+wAM7UF8= X-Google-Smtp-Source: APiQypLbUPUywKZoM/2NsuVw0/xHURTk9/lUiOTFGNHCRiiE6x7G1lSl9l6ZfNheQrlPmEyBaDyVRA== X-Received: by 2002:a37:8d85:: with SMTP id p127mr10510767qkd.44.1588474009144; Sat, 02 May 2020 19:46:49 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:48 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Lukasz Majewski Subject: [PATCH v10 07/21] clk: Add K210 clock support Date: Sat, 2 May 2020 22:46:23 -0400 Message-Id: <20200503024637.327733-8-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean Due to the large number of clocks, I decided to use the CCF. The overall structure is modeled after the imx code. Clocks parameters are stored in several arrays, and are then instantiated at run-time. There are some translation macros (FOOIFY()) which allow for more dense packing. Signed-off-by: Sean Anderson CC: Lukasz Majewski --- Changes in v8: - Rework code to not need a new CCF api - Add some documentation Changes in v7: - Add numbering to some sysctl registers Changes in v6: - Reformat code so checkpatch generates fewer warnings - Give "fictional" clocks their own ids - Rename sysctl CLK_FREQ register to UART_BAUD to better reflect its semantics Changes in v5: - Don't unmap priv->reg - Remove comment on APB clocks since it has been clarified by Kendryte - Add i2s mclks - Reorder clock ids to be continuous - Rewrite to statically allocate all clocks. This has helped find several bugs (since it is easy to see when a clock has the wrong register). - Fix ACLK sometimes having the wrong parent - Fix SPI3 having the wrong divider - Prevent being probed multiple times on failure Changes in v4: - Reparent aclk before configuring pll0 - Update copyright - Lint Changes in v3: - Removed sysctl struct, replacing it with defines. This is to have the same interface to sysctl from C as from the device tree. - Fixed clocks having the same id - Fixed clocks not using the correct register/bits - Aligned the defines in headers Changes in v2: - Add clk.o to obj-y - Don't probe before relocation MAINTAINERS | 7 + .../mfd/kendryte,k210-sysctl.txt | 33 + drivers/clk/kendryte/Kconfig | 2 +- drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/clk.c | 663 ++++++++++++++++++ include/dt-bindings/clock/k210-sysctl.h | 59 ++ include/dt-bindings/mfd/k210-sysctl.h | 38 + include/kendryte/clk.h | 35 + 8 files changed, 837 insertions(+), 2 deletions(-) create mode 100644 doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt create mode 100644 drivers/clk/kendryte/clk.c create mode 100644 include/dt-bindings/clock/k210-sysctl.h create mode 100644 include/dt-bindings/mfd/k210-sysctl.h create mode 100644 include/kendryte/clk.h diff --git a/MAINTAINERS b/MAINTAINERS index 7ac7e21ba1..88443bf82d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -830,6 +830,13 @@ F: arch/riscv/ F: cmd/riscv/ F: tools/prelink-riscv.c +RISC-V KENDRYTE +M: Sean Anderson +S: Maintained +F: doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt +F: drivers/clk/kendryte/ +F: include/kendryte/ + RNG M: Sughosh Ganu R: Heinrich Schuchardt diff --git a/doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt b/doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt new file mode 100644 index 0000000000..5b24abcb62 --- /dev/null +++ b/doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt @@ -0,0 +1,33 @@ +Kendryte K210 Sysctl + +This binding describes the K210 sysctl device, which contains many miscellaneous +registers controlling system functionality. This node is a register map and can +be reference by other bindings which need a phandle to the K210 sysctl regmap. + +Required properties: +- compatible: should be + "kendryte,k210-sysctl", "syscon", "simple-mfd" +- reg: address and length of the sysctl registers +- reg-io-width: must be <4> + +Clock sub-node + +This node is a binding for the clock tree driver + +Required properties: +- compatible: should be "kendryte,k210-clk" +- clocks: phandle to the "in0" external oscillator +- #clock-cells: must be <1> + +Example: +sysctl: syscon@50440000 { + compatible = "kendryte,k210-sysctl", "syscon", "simple-mfd"; + reg = <0x50440000 0x100>; + reg-io-width = <4>; + + sysclk: clock-controller { + compatible = "kendryte,k210-clk"; + clocks = <&in0>; + #clock-cells = <1>; + }; +}; diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig index 7b69c8afaf..073fca0781 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 + depends on CLK && CLK_CCF && CLK_COMPOSITE_CCF help This enables support clock driver for Kendryte K210 platforms. diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index 47f682fce3..6fb68253ae 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += bypass.o pll.o +obj-y += bypass.o clk.o pll.o diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c new file mode 100644 index 0000000000..981b3b7699 --- /dev/null +++ b/drivers/clk/kendryte/clk.c @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ +#include + +#include +#include +#include +#include +#include +#include + +#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 + * probe. To save space, ids are automatically generated for each sub-clock by + * using an enum. Instead of storing a parameter struct for each clock, even for + * those clocks which don't use a particular type of sub-clock, we can just + * store the parameters for the clocks which need them. + * + * So why do it like this? Arranging all the sub-clocks together makes it very + * easy to find bugs in the code. + */ + +#define DIV(id, off, shift, width) DIV_FLAGS(id, off, shift, width, 0) +#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) + +#define _DIVIFY(id) K210_CLK_DIV_##id +#define DIVIFY(id) _DIVIFY(id) + +enum k210_div_ids { +#define DIV_FLAGS(id, ...) DIVIFY(id), + DIV_LIST +#undef DIV_FLAGS +}; + +struct k210_div_params { + u8 off; + u8 shift; + u8 width; + u8 flags; +}; + +static const struct k210_div_params k210_divs[] = { +#define DIV_FLAGS(id, _off, _shift, _width, _flags) \ + [DIVIFY(id)] = { \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ + .flags = (_flags), \ + }, + DIV_LIST +#undef DIV_FLAGS +}; + +#undef DIV +#undef DIV_LIST + +#define GATE_LIST \ + GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \ + GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \ + GATE(K210_CLK_SRAM1, K210_SYSCTL_EN_CENT, 2) \ + GATE(K210_CLK_APB0, K210_SYSCTL_EN_CENT, 3) \ + GATE(K210_CLK_APB1, K210_SYSCTL_EN_CENT, 4) \ + GATE(K210_CLK_APB2, K210_SYSCTL_EN_CENT, 5) \ + GATE(K210_CLK_ROM, K210_SYSCTL_EN_PERI, 0) \ + GATE(K210_CLK_DMA, K210_SYSCTL_EN_PERI, 1) \ + GATE(K210_CLK_AI, K210_SYSCTL_EN_PERI, 2) \ + GATE(K210_CLK_DVP, K210_SYSCTL_EN_PERI, 3) \ + GATE(K210_CLK_FFT, K210_SYSCTL_EN_PERI, 4) \ + GATE(K210_CLK_GPIO, K210_SYSCTL_EN_PERI, 5) \ + GATE(K210_CLK_SPI0, K210_SYSCTL_EN_PERI, 6) \ + GATE(K210_CLK_SPI1, K210_SYSCTL_EN_PERI, 7) \ + GATE(K210_CLK_SPI2, K210_SYSCTL_EN_PERI, 8) \ + GATE(K210_CLK_SPI3, K210_SYSCTL_EN_PERI, 9) \ + GATE(K210_CLK_I2S0, K210_SYSCTL_EN_PERI, 10) \ + GATE(K210_CLK_I2S1, K210_SYSCTL_EN_PERI, 11) \ + GATE(K210_CLK_I2S2, K210_SYSCTL_EN_PERI, 12) \ + GATE(K210_CLK_I2C0, K210_SYSCTL_EN_PERI, 13) \ + GATE(K210_CLK_I2C1, K210_SYSCTL_EN_PERI, 14) \ + GATE(K210_CLK_I2C2, K210_SYSCTL_EN_PERI, 15) \ + GATE(K210_CLK_UART1, K210_SYSCTL_EN_PERI, 16) \ + GATE(K210_CLK_UART2, K210_SYSCTL_EN_PERI, 17) \ + GATE(K210_CLK_UART3, K210_SYSCTL_EN_PERI, 18) \ + GATE(K210_CLK_AES, K210_SYSCTL_EN_PERI, 19) \ + GATE(K210_CLK_FPIOA, K210_SYSCTL_EN_PERI, 20) \ + GATE(K210_CLK_TIMER0, K210_SYSCTL_EN_PERI, 21) \ + GATE(K210_CLK_TIMER1, K210_SYSCTL_EN_PERI, 22) \ + GATE(K210_CLK_TIMER2, K210_SYSCTL_EN_PERI, 23) \ + GATE(K210_CLK_WDT0, K210_SYSCTL_EN_PERI, 24) \ + GATE(K210_CLK_WDT1, K210_SYSCTL_EN_PERI, 25) \ + GATE(K210_CLK_SHA, K210_SYSCTL_EN_PERI, 26) \ + GATE(K210_CLK_OTP, K210_SYSCTL_EN_PERI, 27) \ + GATE(K210_CLK_RTC, K210_SYSCTL_EN_PERI, 29) + +#define _GATEIFY(id) K210_CLK_GATE_##id +#define GATEIFY(id) _GATEIFY(id) + +enum k210_gate_ids { +#define GATE(id, ...) GATEIFY(id), + GATE_LIST +#undef GATE +}; + +struct k210_gate_params { + u8 off; + u8 bit_idx; +}; + +static const struct k210_gate_params k210_gates[] = { +#define GATE(id, _off, _idx) \ + [GATEIFY(id)] = { \ + .off = (_off), \ + .bit_idx = (_idx), \ + }, + GATE_LIST +#undef GATE +}; + +#undef GATE_LIST + +#define MUX(id, reg, shift, width) \ + MUX_PARENTS(id, generic_sels, reg, shift, width) +#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(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) \ + MUX(K210_CLK_TIMER2, K210_SYSCTL_SEL0, 15, 1) + +#define _MUXIFY(id) K210_CLK_MUX_##id +#define MUXIFY(id) _MUXIFY(id) + +enum k210_mux_ids { +#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) \ + [MUXIFY(id)] = { \ + .parent_names = (const char * const *)(parents), \ + .num_parents = ARRAY_SIZE(parents), \ + .off = (_off), \ + .shift = (_shift), \ + .width = (_width), \ + }, + MUX_LIST +#undef MUX_PARENTS +}; + +#undef MUX +#undef MUX_LIST + +struct k210_pll_params { + u8 off; + u8 lock_off; + u8 shift; + u8 width; +}; + +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 +}; + +#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)] = { \ + .mux = (_mux), \ + .div = (_div), \ + .gate = (_gate), \ + }, + COMP_LIST +#undef COMP_FULL +}; + +#undef COMP +#undef COMP_ID +#undef COMP_NOMUX +#undef COMP_NOMUX_ID +#undef COMP_LIST + +static struct clk *k210_bypass_children = { + NULL, +}; + +/* Helper functions to create sub-clocks */ +static struct clk_mux *k210_create_mux(const struct k210_mux_params *params, + void *base) +{ + struct clk_mux *mux = kzalloc(sizeof(*mux), GFP_KERNEL); + + 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; +} + +static struct clk_divider *k210_create_div(const struct k210_div_params *params, + void *base) +{ + struct clk_divider *div = kzalloc(sizeof(*div), GFP_KERNEL); + + if (!div) + return div; + + div->reg = base + params->off; + div->shift = params->shift; + div->width = params->width; + div->flags = params->flags; + + return div; +} + +static struct clk_gate *k210_create_gate(const struct k210_gate_params *params, + void *base) +{ + struct clk_gate *gate = kzalloc(sizeof(*gate), GFP_KERNEL); + + if (!gate) + return gate; + + gate->reg = base + params->off; + gate->bit_idx = params->bit_idx; + + return gate; +} + +static struct k210_pll *k210_create_pll(const struct k210_pll_params *params, + void *base) +{ + struct k210_pll *pll = kzalloc(sizeof(*pll), GFP_KERNEL); + + if (!pll) + return pll; + + pll->reg = base + params->off; + pll->lock = base + params->lock_off; + pll->shift = params->shift; + pll->width = params->width; + + return pll; +} + +/* 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) +{ + 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; + + if (params->mux == K210_CLK_MUX_NONE) { + if (!parent) + return ERR_PTR(-EINVAL); + + 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); + + parent_names = mux->parent_names; + num_parents = mux->num_parents; + } + + div = k210_create_div(&k210_divs[params->div], base); + if (!div) { + comp = ERR_PTR(-ENOMEM); + goto cleanup_mux; + } + + gate = k210_create_gate(&k210_gates[params->gate], base); + if (!gate) { + comp = ERR_PTR(-ENOMEM); + goto cleanup_div; + } + + 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; + +cleanup_gate: + free(gate); +cleanup_div: + free(div); +cleanup_mux: + if (mux) + free(mux); + return comp; +} + +static bool probed; + +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; + + /* + * 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) + return -ENOTSUPP; + + 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); + 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; + } + + { + const struct k210_pll_params *params = &k210_plls[1]; + + clk_dm(K210_CLK_PLL1, + k210_register_pll("pll1", in0, base + params->off, + base + params->lock_off, params->shift, + params->width)); + } + + /* 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 + + return 0; +} + +static const struct udevice_id k210_clk_ids[] = { + { .compatible = "kendryte,k210-clk" }, + { }, +}; + +U_BOOT_DRIVER(k210_clk) = { + .name = "k210_clk", + .id = UCLASS_CLK, + .of_match = k210_clk_ids, + .ops = &k210_clk_ops, + .probe = k210_clk_probe, +}; diff --git a/include/dt-bindings/clock/k210-sysctl.h b/include/dt-bindings/clock/k210-sysctl.h new file mode 100644 index 0000000000..0e3ed3fb9f --- /dev/null +++ b/include/dt-bindings/clock/k210-sysctl.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019-20 Sean Anderson + */ + +#ifndef CLOCK_K210_SYSCTL_H +#define CLOCK_K210_SYSCTL_H + +/* + * 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 + +#endif /* CLOCK_K210_SYSCTL_H */ diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h new file mode 100644 index 0000000000..bfc918d3ba --- /dev/null +++ b/include/dt-bindings/mfd/k210-sysctl.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#ifndef K210_SYSCTL_H +#define K210_SYSCTL_H + +/* Taken from kendryte-standalone-sdk/lib/drivers/include/sysctl.h */ +#define K210_SYSCTL_GIT_ID 0x00 /* Git short commit id */ +#define K210_SYSCTL_UART_BAUD 0x04 /* Default UARTHS baud rate */ +#define K210_SYSCTL_PLL0 0x08 /* PLL0 controller */ +#define K210_SYSCTL_PLL1 0x0C /* PLL1 controller */ +#define K210_SYSCTL_PLL2 0x10 /* PLL2 controller */ +#define K210_SYSCTL_PLL_LOCK 0x18 /* PLL lock tester */ +#define K210_SYSCTL_ROM_ERROR 0x1C /* AXI ROM detector */ +#define K210_SYSCTL_SEL0 0x20 /* Clock select controller 0 */ +#define K210_SYSCTL_SEL1 0x24 /* Clock select controller 1 */ +#define K210_SYSCTL_EN_CENT 0x28 /* Central clock enable */ +#define K210_SYSCTL_EN_PERI 0x2C /* Peripheral clock enable */ +#define K210_SYSCTL_SOFT_RESET 0x30 /* Soft reset ctrl */ +#define K210_SYSCTL_PERI_RESET 0x34 /* Peripheral reset controller */ +#define K210_SYSCTL_THR0 0x38 /* Clock threshold controller 0 */ +#define K210_SYSCTL_THR1 0x3C /* Clock threshold controller 1 */ +#define K210_SYSCTL_THR2 0x40 /* Clock threshold controller 2 */ +#define K210_SYSCTL_THR3 0x44 /* Clock threshold controller 3 */ +#define K210_SYSCTL_THR4 0x48 /* Clock threshold controller 4 */ +#define K210_SYSCTL_THR5 0x4C /* Clock threshold controller 5 */ +#define K210_SYSCTL_THR6 0x50 /* Clock threshold controller 6 */ +#define K210_SYSCTL_MISC 0x54 /* Miscellaneous controller */ +#define K210_SYSCTL_PERI 0x58 /* Peripheral controller */ +#define K210_SYSCTL_SPI_SLEEP 0x5C /* SPI sleep controller */ +#define K210_SYSCTL_RESET_STAT 0x60 /* Reset source status */ +#define K210_SYSCTL_DMA_SEL0 0x64 /* DMA handshake selector 0 */ +#define K210_SYSCTL_DMA_SEL1 0x68 /* DMA handshake selector 1 */ +#define K210_SYSCTL_POWER_SEL 0x6C /* IO Power Mode Select controller */ + +#endif /* K210_SYSCTL_H */ diff --git a/include/kendryte/clk.h b/include/kendryte/clk.h new file mode 100644 index 0000000000..9c6245d468 --- /dev/null +++ b/include/kendryte/clk.h @@ -0,0 +1,35 @@ +/* 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 */ From patchwork Sun May 3 02:46:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281842 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=Z17L7gpD; 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 49F9R76FYZz9sRf for ; Sun, 3 May 2020 12:48:35 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0580581EFC; Sun, 3 May 2020 04:47:01 +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="Z17L7gpD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A1DD981EE3; Sun, 3 May 2020 04:46:56 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x843.google.com (mail-qt1-x843.google.com [IPv6:2607:f8b0:4864:20::843]) (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 D6BDC81ECA for ; Sun, 3 May 2020 04:46:51 +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-x843.google.com with SMTP id w29so11204786qtv.3 for ; Sat, 02 May 2020 19:46:51 -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=/tasDiGZQZkTeZtKwnnvo3qZZzMRIdEpLAJ1fj3o/1Q=; b=Z17L7gpD8yrbKPmI4qaJHlj2TcH0S91p4h7E4wEvLo1NvJvAePkqbLAbPkIVQ3HM2V ABqTZgCnpwGLJ37tDxwTJtxIg7f2XqXNvTJ1cWJZv+ZXTggOdbQKg6DT9a5DSswkPMFg 1IgYW0ldyy1NMz1fhNInlOO2uj5tA+mwABScSgDPObJcfK6ZHjc3ndPod6Mlm9d+Umkh 8VhlrcxzAsUGk9fxluq/GHn158XLr/yGStodzZXexoZfPrjYIEAcupSzymDCnVG7ecUY fUAfDhdYIwaSwECB0DLWPCv5TKA9ijoUhOgA5kqU3JvYeIgqNwc0m2HeieT6ARF/faIj lATA== 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=/tasDiGZQZkTeZtKwnnvo3qZZzMRIdEpLAJ1fj3o/1Q=; b=tDtsSf/zWL9rTB0VfYnVxNmLPJsx+Au5TXnaz/8OOlu7psAGsSyPsmVV8geV0zdqko YTEhYiNS08Y+U3UvFK/jMAy8XCLqtxN6PlEL4t972NC/Nh8Y/u6xHDX9Wi5sca/SLsAs STrkrJvpKRYwxFBqFxjVSH+bpWoNv30IuOhne4ki+QcN9oQCbQh6aaLdsFp4TJGWA46a eYmTht0Ht45d/LyuPlBui2wnWKBvUShyXTRwJApsg8oovozYecHcnBB2E4o8Dcf/oI0q iLF1cypvf+882gK7B+NmDKdnS5dypOHCKyAx+I3uWHXoaeI3ZyAmxfzkWFvoWlAoksk7 0V6w== X-Gm-Message-State: AGi0PuabnA2KNWPw1lULGNsxSKSdbtRLtQk1oYpq89On1BK6vRPGTUAF Ig16yWCadcvnk6z2owxIJneX0rjv4e8= X-Google-Smtp-Source: APiQypITwf4YTiJaplMxDi7rbN2RoiiVd9lbCtBWkZ9lG7E16OFLtvb8eDe8TXMsrvUJfWk89Mxt3w== X-Received: by 2002:ac8:4ccc:: with SMTP id l12mr11054522qtv.129.1588474010132; Sat, 02 May 2020 19:46:50 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:49 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Simon Glass Subject: [PATCH v10 08/21] dm: Add support for simple-pm-bus Date: Sat, 2 May 2020 22:46:24 -0400 Message-Id: <20200503024637.327733-9-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This type of bus is used in Linux to designate buses which have power domains and/or clocks which need to be enabled before their child devices can be used. Because power domains are automatically enabled before probing in U-Boot, we just need to enable any clocks present. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- Changes in v10: - Remove const qualifiers from simple_pm_bus_* functions Changes in v5: - Reorder includes (simple pm) Changes in v4: - Split the bus off into its own driver - Add test - Fix line spacing in Kconfig - Lint Changes in v3: - New arch/sandbox/dts/test.dts | 6 ++ arch/sandbox/include/asm/clk.h | 1 + configs/sandbox_defconfig | 1 + .../bus/simple-pm-bus.txt | 44 +++++++++++++++ drivers/core/Kconfig | 7 +++ drivers/core/Makefile | 1 + drivers/core/simple-pm-bus.c | 56 +++++++++++++++++++ test/dm/Makefile | 1 + test/dm/simple-pm-bus.c | 45 +++++++++++++++ 9 files changed, 162 insertions(+) create mode 100644 doc/device-tree-bindings/bus/simple-pm-bus.txt create mode 100644 drivers/core/simple-pm-bus.c create mode 100644 test/dm/simple-pm-bus.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index df9f1835c9..6567a322dd 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -994,6 +994,12 @@ mdio: mdio-test { compatible = "sandbox,mdio"; }; + + pm-bus-test { + compatible = "simple-pm-bus"; + clocks = <&clk_sandbox 4>; + power-domains = <&pwrdom 1>; + }; }; #include "sandbox_pmic.dtsi" diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h index 1573e4a134..c184c4bffc 100644 --- a/arch/sandbox/include/asm/clk.h +++ b/arch/sandbox/include/asm/clk.h @@ -21,6 +21,7 @@ enum sandbox_clk_id { SANDBOX_CLK_ID_I2C, SANDBOX_CLK_ID_UART1, SANDBOX_CLK_ID_UART2, + SANDBOX_CLK_ID_BUS, SANDBOX_CLK_ID_COUNT, }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index cc38315868..e09ee209f2 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -94,6 +94,7 @@ CONFIG_REGMAP=y CONFIG_SYSCON=y CONFIG_DEVRES=y CONFIG_DEBUG_DEVRES=y +CONFIG_SIMPLE_PM_BUS=y CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_AXI=y diff --git a/doc/device-tree-bindings/bus/simple-pm-bus.txt b/doc/device-tree-bindings/bus/simple-pm-bus.txt new file mode 100644 index 0000000000..6f15037131 --- /dev/null +++ b/doc/device-tree-bindings/bus/simple-pm-bus.txt @@ -0,0 +1,44 @@ +Simple Power-Managed Bus +======================== + +A Simple Power-Managed Bus is a transparent bus that doesn't need a real +driver, as it's typically initialized by the boot loader. + +However, its bus controller is part of a PM domain, or under the control of a +functional clock. Hence, the bus controller's PM domain and/or clock must be +enabled for child devices connected to the bus (either on-SoC or externally) +to function. + +While "simple-pm-bus" follows the "simple-bus" set of properties, as specified +in the Devicetree Specification, it is not an extension of "simple-bus". + + +Required properties: + - compatible: Must contain at least "simple-pm-bus". + Must not contain "simple-bus". + It's recommended to let this be preceded by one or more + vendor-specific compatible values. + - #address-cells, #size-cells, ranges: Must describe the mapping between + parent address and child address spaces. + +Optional platform-specific properties for clock or PM domain control (at least +one of them is required): + - clocks: Must contain a reference to the functional clock(s), + - power-domains: Must contain a reference to the PM domain. +Please refer to the binding documentation for the clock and/or PM domain +providers for more details. + + +Example: + + bsc: bus@fec10000 { + compatible = "renesas,bsc-sh73a0", "renesas,bsc", + "simple-pm-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x20000000>; + reg = <0xfec10000 0x400>; + interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&zb_clk>; + power-domains = <&pd_a4s>; + }; diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index a3b0399342..a594899f37 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -195,6 +195,13 @@ config SPL_SIMPLE_BUS Supports the 'simple-bus' driver, which is used on some systems in SPL. +config SIMPLE_PM_BUS + bool "Support simple-pm-bus driver" + depends on DM && OF_CONTROL && CLK && POWER_DOMAIN + help + Supports the 'simple-pm-bus' driver, which is used for busses that + have power domains and/or clocks which need to be enabled before use. + config OF_TRANSLATE bool "Translate addresses using fdt_translate_address" depends on DM && OF_CONTROL diff --git a/drivers/core/Makefile b/drivers/core/Makefile index c707026a3a..10f4bece33 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o obj-$(CONFIG_DEVRES) += devres.o obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o obj-$(CONFIG_$(SPL_)SIMPLE_BUS) += simple-bus.o +obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o obj-$(CONFIG_DM) += dump.o obj-$(CONFIG_$(SPL_TPL_)REGMAP) += regmap.o obj-$(CONFIG_$(SPL_TPL_)SYSCON) += syscon-uclass.o diff --git a/drivers/core/simple-pm-bus.c b/drivers/core/simple-pm-bus.c new file mode 100644 index 0000000000..51dc9b206f --- /dev/null +++ b/drivers/core/simple-pm-bus.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include + +/* + * Power domains are taken care of by driver_probe, so we just have to enable + * clocks + */ +static int simple_pm_bus_probe(struct udevice *dev) +{ + int ret; + struct clk_bulk *bulk = dev_get_priv(dev); + + ret = clk_get_bulk(dev, bulk); + if (ret) + return ret; + + ret = clk_enable_bulk(bulk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + clk_release_bulk(bulk); + return ret; + } + return 0; +} + +static int simple_pm_bus_remove(struct udevice *dev) +{ + int ret; + struct clk_bulk *bulk = dev_get_priv(dev); + + ret = clk_release_bulk(bulk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) + return ret; + else + return 0; +} + +static const struct udevice_id simple_pm_bus_ids[] = { + { .compatible = "simple-pm-bus" }, + { } +}; + +U_BOOT_DRIVER(simple_pm_bus_drv) = { + .name = "simple_pm_bus", + .id = UCLASS_SIMPLE_BUS, + .of_match = simple_pm_bus_ids, + .probe = simple_pm_bus_probe, + .remove = simple_pm_bus_remove, + .priv_auto_alloc_size = sizeof(struct clk_bulk), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index 5094a7866a..518ee8e377 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -74,4 +74,5 @@ obj-$(CONFIG_DM_MDIO) += mdio.o obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o obj-$(CONFIG_DM_RNG) += rng.o obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o +obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o endif diff --git a/test/dm/simple-pm-bus.c b/test/dm/simple-pm-bus.c new file mode 100644 index 0000000000..978c7f191e --- /dev/null +++ b/test/dm/simple-pm-bus.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include +#include +#include +#include +#include + +/* These must match the ids in the device tree */ +#define TEST_CLOCK_ID 4 +#define TEST_POWER_ID 1 + +static int dm_test_simple_pm_bus(struct unit_test_state *uts) +{ + struct udevice *power; + struct udevice *clock; + struct udevice *bus; + + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", &power)); + ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-sbox", + &clock)); + ut_asserteq(0, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(0, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, "pm-bus-test", + &bus)); + ut_asserteq(1, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(1, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + ut_assertok(device_remove(bus, DM_REMOVE_NORMAL)); + /* must re-probe since device_remove also removes the power domain */ + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", &power)); + ut_asserteq(0, sandbox_power_domain_query(power, TEST_POWER_ID)); + ut_asserteq(0, sandbox_clk_query_enable(clock, TEST_CLOCK_ID)); + + return 0; +} +DM_TEST(dm_test_simple_pm_bus, DM_TESTF_SCAN_FDT); From patchwork Sun May 3 02:46:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281843 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=EbRdgG5A; 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 49F9RP05Zhz9sRf for ; Sun, 3 May 2020 12:48:48 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1A99081EF7; Sun, 3 May 2020 04:47:04 +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="EbRdgG5A"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B5EFE81EE6; Sun, 3 May 2020 04:46:56 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) (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 02C5E81E87 for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qt1-x842.google.com with SMTP id w29so11204803qtv.3 for ; Sat, 02 May 2020 19:46:52 -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=mEms9feIibmv6Z5ZQVurPaAWVGvgo943OroL3Va8W7I=; b=EbRdgG5A8tvtIH35B9zmDJqx0wZuhuTeOWz85Ynun+jdIxh72/EeT3pYzTdyQNPcW0 1V2JgYibOwa8BzROkb9Kya+ZeJRsrZ7vJhSq/TDKjR01UH+ZUTGzvszRrmp69oLN8Exi k0hIiQZe2Pf+7netDnZUA4lvYLbdVSrSgyMAtbxZ8omYVQdhWjzOWXuHbCggDEsnFbyh fjaVX06roZBJFD7zJ0tfbBX7U3z2UpOZ8OqghFTdlI8UNh5tmt3BwBUeMQGIOyEGzq3s eG1pVVXN2NIcCx/zmvs2bh6IL3BmUAfbxL6rcHgI93HxycSRhmP2PKa6cFG44I1YO0nd yYiw== 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=mEms9feIibmv6Z5ZQVurPaAWVGvgo943OroL3Va8W7I=; b=f3qo3Gv28outVW4Q/IVfAZGEN5uI9NSoKJvPjFq4oXAFeeuTPosWJ1qbYBuI9zBUV4 gjFTk7WFU6LFCW66SYRjFG00ku2Kv+1l+Po+UJaQDXXjGXfYs3qdosyklnRTJzipKoBl yJXCQKHzX5ectb5ZZm/XawXqS7yd20z9uMtrYvA4WVcJULKJl5VzWjabcWdk663IVy6J VNetkXapcHeMkubkP70iVZsAgtWqid6LEGgZUqBFavgnS5L3BUE+yIkQqjXU9/XqWL3m m8PreKeXa03ouUz23FSijm5d2HuVaZK+o9jPgd2UGiAt+t7qvLIWeqdYAXhUWjp/kaVm IRNA== X-Gm-Message-State: AGi0PuaDr3TA0i2drFFC6iwnZxQUqbXNl8xpZOca5vUZ1B/nfhwziJ5s Yye3kRRKMMsiex406t5ubQ1Xpr0DSMg= X-Google-Smtp-Source: APiQypImHk4Br6MObHThMUS72EplTgWUngqPQ0UdBCKUqVacWsgfjV0C47Xqgq8HYMRTqvkSNlxbIA== X-Received: by 2002:ac8:12c2:: with SMTP id b2mr10990311qtj.7.1588474011627; Sat, 02 May 2020 19:46:51 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:50 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Simon Glass Subject: [PATCH v10 09/21] dm: Fix error handling for dev_read_addr_ptr Date: Sat, 2 May 2020 22:46:25 -0400 Message-Id: <20200503024637.327733-10-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean dev_read_addr_ptr had different semantics depending on whether OF_LIVE was enabled. This patch converts both implementations to return NULL on error, and converts all call sites which check for FDT_ADDR_T_NONE to check for NULL instead. This patch also removes the call to map_physmem, since we have dev_remap_addr* for those semantics. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng Reviewed-by: Simon Glass --- Changes in v10: - Explicitly cast fdt_addr_t to uintptr_t before casting to void * Changes in v5: - New drivers/clk/imx/clk-imx8mp.c | 2 +- drivers/core/read.c | 2 +- drivers/pinctrl/broadcom/pinctrl-bcm283x.c | 2 +- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +- include/dm/read.h | 4 +++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index a2693d2f7a..df30f4a087 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -281,7 +281,7 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_SYS_PLL2_1000M, imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1)); base = dev_read_addr_ptr(dev); - if (base == (void *)FDT_ADDR_T_NONE) + if (!base) return -EINVAL; clk_dm(IMX8MP_CLK_A53_SRC, imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mp_a53_sels, ARRAY_SIZE(imx8mp_a53_sels))); diff --git a/drivers/core/read.c b/drivers/core/read.c index 47b8e03446..d3e6b46c70 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -167,7 +167,7 @@ void *dev_read_addr_ptr(const struct udevice *dev) { fdt_addr_t addr = dev_read_addr(dev); - return (addr == FDT_ADDR_T_NONE) ? NULL : map_sysmem(addr, 0); + return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)(uintptr_t)addr; } void *dev_remap_addr(const struct udevice *dev) diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c index eb720f09f8..6961536a4d 100644 --- a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c +++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c @@ -116,7 +116,7 @@ int bcm283x_pinctl_probe(struct udevice *dev) } priv->base_reg = dev_read_addr_ptr(dev); - if (priv->base_reg == (void *)FDT_ADDR_T_NONE) { + if (!priv->base_reg) { debug("%s: Failed to get base address\n", __func__); return -EINVAL; } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index c7351f32bb..bd95662ed5 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -630,7 +630,7 @@ int mtk_pinctrl_common_probe(struct udevice *dev, int ret; priv->base = dev_read_addr_ptr(dev); - if (priv->base == (void *)FDT_ADDR_T_NONE) + if (!priv->base) return -EINVAL; priv->soc = soc; diff --git a/include/dm/read.h b/include/dm/read.h index 03c15b8550..17a760230a 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -791,7 +791,9 @@ static inline fdt_addr_t dev_read_addr(const struct udevice *dev) static inline void *dev_read_addr_ptr(const struct udevice *dev) { - return devfdt_get_addr_ptr(dev); + void *addr = devfdt_get_addr_ptr(dev); + + return ((fdt_addr_t)(uintptr_t)addr == FDT_ADDR_T_NONE) ? NULL : addr; } static inline fdt_addr_t dev_read_addr_pci(const struct udevice *dev) From patchwork Sun May 3 02:46:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281845 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=o1NY0Lcc; 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 49F9Rv4Wxcz9sRf for ; Sun, 3 May 2020 12:49:15 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6B820821B6; Sun, 3 May 2020 04:47:07 +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="o1NY0Lcc"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 822B381EF5; Sun, 3 May 2020 04:46:58 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf43.google.com (mail-qv1-xf43.google.com [IPv6:2607:f8b0:4864:20::f43]) (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 5490481ED1 for ; Sun, 3 May 2020 04:46:54 +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-qv1-xf43.google.com with SMTP id t8so6679525qvw.5 for ; Sat, 02 May 2020 19:46:54 -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=l0mlvTjQ1Zaju0SZkCfoExb0zRP6pAMTtg3wql2430s=; b=o1NY0Lccgl3NfK2M25Ap94ZH+aw9m3ku0J4JnJrSoiJ6G8mDFe4lmq3AUJ8P34TO6V zWrLp+vpAPcfBKFwL3BSeOSQ5CuQUagq0RFiAOOak0yfwIBB+d0pkHZD6bhADwymyJvQ SsZrjnllscE4+MrLn/1bZ+LG+VWFmOLMZ04uXM8M/8pnKVrorZIfTxaSw00xdbtqh82o ex1Rl6HJ2Pv4dMZreu9NbnuvXimtjBwKPSNRrWhg65u41LrP8S1UwI0mVCFAzWMxLK7p xThROhedjHfATljOGM2h5LMy/rgc54VrQEuJf0hJdy+TUNuia+n+GeqVBi32X2yYxRqB euTA== 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=l0mlvTjQ1Zaju0SZkCfoExb0zRP6pAMTtg3wql2430s=; b=RJiWTtGkSLv4BYIP/tCm1ddgQu/yrrMeiH6hNHZyh5kAc67VqgkmoknNtVUplCn0IH dYYPGfpGBDCm56nbf0wIUEGHKSmQlMcElvXELJkA7dpa/vftjgUoO+Vu49jIMAYW3zt6 qeHEqiJDDpSbQ309XkpEWRkpRNNy+dqDXttgGMVxqnBijZgRKtmaGArVbm/RF88R8hWU d5rdajHp51jc2W3PjG55cFaZByvYLM4eD/MVljD8Yazh8tOh58FR00hRxgpaCBlg/jDv unI/5+cRdbzLuOiqrSrHZNduNM1oA1KT2sOksAy+1xys6FCeUyJSoFwx8/vG3fatOJox wEoQ== X-Gm-Message-State: AGi0PuZjSIwT8Vx2TvpTkL7a6X6xgCY261XlDMa13sbxlKA1Uo+jv4UT WEgEiKdZgh1g+2HMvJ9ifRIJisYTzUM= X-Google-Smtp-Source: APiQypI1D1yi6Py5/Mrtuah1B26zQ6oIAiAGWV9HYQrCL+8Y22R+UJHvpVV9Qv1M20JXBe8/KiTEAw== X-Received: by 2002:a0c:aec5:: with SMTP id n5mr8542059qvd.0.1588474012755; Sat, 02 May 2020 19:46:52 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:52 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Simon Glass Subject: [PATCH v10 10/21] reset: Add generic reset driver Date: Sat, 2 May 2020 22:46:26 -0400 Message-Id: <20200503024637.327733-11-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This patch adds a generic reset driver. It is designed to be useful when one has a register in a regmap which contains bits that reset other devices. I thought this seemed like a very generic use, so here is a generic driver. The overall structure has been modeled on the syscon-reboot driver. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- Changes in v5: - Reorder includes - Include linux/err.h explicitly Changes in v4: - Added basic test - Fix incorrect usage of regmap_update_bits Changes in v3: - New arch/sandbox/dts/test.dts | 15 ++++ configs/sandbox_defconfig | 2 + .../reset/syscon-reset.txt | 36 +++++++++ drivers/reset/Kconfig | 5 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-syscon.c | 80 +++++++++++++++++++ test/dm/Makefile | 1 + test/dm/syscon-reset.c | 58 ++++++++++++++ 8 files changed, 198 insertions(+) create mode 100644 doc/device-tree-bindings/reset/syscon-reset.txt create mode 100644 drivers/reset/reset-syscon.c create mode 100644 test/dm/syscon-reset.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 6567a322dd..52cf7f305c 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1000,6 +1000,21 @@ clocks = <&clk_sandbox 4>; power-domains = <&pwrdom 1>; }; + + resetc2: syscon-reset { + compatible = "syscon-reset"; + #reset-cells = <1>; + regmap = <&syscon0>; + offset = <1>; + mask = <0x27FFFFFF>; + assert-high = <0>; + }; + + syscon-reset-test { + compatible = "sandbox,misc_sandbox"; + resets = <&resetc2 15>, <&resetc2 30>, <&resetc2 60>; + reset-names = "valid", "no_mask", "out_of_range"; + }; }; #include "sandbox_pmic.dtsi" diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index e09ee209f2..23506850dd 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -194,6 +194,8 @@ CONFIG_REMOTEPROC_SANDBOX=y CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RNG=y +CONFIG_RNG_SANDBOX=y +CONFIG_RESET_SYSCON=y CONFIG_DM_RTC=y CONFIG_RTC_RV8803=y CONFIG_DEBUG_UART_SANDBOX=y diff --git a/doc/device-tree-bindings/reset/syscon-reset.txt b/doc/device-tree-bindings/reset/syscon-reset.txt new file mode 100644 index 0000000000..f136b3d225 --- /dev/null +++ b/doc/device-tree-bindings/reset/syscon-reset.txt @@ -0,0 +1,36 @@ +Generic SYSCON mapped register reset driver + +This is a generic reset driver using syscon to map the reset register. +The reset is generally performed with a write to the reset register +defined by the register map pointed by syscon reference plus the offset and +shifted by the reset specifier/ + +To assert a reset on some device, the equivalent of the following operation is +performed, where reset_id is the reset specifier from the device's resets +property. + + if (BIT(reset_id) & mask) + regmap[offset][reset_id] = assert-high; + +Required properties: +- compatible: should contain "syscon-reset" +- #reset-cells: must be 1 +- regmap: this is phandle to the register map node +- offset: offset in the register map for the reboot register (in bytes) + +Optional properties: +- mask: accept only the reset specifiers defined by the mask (32 bit) +- assert-high: Bit to write when asserting a reset. Defaults to 1. + +Default will be little endian mode, 32 bit access only. + +Example: + + reset-controller { + compatible = "syscon-reset"; + #reset-cells = <1>; + regmap = <&sysctl>; + offset = <0x20>; + mask = <0x27FFFFFF>; + assert-high = <0>; + }; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 75ccd65799..097bf32b21 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -148,4 +148,9 @@ config RESET_IMX7 help Support for reset controller on i.MX7/8 SoCs. +config RESET_SYSCON + bool "Enable generic syscon reset driver support" + depends on DM_RESET + help + Support generic syscon mapped register reset devices. endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 0a044d5d8c..433f1eca54 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o +obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o diff --git a/drivers/reset/reset-syscon.c b/drivers/reset/reset-syscon.c new file mode 100644 index 0000000000..34dfe0bab6 --- /dev/null +++ b/drivers/reset/reset-syscon.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include +#include +#include +#include +#include + +struct syscon_reset_priv { + struct regmap *regmap; + uint offset; + uint mask; + bool assert_high; +}; + +static int syscon_reset_request(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + if (BIT(rst->id) & priv->mask) + return 0; + else + return -EINVAL; +} + +static int syscon_reset_assert(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), + priv->assert_high ? BIT(rst->id) : 0); +} + +static int syscon_reset_deassert(struct reset_ctl *rst) +{ + struct syscon_reset_priv *priv = dev_get_priv(rst->dev); + + return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id), + priv->assert_high ? 0 : BIT(rst->id)); +} + +static const struct reset_ops syscon_reset_ops = { + .request = syscon_reset_request, + .rst_assert = syscon_reset_assert, + .rst_deassert = syscon_reset_deassert, +}; + +int syscon_reset_probe(struct udevice *dev) +{ + struct syscon_reset_priv *priv = dev_get_priv(dev); + + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap"); + if (IS_ERR(priv->regmap)) + return -ENODEV; + + priv->offset = dev_read_u32_default(dev, "offset", 0); + priv->mask = dev_read_u32_default(dev, "mask", 0); + priv->assert_high = dev_read_u32_default(dev, "assert-high", true); + + return 0; +} + +static const struct udevice_id syscon_reset_ids[] = { + { .compatible = "syscon-reset" }, + { }, +}; + +U_BOOT_DRIVER(syscon_reset) = { + .name = "syscon_reset", + .id = UCLASS_RESET, + .of_match = syscon_reset_ids, + .probe = syscon_reset_probe, + .priv_auto_alloc_size = sizeof(struct syscon_reset_priv), + .ops = &syscon_reset_ops, +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index 518ee8e377..0d1c66fa1e 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -75,4 +75,5 @@ obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o obj-$(CONFIG_DM_RNG) += rng.o obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o +obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o endif diff --git a/test/dm/syscon-reset.c b/test/dm/syscon-reset.c new file mode 100644 index 0000000000..1db0206e00 --- /dev/null +++ b/test/dm/syscon-reset.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* The following values must match the device tree */ +#define TEST_RESET_REG 1 +#define TEST_RESET_ASSERT_HIGH 0 +#define TEST_RESET_ASSERT (TEST_RESET_ASSERT_HIGH ? (u32)-1 : (u32)0) +#define TEST_RESET_DEASSERT (~TEST_RESET_ASSERT) + +#define TEST_RESET_VALID 15 +#define TEST_RESET_NOMASK 30 +#define TEST_RESET_OUTOFRANGE 60 + +static int dm_test_syscon_reset(struct unit_test_state *uts) +{ + struct regmap *map; + struct reset_ctl rst; + struct udevice *reset; + struct udevice *syscon; + struct udevice *syscon_reset; + uint reg; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "syscon-reset-test", + &reset)); + ut_assertok(uclass_get_device_by_name(UCLASS_SYSCON, "syscon@0", + &syscon)); + ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "syscon-reset", + &syscon_reset)); + ut_assertok_ptr((map = syscon_get_regmap(syscon))); + + ut_asserteq(-EINVAL, reset_get_by_name(reset, "no_mask", &rst)); + ut_asserteq(-EINVAL, reset_get_by_name(reset, "out_of_range", &rst)); + ut_assertok(reset_get_by_name(reset, "valid", &rst)); + + sandbox_set_enable_memio(true); + ut_assertok(regmap_write(map, TEST_RESET_REG, TEST_RESET_DEASSERT)); + ut_assertok(reset_assert(&rst)); + ut_assertok(regmap_read(map, TEST_RESET_REG, ®)); + ut_asserteq(TEST_RESET_DEASSERT ^ BIT(TEST_RESET_VALID), reg); + + ut_assertok(reset_deassert(&rst)); + ut_assertok(regmap_read(map, TEST_RESET_REG, ®)); + ut_asserteq(TEST_RESET_DEASSERT, reg); + + return 0; +} +DM_TEST(dm_test_syscon_reset, DM_TESTF_SCAN_FDT); From patchwork Sun May 3 02:46:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281847 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=MHw1M3G6; 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 49F9SM38MLz9sRf for ; Sun, 3 May 2020 12:49:39 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 18FE1821B3; Sun, 3 May 2020 04:47:10 +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="MHw1M3G6"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 62A9581EE2; Sun, 3 May 2020 04:46:59 +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=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x843.google.com (mail-qt1-x843.google.com [IPv6:2607:f8b0:4864:20::843]) (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 5F91681EBA for ; Sun, 3 May 2020 04:46:55 +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-x843.google.com with SMTP id i68so11196147qtb.5 for ; Sat, 02 May 2020 19:46:55 -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=JqpTI+R5u1R4y/N876rmleqbQjv+1J0JiV8cYqNQSjk=; b=MHw1M3G6B35XMEmYiUNugY4eM3gD4TPtVN82ixt+JjLweqWhvsL6q4Xh9yr5FGd9Re qFuj+KDCjP2EpX2dipCY4vkEu1m1NWaRgmpF/w/W95HyQ/j0wmfzkeUpqG9RePSuBjFo XXhMwB4Xc1p30o0jrBhNzci7zP6WFaFjP9W3w54bh1mnG+ITJcHrR2ACwzGaHCVSUgZm Ah/yCdv3GwMxqStViwuEt75icQVMBEx+cSmk3HHtSnAhr8TNaOmcvPsmigtmQ4y8JYAj caSDz6j7PxiHPAnBKEtyKG/pkEg6sE/Bmdv+kr+T5NcjdEOA6h2KjDP4ip6Z5r7Ln5Z/ grGw== 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=JqpTI+R5u1R4y/N876rmleqbQjv+1J0JiV8cYqNQSjk=; b=CSzC/v3D/+kvBoj6KOIsyMxcMdinB8ZKRjlbphUAH/eeGIZQlvILxTmeJAV8InQDOi joSyliaC64pwiYKU1iuClOYq3LdyZ7QWWfC74VWffasVBNaMsp1uYIi3o2oXn69DpMuT cOovYXWaAUHRv2YBUYnE0beMECoBY/LF8irbfig7OUYe4THVikDMOn9E0s5l5/IbaXg/ ComDGpvCX5QUwkXear6RN7VNqVC2lCnnc+iP0fRvXCQGm+zFDP3ik0orpYwWpC/jfB4e DhbcKw4UFqUniQ4uSnLyK8P+hvQCcIAKafjtJIcixkOiDzvAILLcHEkJ2OHTfpIQjlIw rvqw== X-Gm-Message-State: AGi0PuZduqfjLYoJCjxK3VMyQX+4gKs5P6/pIThEpVFjK4VdsroRytCh cUpXuPk+dMWZWb1r85Hu3sOurdeWIJs= X-Google-Smtp-Source: APiQypLdPE6y0guXTHPHsPTgQ020xn0HhPYMrl1i5tA5xwXswZ6YTaVut+K/aftlSv1RWZftisi4UA== X-Received: by 2002:ac8:303a:: with SMTP id f55mr2525013qte.270.1588474014026; Sat, 02 May 2020 19:46:54 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:53 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Tom Rini Subject: [PATCH v10 11/21] lib: Always set errno in hcreate_r Date: Sat, 2 May 2020 22:46:27 -0400 Message-Id: <20200503024637.327733-12-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This could give a confusing error message if it failed and didn't set errno. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- Changes in v5: - New lib/hashtable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/hashtable.c b/lib/hashtable.c index 907e8a642f..e9ac7e252e 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -109,8 +109,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) } /* There is still another table active. Return with error. */ - if (htab->table != NULL) + if (htab->table != NULL) { + __set_errno(EINVAL); return 0; + } /* Change nel to the first prime number not smaller as nel. */ nel |= 1; /* make odd */ @@ -123,8 +125,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) /* allocate memory and zero out */ htab->table = (struct env_entry_node *)calloc(htab->size + 1, sizeof(struct env_entry_node)); - if (htab->table == NULL) + if (htab->table == NULL) { + __set_errno(ENOMEM); return 0; + } /* everything went alright */ return 1; From patchwork Sun May 3 02:46:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281846 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=QjbiM8CJ; 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 49F9S74brkz9sSk for ; Sun, 3 May 2020 12:49:27 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D2A2182299; Sun, 3 May 2020 04:47:08 +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="QjbiM8CJ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1EBA381EF6; Sun, 3 May 2020 04:46:59 +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=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x742.google.com (mail-qk1-x742.google.com [IPv6:2607:f8b0:4864:20::742]) (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 7A9D081EE4 for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qk1-x742.google.com with SMTP id i7so4824844qkl.12 for ; Sat, 02 May 2020 19:46:56 -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=sqtGfuF2AUXKzcrv0rJwHetVbh8PLUyiStwRK3XIo/U=; b=QjbiM8CJ33OKfvg5LYZFehWrK3xJ9wNAlhSzZedk0XAIYJaiqZVEt/LyvLexst66qh j7/+RH/gT7N6tI594bAlRUbVazz3YGOerN83LRa8WFTypYaLVHZ8Z9mqrHsTC9kvn79F 36aiswsuQl7mpffSW2oHTlQGhk6HSwzsiRKkudSEHqqj1lPaKavOyekizdamlCo/cWKk p/ugyrD3xMQKuB7yPI7xxZfXKlE2yimW9MZbLfjr3miCsDi6oWIcinvM4rJfftF/A1Wb Zimb4IccG8i3D3wqmmHWHN61PfneoraFyx9bm/Bud1HDrypvKcRZ6vljno7bCv/OrXRk VrjQ== 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=sqtGfuF2AUXKzcrv0rJwHetVbh8PLUyiStwRK3XIo/U=; b=qA5Gs3+s81gceqLhjZABjMaECeL9VIjMLU95EX7a22Mpb1AOtRJQgx87oTbc20bmiH QtrL7AkKSPSsWyQS6MbuBHXUhxswsrfIfIFChLgwd3OE8JTcgbjjDf26dV3Ih25rzdbc /vpw75mBFPVQqZWYxIV75PZ3b419ZZ8uYJb7OFP/SLnUpyHbAlq14C9j+LEWsdZEM1YD iFWs9UnZ3rfcbIqGEXlEzucn0Hrraruf12oofmSp1IrotkFKg66MBdHwvhEscY3jgYwc QF10CDS7KU8kRoQWeenMJklRHvtjP8eUdsLPnxRB7NmnLKbzsuPMS61pZwO9W1NbaFdG J43Q== X-Gm-Message-State: AGi0PuZ7Ig4JhIOdAjI//6Vz1SyeTr5cDMVxPvL/2sbi3rbkvXgXvIsX egaG6QOVghaMwq+dQ8B7DUMGZ+R1Gpo= X-Google-Smtp-Source: APiQypK772wJG7f4xWrBH18pZKe8Lly7rb19o9Dt/bvokXZfju0G67nIxtxyYHqNO6FW3a3F1IYO0A== X-Received: by 2002:a37:9a41:: with SMTP id c62mr10567343qke.244.1588474015265; Sat, 02 May 2020 19:46:55 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:54 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 12/21] riscv: Add headers for asm/global_data.h Date: Sat, 2 May 2020 22:46:28 -0400 Message-Id: <20200503024637.327733-13-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This header depended on bd_t and ulong, but did not include the appropriate headers. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- Changes in v4: - Include compiler.h not linux/compiler.h arch/riscv/include/asm/global_data.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index b74bd7e738..7276d9763f 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -11,6 +11,8 @@ #define __ASM_GBL_DATA_H #include +#include +#include /* Architecture-specific global data */ struct arch_global_data { From patchwork Sun May 3 02:46:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281848 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=ReFj/oCT; 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 49F9SY6jWYz9sRf for ; Sun, 3 May 2020 12:49:49 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9FE01822AB; Sun, 3 May 2020 04:47:11 +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="ReFj/oCT"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8D82081EF7; Sun, 3 May 2020 04:47:00 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf42.google.com (mail-qv1-xf42.google.com [IPv6:2607:f8b0:4864:20::f42]) (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 8CD7E81E5E for ; Sun, 3 May 2020 04:46:57 +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-qv1-xf42.google.com with SMTP id v10so6700080qvr.2 for ; Sat, 02 May 2020 19:46:57 -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=OG5fYq2RPBpL6zzI/KCg3rE4/Ew+dej60jVLSU6jXwY=; b=ReFj/oCTUdbmRBvz8vl/DCKJJK7hPcwAvvahDg45I42BqGE88pGjEbW0f7N5xy5WPH JHAo69Uw3Hv2eMcUp/4ijdu5q6D5IHauowZQ2dPg8nfCakuznIs8JUxjEoiQNbwVzQry x/3p2GyJKd86y6FCfT4cYzYY8VW9/eokX5Y/5g2KNfT0g5qEZuRKWP+HCFrg8cYJeOAl 22+6dZGpZ5ZVh1NUjARzR6UJh2DmgN1tAoCBx8ao2UokLfxggq/CxzNbuWzaN3M0l2U4 gqM5XoCBQ0K1G3oER+ldkFGFXOg9vB7a7dQXxaadqSZ9avR5QUoknVzRhr3di9yt/qHe 4D5w== 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=OG5fYq2RPBpL6zzI/KCg3rE4/Ew+dej60jVLSU6jXwY=; b=RW8/XQuoYJUYcOyjjwouhPO1g4dS+WPDm8aG+sK4D3ESnOc+zy9yulmj8E6oq8UZsz KBTLkZPUfHsOj6K433fxyo45CgnsX46fsjXAg4Jdw2/8RRGEssWohod0a10O476ZDatv 0SVJ2on4cz7fP7Sc54aOEAWdpDbosuSd1dPcBjHF1jbmCpUpzsTOQx2bi8ylC9BoOjDq dUPplPL52LxvYQI5PDmIOxKMYR119s1x5KX0AtTwielQeEpMc7ciD2v+zGTQZ12kzPue 9YAjlPTDgcUnwfoKmzRaDTevKVmUSlQThmXda1918d8e741a0bQ/tVjTMpAmA8Bq20DH 7POQ== X-Gm-Message-State: AGi0PuZOyIUkVkdlS10WvitsYD8o4lPR44i1lJ3GMbZ6+Vxea8tx/fXO 9AJE/knACDiEzyTnxDzSYFgwQmIsZ21jxw== X-Google-Smtp-Source: APiQypLNNeehYBW1q+Sd2UihNiLOIOyHDYK54qwJOjH49l0891ElsgOXBlynbw1K149QKtmBe0dwEw== X-Received: by 2002:a0c:b651:: with SMTP id q17mr10145538qvf.135.1588474016272; Sat, 02 May 2020 19:46:56 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:55 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Rick Chen , Lukas Auer Subject: [PATCH v10 13/21] riscv: Clear pending interrupts before enabling IPIs Date: Sat, 2 May 2020 22:46:29 -0400 Message-Id: <20200503024637.327733-14-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean On some platforms (k210), the previous stage bootloader may have not cleared pending IPIs before transferring control to U-Boot. This can cause race conditions, as multiple harts all attempt to initialize the IPI controller at once. This patch clears IPIs before enabling them, ensuring that only one hart modifies shared memory at once. Signed-off-by: Sean Anderson Reviewed-by: Rick Chen --- Changes in v7: - Split of into its own patch arch/riscv/cpu/start.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 6b3ff99c38..e8740c8568 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -67,6 +67,8 @@ _start: #else li t0, SIE_SSIE #endif + /* Clear any pending IPIs */ + csrc MODE_PREFIX(ip), t0 csrs MODE_PREFIX(ie), t0 #endif From patchwork Sun May 3 02:46:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281849 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=s3jcWZWH; 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 49F9Sp083hz9sRf for ; Sun, 3 May 2020 12:50:01 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 14139822C5; Sun, 3 May 2020 04:47:13 +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="s3jcWZWH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9C91481F01; Sun, 3 May 2020 04:47:02 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf43.google.com (mail-qv1-xf43.google.com [IPv6:2607:f8b0:4864:20::f43]) (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 DC09E81EE3 for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qv1-xf43.google.com with SMTP id ck5so6655069qvb.11 for ; Sat, 02 May 2020 19:46:58 -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=YLn/Ogimo+bGErG08ltdOdLhZd9Kg7Ym3O/o39lYYA0=; b=s3jcWZWHcbNkEDZDP2OXkQla/qyCJTAL67zv7qAzRKhdOkedcJVfymiN+Kc0bOnEA2 235+Ga5P5TyDMVf0+sAx+F4BW3EOyhDq2CAH8Uf0a+rTjcNhkxhV0hh7itQlulNrvk3P SdGHvMw3dE0IWOT0GDj2EqCpgD+fyRcb+VOc/SS2Yl4E5Nmldu09K6I3oUfA8m71yfIc vtOS9Uc7bCqBqelY7ltd/mDUO8kiEL4SYyZ80AOjq4kvTO6P+seeXo6A86njgoa6TTgH wCMR+EP2qFwGXrd/N+HR2QmDQ4u5y/Vs7uMSxtE09dSXnNQVDmI8VIaE05J7fm9neL8P gABw== 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=YLn/Ogimo+bGErG08ltdOdLhZd9Kg7Ym3O/o39lYYA0=; b=EL+0E3amxWbzP892ixEk/F2drx8Uyhz9io4epp5J/V6+nq3UY22ttvxBoSreBDGK60 oZkKsdPbkA+1H8tbyKEEuhVgpHClW64JGbSkrHSn0syjkl4dbtN76c7kt5oVrUyLtiaA ysyXQ961lgC2AdWQbAy6nLJW3npNaTJZOOprVQByzF5QoGQt48OsOoH8qBaAVZMP6Kn3 99l5+3ZQjvUeqQQ+EjfkfPQ3OlMzuwiuju84o5CEI6p6/DpVOzDf83NpNY5N2tsmlShA mIDNFxtBQDr66wYBJ59VjGBQqD55MrG516Jm2GbsON8QBr4EYk0lRSXNqaY9aTg7EUcD X5Rg== X-Gm-Message-State: AGi0PuZDTl4t9tS0TDrOsPxVGzUcLmvLKEIbii/ZyPc7G0lsvkT7dyrB 30FK6FPb7AIZsTSFu+MUsoYq6j4BQnUE0g== X-Google-Smtp-Source: APiQypLgxAL/A1cIDgDRtWJaE+klcZwVu34amaps0aytiOPvxr17R8wbfPIrhYNaJL+4BFSev40Pkg== X-Received: by 2002:a05:6214:12e4:: with SMTP id w4mr10527276qvv.190.1588474017334; Sat, 02 May 2020 19:46:57 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:56 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson , Rick Chen , Lukas Auer Subject: [PATCH v10 14/21] riscv: Clean up IPI initialization code Date: Sat, 2 May 2020 22:46:30 -0400 Message-Id: <20200503024637.327733-15-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean The previous IPI code initialized the device whenever the first call was made to a riscv_*_ipi function. This made it difficult to determine when the IPI device was initialized. This patch introduces a new function riscv_init_ipi. It is called once during arch_cpu_init_dm. Before this point, no riscv_*_ipi functions should be called. Signed-off-by: Sean Anderson Reviewed-by: Rick Chen --- Changes in v9: - Fix type of ret variable in riscv_ipi_init Changes in v7: - Split IPI clearing off into its own patch Changes in v6: - Fix some formatting - Clear IPIs before enabling interrupts instead of using a ipi_ready flag - Only print messages on error in smp code Changes in v5: - New arch/riscv/cpu/cpu.c | 6 ++++ arch/riscv/include/asm/smp.h | 43 +++++++++++++++++++++++++++ arch/riscv/lib/andes_plic.c | 34 ++++++++------------- arch/riscv/lib/sbi_ipi.c | 5 ++++ arch/riscv/lib/sifive_clint.c | 33 +++++++-------------- arch/riscv/lib/smp.c | 56 ++++++++--------------------------- 6 files changed, 90 insertions(+), 87 deletions(-) diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index e457f6acbf..f851374255 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -96,6 +96,12 @@ int arch_cpu_init_dm(void) csr_write(CSR_SATP, 0); } +#ifdef CONFIG_SMP + ret = riscv_init_ipi(); + if (ret) + return ret; +#endif + return 0; } diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index 74de92ed13..1b428856b2 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -51,4 +51,47 @@ void handle_ipi(ulong hart); */ int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait); +/** + * riscv_init_ipi() - Initialize inter-process interrupt (IPI) driver + * + * Platform code must provide this function. This function is called once after + * the cpu driver is initialized. No other riscv_*_ipi() calls will be made + * before this function is called. + * + * @return 0 if OK, -ve on error + */ +int riscv_init_ipi(void); + +/** + * riscv_send_ipi() - Send inter-processor interrupt (IPI) + * + * Platform code must provide this function. + * + * @hart: Hart ID of receiving hart + * @return 0 if OK, -ve on error + */ +int riscv_send_ipi(int hart); + +/** + * riscv_clear_ipi() - Clear inter-processor interrupt (IPI) + * + * Platform code must provide this function. + * + * @hart: Hart ID of hart to be cleared + * @return 0 if OK, -ve on error + */ +int riscv_clear_ipi(int hart); + +/** + * riscv_get_ipi() - Get status of inter-processor interrupt (IPI) + * + * Platform code must provide this function. + * + * @hart: Hart ID of hart to be checked + * @pending: Pointer to variable with result of the check, + * 1 if IPI is pending, 0 otherwise + * @return 0 if OK, -ve on error + */ +int riscv_get_ipi(int hart, int *pending); + #endif diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 20529ab3eb..5cf29df670 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -30,20 +30,6 @@ #define SEND_IPI_TO_HART(hart) (0x80 >> (hart)) DECLARE_GLOBAL_DATA_PTR; -static int init_plic(void); - -#define PLIC_BASE_GET(void) \ - do { \ - long *ret; \ - \ - if (!gd->arch.plic) { \ - ret = syscon_get_first_range(RISCV_SYSCON_PLIC); \ - if (IS_ERR(ret)) \ - return PTR_ERR(ret); \ - gd->arch.plic = ret; \ - init_plic(); \ - } \ - } while (0) static int enable_ipi(int hart) { @@ -93,13 +79,21 @@ static int init_plic(void) return -ENODEV; } +int riscv_init_ipi(void) +{ + long *ret = syscon_get_first_range(RISCV_SYSCON_PLIC); + + if (IS_ERR(ret)) + return PTR_ERR(ret); + gd->arch.plic = ret; + + return init_plic(); +} + int riscv_send_ipi(int hart) { - unsigned int ipi; + unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); - PLIC_BASE_GET(); - - ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart)); @@ -110,8 +104,6 @@ int riscv_clear_ipi(int hart) { u32 source_id; - PLIC_BASE_GET(); - source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart)); writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart)); @@ -120,8 +112,6 @@ int riscv_clear_ipi(int hart) int riscv_get_ipi(int hart, int *pending) { - PLIC_BASE_GET(); - *pending = readl((void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart)); *pending = !!(*pending & SEND_IPI_TO_HART(hart)); diff --git a/arch/riscv/lib/sbi_ipi.c b/arch/riscv/lib/sbi_ipi.c index abafca9e5c..d02e2b4c48 100644 --- a/arch/riscv/lib/sbi_ipi.c +++ b/arch/riscv/lib/sbi_ipi.c @@ -8,6 +8,11 @@ #include #include +int riscv_init_ipi(void) +{ + return 0; +} + int riscv_send_ipi(int hart) { ulong mask; diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c index 5e0d25720b..78fc6c868d 100644 --- a/arch/riscv/lib/sifive_clint.c +++ b/arch/riscv/lib/sifive_clint.c @@ -24,22 +24,8 @@ DECLARE_GLOBAL_DATA_PTR; -#define CLINT_BASE_GET(void) \ - do { \ - long *ret; \ - \ - if (!gd->arch.clint) { \ - ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \ - if (IS_ERR(ret)) \ - return PTR_ERR(ret); \ - gd->arch.clint = ret; \ - } \ - } while (0) - int riscv_get_time(u64 *time) { - CLINT_BASE_GET(); - *time = readq((void __iomem *)MTIME_REG(gd->arch.clint)); return 0; @@ -47,17 +33,24 @@ int riscv_get_time(u64 *time) int riscv_set_timecmp(int hart, u64 cmp) { - CLINT_BASE_GET(); - writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart)); return 0; } +int riscv_init_ipi(void) +{ + long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT); + + if (IS_ERR(ret)) + return PTR_ERR(ret); + gd->arch.clint = ret; + + return 0; +} + int riscv_send_ipi(int hart) { - CLINT_BASE_GET(); - writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; @@ -65,8 +58,6 @@ int riscv_send_ipi(int hart) int riscv_clear_ipi(int hart) { - CLINT_BASE_GET(); - writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; @@ -74,8 +65,6 @@ int riscv_clear_ipi(int hart) int riscv_get_ipi(int hart, int *pending) { - CLINT_BASE_GET(); - *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index 17adb35730..fe992eb00f 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -12,38 +12,6 @@ DECLARE_GLOBAL_DATA_PTR; -/** - * riscv_send_ipi() - Send inter-processor interrupt (IPI) - * - * Platform code must provide this function. - * - * @hart: Hart ID of receiving hart - * @return 0 if OK, -ve on error - */ -extern int riscv_send_ipi(int hart); - -/** - * riscv_clear_ipi() - Clear inter-processor interrupt (IPI) - * - * Platform code must provide this function. - * - * @hart: Hart ID of hart to be cleared - * @return 0 if OK, -ve on error - */ -extern int riscv_clear_ipi(int hart); - -/** - * riscv_get_ipi() - Get status of inter-processor interrupt (IPI) - * - * Platform code must provide this function. - * - * @hart: Hart ID of hart to be checked - * @pending: Pointer to variable with result of the check, - * 1 if IPI is pending, 0 otherwise - * @return 0 if OK, -ve on error - */ -extern int riscv_get_ipi(int hart, int *pending); - static int send_ipi_many(struct ipi_data *ipi, int wait) { ofnode node, cpus; @@ -114,7 +82,6 @@ void handle_ipi(ulong hart) return; __smp_mb(); - smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; invalidate_icache_all(); @@ -124,7 +91,13 @@ void handle_ipi(ulong hart) */ ret = riscv_clear_ipi(hart); if (ret) { - pr_err("Cannot clear IPI of hart %ld\n", hart); + pr_err("Cannot clear IPI of hart %ld (error %d)\n", hart, ret); + return; + } + + /* Sanity check */ + if (!smp_function) { + pr_err("smp_function is NULL on hart %ld\n", hart); return; } @@ -133,14 +106,11 @@ void handle_ipi(ulong hart) int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait) { - int ret = 0; - struct ipi_data ipi; + struct ipi_data ipi = { + .addr = addr, + .arg0 = arg0, + .arg1 = arg1, + }; - ipi.addr = addr; - ipi.arg0 = arg0; - ipi.arg1 = arg1; - - ret = send_ipi_many(&ipi, wait); - - return ret; + return send_ipi_many(&ipi, wait); } From patchwork Sun May 3 02:46:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281850 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=pUuss0O7; 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 49F9T319l4z9sRf for ; Sun, 3 May 2020 12:50:15 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A033B822CA; Sun, 3 May 2020 04:47:14 +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="pUuss0O7"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EBD1A81F09; Sun, 3 May 2020 04:47:03 +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=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x743.google.com (mail-qk1-x743.google.com [IPv6:2607:f8b0:4864:20::743]) (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 DFF3281DA8 for ; Sun, 3 May 2020 04:46: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=seanga2@gmail.com Received: by mail-qk1-x743.google.com with SMTP id k81so10475020qke.5 for ; Sat, 02 May 2020 19:46:59 -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=4zwCyjEKqmIlADY5wOpU+5jD233zyUuXfitF5AgZ0lw=; b=pUuss0O70uJM9mA3b2qb6Y5az9EuzLUFt0sKDmm04+Afml1BnhOR6y4ceqEfqBEmI4 vnrVa9YQrCVRHeLYwQPGsNFU10OQxUPb+5gcS2+ZZPj42YilNdt0MGngJ5hdhcOuP7JL F3JBryjASbnGFL7mZCDJEe8cSNClNbavlbhXF3cOhs3mJMqj/5Dc0mxuWcudGO6J3q+O XyW7dEgf0/j6/qlsFtnoRqhWdvweNc1Zodhe2FB5oxbJ+7HvTqGvnQCQnLwjSzko5CBK mZUQCnUd0BWDofi5P80ycUXSfFFusWWJllxthucQRulrbyZaZya8Ckw3hToIURZ6uUTW UVpw== 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=4zwCyjEKqmIlADY5wOpU+5jD233zyUuXfitF5AgZ0lw=; b=RLjeORWTvgkMzKXm6H5C3adrltqt66z93o9s8IcY0UYRryo4Rqk7KwHjkdTBpN2n2B IG5C394mxB0nq9n+icAXw7ugzvxJwQQ8ORZjBYDttMB/ZIMVWmx9DC4OvpeplFYnH6el EZ1SL5s2WlwCbnmjVySXCBVPQXeiS4TIE5woP2uCRQwCU5QlRRVZZ6INTsTCoTY41CWG GPQkd5Ee5kg2/+JFlYKvkJHaM4UUsD+J2A5bboDIFfGCRLMCu057KagEdMw+GglzbAxM fIOrJBXwV+D5lEaqufJ6FmNsIKrnRFGBBHbHJRFKMI4ZMuVHEXrFddLqzZamCYGjGxb3 e3JQ== X-Gm-Message-State: AGi0PubIpLCFWXDn58xTIZ9iFGTMrw+/N5N1upqpUs1kDrbS+IbSaOwP a2ZAsbVFbJYMK39hDgwdjix8ZkKxYlI= X-Google-Smtp-Source: APiQypJYl8oNd1sDE9SSLrwlCEZR7fc/wL8riA4JmQHtPqQcjfgp0nZrMpZJ9RuttFUjyctKtNWUWA== X-Received: by 2002:ae9:e30d:: with SMTP id v13mr4707754qkf.309.1588474018482; Sat, 02 May 2020 19:46:58 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:57 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 15/21] riscv: Add option to support RISC-V privileged spec 1.9 Date: Sat, 2 May 2020 22:46:31 -0400 Message-Id: <20200503024637.327733-16-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean Some older processors (notably the Kendryte K210) use an older version of the RISC-V privileged specification. The primary changes between the old and new are in virtual memory, and in the merging of three separate counter enable CSRs. Using the new CSR on an old processor causes an illegal instruction exception. This patch adds an option to use the old CSRs instead of the new one. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- Changes in v6: - Reformat so chechpatch errors less Changes in v5: - Rename to 1.9 to reflect the spec as implemented by the k210 Changes in v4: - Fixed CSRs not being defined properly (thanks bmeng) - Added ifdefs for all changed CSRs (e.g. for VM) - Also properly disable VM on boot Changes in v3: - Renamed from "riscv: Add option to disable writes to mcounteren" - Added original functionality back for older priv specs. Changes in v2: - Moved forward in the patch series arch/riscv/Kconfig | 10 +++++++++ arch/riscv/cpu/cpu.c | 9 ++++++++ arch/riscv/include/asm/csr.h | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 3061bf8863..cb1ca31b1b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -238,6 +238,16 @@ config XIP config SHOW_REGS bool "Show registers on unhandled exception" +config RISCV_PRIV_1_9 + bool "Use version 1.9 of the RISC-V priviledged specification" + help + Older versions of the RISC-V priviledged specification had + separate counter enable CSRs for each privilege mode. Writing + to the unified mcounteren CSR on a processor implementing the + old specification will result in an illegal instruction + exception. In addition to counter CSR changes, the way virtual + memory is configured was also changed. + config STACK_SIZE_SHIFT int default 14 diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index f851374255..3c1836694a 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -89,11 +89,20 @@ int arch_cpu_init_dm(void) * Enable perf counters for cycle, time, * and instret counters only */ +#ifdef CONFIG_RISCV_PRIV_1_9 + csr_write(CSR_MSCOUNTEREN, GENMASK(2, 0)); + csr_write(CSR_MUCOUNTEREN, GENMASK(2, 0)); +#else csr_write(CSR_MCOUNTEREN, GENMASK(2, 0)); +#endif /* Disable paging */ if (supports_extension('s')) +#ifdef CONFIG_RISCV_PRIV_1_9 + csr_read_clear(CSR_MSTATUS, SR_VM); +#else csr_write(CSR_SATP, 0); +#endif } #ifdef CONFIG_SMP diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index d1520743a2..1a15089cae 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -15,7 +15,11 @@ #define SR_SIE _AC(0x00000002, UL) /* Supervisor Interrupt Enable */ #define SR_SPIE _AC(0x00000020, UL) /* Previous Supervisor IE */ #define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */ +#ifdef CONFIG_RISCV_PRIV_1_9 +#define SR_PUM _AC(0x00040000, UL) /* Protect User Memory Access */ +#else #define SR_SUM _AC(0x00040000, UL) /* Supervisor User Memory Access */ +#endif #define SR_FS _AC(0x00006000, UL) /* Floating-point Status */ #define SR_FS_OFF _AC(0x00000000, UL) @@ -29,6 +33,22 @@ #define SR_XS_CLEAN _AC(0x00010000, UL) #define SR_XS_DIRTY _AC(0x00018000, UL) +#ifdef CONFIG_RISCV_PRIV_1_9 +#define SR_VM _AC(0x1F000000, UL) /* Virtualization Management */ +#define SR_VM_MODE_BARE _AC(0x00000000, UL) /* No translation or protection */ +#define SR_VM_MODE_BB _AC(0x01000000, UL) /* Single base-and-bound */ +/* Separate instruction and data base-and-bound */ +#define SR_VM_MODE_BBID _AC(0x02000000, UL) +#ifndef CONFIG_64BIT +#define SR_VM_MODE_32 _AC(0x08000000, UL) +#define SR_VM_MODE SR_VM_MODE_32 +#else +#define SR_VM_MODE_39 _AC(0x09000000, UL) +#define SR_VM_MODE_48 _AC(0x0A000000, UL) +#define SR_VM_MODE SR_VM_MODE_39 +#endif +#endif + #ifndef CONFIG_64BIT #define SR_SD _AC(0x80000000, UL) /* FS/XS dirty */ #else @@ -36,6 +56,7 @@ #endif /* SATP flags */ +#ifndef CONFIG_RISCV_PRIV_1_9 #ifndef CONFIG_64BIT #define SATP_PPN _AC(0x003FFFFF, UL) #define SATP_MODE_32 _AC(0x80000000, UL) @@ -45,6 +66,7 @@ #define SATP_MODE_39 _AC(0x8000000000000000, UL) #define SATP_MODE SATP_MODE_39 #endif +#endif /* SCAUSE */ #define SCAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1)) @@ -88,17 +110,35 @@ #define CSR_SCAUSE 0x142 #define CSR_STVAL 0x143 #define CSR_SIP 0x144 +#ifdef CONFIG_RISCV_PRIV_1_9 +#define CSR_SPTBR 0x180 +#else #define CSR_SATP 0x180 +#endif #define CSR_MSTATUS 0x300 #define CSR_MISA 0x301 #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 +#ifdef CONFIG_RISCV_PRIV_1_9 +#define CSR_MUCOUNTEREN 0x320 +#define CSR_MSCOUNTEREN 0x321 +#define CSR_MHCOUNTEREN 0x322 +#else #define CSR_MCOUNTEREN 0x306 +#endif #define CSR_MSCRATCH 0x340 #define CSR_MEPC 0x341 #define CSR_MCAUSE 0x342 #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 +#ifdef CONFIG_RISCV_PRIV_1_9 +#define CSR_MBASE 0x380 +#define CSR_MBOUND 0x381 +#define CSR_MIBASE 0x382 +#define CSR_MIBOUND 0x383 +#define CSR_MDBASE 0x384 +#define CSR_MDBOUND 0x385 +#endif #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 From patchwork Sun May 3 02:46:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281851 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=FHSa1wM8; 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 49F9TH0MC5z9sRf for ; Sun, 3 May 2020 12:50:27 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9F09D822BC; Sun, 3 May 2020 04:47:16 +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="FHSa1wM8"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4486781F0C; Sun, 3 May 2020 04:47:04 +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=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x742.google.com (mail-qk1-x742.google.com [IPv6:2607:f8b0:4864:20::742]) (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 A63DF81E5E for ; Sun, 3 May 2020 04:47:00 +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-x742.google.com with SMTP id f13so1758956qkh.2 for ; Sat, 02 May 2020 19:47:00 -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=ung8iYBanDGVRABymuNx3tQdnpMvc7js4OugY1AZnNo=; b=FHSa1wM8Hx1kKRjfOSK98+OP8Lbwk3e3tC1v2zzLZgqpXd1y6mPVU95MqwD8CArnwM QvDxCZhKEtbEDJkwU/vpwjE27pH42/p3emEG8G5JafnZqSjY/5vOogdXG6vVQm98e4F8 d+4XxQDVIehJ7uJBoPYXTyecjcpq6/krdW3wiEDukA8h1EpjchXf5vaM8XL+WkJGsLY2 9/uIcesOGcpm8r4QKUVHRBsIW9tAeHOGP0me1PYzu6uUT/HrqnJmQRQF9Fl0b4ttz+r4 dbKh7qeWNvWFI0Px5BkTxw39XVPTxNWyKRR1Sepg37NRu+EAY/stROpvRaXqTQmx9H2z 1sUg== 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=ung8iYBanDGVRABymuNx3tQdnpMvc7js4OugY1AZnNo=; b=n5Lb6NRSNETB4epx2VY4tqZops4/lciAbGRJ1UpoQ/yW/PZrpXXKWP/Mo/4Pjjpxbw HSsw3aEZZy0p/taausdgqvo4j8wjn8TzD8+1EjwCpJ12TizKum9r7mMnOUZGTaXkgcoe oDcDJ6yyTJFumjFWsSfXNeWyfm+ChMPWMlJJGrKHetb7ANOLrCATZI1jUJMMOh/UU4bA HZGoXh1Y7wFVqQv+cZva1DROpLWnKuj0DLcdTVWl21OUoxvBFONEkisFTmpGDdDgPg7v l/v823Ds/bm9RxkAGT9rgS5u0lfMZVO+2N5OiAuxkWABbxaZyoncWBM9OOqGrg7z56Jx rEiw== X-Gm-Message-State: AGi0PuZ8pJUE1aW8WvdIhYe9kqH8SWac/Th+Irgdd+0sy3GNZ7tEBrHf hVI+G+v79nDQol/E71VDfvRd0Zv1b5M= X-Google-Smtp-Source: APiQypJfdDEvDusFV5bZX8IZi7IH2bEa69ZUUKlNJTODUq0+JWrrU+R16KS0hRnfK23LPejBYmxZ9Q== X-Received: by 2002:ae9:dcc2:: with SMTP id q185mr10125902qkf.239.1588474019424; Sat, 02 May 2020 19:46:59 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:58 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 16/21] riscv: Allow use of reset drivers Date: Sat, 2 May 2020 22:46:32 -0400 Message-Id: <20200503024637.327733-17-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean Currently, one cannot use a reset driver on RISC-V. Follow the MIPS example, and disable the default reset handler when the sysreset driver is enabled. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- Changes in v3: - New arch/riscv/lib/reset.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/lib/reset.c b/arch/riscv/lib/reset.c index ce3c1cf872..7622e5df43 100644 --- a/arch/riscv/lib/reset.c +++ b/arch/riscv/lib/reset.c @@ -7,6 +7,7 @@ #include #include +#ifndef CONFIG_SYSRESET int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { printf("resetting ...\n"); @@ -16,3 +17,4 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } +#endif From patchwork Sun May 3 02:46:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281853 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=tP5LzCZB; 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 49F9Tj51rZz9sRf for ; Sun, 3 May 2020 12:50:49 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 10903822D8; Sun, 3 May 2020 04:47:19 +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="tP5LzCZB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7672381F0C; Sun, 3 May 2020 04:47:06 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf41.google.com (mail-qv1-xf41.google.com [IPv6:2607:f8b0:4864:20::f41]) (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 D0EA881EFD for ; Sun, 3 May 2020 04:47:01 +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-qv1-xf41.google.com with SMTP id h6so6682651qvz.8 for ; Sat, 02 May 2020 19:47:01 -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=W8XR8O2ClYkH5rbMLgk12zLZE+0jTAEtRK3imMiiaAA=; b=tP5LzCZBuyf+GILCrOGH439favv6KnRORemB8VnGE88ySz6pB7B5GE/9B57oX/3TR1 7nItuk7X7lL34tiU32+XJe1EG8CIugVGfjUgxmQbMqXywoUXqrXClt5rrPFH9gF36f4Z OgVbAgyn1ND0TqRiFQuu5JygoHoSWNSUFF8Cy41L+c86o3zfNg+SI1MjBVCF5F5X03NW YCDDUPU5GdtMfNORYuqFEUl9TvdBkOfFJL16nNOYlhqGgux0lgbIPqWPE6xIq6l3b8H8 EBTONS652SASXfkBJZTLrfvzs/YHrCf9GiVOTMSA3VqKYtndC4EmtFtbpppeMMBW3bny Yo+g== 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=W8XR8O2ClYkH5rbMLgk12zLZE+0jTAEtRK3imMiiaAA=; b=rQl4z7L2NS4g+XtlsOF/fDSCY82UMH+V52KBqmG2YXcbhD5HfwujlS9p5bMJ9VxOgt w66SCO5LoC/HneI1PWpBda5YOd6QUpfH8T1Rje/B46fQ7ZDk9DkXJUWen+CreeYxc0/v B+k/+N25muZKTPnjz5DdeplQJRc420r+pA/SNfZQItWk95uVkms9aVZds2e3MxlkycIW odd0eOHVdf4gIso31pxjhazajkH67sFYSk7OInCmyTPp371Thskudm19ydaennOr2M5L ThIQ7pbT+y8S0rh9yPGbupCC8MwZb7WOEEDfIQ5y6Jl+izbK/iGtiVpAxi0TCjuWXrfp DwMg== X-Gm-Message-State: AGi0PuZmOSJxka6Z6Eok7LDEi4xYBFte5h/mqqYZe1euo50FSS86Wc2q /4d7F5pBGJZRlvDDUcegcolZ84uPKOQ= X-Google-Smtp-Source: APiQypLxlGahom1Fx+bgTO3EuSlreK4hsXvlaGqCGW6kOA1q1pVEJueEXkYQ2Mvqd9MSUdfZBx4sWA== X-Received: by 2002:ad4:4e65:: with SMTP id ec5mr10987369qvb.32.1588474020486; Sat, 02 May 2020 19:47:00 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.46.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:46:59 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 17/21] riscv: Try to get cpu frequency from a "clocks" node if it exists Date: Sat, 2 May 2020 22:46:33 -0400 Message-Id: <20200503024637.327733-18-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean Instead of always using the "clock-frequency" property to determine cpu frequency, try using a clock in "clocks" if it exists. This patch also fixes a bug where there could be spurious higher frequencies if sizeof(u32) != sizeof(ulong). Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- This patch was previously sumbitted on its own as https://patchwork.ozlabs.org/patch/1232420/ This patch is the combination of the patches https://patchwork.ozlabs.org/patch/1223933/ https://patchwork.ozlabs.org/patch/1224957/ "riscv: Fix incorrect cpu frequency on RV64" "riscv: Try to get cpu frequency from device tree" Changes in v5: - Include linux/err.h explicitly - Reword commit message Changes in v4: - New drivers/cpu/riscv_cpu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 28ad0aa30f..c6ed060abc 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -3,12 +3,14 @@ * Copyright (C) 2018, Bin Meng */ +#include #include #include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -27,9 +29,24 @@ static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size) static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) { + int ret; + struct clk clk; const char *mmu; - dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); + /* Zero out the frequency, in case sizeof(ulong) != sizeof(u32) */ + info->cpu_freq = 0; + + /* First try getting the frequency from the assigned clock */ + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_get_rate(&clk); + if (!IS_ERR_VALUE(ret)) + info->cpu_freq = ret; + clk_free(&clk); + } + + if (!info->cpu_freq) + dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); mmu = dev_read_string(dev, "mmu-type"); if (!mmu) From patchwork Sun May 3 02:46:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281852 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=s+nXu2KN; 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 49F9TV2hBnz9sRf for ; Sun, 3 May 2020 12:50:38 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E1342822D0; Sun, 3 May 2020 04:47:17 +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="s+nXu2KN"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 58FAF82249; Sun, 3 May 2020 04:47:06 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) (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 A652381EE3 for ; Sun, 3 May 2020 04:47:02 +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-x842.google.com with SMTP id g26so7330630qtv.13 for ; Sat, 02 May 2020 19:47:02 -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=1jZ2kzlYLR00oLaGWybJTO3LbBf53OaY9p1pQ+a8uoc=; b=s+nXu2KNeSAj7e2y5jXyzbjy58LYEcLdUtgU7cGiJ3YhUOSGoOtkTrZnadMcEWrgRW qtheS1IfVuQaR4gmRI1H0tTPXLYPmdYQ+qiUGWBKQkFFJbkt/Bt3WBi8jyhUkzPeP7IQ dWBCvgtwjSyQXHMcNVZffQrGoyQaNImxaMmfleY/8b12qS0+M8aCwSXNjmHWaOWiQYQ4 zcrHhJjuc1+YsJy/Re2xDDiGqk3fX1hPG/NxGKug3r94Sy1RKCqx6PGSfllI39GAkCNN IxuewIUB/gAZ441C8REBX0uf0jiKtCm9+mvbwDDPRoDVRzyJkL0+nMisMxKkbGcPWL6M fMIw== 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=1jZ2kzlYLR00oLaGWybJTO3LbBf53OaY9p1pQ+a8uoc=; b=HEw3OvNPRcewYKRqdCQZsNJlNqiszGLnXV3AeM+XfuINcWP9YPud7/iWgAN7ZsYPGq N1AtHeCumTHe/NXAAqfOuQeqomGqmMQyUVBD6tYsp5E0+AxRo5l/SxovB8gwgrp/kSWI vB5vQOuGqIuWNc/essyw8eo/2WtaMNWfNTpugcqqMXbNZY0+X9kBj0LUgFVLKwN48rql B02Idoe1tuJUDrhcxCe4+ZTVvBD73bEfLkXSP1oFENkheU1KVs2qagw0vO9ln+6+n6iS TvVXEMhu4AL88WjitFcJKmLk+898NrnYr0Bf2C8czANIjWIS9kGDhdAM74MEcoVLspI4 EdkA== X-Gm-Message-State: AGi0PuZdzB3cDpKkQf6upydm5RKklp+BV3ZfkogBbwZfGaef7mcCSXaz hDn8fmeX7InHvRBAf959JGpzZAOnyNQ= X-Google-Smtp-Source: APiQypJG/ba5WmSXzHyCbT3MHGWUVd+73uED4Uudmy24OB4Z+PDfFICXOp4lAuwk9L3hs3Bf1fwQZQ== X-Received: by 2002:ac8:3a83:: with SMTP id x3mr10686325qte.44.1588474021390; Sat, 02 May 2020 19:47:01 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.47.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:47:00 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 18/21] riscv: Enable cpu clock if it is present Date: Sat, 2 May 2020 22:46:34 -0400 Message-Id: <20200503024637.327733-19-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean The cpu clock is probably already enabled if we are executing code (though we could be executing from a different core). This patch prevents the cpu clock or its parents from being disabled. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- This patch was previously submitted on its own as https://patchwork.ozlabs.org/patch/1232420/ Changes in v4: - New drivers/cpu/riscv_cpu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index c6ed060abc..9ce58695aa 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018, Bin Meng + * Copyright (C) 2020, Sean Anderson */ #include @@ -117,6 +118,24 @@ static int riscv_cpu_bind(struct udevice *dev) return 0; } +static int riscv_cpu_probe(struct udevice *dev) +{ + int ret = 0; + struct clk clk; + + /* Get a clock if it exists */ + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return 0; + + ret = clk_enable(&clk); + clk_free(&clk); + if (ret == -ENOSYS || ret == -ENOTSUPP) + return 0; + else + return ret; +} + static const struct cpu_ops riscv_cpu_ops = { .get_desc = riscv_cpu_get_desc, .get_info = riscv_cpu_get_info, @@ -133,6 +152,7 @@ U_BOOT_DRIVER(riscv_cpu) = { .id = UCLASS_CPU, .of_match = riscv_cpu_ids, .bind = riscv_cpu_bind, + .probe = riscv_cpu_probe, .ops = &riscv_cpu_ops, .flags = DM_FLAG_PRE_RELOC, }; From patchwork Sun May 3 02:46:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281856 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=t1UbhSWV; 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 49F9VS1q71z9sRf for ; Sun, 3 May 2020 12:51:28 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3F771822E7; Sun, 3 May 2020 04:47:23 +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="t1UbhSWV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 86907822AD; Sun, 3 May 2020 04:47:10 +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=ham autolearn_force=no version=3.4.2 Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) (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 9DFFE81EA2 for ; Sun, 3 May 2020 04:47:04 +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-x744.google.com with SMTP id f83so5812396qke.13 for ; Sat, 02 May 2020 19:47:04 -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=sjK9o3Qtq7EfyjSHr3bYtU6coWJ3r+VuJQeYRHs1yGk=; b=t1UbhSWVUguZ6nSaqSGuESzyfGstvYP9v6KkfPxkOLjEohuuHQQ8xwq2xiInhjlLT/ nB+heq5fWoucq6xD0KXv3py8Umg5t7vsDkSPSBJcJYHZiiKX8/vBZYtISc7XfJ5EWkJy wFDuYFIPUDaCIEeitJlPoj6NEPgykxR+FqMwF/m3iJuMDo6leldE7FLtxzFZiiu8uIox 3PlRpR8Y9DlZVZeaRjaT1vuRQ5lCbg6HAO+9N+FPyiaJpgUrSy5SVpSGdB+6mzGbc3Hq gq560qOHWRPFtLil1EGDnZ/Kn96wluVBOiMKwsWoWKRPXygEsOpm24TGUCvavMT3A4pX RdQA== 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=sjK9o3Qtq7EfyjSHr3bYtU6coWJ3r+VuJQeYRHs1yGk=; b=SB1mFrVGhOk2FhLMcYo2wW8+la0lz6/Qg/7sK7VFh88qF8Ezh9BvJr9O5EeDmkk9zC HrEbjQrMlWgUAoB258uQd/avDRVl4QGu5cxzlwnFnmtp8c3GjxXwyIQNS6YZ8tS2yDTH fRPU7/Kn3zJTzXRFwcJJ4ujWDntlfkfyi1DACB5oy8Rec0JpPvzD02FRYqDoAfuysIsH B2pexvGBw8z4mqKMHxjmtY5BeJEC1Vb8DaoFETiMmDpKLY2Do2V5hLP0aidGoWRQ5QPR wQX82xLshkvQhT6vqUhf4sC4SyAujv1+c7gKhBKTfMjdCs7IaneKozCjJxlF8+1RL2RM j4+A== X-Gm-Message-State: AGi0PuYvjYGLWXeMmjvV/62FYjXYjuXFQjp+9XajFK0JCa53NKSQ1SOq cCmLN//8eAH9fRj1DAcOf9DRNtfQfZM= X-Google-Smtp-Source: APiQypKcbN230Ri39aFULRGXhFF6L4FwzsfPKLvrAt53hk54p6bBoiq9H64m2Wx2l5D5xIJ9GyURVQ== X-Received: by 2002:a37:4bd4:: with SMTP id y203mr10485453qka.413.1588474022567; Sat, 02 May 2020 19:47:02 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.47.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:47:01 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 19/21] riscv: Add device tree for K210 and Sipeed Maix BitM Date: Sat, 2 May 2020 22:46:35 -0400 Message-Id: <20200503024637.327733-20-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean Where possible, I have tried to find compatible drivers based on the layout of registers. However, many devices remain untested. All untested devices have been left disabled, but some tentative properties (such as compatible strings, and clocks, interrupts, and resets properties) have been added. Signed-off-by: Sean Anderson --- Changes in v7: - Move clocks node to be just before soc node, matching linux's tree - Merge memory nodes into one node with different registers - Add aliases for uclasses which use them - Fix size of clint Changes in v6: - Remove spi, gpio, pinmux, wdt, and led bindings - Use consistent capitalization for hex digits Changes in v5: - Add more compatible strings - Add cache line size - Document CPUs as rocket cores - Flesh out the gpio devices - Add ports for audio and video devices - Add fpioa pinctrl support - Configure pins for MMC on SPI1 - Enable MMC - Fix a couple uart properties (Thanks laanwj) - Reorder ram now that relocation is handled with CONFIG_SYS defines - Enable WDT - Add pinctrl properties - Add gpio support - Add led support - Add assorted AV bindings - Add compatible strings for ram - Use GPIO-based CS for MMC - Limit SPI flash to 50 MHz Changes in v4: - Set regs sizes to full address range - Remove clock-frequency property from cpus - Add spi-max-frequency to spi devices from documentation - Add more compatible strings for each device - Add AI ram as a separate memory bank. Its clock is disabled on boot, and it cannot be accessed - Reorder memory banks so u-boot relocates higher, leaving more room to load boot images - Add designware ssi CTRL0 field shifts to spi devices - Don't enable the MMC slot - Update copyright - Lint Changes in v3: - Move this patch to the end of the series - Add a max frequency for spi3 - Remov unused compatible strings from spi-flash@0 - Add s and u to isa string - Fix mmu-type - Remove cache-line size since it is unused (in u-boot) and undocumented (upstream) - Add timer interrupts to clint0 - Round up various registers - Add riscv,max-priority to plic - Add apb* busses, since they have clocks which need to be enabled to access their devices - Change uart compatible strings to "snps,dw-apb-uart", since that appears to match their registers - Add compatible string for wdt* - Add system reset device under sysctl - Add reset device under sysctl Changes in v2: - Model changed to "Sipeed Maix Bit" to match file name - Value of stdout-path fixed - SD card slot compatible changed to "mmc-spi-slot" - "jedec,spi-nor" added to spi flash compatible list - Aliases for spi busses added - timebase-frequency divided by 50 to match timer speed - cpu-frequency renamed to clock-frequency - CPUX_intc restyled to cpuX_intc - "kendryte,k210-soc" added to soc compatible list for future-proofing - PLIC handle renamed to plic0 from pic0 - K210_RST_SOC removed from sysrst, due to not being located in the reset register - K210_RST_* numbers changed to match their bit offset within the reset register - gpio_controller restyled to gpio-controller - Added a second clock to the dma binding to match what the driver expects - Changed "snps,designware-spi" compatible string to "snps,dw-apb-ssi" to match the correct driver - Added a name to the spi clocks - Added reg-io-width property to spi bindings - Assigned a default parent to K210_CLK_SPI3 - Removed assigned clocks for ACLK and PLLs - Removed u-boot,dm-pre-reloc bindings arch/riscv/dts/Makefile | 1 + arch/riscv/dts/k210-maix-bit.dts | 47 ++ arch/riscv/dts/k210.dtsi | 594 ++++++++++++++++++++++++ include/dt-bindings/reset/k210-sysctl.h | 38 ++ 4 files changed, 680 insertions(+) create mode 100644 arch/riscv/dts/k210-maix-bit.dts create mode 100644 arch/riscv/dts/k210.dtsi create mode 100644 include/dt-bindings/reset/k210-sysctl.h diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index 4f30e6936f..3a6f96c67d 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -2,6 +2,7 @@ dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb +dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb targets += $(dtb-y) diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts new file mode 100644 index 0000000000..5b32c5fd5f --- /dev/null +++ b/arch/riscv/dts/k210-maix-bit.dts @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ + +/dts-v1/; + +#include "k210.dtsi" + +#include + +/ { + model = "Sipeed Maix Bit 2.0"; + compatible = "sipeed,maix-bitm", "sipeed,maix-bit", "kendryte,k210"; + + chosen { + stdout-path = "serial0:115200"; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + status = "disabled"; + + simple-audio-card,cpu { + sound-dai = <&i2s0 0>; + }; + + simple-audio-card,codec { + sound-dai = <&mic>; + }; + }; + + mic: mic { + #sound-dai-cells = <0>; + compatible = "memsensing,msm61s4030h0"; + status = "disabled"; + }; +}; + +&uarths0 { + status = "okay"; +}; + +&i2s0 { + #sound-dai-cells = <1>; +}; diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi new file mode 100644 index 0000000000..2546c7d4e0 --- /dev/null +++ b/arch/riscv/dts/k210.dtsi @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ + +#include +#include +#include + +/ { + /* + * Although the K210 is a 64-bit CPU, the address bus is only 32-bits + * wide, and the upper half of all addresses is ignored. + */ + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210"; + + aliases { + dma0 = &dmac0; + gpio0 = &gpio0; + gpio1 = &gpio1_0; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + pinctrl0 = &fpioa; + serial0 = &uarths0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; + timer0 = &timer0; + timer1 = &timer1; + timer2 = &timer2; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <7800000>; + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "kendryte,k210", "sifive,rocket0", "riscv"; + reg = <0>; + riscv,isa = "rv64imafdgc"; + mmu-type = "sv39"; + i-cache-block-size = <64>; + i-cache-size = <0x8000>; + d-cache-block-size = <64>; + d-cache-size = <0x8000>; + clocks = <&sysclk K210_CLK_CPU>; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "kendryte,k210", "sifive,rocket0", "riscv"; + reg = <1>; + riscv,isa = "rv64imafdgc"; + mmu-type = "sv39"; + i-cache-block-size = <64>; + i-cache-size = <0x8000>; + d-cache-block-size = <64>; + d-cache-size = <0x8000>; + clocks = <&sysclk K210_CLK_CPU>; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + + sram: memory@80000000 { + device_type = "memory"; + compatible = "kendryte,k210-sram"; + reg = <0x80000000 0x400000>, + <0x80400000 0x200000>, + <0x80600000 0x200000>; + reg-names = "sram0", "sram1", "airam"; + clocks = <&sysclk K210_CLK_SRAM0>, + <&sysclk K210_CLK_SRAM1>, + <&sysclk K210_CLK_PLL1>; + clock-names = "sram0", "sram1", "airam"; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + ai_reserved: ai@80600000 { + reg = <0x80600000 0x200000>; + reusable; + }; + }; + + clocks { + in0: osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210-soc", "simple-bus"; + ranges; + interrupt-parent = <&plic0>; + + debug0: debug@0 { + compatible = "kendryte,k210-debug", "riscv,debug"; + reg = <0x0 0x1000>; + }; + + rom0: nvmem@1000 { + reg = <0x1000 0x1000>; + read-only; + }; + + clint0: interrupt-controller@2000000 { + #interrupt-cells = <1>; + compatible = "kendryte,k210-clint", "riscv,clint0"; + reg = <0x2000000 0xC000>; + interrupt-controller; + interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, + <&cpu1_intc 3>, <&cpu1_intc 7>; + clocks = <&sysclk K210_CLK_CPU>; + }; + + plic0: interrupt-controller@C000000 { + #interrupt-cells = <1>; + compatible = "kendryte,k210-plic", "riscv,plic0"; + reg = <0xC000000 0x4000000>; + interrupt-controller; + interrupts-extended = <&cpu0_intc 9>, <&cpu0_intc 11>, + <&cpu1_intc 9>, <&cpu1_intc 11>; + riscv,ndev = <65>; + riscv,max-priority = <7>; + }; + + uarths0: serial@38000000 { + compatible = "kendryte,k210-uarths", "sifive,uart0"; + reg = <0x38000000 0x1000>; + interrupts = <33>; + clocks = <&sysclk K210_CLK_CPU>; + status = "disabled"; + }; + + gpio0: gpio-controller@38001000 { + #interrupt-cells = <2>; + #gpio-cells = <2>; + compatible = "kendryte,k210-gpiohs", "sifive,gpio0"; + reg = <0x38001000 0x1000>; + interrupt-controller; + interrupts = <34 35 36 37 38 39 40 41 + 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 + 58 59 60 61 62 63 64 65>; + gpio-controller; + ngpios = <32>; + status = "disabled"; + }; + + kpu0: kpu@40800000 { + compatible = "kendryte,k210-kpu"; + reg = <0x40800000 0xc00000>; + interrupts = <25>; + clocks = <&sysclk K210_CLK_AI>; + memory-region = <&ai_reserved>; + status = "disabled"; + }; + + fft0: fft@42000000 { + compatible = "kendryte,k210-fft"; + reg = <0x42000000 0x400000>; + interrupts = <26>; + clocks = <&sysclk K210_CLK_FFT>; + resets = <&sysrst K210_RST_FFT>; + status = "disabled"; + }; + + dmac0: dma-controller@50000000 { + compatible = "kendryte,k210-dmac", "snps,axi-dma-1.01a"; + reg = <0x50000000 0x1000>; + interrupts = <27 28 29 30 31 32>; + clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>; + clock-names = "core-clk", "cfgr-clk"; + resets = <&sysrst K210_RST_DMA>; + dma-channels = <6>; + snps,dma-masters = <2>; + snps,data-width = <5>; + snps,block-size = <0x400000 0x400000 0x400000 + 0x400000 0x400000 0x400000>; + snps,axi-max-burst-len = <256>; + status = "disabled"; + }; + + apb0: bus@50200000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210-apb", "simple-pm-bus"; + ranges; + clocks = <&sysclk K210_CLK_APB0>; + + gpio1: gpio-controller@50200000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "kendryte,k210-gpio", + "snps,dw-apb-gpio"; + reg = <0x50200000 0x80>; + clocks = <&sysclk K210_CLK_GPIO>; + resets = <&sysrst K210_RST_GPIO>; + status = "disabled"; + + gpio1_0: gpio1@0 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "snps,dw-apb-gpio-port"; + reg = <0>; + interrupt-controller; + interrupts = <23>; + gpio-controller; + snps,nr-gpios = <8>; + }; + }; + + uart1: serial@50210000 { + compatible = "kendryte,k210-uart", + "snps,dw-apb-uart"; + reg = <0x50210000 0x100>; + interrupts = <11>; + clocks = <&sysclk K210_CLK_UART1>; + resets = <&sysrst K210_RST_UART1>; + reg-io-width = <4>; + reg-shift = <2>; + dcd-override; + dsr-override; + cts-override; + ri-override; + status = "disabled"; + }; + + uart2: serial@50220000 { + compatible = "kendryte,k210-uart", + "snps,dw-apb-uart"; + reg = <0x50220000 0x100>; + interrupts = <12>; + clocks = <&sysclk K210_CLK_UART2>; + resets = <&sysrst K210_RST_UART2>; + reg-io-width = <4>; + reg-shift = <2>; + dcd-override; + dsr-override; + cts-override; + ri-override; + status = "disabled"; + }; + + uart3: serial@50230000 { + compatible = "kendryte,k210-uart", + "snps,dw-apb-uart"; + reg = <0x50230000 0x100>; + interrupts = <13>; + clocks = <&sysclk K210_CLK_UART3>; + resets = <&sysrst K210_RST_UART3>; + reg-io-width = <4>; + reg-shift = <2>; + dcd-override; + dsr-override; + cts-override; + ri-override; + status = "disabled"; + }; + + spi2: spi@50240000 { + compatible = "kendryte,k120-spislave", + "snps,dw-apb-ssi"; + spi-slave; + reg = <0x50240000 0x100>; + interrupts = <2>; + clocks = <&sysclk K210_CLK_SPI2>; + resets = <&sysrst K210_RST_SPI2>; + spi-max-frequency = <25000000>; + status = "disabled"; + }; + + i2s0: i2s@50250000 { + compatible = "kendryte,k210-i2s", + "snps,designware-i2s"; + reg = <0x50250000 0x200>; + interrupts = <5>; + clocks = <&sysclk K210_CLK_I2S0>; + clock-names = "i2sclk"; + resets = <&sysrst K210_RST_I2S0>; + status = "disabled"; + }; + + apu0: sound@520250200 { + compatible = "kendryte,k210-apu"; + reg = <0x50250200 0x200>; + status = "disabled"; + }; + + i2s1: i2s@50260000 { + compatible = "kendryte,k210-i2s", + "snps,designware-i2s"; + reg = <0x50260000 0x200>; + interrupts = <6>; + clocks = <&sysclk K210_CLK_I2S1>; + clock-names = "i2sclk"; + resets = <&sysrst K210_RST_I2S1>; + status = "disabled"; + }; + + i2s2: i2s@50270000 { + compatible = "kendryte,k210-i2s", + "snps,designware-i2s"; + reg = <0x50270000 0x200>; + interrupts = <7>; + clocks = <&sysclk K210_CLK_I2S2>; + clock-names = "i2sclk"; + resets = <&sysrst K210_RST_I2S2>; + status = "disabled"; + }; + + i2c0: i2c@50280000 { + compatible = "kendryte,k210-i2c", + "snps,designware-i2c"; + reg = <0x50280000 0x100>; + interrupts = <8>; + clocks = <&sysclk K210_CLK_I2C0>; + resets = <&sysrst K210_RST_I2C0>; + status = "disabled"; + }; + + i2c1: i2c@50290000 { + compatible = "kendryte,k210-i2c", + "snps,designware-i2c"; + reg = <0x50290000 0x100>; + interrupts = <9>; + clocks = <&sysclk K210_CLK_I2C1>; + resets = <&sysrst K210_RST_I2C1>; + status = "disabled"; + }; + + i2c2: i2c@502A0000 { + compatible = "kendryte,k210-i2c", + "snps,designware-i2c"; + reg = <0x502A0000 0x100>; + interrupts = <10>; + clocks = <&sysclk K210_CLK_I2C2>; + resets = <&sysrst K210_RST_I2C2>; + status = "disabled"; + }; + + fpioa: pinmux@502B0000 { + compatible = "kendryte,k210-fpioa"; + reg = <0x502B0000 0x100>; + clocks = <&sysclk K210_CLK_FPIOA>; + resets = <&sysrst K210_RST_FPIOA>; + status = "disabled"; + }; + + sha256: sha256@502C0000 { + compatible = "kendryte,k210-sha256"; + reg = <0x502C0000 0x100>; + clocks = <&sysclk K210_CLK_SHA>; + resets = <&sysrst K210_RST_SHA>; + status = "disabled"; + }; + + timer0: timer@502D0000 { + compatible = "kendryte,k210-timer", + "snps,dw-apb-timer"; + reg = <0x502D0000 0x100>; + interrupts = <14 15>; + clocks = <&sysclk K210_CLK_TIMER0>; + clock-names = "timer"; + resets = <&sysrst K210_RST_TIMER0>; + status = "disabled"; + }; + + timer1: timer@502E0000 { + compatible = "kendryte,k210-timer", + "snps,dw-apb-timer"; + reg = <0x502E0000 0x100>; + interrupts = <16 17>; + clocks = <&sysclk K210_CLK_TIMER1>; + clock-names = "timer"; + resets = <&sysrst K210_RST_TIMER1>; + status = "disabled"; + }; + + timer2: timer@502F0000 { + compatible = "kendryte,k210-timer", + "snps,dw-apb-timer"; + reg = <0x502F0000 0x100>; + interrupts = <18 19>; + clocks = <&sysclk K210_CLK_TIMER2>; + clock-names = "timer"; + resets = <&sysrst K210_RST_TIMER2>; + status = "disabled"; + }; + }; + + apb1: bus@50400000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210-apb", "simple-pm-bus"; + ranges; + clocks = <&sysclk K210_CLK_APB1>; + + wdt0: watchdog@50400000 { + compatible = "kendryte,k210-wdt", "snps,dw-wdt"; + reg = <0x50400000 0x100>; + interrupts = <21>; + clocks = <&sysclk K210_CLK_WDT0>; + resets = <&sysrst K210_RST_WDT0>; + status = "disabled"; + }; + + wdt1: watchdog@50410000 { + compatible = "kendryte,k210-wdt", "snps,dw-wdt"; + reg = <0x50410000 0x100>; + interrupts = <22>; + clocks = <&sysclk K210_CLK_WDT1>; + resets = <&sysrst K210_RST_WDT1>; + status = "disabled"; + }; + + otp0: nvmem@50420000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210-otp"; + reg = <0x50420000 0x100>, + <0x88000000 0x20000>; + reg-names = "reg", "mem"; + clocks = <&sysclk K210_CLK_ROM>; + resets = <&sysrst K210_RST_ROM>; + read-only; + status = "disabled"; + + /* Bootloader */ + firmware@00000 { + reg = <0x00000 0xC200>; + }; + + /* + * config string as described in RISC-V + * privileged spec 1.9 + */ + config-1-9@1c000 { + reg = <0x1C000 0x1000>; + }; + + /* + * Device tree containing only registers, + * interrupts, and cpus + */ + fdt@1d000 { + reg = <0x1D000 0x2000>; + }; + + /* CPU/ROM credits */ + credits@1f000 { + reg = <0x1F000 0x1000>; + }; + }; + + dvp0: camera@50430000 { + compatible = "kendryte,k210-dvp"; + reg = <0x50430000 0x100>; + interrupts = <24>; + clocks = <&sysclk K210_CLK_DVP>; + resets = <&sysrst K210_RST_DVP>; + status = "disabled"; + }; + + sysctl: syscon@50440000 { + compatible = "kendryte,k210-sysctl", + "syscon", "simple-mfd"; + reg = <0x50440000 0x100>; + reg-io-width = <4>; + + sysclk: clock-controller { + #clock-cells = <1>; + compatible = "kendryte,k210-clk"; + clocks = <&in0>; + }; + + sysrst: reset-controller { + compatible = "kendryte,k210-rst", + "syscon-reset"; + #reset-cells = <1>; + regmap = <&sysctl>; + offset = ; + mask = <0x27FFFFFF>; + assert-high = <1>; + }; + + reboot { + compatible = "syscon-reboot"; + regmap = <&sysctl>; + offset = ; + mask = <1>; + value = <1>; + }; + }; + + aes0: aes@50450000 { + compatible = "kendryte,k210-aes"; + reg = <0x50450000 0x100>; + clocks = <&sysclk K210_CLK_AES>; + resets = <&sysrst K210_RST_AES>; + status = "disabled"; + }; + + rtc: rtc@50460000 { + compatible = "kendryte,k210-rtc"; + reg = <0x50460000 0x100>; + clocks = <&in0>; + resets = <&sysrst K210_RST_RTC>; + interrupts = <20>; + status = "disabled"; + }; + }; + + apb2: bus@52000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "kendryte,k210-apb", "simple-pm-bus"; + ranges; + clocks = <&sysclk K210_CLK_APB2>; + + spi0: spi@52000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "kendryte,k210-spi", + "snps,dw-apb-ssi"; + reg = <0x52000000 0x100>; + interrupts = <1>; + clocks = <&sysclk K210_CLK_SPI0>; + clock-names = "ssi_clk"; + resets = <&sysrst K210_RST_SPI0>; + spi-max-frequency = <25000000>; + num-cs = <4>; + reg-io-width = <4>; + status = "disabled"; + }; + + spi1: spi@53000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "kendryte,k210-spi", + "snps,dw-apb-ssi"; + reg = <0x53000000 0x100>; + interrupts = <2>; + clocks = <&sysclk K210_CLK_SPI1>; + clock-names = "ssi_clk"; + resets = <&sysrst K210_RST_SPI1>; + spi-max-frequency = <25000000>; + num-cs = <4>; + reg-io-width = <4>; + status = "disabled"; + }; + + spi3: spi@54000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "kendryte,k210-spi", + "snps,dw-apb-ssi"; + reg = <0x54000000 0x200>; + interrupts = <4>; + clocks = <&sysclk K210_CLK_SPI3>; + clock-names = "ssi_clk"; + resets = <&sysrst K210_RST_SPI3>; + /* Could possibly go up to 200 MHz */ + spi-max-frequency = <100000000>; + num-cs = <4>; + reg-io-width = <4>; + status = "disabled"; + }; + }; + }; +}; diff --git a/include/dt-bindings/reset/k210-sysctl.h b/include/dt-bindings/reset/k210-sysctl.h new file mode 100644 index 0000000000..12bb3880d9 --- /dev/null +++ b/include/dt-bindings/reset/k210-sysctl.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Sean Anderson + */ + +#ifndef RESET_K210_SYSCTL_H +#define RESET_K210_SYSCTL_H + +#define K210_RST_ROM 0 +#define K210_RST_DMA 1 +#define K210_RST_AI 2 +#define K210_RST_DVP 3 +#define K210_RST_FFT 4 +#define K210_RST_GPIO 5 +#define K210_RST_SPI0 6 +#define K210_RST_SPI1 7 +#define K210_RST_SPI2 8 +#define K210_RST_SPI3 9 +#define K210_RST_I2S0 10 +#define K210_RST_I2S1 11 +#define K210_RST_I2S2 12 +#define K210_RST_I2C0 13 +#define K210_RST_I2C1 14 +#define K210_RST_I2C2 15 +#define K210_RST_UART1 16 +#define K210_RST_UART2 17 +#define K210_RST_UART3 18 +#define K210_RST_AES 19 +#define K210_RST_FPIOA 20 +#define K210_RST_TIMER0 21 +#define K210_RST_TIMER1 22 +#define K210_RST_TIMER2 23 +#define K210_RST_WDT0 24 +#define K210_RST_WDT1 25 +#define K210_RST_SHA 26 +#define K210_RST_RTC 29 + +#endif /* RESET_K210_SYSCTL_H */ From patchwork Sun May 3 02:46:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281854 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=COeEvgwI; 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 49F9Tx6D9Pz9sRf for ; Sun, 3 May 2020 12:51:01 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 70FB0822DD; Sun, 3 May 2020 04:47:20 +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="COeEvgwI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5664B822AB; Sun, 3 May 2020 04:47:09 +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,URIBL_BLOCKED, WEIRD_QUOTING autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x843.google.com (mail-qt1-x843.google.com [IPv6:2607:f8b0:4864:20::843]) (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 3C3D081F0B for ; Sun, 3 May 2020 04:47:05 +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-x843.google.com with SMTP id g16so7199996qtp.11 for ; Sat, 02 May 2020 19:47:05 -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=9nnKxz33zdakfVPLuvIl9m+uVRCbJzvTS8BH0B2Z62c=; b=COeEvgwIevic0qdQsqOesuf7GS8zqZAwD/gwdaIWBO3Ufb+yOOPBhmRt9rydifXSkG fL9SRxCJk+19sh4F+dPvTY2sRNrjzUY2bVR9kKy00NBKezOt9s2MFiHd39lvNYS+FmnN oE9ORrCKFFC0Gxnv/1m1HxyyAeFJpIz4BfQOz5VX4eRpUbMlva/x33vqJewkus/A2dV6 a7Gd81NMxv8AmEaRv1CmddiSHRjIB4xtJuVeXSst+36vjXso7gbpMivhEsCDl8lmZt68 O4pjlvOKA9MFEPgmxkpE3vyUCJB5HovqpAJiACiY1FWzt5ugcGMNE7I7+uSU1IHvtvsz ZGVw== 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=9nnKxz33zdakfVPLuvIl9m+uVRCbJzvTS8BH0B2Z62c=; b=YossBDciL8F9d8FOzwsyZKF/vOG++vudFWnKMNhX+OEwbtszzJ5MnTcTKe2OeALvUO hwknPZkdQj6qmfzthMcpP6eLMH/R/9EhTq5mLnSl3+jAbC5HwteulY6bx6Ek+xWXwp5+ 7crXBbOyP5/mwls5wyN0YkdheOKrzmSf07rCtDzKAU7leEVTp1M5OCsZbLMmOOmdeMjO sGakDzL3BIWWBBO09RxcVsSxvNJnRu/bqC01Uo+wywAbVgsTlO7Vc79A7m5GU39G1H5c M1nPz8+q+CHxa02Gr3eGyVUmCziJYbmiyLWB4G6QNHRqa2P7aZ5VyDcveoFczzriuh2V NLVg== X-Gm-Message-State: AGi0PuY/D4OovjvoiLPMgG42qvJ3dQJ5v7u8XBPc57naVzIbcoLlu0Bx JT9i+lsNLi3i7OeFnIHrkTs8bHub9vY= X-Google-Smtp-Source: APiQypK+YRSpYjIpOVaKJfSGsWBJauqJdKGfJBj0Syjkz2qHik++S0hPGiKpqgcRznhOBWzv/5vLSQ== X-Received: by 2002:ac8:4983:: with SMTP id f3mr10886390qtq.343.1588474023504; Sat, 02 May 2020 19:47:03 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.47.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:47:03 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 20/21] doc: riscv: Add documentation for Sipeed Maix Bit Date: Sat, 2 May 2020 22:46:36 -0400 Message-Id: <20200503024637.327733-21-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean This patch adds documentation for the Sipeed Maix bit, and more generally for the Kendryte K210 processor. Signed-off-by: Sean Anderson --- Changes in v9: - Mark dts code block as "none" explicitly Changes in v7: - Split off into its own patch - Fix size of clint doc/board/index.rst | 1 + doc/board/sipeed/index.rst | 9 ++ doc/board/sipeed/maix.rst | 298 +++++++++++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 doc/board/sipeed/index.rst create mode 100644 doc/board/sipeed/maix.rst diff --git a/doc/board/index.rst b/doc/board/index.rst index 51a2ae6f28..dcc47c5a21 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -16,6 +16,7 @@ Board-specific doc renesas/index rockchip/index sifive/index + sipeed/index st/index toradex/index xilinx/index diff --git a/doc/board/sipeed/index.rst b/doc/board/sipeed/index.rst new file mode 100644 index 0000000000..3518e2d8f4 --- /dev/null +++ b/doc/board/sipeed/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Sipeed +====== + +.. toctree:: + :maxdepth: 2 + + maix diff --git a/doc/board/sipeed/maix.rst b/doc/board/sipeed/maix.rst new file mode 100644 index 0000000000..06e0008b9f --- /dev/null +++ b/doc/board/sipeed/maix.rst @@ -0,0 +1,298 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (C) 2020 Sean Anderson + +Maix Bit +======== + +Several of the Sipeed Maix series of boards cotain the Kendryte K210 processor, +a 64-bit RISC-V CPU. This processor contains several peripherals to accelerate +neural network processing and other "ai" tasks. This includes a "KPU" neural +network processor, an audio processor supporting beamforming reception, and a +digital video port supporting capture and output at VGA resolution. Other +peripherals include 8M of SRAM (accessible with and without caching); remappable +pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA controller; +and I2C, I2S, and SPI controllers. Maix peripherals vary, but include spi flash; +on-board usb-serial bridges; ports for cameras, displays, and sd cards; and +ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is supported, but +the boards are fairly similar. + +Documentation for Maix boards is available from +`Sipeed's website `_. +Documentation for the Kendryte K210 is available from +`Kendryte's website `_. However, hardware +details are rather lacking, so most technical reference has been taken from the +`standalone sdk `_. + +Build and boot steps +-------------------- + +To build u-boot, run + +.. code-block:: none + + make sipeed_maix_bitm_defconfig + make CROSS_COMPILE= + +To flash u-boot to a maix bit, run + +.. code-block:: none + + kflash -tp /dev/ -B bit_mic u-boot-dtb.bin + +Boot output should look like the following: + +.. code-block:: none + + U-Boot 2020.04-rc2-00087-g2221cc09c1-dirty (Feb 28 2020 - 13:53:09 -0500) + + DRAM: 8 MiB + In: serial@38000000 + Out: serial@38000000 + Err: serial@38000000 + => + +Loading Images +^^^^^^^^^^^^^^ + +To load a kernel, transfer it over serial. + +.. code-block:: none + + => loady 80000000 1500000 + ## Switch baudrate to 1500000 bps and press ENTER ... + + *** baud: 1500000 + + *** baud: 1500000 *** + ## Ready for binary (ymodem) download to 0x80000000 at 1500000 bps... + C + *** file: loader.bin + $ sz -vv loader.bin + Sending: loader.bin + Bytes Sent:2478208 BPS:72937 + Sending: + Ymodem sectors/kbytes sent: 0/ 0k + Transfer complete + + *** exit status: 0 *** + ## Total Size = 0x0025d052 = 2478162 Bytes + ## Switch baudrate to 115200 bps and press ESC ... + + *** baud: 115200 + + *** baud: 115200 *** + => + +Running Programs +^^^^^^^^^^^^^^^^ + +Binaries +"""""""" + +To run a bare binary, use the ``go`` command: + +.. code-block:: none + + => loady + ## Ready for binary (ymodem) download to 0x80000000 at 115200 bps... + C + *** file: ./examples/standalone/hello_world.bin + $ sz -vv ./examples/standalone/hello_world.bin + Sending: hello_world.bin + Bytes Sent: 4864 BPS:649 + Sending: + Ymodem sectors/kbytes sent: 0/ 0k + Transfer complete + + *** exit status: 0 *** + (CAN) packets, 5 retries + ## Total Size = 0x000012f8 = 4856 Bytes + => go 80000000 + ## Starting application at 0x80000000 ... + Example expects ABI version 9 + Actual U-Boot ABI version 9 + Hello World + argc = 1 + argv[0] = "80000000" + argv[1] = "" + Hit any key to exit ... + +Legacy Images +""""""""""""" + +To run legacy images, use the ``bootm`` command: + +.. code-block:: none + + $ tools/mkimage -A riscv -O u-boot -T standalone -C none -a 80000000 -e 80000000 -d examples/standalone/hello_world.bin hello_world.img + Image Name: + Created: Thu Mar 5 12:04:10 2020 + Image Type: RISC-V U-Boot Standalone Program (uncompressed) + Data Size: 4856 Bytes = 4.74 KiB = 0.00 MiB + Load Address: 80000000 + Entry Point: 80000000 + + $ picocom -b 115200 /dev/ttyUSB0i + => loady + ## Ready for binary (ymodem) download to 0x80000000 at 115200 bps... + C + *** file: hello_world.img + $ sz -vv hello_world.img + Sending: hello_world.img + Bytes Sent: 4992 BPS:665 + Sending: + Ymodem sectors/kbytes sent: 0/ 0k + Transfer complete + + *** exit status: 0 *** + CAN) packets, 3 retries + ## Total Size = 0x00001338 = 4920 Bytes + => bootm + ## Booting kernel from Legacy Image at 80000000 ... + Image Name: + Image Type: RISC-V U-Boot Standalone Program (uncompressed) + Data Size: 4856 Bytes = 4.7 KiB + Load Address: 80000000 + Entry Point: 80000000 + Verifying Checksum ... OK + Loading Standalone Program + Example expects ABI version 9 + Actual U-Boot ABI version 9 + Hello World + argc = 0 + argv[0] = "" + Hit any key to exit ... + +Over- and Under-clocking +------------------------ + +To change the clock speed of the K210, you will need to enable +``CONFIG_CLK_K210_SET_RATE`` and edit the board's device tree. To do this, add a +section to ``arch/riscv/arch/riscv/dts/k210-maix-bit.dts`` like the following: + +.. code-block:: none + + &sysclk { + assigned-clocks = <&sysclk K210_CLK_PLL0>; + assigned-clock-rates = <800000000>; + }; + +There are three PLLs on the K210: PLL0 is the parent of most of the components, +including the CPU and RAM. PLL1 is the parent of the neural network coprocessor. +PLL2 is the parent of the sound processing devices. Note that child clocks of +PLL0 and PLL2 run at *half* the speed of the PLLs. For example, if PLL0 is +running at 800 MHz, then the CPU will run at 400 MHz. This is the example given +above. The CPU can be overclocked to around 600 MHz, and underclocked to 26 MHz. + +It is possible to set PLL2's parent to PLL0. The plls are more accurate when +converting between similar frequencies. This makes it easier to get an accurate +frequency for I2S. As an example, consider sampling an I2S device at 44.1 kHz. +On this device, the I2S serial clock runs at 64 times the sample rate. +Therefore, we would like to run PLL2 at an even multiple of 2.8224 MHz. If +PLL2's parent is IN0, we could use a frequency of 390 MHz (the same as the CPU's +default speed). Dividing by 138 yields a serial clock of about 2.8261 MHz. This +results in a sample rate of 44.158 kHz---around 50 Hz or .1% too fast. If, +instead, we set PLL2's parent to PLL1 running at 390 MHz, and request a rate of +2.8224 * 136 = 383.8464 MHz, the achieved rate is 383.90625 MHz. Dividing by 136 +yields a serial clock of about 2.8228 MHz. This results in a sample rate of +44.107 kHz---just 7 Hz or .02% too fast. This configuration is shown in the +following example: + +.. code-block:: none + + &sysclk { + assigned-clocks = <&sysclk K210_CLK_PLL1>, <&sysclk K210_CLK_PLL2>; + assigned-clock-parents = <0>, <&sysclk K210_CLK_PLL1>; + assigned-clock-rates = <390000000>, <383846400>; + }; + +There are a couple of quirks to the PLLs. First, there are more frequency ratios +just above and below 1.0, but there is a small gap around 1.0. To be explicit, +if the input frequency is 100 MHz, it would be impossible to have an output of +99 or 101 MHz. In addition, there is a maximum frequency for the internal VCO, +so higher input/output frequencies will be less accurate than lower ones. + +Technical Details +----------------- + +Boot Sequence +^^^^^^^^^^^^^ + +1. ``RESET`` pin is deasserted. +2. Both harts begin executing at ``0x00001000``. +3. Both harts jump to firmware at ``0x88000000``. +4. One hart is chosen as a boot hart. +5. Firmware reads value of pin ``IO_16`` (ISP). + + * If the pin is low, enter ISP mode. This mode allows loading data to ram, + writing it to flash, and booting from specific addresses. + * If the pin is high, continue boot. +6. Firmware reads the next stage from flash (SPI3) to address ``0x80000000``. + + * If byte 0 is 1, the next stage is decrypted using the built-in AES + accelerator and the one-time programmable, 128-bit AES key. + * Bytes 1 to 4 hold the length of the next stage. + * The SHA-256 sum of the next stage is automatically calculated, and verified + against the 32 bytes following the next stage. +7. The boot hart sends an IPI to the other hart telling it to jump to the next + stage. +8. The boot hart jumps to ``0x80000000``. + +Memory Map +^^^^^^^^^^ + +========== ========= =========== +Address Size Description +========== ========= =========== +0x00000000 0x1000 debug +0x00001000 0x1000 rom +0x02000000 0xC000 clint +0x0C000000 0x4000000 plic +0x38000000 0x1000 uarths +0x38001000 0x1000 gpiohs +0x40000000 0x400000 sram0 (non-cached) +0x40400000 0x200000 sram1 (non-cached) +0x40600000 0x200000 airam (non-cached) +0x40800000 0xC00000 kpu +0x42000000 0x400000 fft +0x50000000 0x1000 dmac +0x50200000 0x200000 apb0 +0x50200000 0x80 gpio +0x50210000 0x100 uart0 +0x50220000 0x100 uart1 +0x50230000 0x100 uart2 +0x50240000 0x100 spi slave +0x50250000 0x200 i2s0 +0x50250200 0x200 apu +0x50260000 0x200 i2s1 +0x50270000 0x200 i2s2 +0x50280000 0x100 i2c0 +0x50290000 0x100 i2c1 +0x502A0000 0x100 i2c2 +0x502B0000 0x100 fpioa +0x502C0000 0x100 sha256 +0x502D0000 0x100 timer0 +0x502E0000 0x100 timer1 +0x502F0000 0x100 timer2 +0x50400000 0x200000 apb1 +0x50400000 0x100 wdt0 +0x50410000 0x100 wdt1 +0x50420000 0x100 otp control +0x50430000 0x100 dvp +0x50440000 0x100 sysctl +0x50450000 0x100 aes +0x50460000 0x100 rtc +0x52000000 0x4000000 apb2 +0x52000000 0x100 spi0 +0x53000000 0x100 spi1 +0x54000000 0x200 spi3 +0x80000000 0x400000 sram0 (cached) +0x80400000 0x200000 sram1 (cached) +0x80600000 0x200000 airam (cached) +0x88000000 0x20000 otp +0x88000000 0xC200 firmware +0x8801C000 0x1000 riscv priv spec 1.9 config +0x8801D000 0x2000 flattened device tree (contains only addresses and + interrupts) +0x8801f000 0x1000 credits +========== ========= =========== From patchwork Sun May 3 02:46:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 1281855 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; dmarc=pass (p=none dis=none) header.from=gmail.com 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=aepksgZD; 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 49F9VC4qKhz9sRf for ; Sun, 3 May 2020 12:51:15 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CFB77822E2; Sun, 3 May 2020 04:47:21 +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="aepksgZD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AF379822AB; Sun, 3 May 2020 04:47:09 +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,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qv1-xf41.google.com (mail-qv1-xf41.google.com [IPv6:2607:f8b0:4864:20::f41]) (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 EDFA0821B3 for ; Sun, 3 May 2020 04:47:05 +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-qv1-xf41.google.com with SMTP id fb4so6689667qvb.7 for ; Sat, 02 May 2020 19:47:05 -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=GnJP1A81JxhT3MHw2fnO57ydn2PSEF50o3EzZ+UySbs=; b=aepksgZDryB8KK6cip2tRo9b2bFKmOc5WVOgAstkdMIO9htzY5Zcx/nQWPPL5uBSxA VyB5lEh4Jq2Qiv3AoIe5Ic+KdxCkaTEB+jMWJx7L3UawUa3rdXz+cD3b2CqtvQ7KEboG 8bqMNGRflj1G71zlrnAbRDMUA24sU7CI5PvQsqKmfXHREr9STzlYmjWB3KpdzTkeBsn+ jhBqgiEa21LRUvC6ImZDD9lyOn8yOwnDqGwaUhbkKJ3X5b5d1XzxdJFJWDpSFEG8eT0/ xsG4zF/Wd14+aNCvclT03QEjKl8HMi5IQNjmvg81o6G8gt9F2oRHPXZcpoN07VaFMBjk vWkQ== 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=GnJP1A81JxhT3MHw2fnO57ydn2PSEF50o3EzZ+UySbs=; b=TIaKT8it1mGJjcg+x1neLyDdYM+eV1CJNb8mXG+3jKkJRkhknPnQVhjOYrt7Jqbuwz ET53jSTKJH9oyc0oGeIM4sbg/clwuGJ3uZoEOFu03oGYHNZMm2rzwRUugGr+mL1eA+Ts 3jyWfg6kYFjzFz6WuTxJbfftTuLU5XkmRzFs0WZkeBvWKcSi/o05GrTlawvDTpm7tuLO hJZvX0hg1n3DtkAasjGPL8fwiBls2N6aJjF2iEcO/FSObDpghLlGkJq2U0y0rgWYwrCo 4Wbk9eiBGuR5r1wUtLyoyhBrmqHCCI6Uqm5vV0EAKKtXWrNnxWncup5ujuFu8RaEXBzx DneQ== X-Gm-Message-State: AGi0Pub6lpL4QJDIuoaZe91p7adoZ+M10NYQcKnLm1QThDtAs0sg5IVD QFmafO3nVczMSIaqfGccrsYzVaSZKhQ= X-Google-Smtp-Source: APiQypKlvhg2wRSNmOanEP/vwvHgR9MV+KMXwihCZyPfEAuv1xTyJQqg/R1njyAVLFJcf9wwN/AbCg== X-Received: by 2002:ad4:4f14:: with SMTP id fb20mr10872391qvb.46.1588474024419; Sat, 02 May 2020 19:47:04 -0700 (PDT) Received: from godwin.fios-router.home (pool-108-51-35-162.washdc.fios.verizon.net. [108.51.35.162]) by smtp.gmail.com with ESMTPSA id h2sm6610696qkh.91.2020.05.02.19.47.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 19:47:03 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de Cc: Bin Meng , Rick Chen , Sean Anderson Subject: [PATCH v10 21/21] riscv: Add Sipeed Maix support Date: Sat, 2 May 2020 22:46:37 -0400 Message-Id: <20200503024637.327733-22-seanga2@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200503024637.327733-1-seanga2@gmail.com> References: <20200503024637.327733-1-seanga2@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 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.2 at phobos.denx.de X-Virus-Status: Clean The Sipeed Maix series is a collection of boards built around the RISC-V Kendryte K210 processor. This processor contains several peripherals to accelerate neural network processing and other "ai" tasks. This includes a "KPU" neural network processor, an audio processor supporting beamforming reception, and a digital video port supporting capture and output at VGA resolution. Other peripherals include 8M of sram (accessible with and without caching); remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but include spi flash; on-board usb-serial bridges; ports for cameras, displays, and sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is supported, but the boards are fairly similar. Documentation for Maix boards is located at . Documentation for the Kendryte K210 is located at . However, hardware details are rather lacking, so most technical reference has been taken from the standalone sdk located at . Signed-off-by: Sean Anderson --- Changes in v9: - Update MAINTAINERS to reflect defconfig name change Changes in v8: - Remove unnecessary fdt fixup for sipeed maix Changes in v7: - Split docs off into their own patch - Enable ram clocks by name Changes in v6: - Remove trailing whitespace from documentation - Remove configuration for spi/pinmux/gpio features - Flesh out documentation some more Changes in v5: - Configure relocation location with CONFIG_SYS_SDRAM_* - Enable ram clocks - Add pinmux/gpio/led support - Remove (broken) MMC support - Store the environment in flash - Add partitions - Add bootcmd - Add docs for pinctrl and booting Changes in v4: - Rework documentation to be organized by board mfg not cpu mfg - Update docs to reflect working SPI support - Add proper spi support - Don't define unneecessary macros in config.h - Lower the default stack so it isn't clobbered on relocation - Update MAINTAINERS - Update copyright Changes in v3: - Reorder to be last in the patch series - Add documentation for the board - Generate defconfig with "make savedefconfig" - Update Kconfig to imply most features we need - Update MAINTAINERS Changes in v2: - Select CONFIG_SYS_RISCV_NOCOUNTER - Imply CONFIG_CLK_K210 - Remove spurious references to CONFIG_ARCH_K210 - Remove many configs from defconfig where the defaults were fine - Add a few "not set" lines to suppress unneeded defaults - Reduce pre-reloc malloc space, now that clocks initialization happens later arch/riscv/Kconfig | 4 +++ board/sipeed/maix/Kconfig | 47 ++++++++++++++++++++++++++++++ board/sipeed/maix/MAINTAINERS | 11 +++++++ board/sipeed/maix/Makefile | 5 ++++ board/sipeed/maix/maix.c | 41 ++++++++++++++++++++++++++ configs/sipeed_maix_bitm_defconfig | 8 +++++ include/configs/sipeed-maix.h | 24 +++++++++++++++ 7 files changed, 140 insertions(+) create mode 100644 board/sipeed/maix/Kconfig create mode 100644 board/sipeed/maix/MAINTAINERS create mode 100644 board/sipeed/maix/Makefile create mode 100644 board/sipeed/maix/maix.c create mode 100644 configs/sipeed_maix_bitm_defconfig create mode 100644 include/configs/sipeed-maix.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index cb1ca31b1b..ba171b4918 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT config TARGET_SIFIVE_FU540 bool "Support SiFive FU540 Board" +config TARGET_SIPEED_MAIX + bool "Support Sipeed Maix Board" + endchoice config SYS_ICACHE_OFF @@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig" source "board/emulation/qemu-riscv/Kconfig" source "board/microchip/mpfs_icicle/Kconfig" source "board/sifive/fu540/Kconfig" +source "board/sipeed/maix/Kconfig" # platform-specific options below source "arch/riscv/cpu/ax25/Kconfig" diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig new file mode 100644 index 0000000000..0cdcd32adc --- /dev/null +++ b/board/sipeed/maix/Kconfig @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2019-20 Sean Anderson + +if TARGET_SIPEED_MAIX + +config SYS_BOARD + default "maix" + +config SYS_VENDOR + default "sipeed" + +config SYS_CPU + default "generic" + +config SYS_CONFIG_NAME + default "sipeed-maix" + +config SYS_TEXT_BASE + default 0x80000000 + +config DEFAULT_DEVICE_TREE + default "k210-maix-bit" + +config NR_CPUS + default 2 + +config NR_DRAM_BANKS + default 3 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select GENERIC_RISCV + select RISCV_PRIV_1_9 + imply SMP + imply DM_SERIAL + imply SIFIVE_SERIAL + 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 + imply SYSRESET + imply SYSRESET_SYSCON +endif diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS new file mode 100644 index 0000000000..e7bb9ec433 --- /dev/null +++ b/board/sipeed/maix/MAINTAINERS @@ -0,0 +1,11 @@ +Sipeed Maix BOARD +M: Sean Anderson +S: Maintained +F: arch/riscv/dts/k210.dtsi +F: arch/riscv/dts/k210-maix-bit.dts +F: board/sipeed/maix/ +F: configs/sipeed_maix_bitm_defconfig +F: doc/board/sipeed/ +F: include/configs/sipeed-maix.h +F: include/dt-bindings/*/k210-sysctl.h +F: test/dm/k210_pll.c diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile new file mode 100644 index 0000000000..4acff5b31e --- /dev/null +++ b/board/sipeed/maix/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. + +obj-y += maix.o diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c new file mode 100644 index 0000000000..cbcb23cf5c --- /dev/null +++ b/board/sipeed/maix/maix.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-20 Sean Anderson + */ + +#include +#include +#include +#include +#include + +phys_size_t get_effective_memsize(void) +{ + return CONFIG_SYS_SDRAM_SIZE; +} + +int board_init(void) +{ + int ret, i; + const char * const banks[] = { "sram0", "sram1", "airam" }; + ofnode memory; + struct clk clk; + + /* Enable RAM clocks */ + memory = ofnode_by_compatible(ofnode_null(), "kendryte,k210-sram"); + if (ofnode_equal(memory, ofnode_null())) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(banks); i++) { + ret = clk_get_by_name_nodev(memory, banks[i], &clk); + if (ret) + continue; + + ret = clk_enable(&clk); + clk_free(&clk); + if (ret) + return ret; + } + + return 0; +} diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig new file mode 100644 index 0000000000..f48f7f06e9 --- /dev/null +++ b/configs/sipeed_maix_bitm_defconfig @@ -0,0 +1,8 @@ +CONFIG_RISCV=y +CONFIG_TARGET_SIPEED_MAIX=y +CONFIG_ARCH_RV64I=y +CONFIG_SYS_REDUNDAND_ENVIRONMENT=y +# CONFIG_NET is not set +# CONFIG_INPUT is not set +# CONFIG_DM_ETH is not set +# CONFIG_EFI_LOADER is not set diff --git a/include/configs/sipeed-maix.h b/include/configs/sipeed-maix.h new file mode 100644 index 0000000000..a46473fc78 --- /dev/null +++ b/include/configs/sipeed-maix.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019-20 Sean Anderson + */ + +#ifndef CONFIGS_SIPEED_MAIX_H +#define CONFIGS_SIPEED_MAIX_H + +#include + +#define CONFIG_SYS_LOAD_ADDR 0x80000000 +/* Start just below the second bank so we don't clobber it during reloc */ +#define CONFIG_SYS_INIT_SP_ADDR 0x803FFFFF +#define CONFIG_SYS_MALLOC_LEN SZ_128K +#define CONFIG_SYS_CACHELINE_SIZE 64 + +#define CONFIG_SYS_SDRAM_BASE 0x80000000 +/* Don't relocate into AI ram since it isn't set up yet */ +#define CONFIG_SYS_SDRAM_SIZE (SZ_4M + SZ_2M) + +/* For early init */ +#define K210_SYSCTL_BASE 0x50440000 + +#endif /* CONFIGS_SIPEED_MAIX_H */