From nobody Fri Oct 30 07:36:59 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jGCbc0wRFz6yP31 for ; Fri, 30 Oct 2026 07:37:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jGCbb5xg9z4qbr for ; Fri, 30 Oct 2026 07:36:59 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793345819; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hvzZa/XFDBMaSfyZBanDtozyPowVW9kC5J0yuYLvv+k=; b=PXr+a3t0T9q/OYgg2Q3IzX18bRj2O8qYIZtg5UiRzpkjEkq52V+cqa5GRkJTIEnNz6S2yb Vyp3XGps1yCTKDn9Qb1b6Sn+DCQcODJfmdjt+Z5uCGLaE3VptXCPl6GxTtGWS9FxKTliZU B4S2jT2Tl6Eku0l8r5mkhftit1QK21zdeo5sKMQ5dbyUi5SbsqpiVR/CWxMu6edX+WaT2T HKFsUtuWxXoxsHeeeffj/ksMEjGwy8F8rTRjltZyeITYEua0UpMCjVZYDeK3H+ZlMN3dY2 YeDZnkYNlcWDiR+sabHT5QnyeScf1yjFGuoOKBSIesGmhK/pmkGPCKx/FEqO3g== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793345819; b=O1BCI4+YFXQpZGRErdW8JsX+bHv2EWyf0x02T4Wg1Wn/hX3zoXfTpEFbNLKvPsAUbUKt+T wtJSzk1ui7+k+YxcJdToWJ8ogx+rFzpeZBRAy6nzzv4NnsWoa3l947jKX+mHtGkwJkgNHN 5tUDnmgMID495oXpn3PtZrHY+LzuekPmCV3IKYygqfkwaBicDv5jcSO7dFBtJl1EGgcgY1 gtzhFtXDgPgnaOnrnvzBMyniFpcB0BKeyWRua7s05gjwP3wKUasW+W9yPDSuhP+WywhO36 pMvvqcp8ex/HRtuZky31/GiEW/b+q+sFvahTWyUYMhZDqZJLMpiTjxqUYVehKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793345819; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hvzZa/XFDBMaSfyZBanDtozyPowVW9kC5J0yuYLvv+k=; b=A9klaaaS02O4OKmMeK2chGyf2m2YqKYo4lWgIAzMeZA4DfL0x+fFqzMUYK5OI8aEj7cLxV 9KqsR2q2WRbxfkrVMxGRsicU5BY0uoPDyl8Wfs4whfHmGTtDmYWklAhj8yzpqN1iLFHzog ZvES/b+3hvNYBgKeKxH35ojfx0K/rbyyM9yh2weWR2yeHmyttwT0wbyc916W6vX929hAPe RyYBSs+4yQHRqYqL0lzK7S3Z+0qeM8vF6LUy5Ir6A0ZZo6qWeYt7ftHpPDibnAYsWUh6OE Ti3VtNI5pBny3fZ7UVAacBbE8qmFRbFtWSe0f1yAstZCcWCPQgQTiOl2kZPLjA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jGCbb5cYczGRP for ; Fri, 30 Oct 2026 07:36:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 20677 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 30 Oct 2026 07:36:59 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Emmanuel Vadot Subject: git: e32b082ba28b - main - clk: rockchip: Add the MMC phase clock List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: manu X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e32b082ba28bd3d0e026782eeb93f124ced7508f Auto-Submitted: auto-generated Date: Fri, 30 Oct 2026 07:36:59 +0000 Message-Id: <6ae4491b.20677.5ae1a95b@gitrepo.freebsd.org> The branch main has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=e32b082ba28bd3d0e026782eeb93f124ced7508f commit e32b082ba28bd3d0e026782eeb93f124ced7508f Author: Emmanuel Vadot AuthorDate: 2026-10-20 08:09:18 +0000 Commit: Emmanuel Vadot CommitDate: 2026-10-30 07:36:46 +0000 clk: rockchip: Add the MMC phase clock Add a clock node type for the Rockchip MMC sample and drive clocks. These clocks have a phase in degrees controlled by a delay line and a fine-grained phase selector, and implement the new clknode phase methods. Reviewed by: mmel Differential Revision: https://reviews.freebsd.org/D60886 --- sys/conf/files.arm64 | 1 + sys/dev/clk/rockchip/rk_clk_mmc.c | 219 ++++++++++++++++++++++++++++++++++++++ sys/dev/clk/rockchip/rk_clk_mmc.h | 41 +++++++ sys/dev/clk/rockchip/rk_cru.c | 3 + sys/dev/clk/rockchip/rk_cru.h | 18 ++++ 5 files changed, 282 insertions(+) diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 105bc679acb8..2f914c4efd64 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -850,6 +850,7 @@ dev/clk/rockchip/rk_clk_armclk.c optional fdt soc_rockchip dev/clk/rockchip/rk_clk_composite.c optional fdt soc_rockchip dev/clk/rockchip/rk_clk_fract.c optional fdt soc_rockchip dev/clk/rockchip/rk_clk_gate.c optional fdt soc_rockchip +dev/clk/rockchip/rk_clk_mmc.c optional fdt soc_rockchip dev/clk/rockchip/rk_clk_mux.c optional fdt soc_rockchip dev/clk/rockchip/rk_clk_pll.c optional fdt soc_rockchip dev/clk/rockchip/rk3328_cru.c optional fdt soc_rockchip_rk3328 diff --git a/sys/dev/clk/rockchip/rk_clk_mmc.c b/sys/dev/clk/rockchip/rk_clk_mmc.c new file mode 100644 index 000000000000..8978280db86e --- /dev/null +++ b/sys/dev/clk/rockchip/rk_clk_mmc.c @@ -0,0 +1,219 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2026 Emmanuel Vadot + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include + +#include "clkdev_if.h" + +#define WR4(_clk, off, val) \ + CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) +#define RD4(_clk, off, val) \ + CLKDEV_READ_4(clknode_get_device(_clk), off, val) +#define DEVICE_LOCK(_clk) \ + CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) +#define DEVICE_UNLOCK(_clk) \ + CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) + +/* + * MMC drive/sample phase clock. The controller output clock is the parent + * rate divided by two (RK_MMC_CLKGEN_DIV). The phase is programmed as a + * coarse 90 degree step plus an optional fine delay of up to 255 elements. + */ +#define RK_MMC_CLKGEN_DIV 2 +#define RK_MMC_DELAY_SEL (1 << 10) +#define RK_MMC_DEGREE_MASK 0x3 +#define RK_MMC_DELAYNUM_OFFSET 2 +#define RK_MMC_DELAYNUM_MASK (0xff << RK_MMC_DELAYNUM_OFFSET) +#define RK_MMC_PHASE_MASK 0x7ff + +/* + * Each fine delay element is between 44 and 77 ps; assume 60 ps. So an + * angle can be off by up to about 25 degrees, which is acceptable because + * the tuning only needs to find a point far from the bad range. + */ +#define RK_MMC_DELAY_ELEMENT_PSEC 60 + +#define DIV_ROUND_CLOSEST_U(n, d) (((n) + ((d) / 2)) / (d)) + +struct rk_clk_mmc_sc { + uint32_t offset; + uint32_t shift; +}; + +static int +rk_clk_mmc_init(struct clknode *clk, device_t dev) +{ + + clknode_init_parent_idx(clk, 0); + return (0); +} + +static int +rk_clk_mmc_recalc_freq(struct clknode *clk, uint64_t *freq) +{ + + *freq /= RK_MMC_CLKGEN_DIV; + return (0); +} + +static int +rk_clk_mmc_get_phase(struct clknode *clk, int *degrees) +{ + struct rk_clk_mmc_sc *sc; + struct clknode *parent; + uint64_t rate; + uint32_t raw; + int rv; + + sc = clknode_get_softc(clk); + + /* + * Read the parent rate: the core holds our node lock while calling + * this method, so clknode_get_freq() on ourselves would relock it. + */ + parent = clknode_get_parent(clk); + if (parent == NULL) { + *degrees = 0; + return (0); + } + rv = clknode_get_freq(parent, &rate); + if (rv != 0) + return (rv); + rate /= RK_MMC_CLKGEN_DIV; + /* Constant signal, no measurable phase shift. */ + if (rate == 0) { + *degrees = 0; + return (0); + } + + DEVICE_LOCK(clk); + rv = RD4(clk, sc->offset, &raw); + DEVICE_UNLOCK(clk); + if (rv != 0) + return (rv); + + raw >>= sc->shift; + *degrees = (raw & RK_MMC_DEGREE_MASK) * 90; + if ((raw & RK_MMC_DELAY_SEL) != 0) { + uint64_t factor, delay_num; + + /* degrees per delay element * 1000000 */ + factor = (RK_MMC_DELAY_ELEMENT_PSEC / 10) * 36 * + (rate / 10000); + delay_num = (raw & RK_MMC_DELAYNUM_MASK) >> + RK_MMC_DELAYNUM_OFFSET; + *degrees += DIV_ROUND_CLOSEST_U(delay_num * factor, 1000000); + } + *degrees %= 360; + return (0); +} + +static int +rk_clk_mmc_set_phase(struct clknode *clk, int degrees) +{ + struct rk_clk_mmc_sc *sc; + struct clknode *parent; + uint64_t rate, delay; + uint32_t raw, nineties, remainder; + int rv; + + sc = clknode_get_softc(clk); + + if (degrees < 0 || degrees >= 360) + return (EINVAL); + /* + * Read the parent rate: the core holds our node lock while calling + * this method, so clknode_get_freq() on ourselves would relock it. + */ + parent = clknode_get_parent(clk); + if (parent == NULL) + return (EINVAL); + rv = clknode_get_freq(parent, &rate); + if (rv != 0) + return (rv); + rate /= RK_MMC_CLKGEN_DIV; + /* The phase can't be calculated for a stopped clock. */ + if (rate == 0) + return (EINVAL); + + nineties = degrees / 90; + remainder = degrees % 90; + + /* Convert the remainder to a number of fine delay elements. */ + delay = 10000000ULL * remainder; + delay = DIV_ROUND_CLOSEST_U(delay, (rate / 1000) * 36 * + (RK_MMC_DELAY_ELEMENT_PSEC / 10)); + if (delay > 255) + delay = 255; + + raw = delay != 0 ? RK_MMC_DELAY_SEL : 0; + raw |= delay << RK_MMC_DELAYNUM_OFFSET; + raw |= nineties; + + /* Hiword update: the upper 16 bits are the write enable mask. */ + DEVICE_LOCK(clk); + rv = WR4(clk, sc->offset, (raw << sc->shift) | + ((RK_MMC_PHASE_MASK << sc->shift) << 16)); + DEVICE_UNLOCK(clk); + return (rv); +} + +static clknode_method_t rk_clk_mmc_methods[] = { + /* Device interface */ + CLKNODEMETHOD(clknode_init, rk_clk_mmc_init), + CLKNODEMETHOD(clknode_recalc_freq, rk_clk_mmc_recalc_freq), + CLKNODEMETHOD(clknode_set_phase, rk_clk_mmc_set_phase), + CLKNODEMETHOD(clknode_get_phase, rk_clk_mmc_get_phase), + CLKNODEMETHOD_END +}; +DEFINE_CLASS_1(rk_clk_mmc, rk_clk_mmc_class, rk_clk_mmc_methods, + sizeof(struct rk_clk_mmc_sc), clknode_class); + +int +rk_clk_mmc_register(struct clkdom *clkdom, struct rk_clk_mmc_def *clkdef) +{ + struct clknode *clk; + struct rk_clk_mmc_sc *sc; + + clk = clknode_create(clkdom, &rk_clk_mmc_class, &clkdef->clkdef); + if (clk == NULL) + return (1); + + sc = clknode_get_softc(clk); + sc->offset = clkdef->offset; + sc->shift = clkdef->shift; + + clknode_register(clkdom, clk); + return (0); +} diff --git a/sys/dev/clk/rockchip/rk_clk_mmc.h b/sys/dev/clk/rockchip/rk_clk_mmc.h new file mode 100644 index 000000000000..1ae31f4f2bea --- /dev/null +++ b/sys/dev/clk/rockchip/rk_clk_mmc.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2026 Emmanuel Vadot + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RK_CLK_MMC_H_ +#define _RK_CLK_MMC_H_ + +#include + +struct rk_clk_mmc_def { + struct clknode_init_def clkdef; + uint32_t offset; + uint32_t shift; +}; + +int rk_clk_mmc_register(struct clkdom *clkdom, struct rk_clk_mmc_def *clkdef); + +#endif /* _RK_CLK_MMC_H_ */ diff --git a/sys/dev/clk/rockchip/rk_cru.c b/sys/dev/clk/rockchip/rk_cru.c index 6b0978e885b5..bc844d035744 100644 --- a/sys/dev/clk/rockchip/rk_cru.c +++ b/sys/dev/clk/rockchip/rk_cru.c @@ -263,6 +263,9 @@ rk_cru_attach(device_t dev) clknode_link_register(sc->clkdom, sc->clks[i].clk.link); break; + case RK_CLK_MMC: + rk_clk_mmc_register(sc->clkdom, sc->clks[i].clk.mmc); + break; default: device_printf(dev, "Unknown clock type\n"); return (ENXIO); diff --git a/sys/dev/clk/rockchip/rk_cru.h b/sys/dev/clk/rockchip/rk_cru.h index 685c6bb67568..3ad5b040dc01 100644 --- a/sys/dev/clk/rockchip/rk_cru.h +++ b/sys/dev/clk/rockchip/rk_cru.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,21 @@ }, \ } +/* MMC drive/sample phase clock. */ +#define MMCPHASE(_id, _name, _pname, _o, _s) \ +{ \ + .type = RK_CLK_MMC, \ + .clk.mmc = &(struct rk_clk_mmc_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .offset = _o, \ + .shift = _s, \ + }, \ +} + /* Fractional rate multipier/divider. */ #define FRACT(_id, _name, _pname, _f, _o) \ { \ @@ -227,6 +243,7 @@ enum rk_clk_type { RK_CLK_MUX, RK_CLK_ARMCLK, RK_CLK_LINK, + RK_CLK_MMC, }; struct rk_clk { @@ -239,6 +256,7 @@ struct rk_clk { struct clk_fixed_def *fixed; struct rk_clk_fract_def *fract; struct clk_link_def *link; + struct rk_clk_mmc_def *mmc; } clk; };