[openwrt/openwrt] bmips: add BCM63268 timer clock and reset support

LEDE Commits lede-commits at lists.infradead.org
Thu Feb 25 14:48:35 EST 2021


noltari pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/5c223fb43f28f23d66421b627adb1975dd762ec3

commit 5c223fb43f28f23d66421b627adb1975dd762ec3
Author: Álvaro Fernández Rojas <noltari at gmail.com>
AuthorDate: Thu Feb 25 20:08:39 2021 +0100

    bmips: add BCM63268 timer clock and reset support
    
    We need this to fix USB support on BCM63268.
    
    Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
---
 target/linux/bmips/config-5.10                     |   1 +
 target/linux/bmips/dts/bcm63268.dtsi               |  15 +-
 ...mips-add-BCM63268-timer-clock-definitions.patch |  35 +++
 ...mips-add-BCM63268-timer-reset-definitions.patch |  26 ++
 ...bindings-clock-Add-BCM63268-timer-binding.patch |  59 +++++
 ...Add-BCM63268-timer-clock-and-reset-driver.patch | 281 +++++++++++++++++++++
 6 files changed, 413 insertions(+), 4 deletions(-)

diff --git a/target/linux/bmips/config-5.10 b/target/linux/bmips/config-5.10
index cfe8888f80..749cc0eb69 100644
--- a/target/linux/bmips/config-5.10
+++ b/target/linux/bmips/config-5.10
@@ -15,6 +15,7 @@ CONFIG_BOARD_SCACHE=y
 CONFIG_BRCMSTB_L2_IRQ=y
 CONFIG_CEVT_R4K=y
 CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLK_BCM63268_TIMER=y
 CONFIG_CLK_BCM_63XX_GATE=y
 CONFIG_CLONE_BACKWARDS=y
 CONFIG_COMMON_CLK=y
diff --git a/target/linux/bmips/dts/bcm63268.dtsi b/target/linux/bmips/dts/bcm63268.dtsi
index 538b43754b..2a0bc3cbec 100644
--- a/target/linux/bmips/dts/bcm63268.dtsi
+++ b/target/linux/bmips/dts/bcm63268.dtsi
@@ -147,6 +147,13 @@
 			timeout-sec = <30>;
 		};
 
