ramips: switch to Linux 6.6
[openwrt/staging/nbd.git] / target / linux / ramips / patches-6.1 / 005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch
diff --git a/target/linux/ramips/patches-6.1/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch b/target/linux/ramips/patches-6.1/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch
deleted file mode 100644 (file)
index cef3997..0000000
+++ /dev/null
@@ -1,1221 +0,0 @@
-From 6f3b15586eef736831abe6a14f2a6906bc0dc074 Mon Sep 17 00:00:00 2001
-From: Sergio Paracuellos <sergio.paracuellos@gmail.com>
-Date: Mon, 19 Jun 2023 06:09:34 +0200
-Subject: [PATCH 2/9] clk: ralink: add clock and reset driver for MTMIPS SoCs
-
-Until now, clock related code for old ralink SoCs was based in fixed clocks
-using 'clk_register_fixed_rate' and 'clkdev_create' directly doing in code
-and not using device tree at all for their definition. Including this driver
-is an effort to be able to define proper clocks using device tree and also
-cleaning all the clock and reset related code from 'arch/mips/ralink' dir.
-This clock and reset driver covers all the ralink SoCs but MT7621 which is
-the newest and provides gating and some differences that make it different
-from its predecesors. It has its own driver since some time ago. The ralink
-SoCs we are taking about are RT2880, RT3050, RT3052, RT3350, RT3352, RT3883,
-RT5350, MT7620, MT7628 and MT7688. Mostly the code in this new driver has
-been extracted from 'arch/mips/ralink' and cleanly put using kernel clock
-driver APIs. The clock plans for this SoCs only talks about relation between
-CPU frequency and BUS frequency. This relation is different depending on the
-particular SoC. CPU clock is derived from XTAL frequencies.
-
-Depending on the SoC we have the following frequencies:
-* RT2880 SoC:
-    - XTAL: 40 MHz.
-    - CPU: 250, 266, 280 or 300 MHz.
-    - BUS: CPU / 2 MHz.
-* RT3050, RT3052, RT3350:
-    - XTAL: 40 MHz.
-    - CPU: 320 or 384 MHz.
-    - BUS: CPU / 3 MHz.
-* RT3352:
-    - XTAL: 40 MHz.
-    - CPU: 384 or 400 MHz.
-    - BUS: CPU / 3 MHz.
-    - PERIPH: 40 MHz.
-* RT3383:
-    - XTAL: 40 MHz.
-    - CPU: 250, 384, 480 or 500 MHz.
-    - BUS: Depends on RAM Type and CPU:
-        + RAM DDR2: 125. ELSE 83 MHz.
-        + RAM DDR2: 128. ELSE 96 MHz.
-        + RAM DDR2: 160. ELSE 120 MHz.
-        + RAM DDR2: 166. ELSE 125 MHz.
-* RT5350:
-    - XTAL: 40 MHz.
-    - CPU: 300, 320 or 360 MHz.
-    - BUS: CPU / 3, CPU / 4, CPU / 3 MHz.
-    - PERIPH: 40 MHz.
-* MT7628 and MT7688:
-    - XTAL: 20 MHz or 40 MHz.
-    - CPU: 575 or 580 MHz.
-    - BUS: CPU / 3.
-    - PCMI2S: 480 MHz.
-    - PERIPH: 40 MHz.
-* MT7620:
-    - XTAL: 20 MHz or 40 MHz.
-    - PLL: XTAL, 480, 600 MHz.
-    - CPU: depends on PLL and some mult and dividers.
-    - BUS: depends on PLL and some mult and dividers.
-    - PERIPH: 40 or XTAL MHz.
-
-MT7620 is a bit more complex deriving CPU clock from a PLL and an bunch of
-register reads and predividers. To derive CPU and BUS frequencies in the
-MT7620 SoC 'mt7620_calc_rate()' helper is used.
-
-In the case XTAL can have different frequencies and we need a different
-clock frequency for peripherals 'periph' clock in introduced.
-
-The rest of the peripherals present in the SoC just follow their parent
-frequencies.
-
-With this information the clk driver will provide all the clock and reset
-functionality from a set of hardcoded clocks allowing to define a nice
-device tree without fixed clocks.
-
-Acked-by: Stephen Boyd <sboyd@kernel.org>
-Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
-Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
----
- drivers/clk/ralink/Kconfig      |    7 +
- drivers/clk/ralink/Makefile     |    1 +
- drivers/clk/ralink/clk-mtmips.c | 1115 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 1123 insertions(+)
- create mode 100644 drivers/clk/ralink/clk-mtmips.c
-
---- a/drivers/clk/ralink/Kconfig
-+++ b/drivers/clk/ralink/Kconfig
-@@ -9,3 +9,10 @@ config CLK_MT7621
-       select MFD_SYSCON
-       help
-         This driver supports MediaTek MT7621 basic clocks.
-+
-+config CLK_MTMIPS
-+      bool "Clock driver for MTMIPS SoCs"
-+      depends on SOC_RT305X || SOC_RT288X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST
-+      select MFD_SYSCON
-+      help
-+        This driver supports MTMIPS basic clocks.
---- a/drivers/clk/ralink/Makefile
-+++ b/drivers/clk/ralink/Makefile
-@@ -1,2 +1,3 @@
- # SPDX-License-Identifier: GPL-2.0
- obj-$(CONFIG_CLK_MT7621) += clk-mt7621.o
-+obj-$(CONFIG_CLK_MTMIPS) += clk-mtmips.o
---- /dev/null
-+++ b/drivers/clk/ralink/clk-mtmips.c
-@@ -0,0 +1,1115 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * MTMIPS SoCs Clock Driver
-+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
-+ */
-+
-+#include <linux/bitops.h>
-+#include <linux/clk-provider.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/platform_device.h>
-+#include <linux/regmap.h>
-+#include <linux/reset-controller.h>
-+#include <linux/slab.h>
-+
-+/* Configuration registers */
-+#define SYSC_REG_SYSTEM_CONFIG                0x10
-+#define SYSC_REG_CLKCFG0              0x2c
-+#define SYSC_REG_RESET_CTRL           0x34
-+#define SYSC_REG_CPU_SYS_CLKCFG               0x3c
-+#define SYSC_REG_CPLL_CONFIG0         0x54
-+#define SYSC_REG_CPLL_CONFIG1         0x58
-+
-+/* RT2880 SoC */
-+#define RT2880_CONFIG_CPUCLK_SHIFT    20
-+#define RT2880_CONFIG_CPUCLK_MASK     0x3
-+#define RT2880_CONFIG_CPUCLK_250      0x0
-+#define RT2880_CONFIG_CPUCLK_266      0x1
-+#define RT2880_CONFIG_CPUCLK_280      0x2
-+#define RT2880_CONFIG_CPUCLK_300      0x3
-+
-+/* RT305X SoC */
-+#define RT305X_SYSCFG_CPUCLK_SHIFT    18
-+#define RT305X_SYSCFG_CPUCLK_MASK     0x1
-+#define RT305X_SYSCFG_CPUCLK_LOW      0x0
-+#define RT305X_SYSCFG_CPUCLK_HIGH     0x1
-+
-+/* RT3352 SoC */
-+#define RT3352_SYSCFG0_CPUCLK_SHIFT   8
-+#define RT3352_SYSCFG0_CPUCLK_MASK    0x1
-+#define RT3352_SYSCFG0_CPUCLK_LOW     0x0
-+#define RT3352_SYSCFG0_CPUCLK_HIGH    0x1
-+
-+/* RT3383 SoC */
-+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17)
-+#define RT3883_SYSCFG0_CPUCLK_SHIFT   8
-+#define RT3883_SYSCFG0_CPUCLK_MASK    0x3
-+#define RT3883_SYSCFG0_CPUCLK_250     0x0
-+#define RT3883_SYSCFG0_CPUCLK_384     0x1
-+#define RT3883_SYSCFG0_CPUCLK_480     0x2
-+#define RT3883_SYSCFG0_CPUCLK_500     0x3
-+
-+/* RT5350 SoC */
-+#define RT5350_CLKCFG0_XTAL_SEL               BIT(20)
-+#define RT5350_SYSCFG0_CPUCLK_SHIFT   8
-+#define RT5350_SYSCFG0_CPUCLK_MASK    0x3
-+#define RT5350_SYSCFG0_CPUCLK_360     0x0
-+#define RT5350_SYSCFG0_CPUCLK_320     0x2
-+#define RT5350_SYSCFG0_CPUCLK_300     0x3
-+
-+/* MT7620 and MT76x8 SoCs */
-+#define MT7620_XTAL_FREQ_SEL          BIT(6)
-+#define CPLL_CFG0_SW_CFG              BIT(31)
-+#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT        16
-+#define CPLL_CFG0_PLL_MULT_RATIO_MASK   0x7
-+#define CPLL_CFG0_LC_CURFCK           BIT(15)
-+#define CPLL_CFG0_BYPASS_REF_CLK      BIT(14)
-+#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10
-+#define CPLL_CFG0_PLL_DIV_RATIO_MASK  0x3
-+#define CPLL_CFG1_CPU_AUX1            BIT(25)
-+#define CPLL_CFG1_CPU_AUX0            BIT(24)
-+#define CLKCFG0_PERI_CLK_SEL          BIT(4)
-+#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT        16
-+#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf
-+#define CPU_SYS_CLKCFG_OCP_RATIO_1    0       /* 1:1   (Reserved) */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_1_5  1       /* 1:1.5 (Reserved) */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_2    2       /* 1:2   */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_2_5  3       /* 1:2.5 (Reserved) */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_3    4       /* 1:3   */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_3_5  5       /* 1:3.5 (Reserved) */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_4    6       /* 1:4   */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_5    7       /* 1:5   */
-+#define CPU_SYS_CLKCFG_OCP_RATIO_10   8       /* 1:10  */
-+#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8
-+#define CPU_SYS_CLKCFG_CPU_FDIV_MASK  0x1f
-+#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT        0
-+#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f
-+
-+/* clock scaling */
-+#define CLKCFG_FDIV_MASK              0x1f00
-+#define CLKCFG_FDIV_USB_VAL           0x0300
-+#define CLKCFG_FFRAC_MASK             0x001f
-+#define CLKCFG_FFRAC_USB_VAL          0x0003
-+
-+struct mtmips_clk;
-+struct mtmips_clk_fixed;
-+struct mtmips_clk_factor;
-+
-+struct mtmips_clk_data {
-+      struct mtmips_clk *clk_base;
-+      size_t num_clk_base;
-+      struct mtmips_clk_fixed *clk_fixed;
-+      size_t num_clk_fixed;
-+      struct mtmips_clk_factor *clk_factor;
-+      size_t num_clk_factor;
-+      struct mtmips_clk *clk_periph;
-+      size_t num_clk_periph;
-+};
-+
-+struct mtmips_clk_priv {
-+      struct regmap *sysc;
-+      const struct mtmips_clk_data *data;
-+};
-+
-+struct mtmips_clk {
-+      struct clk_hw hw;
-+      struct mtmips_clk_priv *priv;
-+};
-+
-+struct mtmips_clk_fixed {
-+      const char *name;
-+      const char *parent;
-+      unsigned long rate;
-+      struct clk_hw *hw;
-+};
-+
-+struct mtmips_clk_factor {
-+      const char *name;
-+      const char *parent;
-+      int mult;
-+      int div;
-+      unsigned long flags;
-+      struct clk_hw *hw;
-+};
-+
-+static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      return parent_rate;
-+}
-+
-+static const struct clk_ops mtmips_periph_clk_ops = {
-+      .recalc_rate = mtmips_pherip_clk_rate,
-+};
-+
-+#define CLK_PERIPH(_name, _parent) {                          \
-+      .init = &(const struct clk_init_data) {                 \
-+              .name = _name,                                  \
-+              .ops = &mtmips_periph_clk_ops,                  \
-+              .parent_data = &(const struct clk_parent_data) {\
-+                      .name = _parent,                        \
-+                      .fw_name = _parent                      \
-+              },                                              \
-+              .num_parents = 1,                               \
-+              /*                                              \
-+               * There are drivers for these SoCs that are    \
-+               * older than clock driver and are not prepared \
-+               * for the clock. We don't want the kernel to   \
-+               * disable anything so we add CLK_IS_CRITICAL   \
-+               * flag here.                                   \
-+               */                                             \
-+              .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL  \
-+      },                                                      \
-+}
-+
-+static struct mtmips_clk rt2880_pherip_clks[] = {
-+      { CLK_PERIPH("300100.timer", "bus") },
-+      { CLK_PERIPH("300120.watchdog", "bus") },
-+      { CLK_PERIPH("300500.uart", "bus") },
-+      { CLK_PERIPH("300900.i2c", "bus") },
-+      { CLK_PERIPH("300c00.uartlite", "bus") },
-+      { CLK_PERIPH("400000.ethernet", "bus") },
-+      { CLK_PERIPH("480000.wmac", "xtal") }
-+};
-+
-+static struct mtmips_clk rt305x_pherip_clks[] = {
-+      { CLK_PERIPH("10000100.timer", "bus") },
-+      { CLK_PERIPH("10000120.watchdog", "bus") },
-+      { CLK_PERIPH("10000500.uart", "bus") },
-+      { CLK_PERIPH("10000900.i2c", "bus") },
-+      { CLK_PERIPH("10000a00.i2s", "bus") },
-+      { CLK_PERIPH("10000b00.spi", "bus") },
-+      { CLK_PERIPH("10000b40.spi", "bus") },
-+      { CLK_PERIPH("10000c00.uartlite", "bus") },
-+      { CLK_PERIPH("10100000.ethernet", "bus") },
-+      { CLK_PERIPH("10180000.wmac", "xtal") }
-+};
-+
-+static struct mtmips_clk rt5350_pherip_clks[] = {
-+      { CLK_PERIPH("10000100.timer", "bus") },
-+      { CLK_PERIPH("10000120.watchdog", "bus") },
-+      { CLK_PERIPH("10000500.uart", "periph") },
-+      { CLK_PERIPH("10000900.i2c", "periph") },
-+      { CLK_PERIPH("10000a00.i2s", "periph") },
-+      { CLK_PERIPH("10000b00.spi", "bus") },
-+      { CLK_PERIPH("10000b40.spi", "bus") },
-+      { CLK_PERIPH("10000c00.uartlite", "periph") },
-+      { CLK_PERIPH("10100000.ethernet", "bus") },
-+      { CLK_PERIPH("10180000.wmac", "xtal") }
-+};
-+
-+static struct mtmips_clk mt7620_pherip_clks[] = {
-+      { CLK_PERIPH("10000100.timer", "periph") },
-+      { CLK_PERIPH("10000120.watchdog", "periph") },
-+      { CLK_PERIPH("10000500.uart", "periph") },
-+      { CLK_PERIPH("10000900.i2c", "periph") },
-+      { CLK_PERIPH("10000a00.i2s", "periph") },
-+      { CLK_PERIPH("10000b00.spi", "bus") },
-+      { CLK_PERIPH("10000b40.spi", "bus") },
-+      { CLK_PERIPH("10000c00.uartlite", "periph") },
-+      { CLK_PERIPH("10180000.wmac", "xtal") }
-+};
-+
-+static struct mtmips_clk mt76x8_pherip_clks[] = {
-+      { CLK_PERIPH("10000100.timer", "periph") },
-+      { CLK_PERIPH("10000120.watchdog", "periph") },
-+      { CLK_PERIPH("10000900.i2c", "periph") },
-+      { CLK_PERIPH("10000a00.i2s", "pcmi2s") },
-+      { CLK_PERIPH("10000b00.spi", "bus") },
-+      { CLK_PERIPH("10000b40.spi", "bus") },
-+      { CLK_PERIPH("10000c00.uart0", "periph") },
-+      { CLK_PERIPH("10000d00.uart1", "periph") },
-+      { CLK_PERIPH("10000e00.uart2", "periph") },
-+      { CLK_PERIPH("10300000.wmac", "xtal") }
-+};
-+
-+static int mtmips_register_pherip_clocks(struct device_node *np,
-+                                       struct clk_hw_onecell_data *clk_data,
-+                                       struct mtmips_clk_priv *priv)
-+{
-+      struct clk_hw **hws = clk_data->hws;
-+      struct mtmips_clk *sclk;
-+      size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed +
-+                         priv->data->num_clk_factor;
-+      int ret, i;
-+
-+      for (i = 0; i < priv->data->num_clk_periph; i++) {
-+              int idx = idx_start + i;
-+
-+              sclk = &priv->data->clk_periph[i];
-+              ret = of_clk_hw_register(np, &sclk->hw);
-+              if (ret) {
-+                      pr_err("Couldn't register peripheral clock %d\n", idx);
-+                      goto err_clk_unreg;
-+              }
-+
-+              hws[idx] = &sclk->hw;
-+      }
-+
-+      return 0;
-+
-+err_clk_unreg:
-+      while (--i >= 0) {
-+              sclk = &priv->data->clk_periph[i];
-+              clk_hw_unregister(&sclk->hw);
-+      }
-+      return ret;
-+}
-+
-+#define CLK_FIXED(_name, _parent, _rate) \
-+      {                                \
-+              .name = _name,           \
-+              .parent = _parent,       \
-+              .rate = _rate            \
-+      }
-+
-+static struct mtmips_clk_fixed rt305x_fixed_clocks[] = {
-+      CLK_FIXED("xtal", NULL, 40000000)
-+};
-+
-+static struct mtmips_clk_fixed rt3352_fixed_clocks[] = {
-+      CLK_FIXED("periph", "xtal", 40000000)
-+};
-+
-+static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = {
-+      CLK_FIXED("pcmi2s", "xtal", 480000000),
-+      CLK_FIXED("periph", "xtal", 40000000)
-+};
-+
-+static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data,
-+                                      struct mtmips_clk_priv *priv)
-+{
-+      struct clk_hw **hws = clk_data->hws;
-+      struct mtmips_clk_fixed *sclk;
-+      size_t idx_start = priv->data->num_clk_base;
-+      int ret, i;
-+
-+      for (i = 0; i < priv->data->num_clk_fixed; i++) {
-+              int idx = idx_start + i;
-+
-+              sclk = &priv->data->clk_fixed[i];
-+              sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name,
-+                                                    sclk->parent, 0,
-+                                                    sclk->rate);
-+              if (IS_ERR(sclk->hw)) {
-+                      pr_err("Couldn't register fixed clock %d\n", idx);
-+                      goto err_clk_unreg;
-+              }
-+
-+              hws[idx] = sclk->hw;
-+      }
-+
-+      return 0;
-+
-+err_clk_unreg:
-+      while (--i >= 0) {
-+              sclk = &priv->data->clk_fixed[i];
-+              clk_hw_unregister_fixed_rate(sclk->hw);
-+      }
-+      return ret;
-+}
-+
-+#define CLK_FACTOR(_name, _parent, _mult, _div)               \
-+      {                                               \
-+              .name = _name,                          \
-+              .parent = _parent,                      \
-+              .mult = _mult,                          \
-+              .div = _div,                            \
-+              .flags = CLK_SET_RATE_PARENT            \
-+      }
-+
-+static struct mtmips_clk_factor rt2880_factor_clocks[] = {
-+      CLK_FACTOR("bus", "cpu", 1, 2)
-+};
-+
-+static struct mtmips_clk_factor rt305x_factor_clocks[] = {
-+      CLK_FACTOR("bus", "cpu", 1, 3)
-+};
-+
-+static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data,
-+                                       struct mtmips_clk_priv *priv)
-+{
-+      struct clk_hw **hws = clk_data->hws;
-+      struct mtmips_clk_factor *sclk;
-+      size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed;
-+      int ret, i;
-+
-+      for (i = 0; i < priv->data->num_clk_factor; i++) {
-+              int idx = idx_start + i;
-+
-+              sclk = &priv->data->clk_factor[i];
-+              sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name,
-+                                                sclk->parent, sclk->flags,
-+                                                sclk->mult, sclk->div);
-+              if (IS_ERR(sclk->hw)) {
-+                      pr_err("Couldn't register factor clock %d\n", idx);
-+                      goto err_clk_unreg;
-+              }
-+
-+              hws[idx] = sclk->hw;
-+      }
-+
-+      return 0;
-+
-+err_clk_unreg:
-+      while (--i >= 0) {
-+              sclk = &priv->data->clk_factor[i];
-+              clk_hw_unregister_fixed_factor(sclk->hw);
-+      }
-+      return ret;
-+}
-+
-+static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw)
-+{
-+      return container_of(hw, struct mtmips_clk, hw);
-+}
-+
-+static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw,
-+                                           unsigned long parent_rate)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 val;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val);
-+      if (!(val & RT5350_CLKCFG0_XTAL_SEL))
-+              return 20000000;
-+
-+      return 40000000;
-+}
-+
-+static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK;
-+
-+      switch (t) {
-+      case RT5350_SYSCFG0_CPUCLK_360:
-+              return 360000000;
-+      case RT5350_SYSCFG0_CPUCLK_320:
-+              return 320000000;
-+      case RT5350_SYSCFG0_CPUCLK_300:
-+              return 300000000;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      if (parent_rate == 320000000)
-+              return parent_rate / 4;
-+
-+      return parent_rate / 3;
-+}
-+
-+static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK;
-+
-+      switch (t) {
-+      case RT3352_SYSCFG0_CPUCLK_LOW:
-+              return 384000000;
-+      case RT3352_SYSCFG0_CPUCLK_HIGH:
-+              return 400000000;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK;
-+
-+      switch (t) {
-+      case RT305X_SYSCFG_CPUCLK_LOW:
-+              return 320000000;
-+      case RT305X_SYSCFG_CPUCLK_HIGH:
-+              return 384000000;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK;
-+
-+      switch (t) {
-+      case RT3883_SYSCFG0_CPUCLK_250:
-+              return 250000000;
-+      case RT3883_SYSCFG0_CPUCLK_384:
-+              return 384000000;
-+      case RT3883_SYSCFG0_CPUCLK_480:
-+              return 480000000;
-+      case RT3883_SYSCFG0_CPUCLK_500:
-+              return 500000000;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 ddr2;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
-+
-+      switch (parent_rate) {
-+      case 250000000:
-+              return (ddr2) ? 125000000 : 83000000;
-+      case 384000000:
-+              return (ddr2) ? 128000000 : 96000000;
-+      case 480000000:
-+              return (ddr2) ? 160000000 : 120000000;
-+      case 500000000:
-+              return (ddr2) ? 166000000 : 125000000;
-+      default:
-+              WARN_ON_ONCE(parent_rate == 0);
-+              return parent_rate / 4;
-+      }
-+}
-+
-+static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK;
-+
-+      switch (t) {
-+      case RT2880_CONFIG_CPUCLK_250:
-+              return 250000000;
-+      case RT2880_CONFIG_CPUCLK_266:
-+              return 266000000;
-+      case RT2880_CONFIG_CPUCLK_280:
-+              return 280000000;
-+      case RT2880_CONFIG_CPUCLK_300:
-+              return 300000000;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
-+{
-+      u64 t;
-+
-+      t = ref_rate;
-+      t *= mul;
-+      t = div_u64(t, div);
-+
-+      return t;
-+}
-+
-+static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      static const u32 clk_divider[] = { 2, 3, 4, 8 };
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      unsigned long cpu_pll;
-+      u32 t;
-+      u32 mul;
-+      u32 div;
-+
-+      regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t);
-+      if (t & CPLL_CFG0_BYPASS_REF_CLK) {
-+              cpu_pll = parent_rate;
-+      } else if ((t & CPLL_CFG0_SW_CFG) == 0) {
-+              cpu_pll = 600000000;
-+      } else {
-+              mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) &
-+                      CPLL_CFG0_PLL_MULT_RATIO_MASK;
-+              mul += 24;
-+              if (t & CPLL_CFG0_LC_CURFCK)
-+                      mul *= 2;
-+
-+              div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) &
-+                      CPLL_CFG0_PLL_DIV_RATIO_MASK;
-+
-+              WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider));
-+
-+              cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]);
-+      }
-+
-+      regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t);
-+      if (t & CPLL_CFG1_CPU_AUX1)
-+              return parent_rate;
-+
-+      if (t & CPLL_CFG1_CPU_AUX0)
-+              return 480000000;
-+
-+      return cpu_pll;
-+}
-+
-+static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+      u32 mul;
-+      u32 div;
-+
-+      regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
-+      mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK;
-+      div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) &
-+              CPU_SYS_CLKCFG_CPU_FDIV_MASK;
-+
-+      return mt7620_calc_rate(parent_rate, mul, div);
-+}
-+
-+static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long parent_rate)
-+{
-+      static const u32 ocp_dividers[16] = {
-+              [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2,
-+              [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3,
-+              [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4,
-+              [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5,
-+              [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10,
-+      };
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+      u32 ocp_ratio;
-+      u32 div;
-+
-+      regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
-+      ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) &
-+              CPU_SYS_CLKCFG_OCP_RATIO_MASK;
-+
-+      if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers)))
-+              return parent_rate;
-+
-+      div = ocp_dividers[ocp_ratio];
-+
-+      if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio))
-+              return parent_rate;
-+
-+      return parent_rate / div;
-+}
-+
-+static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw,
-+                                             unsigned long parent_rate)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_CLKCFG0, &t);
-+      if (t & CLKCFG0_PERI_CLK_SEL)
-+              return parent_rate;
-+
-+      return 40000000;
-+}
-+
-+static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw,
-+                                           unsigned long parent_rate)
-+{
-+      struct mtmips_clk *clk = to_mtmips_clk(hw);
-+      struct regmap *sysc = clk->priv->sysc;
-+      u32 t;
-+
-+      regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
-+      if (t & MT7620_XTAL_FREQ_SEL)
-+              return 40000000;
-+
-+      return 20000000;
-+}
-+
-+static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw,
-+                                          unsigned long xtal_clk)
-+{
-+      if (xtal_clk == 40000000)
-+              return 580000000;
-+
-+      return 575000000;
-+}
-+
-+#define CLK_BASE(_name, _parent, _recalc) {                           \
-+      .init = &(const struct clk_init_data) {                         \
-+              .name = _name,                                          \
-+              .ops = &(const struct clk_ops) {                        \
-+                      .recalc_rate = _recalc,                         \
-+              },                                                      \
-+              .parent_data = &(const struct clk_parent_data) {        \
-+                      .name = _parent,                                \
-+                      .fw_name = _parent                              \
-+              },                                                      \
-+              .num_parents = _parent ? 1 : 0                          \
-+      },                                                              \
-+}
-+
-+static struct mtmips_clk rt2880_clks_base[] = {
-+      { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) }
-+};
-+
-+static struct mtmips_clk rt305x_clks_base[] = {
-+      { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) }
-+};
-+
-+static struct mtmips_clk rt3352_clks_base[] = {
-+      { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
-+      { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) }
-+};
-+
-+static struct mtmips_clk rt3883_clks_base[] = {
-+      { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) },
-+      { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) }
-+};
-+
-+static struct mtmips_clk rt5350_clks_base[] = {
-+      { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
-+      { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) },
-+      { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) }
-+};
-+
-+static struct mtmips_clk mt7620_clks_base[] = {
-+      { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
-+      { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) },
-+      { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) },
-+      { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) },
-+      { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) }
-+};
-+
-+static struct mtmips_clk mt76x8_clks_base[] = {
-+      { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
-+      { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) }
-+};
-+
-+static int mtmips_register_clocks(struct device_node *np,
-+                                struct clk_hw_onecell_data *clk_data,
-+                                struct mtmips_clk_priv *priv)
-+{
-+      struct clk_hw **hws = clk_data->hws;
-+      struct mtmips_clk *sclk;
-+      int ret, i;
-+
-+      for (i = 0; i < priv->data->num_clk_base; i++) {
-+              sclk = &priv->data->clk_base[i];
-+              sclk->priv = priv;
-+              ret = of_clk_hw_register(np, &sclk->hw);
-+              if (ret) {
-+                      pr_err("Couldn't register top clock %i\n", i);
-+                      goto err_clk_unreg;
-+              }
-+
-+              hws[i] = &sclk->hw;
-+      }
-+
-+      return 0;
-+
-+err_clk_unreg:
-+      while (--i >= 0) {
-+              sclk = &priv->data->clk_base[i];
-+              clk_hw_unregister(&sclk->hw);
-+      }
-+      return ret;
-+}
-+
-+static const struct mtmips_clk_data rt2880_clk_data = {
-+      .clk_base = rt2880_clks_base,
-+      .num_clk_base = ARRAY_SIZE(rt2880_clks_base),
-+      .clk_fixed = rt305x_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
-+      .clk_factor = rt2880_factor_clocks,
-+      .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks),
-+      .clk_periph = rt2880_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data rt305x_clk_data = {
-+      .clk_base = rt305x_clks_base,
-+      .num_clk_base = ARRAY_SIZE(rt305x_clks_base),
-+      .clk_fixed = rt305x_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
-+      .clk_factor = rt305x_factor_clocks,
-+      .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
-+      .clk_periph = rt305x_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data rt3352_clk_data = {
-+      .clk_base = rt3352_clks_base,
-+      .num_clk_base = ARRAY_SIZE(rt3352_clks_base),
-+      .clk_fixed = rt3352_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
-+      .clk_factor = rt305x_factor_clocks,
-+      .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
-+      .clk_periph = rt5350_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data rt3883_clk_data = {
-+      .clk_base = rt3883_clks_base,
-+      .num_clk_base = ARRAY_SIZE(rt3883_clks_base),
-+      .clk_fixed = rt305x_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
-+      .clk_factor = NULL,
-+      .num_clk_factor = 0,
-+      .clk_periph = rt5350_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data rt5350_clk_data = {
-+      .clk_base = rt5350_clks_base,
-+      .num_clk_base = ARRAY_SIZE(rt5350_clks_base),
-+      .clk_fixed = rt3352_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
-+      .clk_factor = NULL,
-+      .num_clk_factor = 0,
-+      .clk_periph = rt5350_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data mt7620_clk_data = {
-+      .clk_base = mt7620_clks_base,
-+      .num_clk_base = ARRAY_SIZE(mt7620_clks_base),
-+      .clk_fixed = NULL,
-+      .num_clk_fixed = 0,
-+      .clk_factor = NULL,
-+      .num_clk_factor = 0,
-+      .clk_periph = mt7620_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks),
-+};
-+
-+static const struct mtmips_clk_data mt76x8_clk_data = {
-+      .clk_base = mt76x8_clks_base,
-+      .num_clk_base = ARRAY_SIZE(mt76x8_clks_base),
-+      .clk_fixed = mt76x8_fixed_clocks,
-+      .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks),
-+      .clk_factor = rt305x_factor_clocks,
-+      .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
-+      .clk_periph = mt76x8_pherip_clks,
-+      .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks),
-+};
-+
-+static const struct of_device_id mtmips_of_match[] = {
-+      {
-+              .compatible = "ralink,rt2880-sysc",
-+              .data = &rt2880_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,rt3050-sysc",
-+              .data = &rt305x_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,rt3052-sysc",
-+              .data = &rt305x_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,rt3352-sysc",
-+              .data = &rt3352_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,rt3883-sysc",
-+              .data = &rt3883_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,rt5350-sysc",
-+              .data = &rt5350_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,mt7620-sysc",
-+              .data = &mt7620_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,mt7628-sysc",
-+              .data = &mt76x8_clk_data,
-+      },
-+      {
-+              .compatible = "ralink,mt7688-sysc",
-+              .data = &mt76x8_clk_data,
-+      },
-+      {}
-+};
-+
-+static void __init mtmips_clk_regs_init(struct device_node *node,
-+                                      struct mtmips_clk_priv *priv)
-+{
-+      u32 t;
-+
-+      if (!of_device_is_compatible(node, "ralink,mt7620-sysc"))
-+              return;
-+
-+      /*
-+       * When the CPU goes into sleep mode, the BUS
-+       * clock will be too low for USB to function properly.
-+       * Adjust the busses fractional divider to fix this
-+       */
-+      regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
-+      t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
-+      t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
-+      regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t);
-+}
-+
-+static void __init mtmips_clk_init(struct device_node *node)
-+{
-+      const struct of_device_id *match;
-+      const struct mtmips_clk_data *data;
-+      struct mtmips_clk_priv *priv;
-+      struct clk_hw_onecell_data *clk_data;
-+      int ret, i, count;
-+
-+      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return;
-+
-+      priv->sysc = syscon_node_to_regmap(node);
-+      if (IS_ERR(priv->sysc)) {
-+              pr_err("Could not get sysc syscon regmap\n");
-+              goto free_clk_priv;
-+      }
-+
-+      mtmips_clk_regs_init(node, priv);
-+
-+      match = of_match_node(mtmips_of_match, node);
-+      if (WARN_ON(!match))
-+              return;
-+
-+      data = match->data;
-+      priv->data = data;
-+      count = priv->data->num_clk_base + priv->data->num_clk_fixed +
-+              priv->data->num_clk_factor + priv->data->num_clk_periph;
-+      clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL);
-+      if (!clk_data)
-+              goto free_clk_priv;
-+
-+      ret = mtmips_register_clocks(node, clk_data, priv);
-+      if (ret) {
-+              pr_err("Couldn't register top clocks\n");
-+              goto free_clk_data;
-+      }
-+
-+      ret = mtmips_register_fixed_clocks(clk_data, priv);
-+      if (ret) {
-+              pr_err("Couldn't register fixed clocks\n");
-+              goto unreg_clk_top;
-+      }
-+
-+      ret = mtmips_register_factor_clocks(clk_data, priv);
-+      if (ret) {
-+              pr_err("Couldn't register factor clocks\n");
-+              goto unreg_clk_fixed;
-+      }
-+
-+      ret = mtmips_register_pherip_clocks(node, clk_data, priv);
-+      if (ret) {
-+              pr_err("Couldn't register peripheral clocks\n");
-+              goto unreg_clk_factor;
-+      }
-+
-+      clk_data->num = count;
-+
-+      ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
-+      if (ret) {
-+              pr_err("Couldn't add clk hw provider\n");
-+              goto unreg_clk_periph;
-+      }
-+
-+      return;
-+
-+unreg_clk_periph:
-+      for (i = 0; i < priv->data->num_clk_periph; i++) {
-+              struct mtmips_clk *sclk = &priv->data->clk_periph[i];
-+
-+              clk_hw_unregister(&sclk->hw);
-+      }
-+
-+unreg_clk_factor:
-+      for (i = 0; i < priv->data->num_clk_factor; i++) {
-+              struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i];
-+
-+              clk_hw_unregister_fixed_factor(sclk->hw);
-+      }
-+
-+unreg_clk_fixed:
-+      for (i = 0; i < priv->data->num_clk_fixed; i++) {
-+              struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i];
-+
-+              clk_hw_unregister_fixed_rate(sclk->hw);
-+      }
-+
-+unreg_clk_top:
-+      for (i = 0; i < priv->data->num_clk_base; i++) {
-+              struct mtmips_clk *sclk = &priv->data->clk_base[i];
-+
-+              clk_hw_unregister(&sclk->hw);
-+      }
-+
-+free_clk_data:
-+      kfree(clk_data);
-+
-+free_clk_priv:
-+      kfree(priv);
-+}
-+CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init);
-+CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init);
-+
-+struct mtmips_rst {
-+      struct reset_controller_dev rcdev;
-+      struct regmap *sysc;
-+};
-+
-+static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev)
-+{
-+      return container_of(dev, struct mtmips_rst, rcdev);
-+}
-+
-+static int mtmips_assert_device(struct reset_controller_dev *rcdev,
-+                              unsigned long id)
-+{
-+      struct mtmips_rst *data = to_mtmips_rst(rcdev);
-+      struct regmap *sysc = data->sysc;
-+
-+      return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id));
-+}
-+
-+static int mtmips_deassert_device(struct reset_controller_dev *rcdev,
-+                                unsigned long id)
-+{
-+      struct mtmips_rst *data = to_mtmips_rst(rcdev);
-+      struct regmap *sysc = data->sysc;
-+
-+      return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0);
-+}
-+
-+static int mtmips_reset_device(struct reset_controller_dev *rcdev,
-+                             unsigned long id)
-+{
-+      int ret;
-+
-+      ret = mtmips_assert_device(rcdev, id);
-+      if (ret < 0)
-+              return ret;
-+
-+      return mtmips_deassert_device(rcdev, id);
-+}
-+
-+static int mtmips_rst_xlate(struct reset_controller_dev *rcdev,
-+                          const struct of_phandle_args *reset_spec)
-+{
-+      unsigned long id = reset_spec->args[0];
-+
-+      if (id == 0 || id >= rcdev->nr_resets)
-+              return -EINVAL;
-+
-+      return id;
-+}
-+
-+static const struct reset_control_ops reset_ops = {
-+      .reset = mtmips_reset_device,
-+      .assert = mtmips_assert_device,
-+      .deassert = mtmips_deassert_device
-+};
-+
-+static int mtmips_reset_init(struct device *dev, struct regmap *sysc)
-+{
-+      struct mtmips_rst *rst_data;
-+
-+      rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
-+      if (!rst_data)
-+              return -ENOMEM;
-+
-+      rst_data->sysc = sysc;
-+      rst_data->rcdev.ops = &reset_ops;
-+      rst_data->rcdev.owner = THIS_MODULE;
-+      rst_data->rcdev.nr_resets = 32;
-+      rst_data->rcdev.of_reset_n_cells = 1;
-+      rst_data->rcdev.of_xlate = mtmips_rst_xlate;
-+      rst_data->rcdev.of_node = dev_of_node(dev);
-+
-+      return devm_reset_controller_register(dev, &rst_data->rcdev);
-+}
-+
-+static int mtmips_clk_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      struct device *dev = &pdev->dev;
-+      struct mtmips_clk_priv *priv;
-+      int ret;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      priv->sysc = syscon_node_to_regmap(np);
-+      if (IS_ERR(priv->sysc))
-+              return dev_err_probe(dev, PTR_ERR(priv->sysc),
-+                                   "Could not get sysc syscon regmap\n");
-+
-+      ret = mtmips_reset_init(dev, priv->sysc);
-+      if (ret)
-+              return dev_err_probe(dev, ret, "Could not init reset controller\n");
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id mtmips_clk_of_match[] = {
-+      { .compatible = "ralink,rt2880-reset" },
-+      { .compatible = "ralink,rt2880-sysc" },
-+      { .compatible = "ralink,rt3050-sysc" },
-+      { .compatible = "ralink,rt3052-sysc" },
-+      { .compatible = "ralink,rt3352-sysc" },
-+      { .compatible = "ralink,rt3883-sysc" },
-+      { .compatible = "ralink,rt5350-sysc" },
-+      { .compatible = "ralink,mt7620-sysc" },
-+      { .compatible = "ralink,mt7628-sysc" },
-+      { .compatible = "ralink,mt7688-sysc" },
-+      {}
-+};
-+
-+static struct platform_driver mtmips_clk_driver = {
-+      .probe = mtmips_clk_probe,
-+      .driver = {
-+              .name = "mtmips-clk",
-+              .of_match_table = mtmips_clk_of_match,
-+      },
-+};
-+
-+static int __init mtmips_clk_reset_init(void)
-+{
-+      return platform_driver_register(&mtmips_clk_driver);
-+}
-+arch_initcall(mtmips_clk_reset_init);