Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1941000/?format=api
{ "id": 1941000, "url": "http://patchwork.ozlabs.org/api/patches/1941000/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/3d4f043db8f4827c6bcf63c23cba00e03a8a2721.1716965617.git.ysato@users.sourceforge.jp/", "project": { "id": 28, "url": "http://patchwork.ozlabs.org/api/projects/28/?format=api", "name": "Linux PCI development", "link_name": "linux-pci", "list_id": "linux-pci.vger.kernel.org", "list_email": "linux-pci@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<3d4f043db8f4827c6bcf63c23cba00e03a8a2721.1716965617.git.ysato@users.sourceforge.jp>", "list_archive_url": null, "date": "2024-05-29T08:01:01", "name": "[DO,NOT,MERGE,v8,15/36] clk: renesas: Add SH7750/7751 CPG Driver", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "7aba4564d4c27cf9605c12bb5f420e82adea8e1a", "submitter": { "id": 7114, "url": "http://patchwork.ozlabs.org/api/people/7114/?format=api", "name": "Yoshinori Sato", "email": "ysato@users.sourceforge.jp" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/3d4f043db8f4827c6bcf63c23cba00e03a8a2721.1716965617.git.ysato@users.sourceforge.jp/mbox/", "series": [ { "id": 408652, "url": "http://patchwork.ozlabs.org/api/series/408652/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=408652", "date": "2024-05-29T08:00:51", "name": "Device Tree support for SH7751 based board", "version": 8, "mbox": "http://patchwork.ozlabs.org/series/408652/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1941000/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1941000/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-pci+bounces-7969-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-pci@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2604:1380:40f1:3f00::1; helo=sy.mirrors.kernel.org;\n envelope-from=linux-pci+bounces-7969-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=153.127.30.23", "smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=users.sourceforge.jp", "smtp.subspace.kernel.org;\n spf=fail smtp.mailfrom=users.sourceforge.jp" ], "Received": [ "from sy.mirrors.kernel.org (sy.mirrors.kernel.org\n [IPv6:2604:1380:40f1:3f00::1])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature ECDSA (secp384r1))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4Vq24f4njzz20Pr\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 May 2024 18:05:38 +1000 (AEST)", "from smtp.subspace.kernel.org (wormhole.subspace.kernel.org\n [52.25.139.140])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby sy.mirrors.kernel.org (Postfix) with ESMTPS id 3FB44B2740C\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 May 2024 08:05:38 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 6939F1779B8;\n\tWed, 29 May 2024 08:01:59 +0000 (UTC)", "from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp\n [153.127.30.23])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 1E77A175549;\n\tWed, 29 May 2024 08:01:57 +0000 (UTC)", "from SIOS1075.ysato.name (al128006.dynamic.ppp.asahi-net.or.jp\n [111.234.128.6])\n\tby sakura.ysato.name (Postfix) with ESMTPSA id 044571C0F53;\n\tWed, 29 May 2024 17:01:54 +0900 (JST)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1716969719; cv=none;\n b=ECHus+Cn8Qi7tacSN018Jw19YuQaawIbwKN8gPfutB6Mfa/N1/6mEATW8EDc3bOAQIPXkC+Hjv3vafAajriPFZPQN9YbVd/cGowFj0Asb4DBb5XjMy38UTWevKjIDxyJP2l/YT/zsGfaT3tB7iU6x5LHfvbYNPiHT0O9+EOicO0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1716969719; c=relaxed/simple;\n\tbh=5TYIRCdROfZPD6bJqJjCWvlz/HuX0IO4NZXzSUELV/M=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t MIME-Version;\n b=WWXjeNDww4hZu8DOqRCp+SREs7OKdyp1xO2rFrLi5TBNcBtcxEM5dk51i2ewDq4LX0scpCvpDMH3LbYScCels0DYmmbXt+KNDiPorUhDXXBAmrRi+IJMnylJji8QDNmp3CYUFQSsWE4JXzmep+IyOqJrH98o7Kva/ovE6O/wEFQ=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=users.sourceforge.jp;\n spf=fail smtp.mailfrom=users.sourceforge.jp;\n arc=none smtp.client-ip=153.127.30.23", "From": "Yoshinori Sato <ysato@users.sourceforge.jp>", "To": "linux-sh@vger.kernel.org", "Cc": "Yoshinori Sato <ysato@users.sourceforge.jp>,\n Damien Le Moal <dlemoal@kernel.org>, Niklas Cassel <cassel@kernel.org>,\n Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,\n Conor Dooley <conor+dt@kernel.org>,\n Geert Uytterhoeven <geert+renesas@glider.be>,\n Michael Turquette <mturquette@baylibre.com>, Stephen Boyd <sboyd@kernel.org>,\n David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,\n Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,\n Maxime Ripard <mripard@kernel.org>, Thomas Zimmermann <tzimmermann@suse.de>,\n Thomas Gleixner <tglx@linutronix.de>, Bjorn Helgaas <bhelgaas@google.com>,\n Lorenzo Pieralisi <lpieralisi@kernel.org>, =?utf-8?q?Krzysztof_Wilczy=C5=84?=\n\t=?utf-8?q?ski?= <kw@linux.com>,\n Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n Jiri Slaby <jirislaby@kernel.org>, Magnus Damm <magnus.damm@gmail.com>,\n Daniel Lezcano <daniel.lezcano@linaro.org>, Rich Felker <dalias@libc.org>,\n John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>,\n Lee Jones <lee@kernel.org>, Helge Deller <deller@gmx.de>,\n Heiko Stuebner <heiko.stuebner@cherry.de>,\n Neil Armstrong <neil.armstrong@linaro.org>,\n Chris Morgan <macromorgan@hotmail.com>, Sebastian Reichel <sre@kernel.org>,\n Linus Walleij <linus.walleij@linaro.org>, Arnd Bergmann <arnd@arndb.de>,\n Masahiro Yamada <masahiroy@kernel.org>, Baoquan He <bhe@redhat.com>,\n Andrew Morton <akpm@linux-foundation.org>,\n Guenter Roeck <linux@roeck-us.net>, Kefeng Wang <wangkefeng.wang@huawei.com>,\n Stephen Rothwell <sfr@canb.auug.org.au>,\n Azeem Shaikh <azeemshaikh38@gmail.com>, Guo Ren <guoren@kernel.org>,\n Max Filippov <jcmvbkbc@gmail.com>, Jernej Skrabec <jernej.skrabec@gmail.com>,\n Herve Codina <herve.codina@bootlin.com>,\n Andy Shevchenko <andriy.shevchenko@linux.intel.com>,\n Anup Patel <apatel@ventanamicro.com>, Jacky Huang <ychuang3@nuvoton.com>,\n Hugo Villeneuve <hvilleneuve@dimonoff.com>, Jonathan Corbet <corbet@lwn.net>,\n Wolfram Sang <wsa+renesas@sang-engineering.com>, =?utf-8?q?Uwe_Kleine-K?=\n\t=?utf-8?q?=C3=B6nig?= <u.kleine-koenig@pengutronix.de>,\n Christophe JAILLET <christophe.jaillet@wanadoo.fr>,\n Sam Ravnborg <sam@ravnborg.org>,\n Javier Martinez Canillas <javierm@redhat.com>,\n Sergey Shtylyov <s.shtylyov@omp.ru>,\n Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>,\n linux-ide@vger.kernel.org, devicetree@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,\n linux-clk@vger.kernel.org, dri-devel@lists.freedesktop.org,\n linux-pci@vger.kernel.org, linux-serial@vger.kernel.org,\n linux-fbdev@vger.kernel.org", "Subject": "[DO NOT MERGE v8 15/36] clk: renesas: Add SH7750/7751 CPG Driver", "Date": "Wed, 29 May 2024 17:01:01 +0900", "Message-Id": "\n <3d4f043db8f4827c6bcf63c23cba00e03a8a2721.1716965617.git.ysato@users.sourceforge.jp>", "X-Mailer": "git-send-email 2.39.2", "In-Reply-To": "<cover.1716965617.git.ysato@users.sourceforge.jp>", "References": "<cover.1716965617.git.ysato@users.sourceforge.jp>", "Precedence": "bulk", "X-Mailing-List": "linux-pci@vger.kernel.org", "List-Id": "<linux-pci.vger.kernel.org>", "List-Subscribe": "<mailto:linux-pci+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-pci+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit" }, "content": "Renesas SH7750 and SH7751 series CPG driver.\nThis driver supported frequency control and clock gating.\n\nSigned-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>\n---\n drivers/clk/renesas/Kconfig | 13 +-\n drivers/clk/renesas/Makefile | 1 +\n drivers/clk/renesas/clk-sh7750.c | 480 +++++++++++++++++++++++++++++++\n 3 files changed, 491 insertions(+), 3 deletions(-)\n create mode 100644 drivers/clk/renesas/clk-sh7750.c", "diff": "diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig\nindex d252150402e8..482efcb6e76e 100644\n--- a/drivers/clk/renesas/Kconfig\n+++ b/drivers/clk/renesas/Kconfig\n@@ -1,8 +1,8 @@\n # SPDX-License-Identifier: GPL-2.0\n \n config CLK_RENESAS\n-\tbool \"Renesas SoC clock support\" if COMPILE_TEST && !ARCH_RENESAS\n-\tdefault y if ARCH_RENESAS\n+\tbool \"Renesas SoC clock support\" if COMPILE_TEST && !ARCH_RENESAS && !SUPERH\n+\tdefault y if ARCH_RENESAS || SUPERH\n \tselect CLK_EMEV2 if ARCH_EMEV2\n \tselect CLK_RZA1 if ARCH_R7S72100\n \tselect CLK_R7S9210 if ARCH_R7S9210\n@@ -41,6 +41,9 @@ config CLK_RENESAS\n \tselect CLK_R9A08G045 if ARCH_R9A08G045\n \tselect CLK_R9A09G011 if ARCH_R9A09G011\n \tselect CLK_SH73A0 if ARCH_SH73A0\n+\tselect CLK_SH7750 if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7750S || \\\n+\t CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751 || \\\n+\t\t\t CPU_SUBTYPE_SH7751R\n \n if CLK_RENESAS\n \n@@ -198,7 +201,6 @@ config CLK_SH73A0\n \tselect CLK_RENESAS_CPG_MSTP\n \tselect CLK_RENESAS_DIV6\n \n-\n # Family\n config CLK_RCAR_CPG_LIB\n \tbool \"CPG/MSSR library functions\" if COMPILE_TEST\n@@ -228,6 +230,11 @@ config CLK_RZG2L\n \tbool \"Renesas RZ/{G2L,G2UL,G3S,V2L} family clock support\" if COMPILE_TEST\n \tselect RESET_CONTROLLER\n \n+config CLK_SH7750\n+\tbool \"Renesas SH7750/7751 family clock support\" if COMPILE_TEST\n+\thelp\n+\t This is a driver for SH7750 / SH7751 CPG.\n+\n # Generic\n config CLK_RENESAS_CPG_MSSR\n \tbool \"CPG/MSSR clock support\" if COMPILE_TEST\ndiff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile\nindex f7e18679c3b8..ea0ffa8d59c4 100644\n--- a/drivers/clk/renesas/Makefile\n+++ b/drivers/clk/renesas/Makefile\n@@ -38,6 +38,7 @@ obj-$(CONFIG_CLK_R9A07G054)\t\t+= r9a07g044-cpg.o\n obj-$(CONFIG_CLK_R9A08G045)\t\t+= r9a08g045-cpg.o\n obj-$(CONFIG_CLK_R9A09G011)\t\t+= r9a09g011-cpg.o\n obj-$(CONFIG_CLK_SH73A0)\t\t+= clk-sh73a0.o\n+obj-$(CONFIG_CLK_SH7750)\t\t+= clk-sh7750.o\n \n # Family\n obj-$(CONFIG_CLK_RCAR_CPG_LIB)\t\t+= rcar-cpg-lib.o\ndiff --git a/drivers/clk/renesas/clk-sh7750.c b/drivers/clk/renesas/clk-sh7750.c\nnew file mode 100644\nindex 000000000000..6f1580ce96c5\n--- /dev/null\n+++ b/drivers/clk/renesas/clk-sh7750.c\n@@ -0,0 +1,480 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Renesas SH7750/51 CPG driver\n+ *\n+ * Copyright 2023 Yoshinori Sato <ysato@users.sourceforge.jp>\n+ */\n+\n+#include <linux/clkdev.h>\n+#include <linux/clk-provider.h>\n+#include <linux/err.h>\n+#include <linux/of.h>\n+#include <linux/of_address.h>\n+#include <linux/io.h>\n+#include <linux/platform_device.h>\n+\n+/* PCLK divide rate selector */\n+static const struct clk_div_table pdiv_table[] = {\n+\t{ .val = 0, .div = 2, },\n+\t{ .val = 1, .div = 3, },\n+\t{ .val = 2, .div = 4, },\n+\t{ .val = 3, .div = 6, },\n+\t{ .val = 4, .div = 8, },\n+\t{ }\n+};\n+\n+/* ICLK and BCLK divide rate selector */\n+static const struct clk_div_table div_table[] = {\n+\t{ .val = 0, .div = 1, },\n+\t{ .val = 1, .div = 2, },\n+\t{ .val = 2, .div = 3, },\n+\t{ .val = 3, .div = 4, },\n+\t{ .val = 4, .div = 6, },\n+\t{ .val = 5, .div = 8, },\n+\t{ }\n+};\n+\n+struct cpg_priv {\n+\tstruct clk_hw hw;\n+\tspinlock_t clklock;\n+\tvoid __iomem *frqcr;\n+\tvoid __iomem *clkstp00;\n+\tu32 mode;\n+\tu32 feat;\n+};\n+\n+/* CPG feature flag */\n+#define CPG_DIV1\tBIT(0)\t/* 7750, 7750S, 7751 */\n+#define MSTP_CR2\tBIT(1)\t/* 7750S, 7750R, 7751, 7751R */\n+#define MSTP_CLKSTP\tBIT(2)\t/* 7750R, 7751, 7751R */\n+#define MSTP_CSTP2\tBIT(3)\t/* 7751, 7751R */\n+\n+enum {\n+\tCPG_SH7750,\n+\tCPG_SH7750S,\n+\tCPG_SH7750R,\n+\tCPG_SH7751,\n+\tCPG_SH7751R,\n+};\n+\n+static const u32 cpg_feature[] = {\n+\t[CPG_SH7750] = CPG_DIV1,\n+\t[CPG_SH7750S] = CPG_DIV1 | MSTP_CR2,\n+\t[CPG_SH7750R] = MSTP_CR2 | MSTP_CLKSTP,\n+\t[CPG_SH7751] = CPG_DIV1 | MSTP_CR2 | MSTP_CLKSTP | MSTP_CSTP2,\n+\t[CPG_SH7751R] = MSTP_CR2 | MSTP_CLKSTP | MSTP_CSTP2,\n+};\n+\n+enum clk_type {CLK_DIV, CLK_STBCR, CLK_STBCR2, CLK_CLKSTP00};\n+\n+enum {\n+\tFRQCR = 0,\n+\tSTBCR = 4,\n+\tWTCNT = 8,\n+\tWTCSR = 12,\n+\tSTBCR2 = 16,\n+\tCLKSTP00 = 0,\n+\tCLKSTPCLR00 = 8,\n+};\n+\n+static struct cpg_priv *cpg_data;\n+\n+#define to_priv(_hw) container_of(_hw, struct cpg_priv, hw)\n+\n+#define FRQCR_PLL1EN BIT(10)\n+static const unsigned int pll1mult[] = { 12, 12, 6, 12, 6, 12, 1};\n+\n+static unsigned long pll_recalc_rate(struct clk_hw *hw,\n+\t\t\t\t unsigned long parent_rate)\n+{\n+\tstruct cpg_priv *cpg = to_priv(hw);\n+\tunsigned long rate = parent_rate;\n+\tu16 frqcr;\n+\n+\tfrqcr = ioread16(cpg->frqcr);\n+\tif (frqcr & FRQCR_PLL1EN) {\n+\t\trate *= pll1mult[cpg->mode];\n+\t\tif (cpg->mode < 6 && (cpg->feat & CPG_DIV1))\n+\t\t\trate /= 2;\n+\t}\n+\treturn rate;\n+}\n+\n+static void get_round_rate(struct cpg_priv *cpg,\n+\t\t\t unsigned long *out, bool *pllen,\n+\t\t\t unsigned long rate, unsigned long prate)\n+{\n+\tlong pllout, res;\n+\tbool pll;\n+\n+\tif (cpg->mode < 6 && (cpg->feat & CPG_DIV1))\n+\t\tprate /= 2;\n+\n+\tpllout = prate * pll1mult[cpg->mode];\n+\tif (abs(pllout - rate) > abs(prate - rate)) {\n+\t\tres = prate;\n+\t\tpll = false;\n+\t} else {\n+\t\tres = pllout;\n+\t\tpll = true;\n+\t}\n+\tif (out)\n+\t\t*out = res;\n+\tif (pllen)\n+\t\t*pllen = pll;\n+}\n+\n+static int pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)\n+{\n+\tstruct cpg_priv *cpg = to_priv(hw);\n+\n+\tget_round_rate(cpg, &req->rate, NULL, req->rate, req->best_parent_rate);\n+\treturn 0;\n+}\n+\n+static int pll_set_rate(struct clk_hw *hw,\n+\t\t\tunsigned long rate, unsigned long prate)\n+{\n+\tstruct cpg_priv *cpg = to_priv(hw);\n+\tbool oldpll, newpll;\n+\tu16 frqcr;\n+\n+\tfrqcr = ioread16(cpg->frqcr);\n+\tget_round_rate(cpg, NULL, &newpll, rate, prate);\n+\toldpll = frqcr & FRQCR_PLL1EN;\n+\tfrqcr &= ~FRQCR_PLL1EN;\n+\n+\tif (newpll) {\n+\t\tfrqcr |= FRQCR_PLL1EN;\n+\t\tif (!oldpll) {\n+\t\t\t/* set PLL wakeup delay time */\n+\t\t\tiowrite16(0xa500, cpg->frqcr + WTCNT);\n+\t\t\tiowrite16(0xa507, cpg->frqcr + WTCNT);\n+\t\t\tiowrite16(0x5a00, cpg->frqcr + WTCSR);\n+\t\t}\n+\t}\n+\tiowrite16(frqcr, cpg->frqcr);\n+\n+\t/* Test for new PLL state */\n+\tfrqcr = ioread16(cpg->frqcr);\n+\toldpll = frqcr & FRQCR_PLL1EN;\n+\treturn !(oldpll == newpll);\n+}\n+\n+static const struct clk_ops pll_ops = {\n+\t.recalc_rate = pll_recalc_rate,\n+\t.determine_rate = pll_determine_rate,\n+\t.set_rate = pll_set_rate,\n+};\n+\n+#define PLLOUT \"pllout\"\n+\n+static int register_pll(struct device_node *node, struct cpg_priv *cpg)\n+{\n+\tconst char *clk_name = node->name;\n+\tconst char *parent_name;\n+\tstruct clk_init_data init = {\n+\t\t.name = PLLOUT,\n+\t\t.ops = &pll_ops,\n+\t\t.flags = 0,\n+\t\t.num_parents = 1,\n+\t};\n+\tint ret;\n+\n+\tparent_name = of_clk_get_parent_name(node, 0);\n+\tinit.parent_names = &parent_name;\n+\tcpg->hw.init = &init;\n+\n+\tret = of_clk_hw_register(node, &cpg->hw);\n+\tif (ret < 0)\n+\t\tpr_err(\"%pOF: failed to register pll clock %s (%d)\\n\",\n+\t\t node, clk_name, ret);\n+\treturn ret;\n+}\n+\n+static void clkstp00_sw(struct clk_hw *hw, bool on)\n+{\n+\tu32 val;\n+\tstruct clk_gate *gate = to_clk_gate(hw);\n+\n+\tval = BIT(gate->bit_idx);\n+\tif (on)\n+\t\twritel(val, gate->reg + CLKSTPCLR00);\n+\telse\n+\t\twritel(val, gate->reg);\n+}\n+\n+static int clkstp00_enable(struct clk_hw *hw)\n+{\n+\tclkstp00_sw(hw, true);\n+\treturn 0;\n+}\n+\n+static void clkstp00_disable(struct clk_hw *hw)\n+{\n+\tclkstp00_sw(hw, false);\n+}\n+\n+static int clkstp00_is_enabled(struct clk_hw *hw)\n+{\n+\tu8 val;\n+\tstruct clk_gate *gate = to_clk_gate(hw);\n+\n+\tval = readb(gate->reg);\n+\tval &= 1 << gate->bit_idx;\n+\treturn val == 0;\n+}\n+\n+static const struct clk_ops gate_clkstp00_ops = {\n+\t.enable = clkstp00_enable,\n+\t.disable = clkstp00_disable,\n+\t.is_enabled = clkstp00_is_enabled,\n+};\n+\n+static struct clk_hw *clk_hw_register_clkstp(struct device_node *node,\n+\t\t\t\t\t const char *name,\n+\t\t\t\t\t const char *parent,\n+\t\t\t\t\t void __iomem *reg, int bit,\n+\t\t\t\t\t spinlock_t *lock)\n+{\n+\tstruct clk_gate *gate;\n+\tstruct clk_init_data init = {\n+\t\t.name = name,\n+\t\t.ops = &gate_clkstp00_ops,\n+\t\t.flags = 0,\n+\t\t.parent_names = &parent,\n+\t\t.num_parents = 1,\n+\t};\n+\tstruct clk_hw *hw;\n+\tint ret;\n+\n+\tgate = kzalloc(sizeof(*gate), GFP_KERNEL);\n+\tif (gate == NULL)\n+\t\tgoto error;\n+\tgate->reg = reg;\n+\tgate->bit_idx = bit;\n+\tgate->flags = 0;\n+\tgate->lock = lock;\n+\tgate->hw.init = &init;\n+\thw = &gate->hw;\n+\tret = of_clk_hw_register(node, hw);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\treturn hw;\n+error:\n+\tkfree(gate);\n+\treturn ERR_PTR(ret);\n+}\n+\n+#define STBCR_BASE 5\n+#define CLKSTP_BASE 2\n+static int register_div(struct device_node *node, struct cpg_priv *cpg)\n+{\n+\tstatic const char * const divout[] = {\n+\t\t\"fck\", \"bck\", \"ick\",\n+\t};\n+\tstatic const char * const stbcrout[] = {\n+\t\t\"sci_clk\", \"rtc_clk\", \"tmu012_clk\",\t/* STBCR */\n+\t\t\"scif_clk\", \"dmac_clk\",\t\t\t/* STBCR */\n+\t\t\"ubc_clk\", \"sq_clk\",\t\t\t/* STBCR2 */\n+\t};\n+\tstatic const char * const clkstpout[] = {\n+\t\t\"intc_clk\", \"tmu34_clk\", \"pcic_clk\",\t/* CLKSTP00 */\n+\t};\n+\n+\tint num_clk = ARRAY_SIZE(divout) + ARRAY_SIZE(stbcrout) + ARRAY_SIZE(clkstpout);\n+\tstruct clk_hw_onecell_data *data;\n+\tstruct clk_hw *reg_hw;\n+\tunsigned int i, n;\n+\tint ret;\n+\n+\tdata = kzalloc(struct_size(data, hws, num_clk + 1), GFP_KERNEL);\n+\tif (!data)\n+\t\treturn -ENOMEM;\n+\n+\tnum_clk = 0;\n+\tfor (i = 0; i < ARRAY_SIZE(divout); i++) {\n+\t\treg_hw = __clk_hw_register_divider(NULL, node, divout[i],\n+\t\t\t\t\t\t PLLOUT, NULL, NULL,\n+\t\t\t\t\t\t 0, cpg->frqcr, i * 3, 3,\n+\t\t\t\t\t\t CLK_DIVIDER_REG_16BIT,\n+\t\t\t\t\t\t (i == 0) ? pdiv_table : div_table,\n+\t\t\t\t\t\t &cpg->clklock);\n+\t\tif (IS_ERR(reg_hw)) {\n+\t\t\tret = PTR_ERR(reg_hw);\n+\t\t\tgoto error;\n+\t\t}\n+\t\tdata->hws[num_clk++] = reg_hw;\n+\t}\n+\n+\tn = (cpg->feat & MSTP_CR2) ? ARRAY_SIZE(stbcrout) : STBCR_BASE;\n+\tfor (i = 0; i < n; i++) {\n+\t\tu32 off = (i < (ARRAY_SIZE(stbcrout) - 2)) ? STBCR : STBCR2;\n+\n+\t\treg_hw = __clk_hw_register_gate(NULL, node, stbcrout[i],\n+\t\t\t\t\t\tdivout[0], NULL, NULL,\n+\t\t\t\t\t\t0, cpg->frqcr + off, i % STBCR_BASE,\n+\t\t\t\t\t\tCLK_GATE_REG_8BIT | CLK_GATE_SET_TO_DISABLE,\n+\t\t\t\t\t\t&cpg->clklock);\n+\t\tif (IS_ERR(reg_hw)) {\n+\t\t\tret = PTR_ERR(reg_hw);\n+\t\t\tgoto error;\n+\t\t}\n+\t\tdata->hws[num_clk++] = reg_hw;\n+\t}\n+\n+\tif (cpg->feat & MSTP_CLKSTP) {\n+\t\tn = (cpg->feat & MSTP_CSTP2) ? ARRAY_SIZE(clkstpout) : CLKSTP_BASE;\n+\t\tfor (i = 0; i < n; i++) {\n+\t\t\treg_hw = clk_hw_register_clkstp(node, clkstpout[i],\n+\t\t\t\t\t\t\tdivout[0], cpg->clkstp00,\n+\t\t\t\t\t\t\ti, &cpg->clklock);\n+\t\t\tif (IS_ERR(reg_hw)) {\n+\t\t\t\tret = PTR_ERR(reg_hw);\n+\t\t\t\tgoto error;\n+\t\t\t}\n+\t\t\tdata->hws[num_clk++] = reg_hw;\n+\t\t}\n+\t}\n+\n+\tdata->num = num_clk;\n+\tret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\treturn 0;\n+\n+error:\n+\tpr_err(\"%pOF: failed to register clock divider (%d)\\n\",\n+\t node, ret);\n+\tfor (num_clk--; num_clk >= 0; num_clk--)\n+\t\tkfree(data->hws[num_clk]);\n+\tkfree(data);\n+\treturn ret;\n+}\n+\n+#define NR_CLKMODE 7\n+static int sh7750_cpg_setup(struct device_node *node, u32 feat)\n+{\n+\tstruct cpg_priv *cpg;\n+\tu32 mode = NR_CLKMODE;\n+\tint ret = 0;\n+\n+\tcpg_data = NULL;\n+\n+\tof_property_read_u32_index(node, \"renesas,mode\", 0, &mode);\n+\tif (mode >= NR_CLKMODE) {\n+\t\tpr_err(\"%s: Invalid clock mode setting (%u)\\n\",\n+\t\t node->name, mode);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcpg = kzalloc(sizeof(struct cpg_priv), GFP_KERNEL);\n+\tif (!cpg)\n+\t\treturn -ENOMEM;\n+\n+\tcpg->frqcr = of_iomap(node, 0);\n+\tif (cpg->frqcr == NULL) {\n+\t\tpr_err(\"%pOF: failed to map divide register\", node);\n+\t\tret = -ENODEV;\n+\t\tgoto cpg_free;\n+\t}\n+\n+\tif (feat & MSTP_CLKSTP) {\n+\t\tcpg->clkstp00 = of_iomap(node, 1);\n+\t\tif (cpg->clkstp00 == NULL) {\n+\t\t\tpr_err(\"%pOF: failed to map clkstp00 register\", node);\n+\t\t\tret = -ENODEV;\n+\t\t\tgoto unmap_frqcr;\n+\t\t}\n+\t}\n+\tcpg->feat = feat;\n+\tcpg->mode = mode;\n+\n+\tret = register_pll(node, cpg);\n+\tif (ret < 0)\n+\t\tgoto unmap_clkstp00;\n+\n+\tret = register_div(node, cpg);\n+\tif (ret < 0)\n+\t\tgoto unmap_clkstp00;\n+\n+\tcpg_data = cpg;\n+\treturn 0;\n+\n+unmap_clkstp00:\n+\tiounmap(cpg->clkstp00);\n+unmap_frqcr:\n+\tiounmap(cpg->frqcr);\n+cpg_free:\n+\tkfree(cpg);\n+\treturn ret;\n+}\n+\n+static void __init sh7750_cpg_init(struct device_node *node)\n+{\n+\tsh7750_cpg_setup(node, cpg_feature[CPG_SH7750]);\n+}\n+\n+static void __init sh7750s_cpg_init(struct device_node *node)\n+{\n+\tsh7750_cpg_setup(node, cpg_feature[CPG_SH7750S]);\n+}\n+\n+static void __init sh7750r_cpg_init(struct device_node *node)\n+{\n+\tsh7750_cpg_setup(node, cpg_feature[CPG_SH7750R]);\n+}\n+\n+static void __init sh7751_cpg_init(struct device_node *node)\n+{\n+\tsh7750_cpg_setup(node, cpg_feature[CPG_SH7751]);\n+}\n+\n+static void __init sh7751r_cpg_init(struct device_node *node)\n+{\n+\tsh7750_cpg_setup(node, cpg_feature[CPG_SH7751R]);\n+}\n+\n+CLK_OF_DECLARE_DRIVER(sh7750_cpg, \"renesas,sh7750-cpg\",\n+\t\t sh7750_cpg_init);\n+CLK_OF_DECLARE_DRIVER(sh7750s_cpg, \"renesas,sh7750s-cpg\",\n+\t\t sh7750s_cpg_init);\n+CLK_OF_DECLARE_DRIVER(sh7750r_cpg, \"renesas,sh7750r-cpg\",\n+\t\t sh7750r_cpg_init);\n+CLK_OF_DECLARE_DRIVER(sh7751_cpg, \"renesas,sh7751-cpg\",\n+\t\t sh7751_cpg_init);\n+CLK_OF_DECLARE_DRIVER(sh7751r_cpg, \"renesas,sh7751r-cpg\",\n+\t\t sh7751r_cpg_init);\n+\n+static int sh7750_cpg_probe(struct platform_device *pdev)\n+{\n+\tu32 feature;\n+\n+\tif (cpg_data)\n+\t\treturn 0;\n+\tfeature = *(u32 *)of_device_get_match_data(&pdev->dev);\n+\treturn sh7750_cpg_setup(pdev->dev.of_node, feature);\n+}\n+\n+static const struct of_device_id sh7750_cpg_of_match[] = {\n+\t{ .compatible = \"renesas,sh7750-cpg\",\n+\t .data = &cpg_feature[CPG_SH7750] },\n+\t{ .compatible = \"renesas,sh7750s-cpg\",\n+\t .data = &cpg_feature[CPG_SH7750S] },\n+\t{ .compatible = \"renesas,sh7750r-cpg\",\n+\t .data = &cpg_feature[CPG_SH7750R] },\n+\t{ .compatible = \"renesas,sh7751-cpg\",\n+\t .data = &cpg_feature[CPG_SH7751] },\n+\t{ .compatible = \"renesas,sh7751r-cpg\",\n+\t .data = &cpg_feature[CPG_SH7751R] },\n+\t{ }\n+};\n+\n+static struct platform_driver sh7750_cpg_driver = {\n+\t.probe = sh7750_cpg_probe,\n+\t.driver = {\n+\t\t.name = \"sh7750-cpg\",\n+\t\t.of_match_table = sh7750_cpg_of_match,\n+\t},\n+};\n+builtin_platform_driver(sh7750_cpg_driver);\n", "prefixes": [ "DO", "NOT", "MERGE", "v8", "15/36" ] }