+		timer_clk: clock-controller at 100000ac {
+			compatible = "brcm,bcm63268-timer-clocks";
+			reg = <0x100000ac 0x4>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		gpio: syscon at 100000c0 {
 			compatible = "syscon", "simple-mfd";
 			reg = <0x100000c0 0x80>;
@@ -416,10 +423,10 @@
 
 			#phy-cells = <1>;
 
-			clocks = <&periph_clk BCM63268_CLK_USBH>;
-			/* FIXME! <&timer_clk BCM63268_TCLK_USB_REF> */
-			clock-names = "usbh";
-			/* FIXME! usb_ref */
+			clocks = <&periph_clk BCM63268_CLK_USBH>,
+				 <&timer_clk BCM63268_TCLK_USB_REF>;
+			clock-names = "usbh",
+				      "usb_ref";
 
 			power-domains = <&periph_pwr BCM63268_POWER_DOMAIN_USBH>;
 			resets = <&periph_rst BCM63268_RST_USBH>;
diff --git a/target/linux/bmips/patches-5.10/110-mips-bmips-add-BCM63268-timer-clock-definitions.patch b/target/linux/bmips/patches-5.10/110-mips-bmips-add-BCM63268-timer-clock-definitions.patch
new file mode 100644
index 0000000000..0df7db9717
--- /dev/null
+++ b/target/linux/bmips/patches-5.10/110-mips-bmips-add-BCM63268-timer-clock-definitions.patch
@@ -0,0 +1,35 @@
+From 5a079515cb3066aeb658634301a98871b47c2af4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari at gmail.com>
+Date: Thu, 25 Feb 2021 19:44:22 +0100
+Subject: [PATCH 1/4] mips: bmips: add BCM63268 timer clock definitions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add missing timer clock definitions for BCM63268.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
+---
+ include/dt-bindings/clock/bcm63268-clock.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/include/dt-bindings/clock/bcm63268-clock.h
++++ b/include/dt-bindings/clock/bcm63268-clock.h
+@@ -27,4 +27,17 @@
+ #define BCM63268_CLK_TBUS	27
+ #define BCM63268_CLK_ROBOSW250	31
+ 
++#define BCM63268_TCLK_EPHY1		0
++#define BCM63268_TCLK_EPHY2		1
++#define BCM63268_TCLK_EPHY3		2
++#define BCM63268_TCLK_GPHY1		3
++#define BCM63268_TCLK_DSL		4
++#define BCM63268_TCLK_WAKEON_EPHY	6
++#define BCM63268_TCLK_WAKEON_DSL	7
++#define BCM63268_TCLK_FAP1		11
++#define BCM63268_TCLK_FAP2		15
++#define BCM63268_TCLK_UTO_50		16
++#define BCM63268_TCLK_UTO_EXTIN		17
++#define BCM63268_TCLK_USB_REF		18
++
+ #endif /* __DT_BINDINGS_CLOCK_BCM63268_H */
diff --git a/target/linux/bmips/patches-5.10/111-mips-bmips-add-BCM63268-timer-reset-definitions.patch b/target/linux/bmips/patches-5.10/111-mips-bmips-add-BCM63268-timer-reset-definitions.patch
new file mode 100644
index 0000000000..7b694d3289
--- /dev/null
+++ b/target/linux/bmips/patches-5.10/111-mips-bmips-add-BCM63268-timer-reset-definitions.patch
@@ -0,0 +1,26 @@
+From 3327df17635dd9d24a855ac6b7247fac381514cf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari at gmail.com>
+Date: Thu, 25 Feb 2021 19:45:04 +0100
+Subject: [PATCH 2/4] mips: bmips: add BCM63268 timer reset definitions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add missing timer reset definitions for BCM63268.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
+---
+ include/dt-bindings/reset/bcm63268-reset.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/include/dt-bindings/reset/bcm63268-reset.h
++++ b/include/dt-bindings/reset/bcm63268-reset.h
+@@ -23,4 +23,8 @@
+ #define BCM63268_RST_PCIE_HARD	17
+ #define BCM63268_RST_GPHY	18
+ 
++#define BCM63268_TRST_SW	29
++#define BCM63268_TRST_HW	30
++#define BCM63268_TRST_POR	31
++
+ #endif /* __DT_BINDINGS_RESET_BCM63268_H */
diff --git a/target/linux/bmips/patches-5.10/112-dt-bindings-clock-Add-BCM63268-timer-binding.patch b/target/linux/bmips/patches-5.10/112-dt-bindings-clock-Add-BCM63268-timer-binding.patch
new file mode 100644
index 0000000000..945bdfc3d0
--- /dev/null
+++ b/target/linux/bmips/patches-5.10/112-dt-bindings-clock-Add-BCM63268-timer-binding.patch
@@ -0,0 +1,59 @@
+From c17702bad18a085ae913752b45bcc20c2cea879e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari at gmail.com>
+Date: Thu, 25 Feb 2021 19:53:08 +0100
+Subject: [PATCH 3/4] dt-bindings: clock: Add BCM63268 timer binding
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Document the Broadcom BCM63268 Clock and Reset controller.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
+---
+ .../clock/brcm,bcm63268-timer-clocks.yaml     | 40 +++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml
+@@ -0,0 +1,40 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/brcm,bcm63268-timer-clocks.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Broadcom BCM63268 Timer Clock and Reset Device Tree Bindings
++
++maintainers:
++  - Álvaro Fernández Rojas <noltari at gmail.com>
++
++properties:
++  compatible:
++    const: brcm,bcm63268-timer-clocks
++
++  reg:
++    maxItems: 1
++
++  "#clock-cells":
++    const: 1
++
++  "#reset-cells":
++    const: 1
++
++required:
++  - compatible
++  - reg
++  - "#clock-cells"
++  - "#reset-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    timer_clk: clock-controller at 100000ac {
++      compatible = "brcm,bcm63268-timer-clocks";
++      reg = <0x100000ac 0x4>;
++      #clock-cells = <1>;
++      #reset-cells = <1>;
++    };
diff --git a/target/linux/bmips/patches-5.10/113-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch b/target/linux/bmips/patches-5.10/113-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch
new file mode 100644
index 0000000000..484647a6e1
--- /dev/null
+++ b/target/linux/bmips/patches-5.10/113-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch
@@ -0,0 +1,281 @@
+From 3c8dd9d0937a19f3f20f28ba0b0b64f448d50dd4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari at gmail.com>
+Date: Thu, 25 Feb 2021 19:54:04 +0100
+Subject: [PATCH 4/4] clk: bcm: Add BCM63268 timer clock and reset driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add driver for BCM63268 timer clock and reset controller.
+
+Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
+---
+ drivers/clk/bcm/Kconfig              |   9 ++
+ drivers/clk/bcm/Makefile             |   1 +
+ drivers/clk/bcm/clk-bcm63268-timer.c | 232 +++++++++++++++++++++++++++
+ 3 files changed, 242 insertions(+)
+ create mode 100644 drivers/clk/bcm/clk-bcm63268-timer.c
+
+--- a/drivers/clk/bcm/Kconfig
++++ b/drivers/clk/bcm/Kconfig
+@@ -37,6 +37,15 @@ config CLK_BCM_63XX_GATE
+ 	  Enable common clock framework support for Broadcom BCM63xx DSL SoCs
+ 	  based on the MIPS architecture
+ 
++config CLK_BCM63268_TIMER
++	bool "Broadcom BCM63268 timer clock and reset support"
++	depends on BMIPS_GENERIC || COMPILE_TEST
++	default BMIPS_GENERIC
++	select RESET_CONTROLLER
++	help
++	  Enable timer clock and reset support for Broadcom BCM63268 DSL SoCs
++	  based on the MIPS architecture.
++
+ config CLK_BCM_KONA
+ 	bool "Broadcom Kona CCU clock support"
+ 	depends on ARCH_BCM_MOBILE || COMPILE_TEST
+--- a/drivers/clk/bcm/Makefile
++++ b/drivers/clk/bcm/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_CLK_BCM_63XX)	+= clk-bcm63xx.o
+ obj-$(CONFIG_CLK_BCM_63XX_GATE)	+= clk-bcm63xx-gate.o
++obj-$(CONFIG_CLK_BCM63268_TIMER) += clk-bcm63268-timer.o
+ obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona.o
+ obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona-setup.o
+ obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm281xx.o
+--- /dev/null
++++ b/drivers/clk/bcm/clk-bcm63268-timer.c
+@@ -0,0 +1,232 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * BCM63268 Timer Clock and Reset Controller Driver
++ *
++ * Copyright (C) 2021 Álvaro Fernández Rojas <noltari at gmail.com>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset-controller.h>
++
++#include <dt-bindings/clock/bcm63268-clock.h>
++
++#define BCM63268_TIMER_RESET_SLEEP_MIN_US	10000
++#define BCM63268_TIMER_RESET_SLEEP_MAX_US	20000
++
++struct bcm63268_tclkrst_hw {
++	void __iomem *regs;
++	spinlock_t lock;
++
++	struct reset_controller_dev rcdev;
++	struct clk_hw_onecell_data data;
++};
++
++struct bcm63268_tclk_table_entry {
++	const char * const name;
++	u8 bit;
++	unsigned long flags;
++};
++
++static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = {
++	{
++		.name = "ephy1",
++		.bit = BCM63268_TCLK_EPHY1,
++	}, {
++		.name = "ephy2",
++		.bit = BCM63268_TCLK_EPHY2,
++	}, {
++		.name = "ephy3",
++		.bit = BCM63268_TCLK_EPHY3,
++	}, {
++		.name = "gphy1",
++		.bit = BCM63268_TCLK_GPHY1,
++	}, {
++		.name = "dsl",
++		.bit = BCM63268_TCLK_DSL,
++	}, {
++		.name = "wakeon_ephy",
++		.bit = BCM63268_TCLK_WAKEON_EPHY,
++	}, {
++		.name = "wakeon_dsl",
++		.bit = BCM63268_TCLK_WAKEON_DSL,
++	}, {
++		.name = "fap1_pll",
++		.bit = BCM63268_TCLK_FAP1,
++	}, {
++		.name = "fap2_pll",
++		.bit = BCM63268_TCLK_FAP2,
++	}, {
++		.name = "uto_50",
++		.bit = BCM63268_TCLK_UTO_50,
++	}, {
++		.name = "uto_extin",
++		.bit = BCM63268_TCLK_UTO_EXTIN,
++	}, {
++		.name = "usb_ref",
++		.bit = BCM63268_TCLK_USB_REF,
++	}, {
++		/* sentinel */
++	}
++};
++
++static inline struct bcm63268_tclkrst_hw *
++to_bcm63268_timer_reset(struct reset_controller_dev *rcdev)
++{
++	return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev);
++}
++
++static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev,
++				unsigned long id, bool assert)
++{
++	struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
++	unsigned long flags;
++	uint32_t val;
++
++	spin_lock_irqsave(&reset->lock, flags);
++	val = __raw_readl(reset->regs);
++	if (assert)
++		val &= ~BIT(id);
++	else
++		val |= BIT(id);
++	__raw_writel(val, reset->regs);
++	spin_unlock_irqrestore(&reset->lock, flags);
++
++	return 0;
++}
++
++static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev,
++				unsigned long id)
++{
++	return bcm63268_timer_reset_update(rcdev, id, true);
++}
++
++static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev,
++				  unsigned long id)
++{
++	return bcm63268_timer_reset_update(rcdev, id, false);
++}
++
++static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev,
++			       unsigned long id)
++{
++	bcm63268_timer_reset_update(rcdev, id, true);
++	usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
++		     BCM63268_TIMER_RESET_SLEEP_MAX_US);
++
++	bcm63268_timer_reset_update(rcdev, id, false);
++	/*
++	 * Ensure component is taken out reset state by sleeping also after
++	 * deasserting the reset. Otherwise, the component may not be ready
++	 * for operation.
++	 */
++	usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
++		     BCM63268_TIMER_RESET_SLEEP_MAX_US);
++
++	return 0;
++}
++
++static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev,
++				unsigned long id)
++{
++	struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
++
++	return !(__raw_readl(reset->regs) & BIT(id));
++}
++
++static struct reset_control_ops bcm63268_timer_reset_ops = {
++	.assert = bcm63268_timer_reset_assert,
++	.deassert = bcm63268_timer_reset_deassert,
++	.reset = bcm63268_timer_reset_reset,
++	.status = bcm63268_timer_reset_status,
++};
++
++static int bcm63268_tclk_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct bcm63268_tclk_table_entry *entry, *table;
++	struct bcm63268_tclkrst_hw *hw;
++	u8 maxbit = 0;
++	int i, ret;
++
++	table = of_device_get_match_data(dev);
++	if (!table)
++		return -EINVAL;
++
++	for (entry = table; entry->name; entry++)
++		maxbit = max_t(u8, maxbit, entry->bit);
++	maxbit++;
++
++	hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
++			  GFP_KERNEL);
++	if (!hw)
++		return -ENOMEM;
++
++	platform_set_drvdata(pdev, hw);
++
++	spin_lock_init(&hw->lock);
++
++	hw->data.num = maxbit;
++	for (i = 0; i < maxbit; i++)
++		hw->data.hws[i] = ERR_PTR(-ENODEV);
++
++	hw->regs = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(hw->regs))
++		return PTR_ERR(hw->regs);
++
++	for (entry = table; entry->name; entry++) {
++		struct clk_hw *clk;
++
++		clk = clk_hw_register_gate(dev, entry->name, NULL,
++					   entry->flags, hw->regs, entry->bit,
++					   CLK_GATE_BIG_ENDIAN, &hw->lock);
++		if (IS_ERR(clk)) {
++			ret = PTR_ERR(clk);
++			goto out_err;
++		}
++
++		hw->data.hws[entry->bit] = clk;
++	}
++
++	ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
++				     &hw->data);
++	if (!ret)
++		return 0;
++
++	hw->rcdev.of_node = dev->of_node;
++	hw->rcdev.ops = &bcm63268_timer_reset_ops;
++
++	ret = devm_reset_controller_register(dev, &hw->rcdev);
++	if (ret)
++		dev_err(dev, "Failed to register reset controller\n");
++
++out_err:
++	for (i = 0; i < hw->data.num; i++) {
++		if (!IS_ERR(hw->data.hws[i]))
++			clk_hw_unregister_gate(hw->data.hws[i]);
++	}
++
++	return ret;
++}
++
++static const struct of_device_id bcm63268_tclk_dt_ids[] = {
++	{
++		.compatible = "brcm,bcm63268-timer-clocks",
++		.data = &bcm63268_timer_clocks,
++	}, {
++		/* sentinel */
++	}
++};
++
++static struct platform_driver bcm63268_tclk = {
++	.probe = bcm63268_tclk_probe,
++	.driver = {
++		.name = "bcm63268-timer-clock",
++		.of_match_table = bcm63268_tclk_dt_ids,
++	},
++};
++builtin_platform_driver(bcm63268_tclk);



More information about the lede-commits mailing list