From 5c223fb43f28f23d66421b627adb1975dd762ec3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 25 Feb 2021 20:08:39 +0100 Subject: [PATCH] bmips: add BCM63268 timer clock and reset support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We need this to fix USB support on BCM63268. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/config-5.10 | 1 + target/linux/bmips/dts/bcm63268.dtsi | 15 +- ...add-BCM63268-timer-clock-definitions.patch | 35 +++ ...add-BCM63268-timer-reset-definitions.patch | 26 ++ ...ngs-clock-Add-BCM63268-timer-binding.patch | 59 ++++ ...CM63268-timer-clock-and-reset-driver.patch | 281 ++++++++++++++++++ 6 files changed, 413 insertions(+), 4 deletions(-) create mode 100644 target/linux/bmips/patches-5.10/110-mips-bmips-add-BCM63268-timer-clock-definitions.patch create mode 100644 target/linux/bmips/patches-5.10/111-mips-bmips-add-BCM63268-timer-reset-definitions.patch create mode 100644 target/linux/bmips/patches-5.10/112-dt-bindings-clock-Add-BCM63268-timer-binding.patch create mode 100644 target/linux/bmips/patches-5.10/113-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch diff --git a/target/linux/bmips/config-5.10 b/target/linux/bmips/config-5.10 index cfe8888f8032..749cc0eb697d 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 538b43754b64..2a0bc3cbec4e 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@100000ac { + compatible = "brcm,bcm63268-timer-clocks"; + reg = <0x100000ac 0x4>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + gpio: syscon@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 000000000000..0df7db97179b --- /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?= +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 +--- + 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 000000000000..7b694d328976 --- /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?= +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 +--- + 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 000000000000..945bdfc3d08f --- /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?= +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 +--- + .../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 ++ ++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@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 000000000000..484647a6e137 --- /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?= +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 +--- + 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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); -- 2.30.2