From patchwork Thu Aug 22 15:27:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudiu Beznea X-Patchwork-Id: 13773832 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6AE3C5321D for ; Thu, 22 Aug 2024 15:54:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8yZE+/BMdqFGWB41aHQFfqwrB0gC3abtJVPkg8S54GU=; b=Nw31eVbtX3j69U Ow98kNz28ZGMm7/m1LxBkB8mv63I/h524/EXwI3FPwH5aSp5h0fYS6pI+C4EpQ2QCyMGRwiwNJDnq 3yK2sFrjvxltnMG5uIYa/VfyRRPNCef4pw39pT74WbrxZ1MmGrORqXfiQnTY766bDHZ9zMlSz6Ali nxrUWY7xGGKNoq4brTr2S5qZnztBVHIYjUXvWkSQxVvPyHL5gElYPsUadLpv1JsFiaWCQKNDSr+En DfU7FRSoSzDN9IXjwxInyeCr26e4Pnefjff402IuE4zZg7FyrxOvt1PxgwcbXzOcAnJasImAkOcUL +e8VQgoIEKTerQcDiptw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1shA8y-0000000DRV9-2Iac; Thu, 22 Aug 2024 15:54:36 +0000 Received: from mail-ej1-x62d.google.com ([2a00:1450:4864:20::62d]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sh9jd-0000000DKnn-44eL for linux-phy@lists.infradead.org; Thu, 22 Aug 2024 15:28:27 +0000 Received: by mail-ej1-x62d.google.com with SMTP id a640c23a62f3a-a864574429aso141571466b.0 for ; Thu, 22 Aug 2024 08:28:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tuxon.dev; s=google; t=1724340504; x=1724945304; darn=lists.infradead.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=+9DOBqvnZ/STjSdrebzztVFaplbBr0hBrOhxjpVMxCw=; b=AaxbVr81B/oBz2JLcg+2YJMBcWQhYcN0sggoW0UTXmLAD4PVgxuzBOtAaVBpLr9sDO BLqYkrZGr/+Er+3Syr2bqodmvKU8a+wVf+TzL2XB1EXA/DqXPwIRPSKNp7eaPzrbRo1q rjJ31lNo2MUJdyIQaCADMQyeG90KuqmRihLsw5BwiVQ8h8GS9r+Z2dno6ITO2M6KgTLJ Z+qeosO1lPYsIXcqOkq8vTVrhYLMn7EX0udJo+grdRm7DaWQhoCtDu1t/qqb1UpVWFsK JkM9AjfYKswRXdyr1mlFKc4hNGTDMnpFlW5ozquwKxZ3Coq0/CRaKJv75nCRZafxclfz F3iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724340504; x=1724945304; 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=+9DOBqvnZ/STjSdrebzztVFaplbBr0hBrOhxjpVMxCw=; b=uTPoMcYlhJw7TE34W5wcxSmVBwBpX4gVV9n5CFk9BIFkKW34EbMbyUIux+qzTBaS8l nTYLAMA7eroNTUg9Tuzn+HO0KVnZ9c9aMsXuLSAQmMPMnLPzoV0LOZpf6lpdEzi+PSqA KvHdymqAGLlujPRdHUFZy7ZbAiOdYoT7BTu/giF37gjN6KKkq9ratswDP0QIbvqGn2vv mvZMGJcSOU13CBiglOx85trZXmDlWXJXlVSpGK92pzxUjjtP7ewkwiB1xzDp5yAE7nw9 IEA30L3vHLafs6VblW/i/9KlbHNkeaPj+JiI4V08y8WDokRDvay6wb7Zu71NKl+oG/dx Y/rg== X-Gm-Message-State: AOJu0YyRjXkRx0BgeTOJaE+Ocv5Fj/kCcg9LLJRzZfQC3EMopp0psPNR nQ/iWNf0ql5wyHyMcYPchBjvVe6U7b9OFHLCHI8M39VdsPovroJ4xSql7oCXqVc= X-Google-Smtp-Source: AGHT+IFlSIRkRZTOFLNyPatfUw5Y174bZy9lMxma4FnpCObFSnO03fmX9lo7w0eBmJXtveDmWb0cnA== X-Received: by 2002:a17:907:7f25:b0:a7a:b561:3564 with SMTP id a640c23a62f3a-a8691cb98f9mr188865766b.61.1724340504353; Thu, 22 Aug 2024 08:28:24 -0700 (PDT) Received: from claudiu-X670E-Pro-RS.. ([82.78.167.177]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a868f484dc5sm134189166b.171.2024.08.22.08.28.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Aug 2024 08:28:23 -0700 (PDT) From: Claudiu X-Google-Original-From: Claudiu To: vkoul@kernel.org, kishon@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, p.zabel@pengutronix.de, geert+renesas@glider.be, magnus.damm@gmail.com, gregkh@linuxfoundation.org, mturquette@baylibre.com, sboyd@kernel.org, yoshihiro.shimoda.uh@renesas.com, biju.das.jz@bp.renesas.com, ulf.hansson@linaro.org Cc: linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, linux-pm@vger.kernel.org, claudiu.beznea@tuxon.dev, Claudiu Beznea Subject: [PATCH 04/16] soc: renesas: Add SYSC driver for Renesas RZ/G3S Date: Thu, 22 Aug 2024 18:27:49 +0300 Message-Id: <20240822152801.602318-5-claudiu.beznea.uj@bp.renesas.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240822152801.602318-1-claudiu.beznea.uj@bp.renesas.com> References: <20240822152801.602318-1-claudiu.beznea.uj@bp.renesas.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240822_082826_087162_B2FAB490 X-CRM114-Status: GOOD ( 30.33 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org From: Claudiu Beznea The RZ/G3S SYS Controller has 2 registers (one for PCIE one for USB) that need to be configured before/after powering off/on the PCI or USB ares. The bits in these registers control signals to PCIE and USB that need to be de-asserted/asserted after/before power on/off event. For this add SYSC controller driver that registers a reset controller driver on auxiliary bus which allows USB, PCIE drivers to control these signals. Signed-off-by: Claudiu Beznea --- Hi, Philipp, Ulf, Geert, all, In this series the control of USB and PCIE signals was implemented though a reset control driver. This approach was chosen as a result of looking though the HW manual and trying to understand how these signals behave. HW manual can be downloaded from [1] (download manual hardware button -> confirm -> extract archive -> Deliverables -> r01uh1014ej0110-rzg3s.pdf). The description of the USB and PCIE control registers is as follows: SYS_USB_PWRRDY Register (Signal is called PWRRDY), Chapter 6.3.83: Controls PWRRDY terminal of USB: 0: PWRRDY 1: PWRRDY down When turning off the USB region power, set this bit to 1. When turning on the USB region power, set this bit to 0. SYS_PCIE_RST_RSM_B (Signal is called RST_RSM_B), Chapter 6.3.84: Controls RST_RSM_B terminal of PCIe 0: RST_RSM_B=0 1: RST_RSM_B=1 Set RST_RSM_B=1 after PCIe power is applied. When the power in the PCIe region is turned off, set RST_RSM_B=0 before turning off the power supply. From this description I understood that the control of the USB PWRRDY, PCIE RST_RSM_B signals and the power control for the domains the USB, PCI belongs are different things [A]. As of Figure 41.1 (Power Domain and Power Supply) and Table 41.1 (Power Domain to which Power Supply Pins Belong) the USB and PCIE belongs to PD_ISOVCC power domain controlled though PMIC [B]. The USB, PCI signals are also reference in HW manual in the low power consumption chapter describing the transition to different power modes. E.g., chapter 41.6.1 (ALL_ON to VBATT), Table 41.8 (Example Transition Flow Outline from ALL_ON Mode to VBATT Mode) says at steps 6 and 7: 6. USB PHY PWRRDY signal control (if using USB) SYS_USB_PWRRDY 7. PCIe RST_RSM_B signal control (if using PCIe) SYS_PCIE_RST_RSM_B Meaning these signals need to be controlled before going to VBATT power mode (where the power supply to USB is turned off) [C]. Due to [A], [B] and [C] I chosed to have the implementation of these signals though a reset control driver. Other option I explored was though power domains as follows: 1/ registering one domain for USB, one of PCIE 2/ passed the domain ID to USB though device tree 3/ attach from USB PHY control driver to the USB power domain with dev_pm_domain_attach_by_name() 4/ and controlling the SYSC registers with pm_runtime_resume_and_get(usb_sysc_domain). Please let me know what do you think about this! Thank you, Claudiu Beznea [1] https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-mpus/rzg3s-general-purpose-microprocessors-single-core-arm-cortex-a55-11-ghz-cpu-and-dual-core-cortex-m33-250 drivers/reset/Kconfig | 7 + drivers/reset/Makefile | 1 + drivers/reset/reset-rzg3s-sysc.c | 140 +++++++++++++++++++ drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/rzg3s-sysc.c | 113 +++++++++++++++ include/linux/soc/renesas/rzg3s-sysc-reset.h | 24 ++++ 6 files changed, 286 insertions(+) create mode 100644 drivers/reset/reset-rzg3s-sysc.c create mode 100644 drivers/soc/renesas/rzg3s-sysc.c create mode 100644 include/linux/soc/renesas/rzg3s-sysc-reset.h diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 67bce340a87e..fbdf860b2293 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -218,6 +218,13 @@ config RESET_RZG2L_USBPHY_CTRL Support for USBPHY Control found on RZ/G2L family. It mainly controls reset and power down of the USB/PHY. +config RESET_RZG3S_SYSC + tristate "Renesas RZ/G3S SYSC reset driver" + depends on ARCH_R9A08G045 || COMPILE_TEST + help + Support for SYSC reset found on RZ/G3S family. It mainly + controls reset on USB and PCIE. + config RESET_SCMI tristate "Reset driver controlled via ARM SCMI interface" depends on ARM_SCMI_PROTOCOL || COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 27b0bbdfcc04..ee5ca21acc44 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o +obj-$(CONFIG_RESET_RZG3S_SYSC) += reset-rzg3s-sysc.o obj-$(CONFIG_RESET_SCMI) += reset-scmi.o obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o diff --git a/drivers/reset/reset-rzg3s-sysc.c b/drivers/reset/reset-rzg3s-sysc.c new file mode 100644 index 000000000000..56af03f1d8a2 --- /dev/null +++ b/drivers/reset/reset-rzg3s-sysc.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G3S SYSC reset driver + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define RZG3S_SYSC_USB_PWRRDY 0xd70 +#define RZG3S_SYSC_PCIE_RST_RSM_B 0xd74 +#define RZG3S_SYSC_RESET_MASK 0x1 + +/** + * struct rzg3s_sysc_reset_info - SYSC reset information + * @offset: offset to configure the reset + * @assert_val: value to write to register on assert + * @deassert_val: value to write to register on de-assert + */ +struct rzg3s_sysc_reset_info { + u16 offset; + u8 assert_val; + u8 deassert_val; +}; + +/** + * struct rzg3s_sysc_reset - SYSC reset + * @info: SYSC reset information + * @radev: SYSC reset auxiliary device + * @rcdev: reset controller device + */ +struct rzg3s_sysc_reset { + const struct rzg3s_sysc_reset_info *info; + struct rzg3s_sysc_reset_adev *radev; + struct reset_controller_dev rcdev; +}; + +#define to_rzg3s_sysc_reset(r) container_of(r, struct rzg3s_sysc_reset, rcdev) + +static int rzg3s_sysc_reset_set(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct rzg3s_sysc_reset *reset = to_rzg3s_sysc_reset(rcdev); + struct rzg3s_sysc_reset_adev *radev = reset->radev; + struct rzg3s_sysc_reset_info info = reset->info[id]; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(radev->lock, flags); + tmp = readl(radev->base + info.offset); + tmp &= ~RZG3S_SYSC_RESET_MASK; + tmp |= assert ? info.assert_val : info.deassert_val; + writel(tmp, radev->base + info.offset); + spin_unlock_irqrestore(radev->lock, flags); + + return 0; +} + +static int rzg3s_sysc_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return rzg3s_sysc_reset_set(rcdev, id, true); +} + +static int rzg3s_sysc_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return rzg3s_sysc_reset_set(rcdev, id, false); +} + +static int rzg3s_sysc_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg3s_sysc_reset *reset = to_rzg3s_sysc_reset(rcdev); + const struct rzg3s_sysc_reset_info info = reset->info[id]; + struct rzg3s_sysc_reset_adev *radev = reset->radev; + u32 tmp; + + tmp = readl(radev->base + info.offset); + tmp = !!(tmp & RZG3S_SYSC_RESET_MASK); + + return info.assert_val ? tmp : !tmp; +} + +static const struct reset_control_ops rzg3s_sysc_reset_ops = { + .assert = rzg3s_sysc_reset_assert, + .deassert = rzg3s_sysc_reset_deassert, + .status = rzg3s_sysc_reset_status, +}; + +static const struct rzg3s_sysc_reset_info rzg3s_sysc_reset_info[] = { + [R9A08G045_SYSC_RESET_USB] = { + .offset = RZG3S_SYSC_USB_PWRRDY, .assert_val = 1, .deassert_val = 0 + }, + [R9A08G045_SYSC_RESET_PCIE] = { + .offset = RZG3S_SYSC_PCIE_RST_RSM_B, .assert_val = 0, .deassert_val = 1 + }, +}; + +static int rzg3s_sysc_reset_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct rzg3s_sysc_reset_adev *reset_adev = to_rzg3s_sysc_reset_adev(adev); + struct device *dev = &adev->dev; + struct rzg3s_sysc_reset *reset; + + reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL); + if (!reset) + return -ENOMEM; + + reset->radev = reset_adev; + reset->info = rzg3s_sysc_reset_info; + + reset->rcdev.ops = &rzg3s_sysc_reset_ops; + reset->rcdev.of_reset_n_cells = 1; + reset->rcdev.nr_resets = ARRAY_SIZE(rzg3s_sysc_reset_info); + reset->rcdev.of_node = dev->parent->of_node; + reset->rcdev.dev = dev; + + return devm_reset_controller_register(dev, &reset->rcdev); +} + +static const struct auxiliary_device_id rzg3s_sysc_reset_ids[] = { + { .name = "rzg3s_sysc.reset" }, + { } +}; +MODULE_DEVICE_TABLE(auxiliary, rzg3s_sysc_reset_ids); + +static struct auxiliary_driver rzg3s_sysc_reset_driver = { + .probe = rzg3s_sysc_reset_probe, + .id_table = rzg3s_sysc_reset_ids, +}; +module_auxiliary_driver(rzg3s_sysc_reset_driver); diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 734f8f8cefa4..74c72ac46f91 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o ifdef CONFIG_SMP obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o endif +obj-$(CONFIG_ARCH_R9A08G045) += rzg3s-sysc.o # Family obj-$(CONFIG_PWC_RZV2M) += pwc-rzv2m.o diff --git a/drivers/soc/renesas/rzg3s-sysc.c b/drivers/soc/renesas/rzg3s-sysc.c new file mode 100644 index 000000000000..e664d29ce5c3 --- /dev/null +++ b/drivers/soc/renesas/rzg3s-sysc.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G3S System controller driver + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include +#include + +#include + +/** + * struct rzg3s_sysc - SYSC private data structure + * @base: base address + * @dev: device + * @lock: lock + */ +struct rzg3s_sysc { + void __iomem *base; + struct device *dev; + spinlock_t lock; +}; + +static void rzg3s_sysc_reset_adev_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + struct rzg3s_sysc_reset_adev *reset_adev = to_rzg3s_sysc_reset_adev(adev); + + kfree(reset_adev); +} + +static void rzg3s_sysc_reset_unregister_adev(void *adev) +{ + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +static int rzg3s_sysc_reset_probe(struct rzg3s_sysc *sysc, const char *adev_name, + u32 adev_id) +{ + struct rzg3s_sysc_reset_adev *radev; + struct auxiliary_device *adev; + int ret; + + radev = kzalloc(sizeof(*radev), GFP_KERNEL); + if (!radev) + return -ENOMEM; + + radev->base = sysc->base; + radev->lock = &sysc->lock; + + adev = &radev->adev; + adev->name = adev_name; + adev->dev.parent = sysc->dev; + adev->dev.release = rzg3s_sysc_reset_adev_release; + adev->id = adev_id; + + ret = auxiliary_device_init(adev); + if (ret) + return ret; + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + return devm_add_action_or_reset(sysc->dev, rzg3s_sysc_reset_unregister_adev, adev); +} + +static int rzg3s_sysc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rzg3s_sysc *sysc; + + sysc = devm_kzalloc(dev, sizeof(*sysc), GFP_KERNEL); + if (!sysc) + return -ENOMEM; + + sysc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sysc->base)) + return PTR_ERR(sysc->base); + + sysc->dev = dev; + spin_lock_init(&sysc->lock); + + return rzg3s_sysc_reset_probe(sysc, "reset", 0); +} + +static const struct of_device_id rzg3s_sysc_match[] = { + { .compatible = "renesas,r9a08g045-sysc" }, + { } +}; +MODULE_DEVICE_TABLE(of, rzg3s_sysc_match); + +static struct platform_driver rzg3s_sysc_driver = { + .driver = { + .name = "renesas-rzg3s-sysc", + .of_match_table = rzg3s_sysc_match + }, + .probe = rzg3s_sysc_probe +}; + +static int __init rzg3s_sysc_init(void) +{ + return platform_driver_register(&rzg3s_sysc_driver); +} +subsys_initcall(rzg3s_sysc_init); + +MODULE_DESCRIPTION("Renesas RZ/G3S System Controller Driver"); +MODULE_AUTHOR("Claudiu Beznea "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/soc/renesas/rzg3s-sysc-reset.h b/include/linux/soc/renesas/rzg3s-sysc-reset.h new file mode 100644 index 000000000000..813cbe82a68a --- /dev/null +++ b/include/linux/soc/renesas/rzg3s-sysc-reset.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __SOC_RENESAS_SYSC_RESET_RZG3S_H +#define __SOC_RENESAS_SYSC_RESET_RZG3S_H + +#include +#include +#include + +/** + * struct rzg3s_sysc_reset_adev - SYSC reset auxiliary device + * @base: base address + * @lock: lock + * @adev: auxiliary device + */ +struct rzg3s_sysc_reset_adev { + void __iomem *base; + spinlock_t *lock; + struct auxiliary_device adev; +}; + +#define to_rzg3s_sysc_reset_adev(a) container_of(a, struct rzg3s_sysc_reset_adev, adev) + +#endif