From patchwork Mon Dec 20 21:18:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Fietkau X-Patchwork-Id: 12688635 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C28FAC4332F for ; Mon, 20 Dec 2021 21:19:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230466AbhLTVTP (ORCPT ); Mon, 20 Dec 2021 16:19:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230422AbhLTVTM (ORCPT ); Mon, 20 Dec 2021 16:19:12 -0500 Received: from nbd.name (nbd.name [IPv6:2a01:4f8:221:3d45::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CFADC061401; Mon, 20 Dec 2021 13:19:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nbd.name; s=20160729; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=tEim5RohUL9zs+9t9JXe9WqjWk4uk9j1mrxooRuiKW0=; b=iHITWSK/Z9cLBrljxTCdSAxgxZ PKIZ5j3M5atDHFY0MyNXO1I0tDnmmP0WCtQRd29ahusv9W6DoQ3RgEVjFbq/5aVrZKEYO7TuGdwR4 YN+qMPxQp/gvohJHudB+FQ4EaC+DjZyuQh8XllaEQTAXwjBvxVwn2Yq+qSzuMuu4ib2Q=; Received: from p54ae911a.dip0.t-ipconnect.de ([84.174.145.26] helo=localhost.localdomain) by ds12 with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1mzQ3n-0000zo-07; Mon, 20 Dec 2021 22:19:07 +0100 From: Felix Fietkau To: linux-arm-kernel@lists.infradead.org, Michael Turquette , Stephen Boyd , Rob Herring Cc: john@phrozen.org, Rob Herring , linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 06/14] dt-bindings: Add en7523-scu device tree binding documentation Date: Mon, 20 Dec 2021 22:18:46 +0100 Message-Id: <20211220211854.89452-7-nbd@nbd.name> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211220211854.89452-1-nbd@nbd.name> References: <20211220211854.89452-1-nbd@nbd.name> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org From: John Crispin Adds device tree binding documentation for clocks in the EN7523 SOC. Reviewed-by: Rob Herring Signed-off-by: Felix Fietkau Signed-off-by: John Crispin Signed-off-by: Felix Fietkau --- .../bindings/clock/airoha,en7523-scu.yaml | 58 +++++++++++++++++++ include/dt-bindings/clock/en7523-clk.h | 17 ++++++ 2 files changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml create mode 100644 include/dt-bindings/clock/en7523-clk.h diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml new file mode 100644 index 000000000000..79660f8126fa --- /dev/null +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/airoha,en7523-scu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EN7523 Clock Device Tree Bindings + +maintainers: + - Felix Fietkau + - John Crispin + +description: | + This node defines the System Control Unit of the EN7523 SoC, + a collection of registers configuring many different aspects of the SoC. + + The clock driver uses it to read and configure settings of the + PLL controller, which provides clocks for the CPU, the bus and + other SoC internal peripherals. + + Each clock is assigned an identifier and client nodes use this identifier + to specify which clock they consume. + + All these identifiers can be found in: + [1]: . + + The clocks are provided inside a system controller node. + +properties: + compatible: + items: + - const: airoha,en7523-scu + + reg: + maxItems: 2 + + "#clock-cells": + description: + The first cell indicates the clock number, see [1] for available + clocks. + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include + scu: scu@1fa20000 { + compatible = "airoha,en7523-scu"; + reg = <0x1fa20000 0x400>, + <0x1fb00000 0x1000>; + #clock-cells = <1>; + }; diff --git a/include/dt-bindings/clock/en7523-clk.h b/include/dt-bindings/clock/en7523-clk.h new file mode 100644 index 000000000000..717d23a5e5ae --- /dev/null +++ b/include/dt-bindings/clock/en7523-clk.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ +#define _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ + +#define EN7523_CLK_GSW 0 +#define EN7523_CLK_EMI 1 +#define EN7523_CLK_BUS 2 +#define EN7523_CLK_SLIC 3 +#define EN7523_CLK_SPI 4 +#define EN7523_CLK_NPU 5 +#define EN7523_CLK_CRYPTO 6 +#define EN7523_CLK_PCIE 7 + +#define EN7523_NUM_CLOCKS 8 + +#endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ From patchwork Mon Dec 20 21:18:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Fietkau X-Patchwork-Id: 12688637 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFBFCC4321E for ; Mon, 20 Dec 2021 21:19:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230487AbhLTVTP (ORCPT ); Mon, 20 Dec 2021 16:19:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39062 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230460AbhLTVTO (ORCPT ); Mon, 20 Dec 2021 16:19:14 -0500 Received: from nbd.name (nbd.name [IPv6:2a01:4f8:221:3d45::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 31720C06173E; Mon, 20 Dec 2021 13:19:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nbd.name; s=20160729; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=/S9JxZ9sXF/7ep+LcG1ZWqE+PDcuY6kcgBg3LjCLV0M=; b=MCd4mfxFzwEx2XrKLOsWLj7guc Hkltql1qHzw3l+/H9cyb+OMq3sc5talXBRZ3zIg69j2bdESpQzLVi8469ImdXL96ZvdXZCL9PZcjJ c/S/Q5qow4E1DUx+yxlG4KRYDsIAIWmLpXE/kOrAs+tU00tUD8t8u5PcD+KsKtiGgBZc=; Received: from p54ae911a.dip0.t-ipconnect.de ([84.174.145.26] helo=localhost.localdomain) by ds12 with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1mzQ3o-0000zo-ET; Mon, 20 Dec 2021 22:19:08 +0100 From: Felix Fietkau To: linux-arm-kernel@lists.infradead.org, Michael Turquette , Stephen Boyd Cc: john@phrozen.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v8 07/14] clk: en7523: Add clock driver for Airoha EN7523 SoC Date: Mon, 20 Dec 2021 22:18:47 +0100 Message-Id: <20211220211854.89452-8-nbd@nbd.name> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211220211854.89452-1-nbd@nbd.name> References: <20211220211854.89452-1-nbd@nbd.name> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org This driver only registers fixed rate clocks, since the clocks are fully initialized by the boot loader and should not be changed later, according to Airoha. Signed-off-by: Felix Fietkau --- drivers/clk/Kconfig | 9 + drivers/clk/Makefile | 1 + drivers/clk/clk-en7523.c | 350 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) create mode 100644 drivers/clk/clk-en7523.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c5b3dc97396a..c973ac1a4890 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -192,6 +192,15 @@ config COMMON_CLK_CS2000_CP help If you say yes here you get support for the CS2000 clock multiplier. +config COMMON_CLK_EN7523 + bool "Clock driver for Airoha EN7523 SoC system clocks" + depends on OF + depends on ARCH_AIROHA || COMPILE_TEST + default ARCH_AIROHA + help + This driver provides the fixed clocks and gates present on Airoha + ARM silicon. + config COMMON_CLK_FSL_FLEXSPI tristate "Clock driver for FlexSPI on Layerscape SoCs" depends on ARCH_LAYERSCAPE || COMPILE_TEST diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e42312121e51..be11d88c1603 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o +obj-$(CONFIG_COMMON_CLK_EN7523) += clk-en7523.o obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c new file mode 100644 index 000000000000..0ee44f6538e6 --- /dev/null +++ b/drivers/clk/clk-en7523.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include + +#define REG_PCI_CONTROL 0x88 +#define REG_PCI_CONTROL_PERSTOUT BIT(29) +#define REG_PCI_CONTROL_PERSTOUT1 BIT(26) +#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22) +#define REG_GSW_CLK_DIV_SEL 0x1b4 +#define REG_EMI_CLK_DIV_SEL 0x1b8 +#define REG_BUS_CLK_DIV_SEL 0x1bc +#define REG_SPI_CLK_DIV_SEL 0x1c4 +#define REG_SPI_CLK_FREQ_SEL 0x1c8 +#define REG_NPU_CLK_DIV_SEL 0x1fc +#define REG_CRYPTO_CLKSRC 0x200 +#define REG_RESET_CONTROL 0x834 +#define REG_RESET_CONTROL_PCIEHB BIT(29) +#define REG_RESET_CONTROL_PCIE1 BIT(27) +#define REG_RESET_CONTROL_PCIE2 BIT(26) + +struct en_clk_desc { + int id; + const char *name; + u32 base_reg; + u32 base_bits; + u32 base_shift; + union { + const u32 *base_values; + u32 base_value; + }; + int n_base_values; + + u32 div_reg; + u32 div_bits; + u32 div_shift; + u32 div_val0; + u32 div_step; +}; + +struct en_clk_gate { + void __iomem *base; + struct clk_hw hw; +}; + +static const u32 gsw_base[] = { 400000000, 500000000 }; +static const u32 emi_base[] = { 333000000, 400000000 }; +static const u32 bus_base[] = { 500000000, 540000000 }; +static const u32 slic_base[] = { 100000000, 3125000 }; +static const u32 npu_base[] = { 333000000, 400000000, 500000000 }; + +static const struct en_clk_desc en7523_base_clks[] = { + { + .id = EN7523_CLK_GSW, + .name = "gsw", + + .base_reg = REG_GSW_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = gsw_base, + .n_base_values = ARRAY_SIZE(gsw_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_EMI, + .name = "emi", + + .base_reg = REG_EMI_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_BUS, + .name = "bus", + + .base_reg = REG_BUS_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = bus_base, + .n_base_values = ARRAY_SIZE(bus_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_SLIC, + .name = "slic", + + .base_reg = REG_SPI_CLK_FREQ_SEL, + .base_bits = 1, + .base_shift = 0, + .base_values = slic_base, + .n_base_values = ARRAY_SIZE(slic_base), + + .div_reg = REG_SPI_CLK_DIV_SEL, + .div_bits = 5, + .div_shift = 24, + .div_val0 = 20, + .div_step = 2, + }, { + .id = EN7523_CLK_SPI, + .name = "spi", + + .base_reg = REG_SPI_CLK_DIV_SEL, + + .base_value = 400000000, + + .div_bits = 5, + .div_shift = 8, + .div_val0 = 40, + .div_step = 2, + }, { + .id = EN7523_CLK_NPU, + .name = "npu", + + .base_reg = REG_NPU_CLK_DIV_SEL, + .base_bits = 2, + .base_shift = 8, + .base_values = npu_base, + .n_base_values = ARRAY_SIZE(npu_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_CRYPTO, + .name = "crypto", + + .base_reg = REG_CRYPTO_CLKSRC, + .base_bits = 1, + .base_shift = 8, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + } +}; + +static const struct of_device_id of_match_clk_en7523[] = { + { .compatible = "airoha,en7523-scu", }, + { /* sentinel */ } +}; + +static u32 en7523_get_base_rate(void __iomem *base, int i) +{ + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 val; + + if (!desc->base_bits) + return desc->base_value; + + val = readl(base + desc->base_reg); + val >>= desc->base_shift; + val &= (1 << desc->base_bits) - 1; + + if (val >= desc->n_base_values) + return 0; + + return desc->base_values[val]; +} + +static u32 en7523_get_div(void __iomem *base, int i) +{ + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 reg, val; + + if (!desc->div_bits) + return 1; + + reg = desc->div_reg ? desc->div_reg : desc->base_reg; + val = readl(base + reg); + val >>= desc->div_shift; + val &= (1 << desc->div_bits) - 1; + + if (!val && desc->div_val0) + return desc->div_val0; + + return (val + 1) * desc->div_step; +} + +static int en7523_pci_is_enabled(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + + return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1); +} + +static int en7523_pci_enable(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + /* Need to pull device low before reset */ + val = readl(np_base + REG_PCI_CONTROL); + val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT); + writel(val, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + + /* Enable PCIe port 1 */ + val |= REG_PCI_CONTROL_REFCLK_EN1; + writel(val, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + + /* Reset to default */ + val = readl(np_base + REG_RESET_CONTROL); + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | + REG_RESET_CONTROL_PCIEHB; + writel(val & ~mask, np_base + REG_RESET_CONTROL); + usleep_range(1000, 2000); + writel(val | mask, np_base + REG_RESET_CONTROL); + msleep(100); + writel(val & ~mask, np_base + REG_RESET_CONTROL); + usleep_range(5000, 10000); + + /* Release device */ + mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val & ~mask, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + writel(val | mask, np_base + REG_PCI_CONTROL); + msleep(250); + + return 0; +} + +static void en7523_pci_disable(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val; + + val = readl(np_base + REG_PCI_CONTROL); + val &= ~REG_PCI_CONTROL_REFCLK_EN1; + writel(val, np_base + REG_PCI_CONTROL); +} + +static struct clk_hw *en7523_register_pcie_clk(struct device *dev, + void __iomem *np_base) +{ + static const struct clk_ops pcie_gate_ops = { + .is_enabled = en7523_pci_is_enabled, + .enable = en7523_pci_enable, + .disable = en7523_pci_disable, + }; + struct clk_init_data init = { + .name = "pcie", + .ops = &pcie_gate_ops, + }; + struct en_clk_gate *cg; + + cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL); + if (!cg) + return NULL; + + cg->base = np_base; + cg->hw.init = &init; + en7523_pci_disable(&cg->hw); + + if (clk_hw_register(NULL, &cg->hw)) + return NULL; + + return &cg->hw; +} + +static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, + void __iomem *base, void __iomem *np_base) +{ + struct clk_hw *hw; + u32 rate; + int i; + + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; + + rate = en7523_get_base_rate(base, i); + rate /= en7523_get_div(base, i); + + hw = clk_hw_register_fixed_rate(NULL, desc->name, NULL, 0, rate); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %ld\n", + desc->name, PTR_ERR(hw)); + continue; + } + + clk_data->hws[desc->id] = hw; + } + + hw = en7523_register_pcie_clk(dev, np_base); + clk_data->hws[EN7523_CLK_PCIE] = hw; + + clk_data->num = EN7523_NUM_CLOCKS; +} + +static int en7523_clk_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data; + void __iomem *base, *np_base; + int r; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + np_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(base)) + return PTR_ERR(np_base); + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, hws, EN7523_NUM_CLOCKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + en7523_register_clocks(&pdev->dev, clk_data, base, np_base); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_en7523_drv = { + .probe = en7523_clk_probe, + .driver = { + .name = "clk-en7523", + .of_match_table = of_match_clk_en7523, + }, +}; + +static int clk_en7523_init(void) +{ + return platform_driver_register(&clk_en7523_drv); +} + +arch_initcall(clk_en7523_init);