From nobody Fri Sep 20 01:39:41 2024 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F8A21598E2 for ; Thu, 30 May 2024 08:35:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717058129; cv=none; b=PNGtaLapumKY/u1xkWMPp6kPnl3Neb6UQeiqxnEeoV1r8XhPc+hxCSmCXX+vzsh0kKOPMCX0803Z/XKNxbeUgdil5vVQqRhzTY1UltBcqIK5LreQpVVhXsSBTqv+rLhlHiK4PJzQt45ow02jsSYm8e+iceMa7iYFqjxFheQ6NI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717058129; c=relaxed/simple; bh=W0SC8G/jIszLFajvIONxwU5d7chA4Rn7+xq+d1EhCkk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u0F08RuOfFCh/S3SpJzErr/3dLVgO6OH5wtTX8YndlOATaz4FCQS+ZscV3svwjF+3UilNbGKykDE2Ik+xXqhCiErxvxheeHhVTtVlwfRI3Jg9HindX6E4I6kmSyfwoHwcUzYxkG6a5UBuWWfp+eKCOjazrQR2FYwz5G561Eq1n4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=BSbN5+CN; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="BSbN5+CN" Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-1f47eb2354bso4430765ad.3 for ; Thu, 30 May 2024 01:35:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1717058127; x=1717662927; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kAVvhQV9mDNvHBPovdoxXEWHQ5sjxf2IkeHwkDa/ZGA=; b=BSbN5+CNy1/hkmrQKXilsGSqJsmdaTQUanaGovt7OJja37fEkO9Dd0ZvASu6RiHZsw IZE309wJJPerPK27pREYI00GfbBSWo1V79jnqMwesgM8cFOqsGeUgzaM4C6iJmglJK3d jUlWIsXlmxLf73xDROr7enUS8rg0Y30hARvlU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717058127; x=1717662927; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kAVvhQV9mDNvHBPovdoxXEWHQ5sjxf2IkeHwkDa/ZGA=; b=e3CsAjqVsZ2yd6OVNt1tdtd4DOu3doe8wS20TDrITQ+KHtZXG9sY6s+LHZbjMSUT4v PpJ2oKUQZeZy3wvmlgZ3i/UxDoBxNHNgZ4wRMDcKun5+WB94ylZs8KfP7RYb8hPmvZ1D snJrX52gai2EKfeV/B5B8Ig1QFG1wc9mR9A+IEgc8A7NXz+zhVioSMTiBZI/3pjlIBSC ohLV4Is1vkfledOnE44+MTH2PJPvu9GSgy5oXrEMj0pGt6k4joF532YyxXZXsXG0Mo+7 XcKE+v+ZjW4qxUOSNUfTiXUL4/oZkDaazm0EhzeWb80vbuRDQ7ZFOBtF2pswIlva+0ZF 4krA== X-Forwarded-Encrypted: i=1; AJvYcCUj9J4hzMAn88J2qu6AC83qoYqBq5PsCDpEXkPk/+02xyZDAJNpLBQUlX6Mw9OuAEuum5H/Iamh5cA27y5Lg7E74LHEgepXgwmX1yDl X-Gm-Message-State: AOJu0YznRJgd7TNw+ix3NZDrqDiiDeeLDuHBJXkOgt+VyB67MdftJDZ0 GyXQMj+aTUKBpyqi5D9FcxG7mdd3vUDMOuXuIPBCuG2bc0JkWf3aFHlt8tw8Jg== X-Google-Smtp-Source: AGHT+IHoBbIOM5vNh6pT5ABfKxUt7FMpI6uVxEi+iIx5qDC7QCH2GBkDA8qTZy2Bcn1PQP+qDLEUiA== X-Received: by 2002:a17:902:f70f:b0:1f4:9c26:d036 with SMTP id d9443c01a7336-1f6193ee9d9mr14442085ad.14.1717058127331; Thu, 30 May 2024 01:35:27 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:65f0:63a9:90bb:50b8]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1f617390fe7sm10950635ad.146.2024.05.30.01.35.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 01:35:26 -0700 (PDT) From: Chen-Yu Tsai To: Frank Binns , Matt Coster , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno Cc: Chen-Yu Tsai , David Airlie , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/6] clk: mediatek: Add mt8173-mfgtop driver Date: Thu, 30 May 2024 16:35:01 +0800 Message-ID: <20240530083513.4135052-3-wenst@chromium.org> X-Mailer: git-send-email 2.45.1.288.g0e0cd299f1-goog In-Reply-To: <20240530083513.4135052-1-wenst@chromium.org> References: <20240530083513.4135052-1-wenst@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The MFG (GPU) block on the MT8173 has a small glue layer, named MFG_TOP in the datasheet, that contains clock gates, some power sequence signal delays, and other unknown registers that get toggled when the GPU is powered on. The clock gates are exposed as clocks provided by a clock controller, while the power sequencing bits are exposed as one singular power domain. Signed-off-by: Chen-Yu Tsai --- drivers/clk/mediatek/Kconfig | 9 + drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-mt8173-mfgtop.c | 240 +++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 drivers/clk/mediatek/clk-mt8173-mfgtop.c diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 70a005e7e1b1..9e279c739f1c 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -500,6 +500,15 @@ config COMMON_CLK_MT8173_IMGSYS help This driver supports MediaTek MT8173 imgsys clocks. =20 +config COMMON_CLK_MT8173_MFGTOP + tristate "Clock and power driver for MediaTek MT8173 mfgtop" + depends on COMMON_CLK_MT8173 + default COMMON_CLK_MT8173 + select PM_GENERIC_DOMAINS + select PM_GENERIC_DOMAINS_OF + help + This driver supports MediaTek MT8173 mfgtop clocks and power domain. + config COMMON_CLK_MT8173_MMSYS tristate "Clock driver for MediaTek MT8173 mmsys" depends on COMMON_CLK_MT8173 diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index eeccfa039896..fdd3a76e12a1 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) +=3D clk-mt8167-v= dec.o obj-$(CONFIG_COMMON_CLK_MT8173) +=3D clk-mt8173-apmixedsys.o clk-mt8173-in= fracfg.o \ clk-mt8173-pericfg.o clk-mt8173-topckgen.o obj-$(CONFIG_COMMON_CLK_MT8173_IMGSYS) +=3D clk-mt8173-img.o +obj-$(CONFIG_COMMON_CLK_MT8173_MFGTOP) +=3D clk-mt8173-mfgtop.o obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) +=3D clk-mt8173-mm.o obj-$(CONFIG_COMMON_CLK_MT8173_VDECSYS) +=3D clk-mt8173-vdecsys.o obj-$(CONFIG_COMMON_CLK_MT8173_VENCSYS) +=3D clk-mt8173-vencsys.o diff --git a/drivers/clk/mediatek/clk-mt8173-mfgtop.c b/drivers/clk/mediate= k/clk-mt8173-mfgtop.c new file mode 100644 index 000000000000..85fa7a7453ed --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8173-mfgtop.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Google LLC + * Author: Chen-Yu Tsai + * + * Based on driver in downstream ChromeOS v5.15 kernel. + * + * Copyright (c) 2014 MediaTek Inc. + * Author: Chiawen Lee + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mfg_cg_regs =3D { + .sta_ofs =3D 0x0000, + .clr_ofs =3D 0x0008, + .set_ofs =3D 0x0004, +}; + +#define GATE_MFG(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_= ops_setclr, _flags) + +/* TODO: The block actually has dividers for the core and mem clocks. */ +static const struct mtk_gate mfg_clks[] =3D { + GATE_MFG(CLK_MFG_AXI, "mfg_axi", "axi_mfg_in_sel", 0, CLK_SET_RATE_PARENT= ), + GATE_MFG(CLK_MFG_MEM, "mfg_mem", "mem_mfg_in_sel", 1, CLK_SET_RATE_PARENT= ), + GATE_MFG(CLK_MFG_G3D, "mfg_g3d", "mfg_sel", 2, CLK_SET_RATE_PARENT), + GATE_MFG(CLK_MFG_26M, "mfg_26m", "clk26m", 3, 0), +}; + +static const struct mtk_clk_desc mfg_desc =3D { + .clks =3D mfg_clks, + .num_clks =3D ARRAY_SIZE(mfg_clks), +}; + +struct mt8173_mfgtop_data { + struct clk_hw_onecell_data *clk_data; + struct regmap *regmap; + struct generic_pm_domain genpd; + struct of_phandle_args parent_pd, child_pd; + struct clk *clk_26m; +}; + +static const struct of_device_id of_match_clk_mt8173_mfgtop[] =3D { + { .compatible =3D "mediatek,mt8173-mfgtop", .data =3D &mfg_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_mfgtop); + +/* Delay count in clock cycles */ +#define MFG_ACTIVE_POWER_CON0 0x24 + #define RST_B_DELAY_CNT GENMASK(7, 0) /* pwr_rst_b de-assert delay during= power-up */ + #define CLK_EN_DELAY_CNT GENMASK(15, 8) /* CLK_DIS deassert delay during = power-up */ + #define CLK_DIS_DELAY_CNT GENMASK(23, 16) /* CLK_DIS assert delay during = power-down */ + +#define MFG_ACTIVE_POWER_CON1 0x28 + #define PWR_ON_S_DELAY_CNT GENMASK(7, 0) /* pwr_on_s assert delay during = power-up */ + #define ISO_DELAY_CNT GENMASK(15, 8) /* ISO assert delay during power-do= wn */ + #define ISOOFF_DELAY_CNT GENMASK(23, 16) /* ISO de-assert delay during po= wer-up */ + #define RST__DELAY_CNT GENMASK(31, 24) /* pwr_rsb_b assert delay during = power-down */ + +static int clk_mt8173_mfgtop_power_on(struct generic_pm_domain *domain) +{ + struct mt8173_mfgtop_data *data =3D container_of(domain, struct mt8173_mf= gtop_data, genpd); + + /* drives internal power management */ + clk_prepare_enable(data->clk_26m); + + /* Power on/off delays for various signals */ + regmap_write(data->regmap, MFG_ACTIVE_POWER_CON0, + FIELD_PREP(RST_B_DELAY_CNT, 77) | + FIELD_PREP(CLK_EN_DELAY_CNT, 61) | + FIELD_PREP(CLK_DIS_DELAY_CNT, 60)); + regmap_write(data->regmap, MFG_ACTIVE_POWER_CON1, + FIELD_PREP(PWR_ON_S_DELAY_CNT, 11) | + FIELD_PREP(ISO_DELAY_CNT, 68) | + FIELD_PREP(ISOOFF_DELAY_CNT, 69) | + FIELD_PREP(RST__DELAY_CNT, 77)); + + /* Magic numbers related to core switch sequence and delays */ + regmap_write(data->regmap, 0xe0, 0x7a710184); + regmap_write(data->regmap, 0xe4, 0x835f6856); + regmap_write(data->regmap, 0xe8, 0x002b0234); + regmap_write(data->regmap, 0xec, 0x80000000); + regmap_write(data->regmap, 0xa0, 0x08000000); + + return 0; +} + +static int clk_mt8173_mfgtop_power_off(struct generic_pm_domain *domain) +{ + struct mt8173_mfgtop_data *data =3D container_of(domain, struct mt8173_mf= gtop_data, genpd); + + /* Magic numbers related to core switch sequence and delays */ + regmap_write(data->regmap, 0xec, 0); + + /* drives internal power management */ + clk_disable_unprepare(data->clk_26m); + + return 0; +} + +static int clk_mt8173_mfgtop_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct device_node *node =3D dev->of_node; + struct mt8173_mfgtop_data *data; + int ret; + + data =3D devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + platform_set_drvdata(pdev, data); + + data->clk_data =3D mtk_devm_alloc_clk_data(dev, ARRAY_SIZE(mfg_clks)); + if (!data->clk_data) + return -ENOMEM; + + /* MTK clock gates also uses regmap */ + data->regmap =3D device_node_to_regmap(node); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to get regmap\n= "); + + data->child_pd.np =3D node; + data->child_pd.args_count =3D 0; + ret =3D of_parse_phandle_with_args(node, "power-domains", "#power-domain-= cells", 0, + &data->parent_pd); + if (ret) + return dev_err_probe(dev, ret, "Failed to parse power domain\n"); + + devm_pm_runtime_enable(dev); + /* + * Do a pm_runtime_resume_and_get() to workaround a possible + * deadlock between clk_register() and the genpd framework. + */ + ret =3D pm_runtime_resume_and_get(dev); + if (ret) { + dev_err_probe(dev, ret, "Failed to runtime resume device\n"); + goto put_of_node; + } + + ret =3D mtk_clk_register_gates(dev, node, mfg_clks, ARRAY_SIZE(mfg_clks), + data->clk_data); + if (ret) { + dev_err_probe(dev, ret, "Failed to register clock gates\n"); + goto put_pm_runtime; + } + + data->clk_26m =3D clk_hw_get_clk(data->clk_data->hws[CLK_MFG_26M], "26m"); + if (IS_ERR(data->clk_26m)) { + dev_err_probe(dev, PTR_ERR(data->clk_26m), "Failed to get 26 MHz clock\n= "); + goto unregister_clks; + } + + ret =3D of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data->clk_dat= a); + if (ret) { + dev_err_probe(dev, ret, "Failed to add clk OF provider\n"); + goto put_26m_clk; + } + + data->genpd.name =3D "mfg_apm"; + data->genpd.power_on =3D clk_mt8173_mfgtop_power_on; + data->genpd.power_off =3D clk_mt8173_mfgtop_power_off; + ret =3D pm_genpd_init(&data->genpd, NULL, true); + if (ret) { + dev_err_probe(dev, ret, "Failed to add power domain\n"); + goto del_clk_provider; + } + + ret =3D of_genpd_add_provider_simple(node, &data->genpd); + if (ret) { + dev_err_probe(dev, ret, "Failed to add power domain OF provider\n"); + goto remove_pd; + } + + ret =3D of_genpd_add_subdomain(&data->parent_pd, &data->child_pd); + if (ret) { + dev_err_probe(dev, ret, "Failed to link PM domains\n"); + goto del_pd_provider; + } + + pm_runtime_put(dev); + return 0; + +del_pd_provider: + of_genpd_del_provider(node); +remove_pd: + pm_genpd_remove(&data->genpd); +del_clk_provider: + of_clk_del_provider(node); +put_26m_clk: + clk_put(data->clk_26m); +unregister_clks: + mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data); +put_pm_runtime: + pm_runtime_put(dev); +put_of_node: + of_node_put(data->parent_pd.np); + return ret; +} + +static void clk_mt8173_mfgtop_remove(struct platform_device *pdev) +{ + struct mt8173_mfgtop_data *data =3D platform_get_drvdata(pdev); + struct device_node *node =3D pdev->dev.of_node; + + of_genpd_remove_subdomain(&data->parent_pd, &data->child_pd); + of_genpd_del_provider(node); + pm_genpd_remove(&data->genpd); + of_clk_del_provider(node); + clk_put(data->clk_26m); + mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data); +} + +static struct platform_driver clk_mt8173_mfgtop_drv =3D { + .probe =3D clk_mt8173_mfgtop_probe, + .remove_new =3D clk_mt8173_mfgtop_remove, + .driver =3D { + .name =3D "clk-mt8173-mfgtop", + .of_match_table =3D of_match_clk_mt8173_mfgtop, + }, +}; +module_platform_driver(clk_mt8173_mfgtop_drv); + +MODULE_DESCRIPTION("MediaTek MT8173 mfgtop clock driver"); +MODULE_LICENSE("GPL"); --=20 2.45.1.288.g0e0cd299f1-goog