Hi Andreas,
This series adds clock and reset controllers for the Realtek RTD1619 SoC.
Cc: Andreas Färber <[email protected]>
Cc: Cheng-Yu Lee <[email protected]>
Cc: [email protected]
cylee12 (6):
dt-bindings: clock: add bindings for RTD1619 clocks
dt-bindings: reset: add bindings for rtd1619 reset controls
clk: realtek: add common clock support for Realtek SoCs
clk: realtek: add reset controller support for Realtek SoCs
clk: realtek: add rtd1619 controllers
dt-bindings: clk: realtek: add rtd1619 clock controller bindings
.../bindings/clock/realtek,clocks.txt | 38 ++
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/realtek/Kconfig | 21 +
drivers/clk/realtek/Makefile | 12 +
drivers/clk/realtek/clk-pll-dif.c | 81 +++
drivers/clk/realtek/clk-pll-psaud.c | 120 ++++
drivers/clk/realtek/clk-pll.c | 400 +++++++++++++
drivers/clk/realtek/clk-pll.h | 151 +++++
drivers/clk/realtek/clk-regmap-gate.c | 89 +++
drivers/clk/realtek/clk-regmap-gate.h | 26 +
drivers/clk/realtek/clk-regmap-mux.c | 63 ++
drivers/clk/realtek/clk-regmap-mux.h | 26 +
drivers/clk/realtek/clk-rtd1619-cc.c | 553 ++++++++++++++++++
drivers/clk/realtek/clk-rtd1619-ic.c | 112 ++++
drivers/clk/realtek/common.c | 320 ++++++++++
drivers/clk/realtek/common.h | 123 ++++
drivers/clk/realtek/reset.c | 107 ++++
drivers/clk/realtek/reset.h | 37 ++
include/dt-bindings/clock/rtk,clock-rtd1619.h | 88 +++
include/dt-bindings/reset/rtk,reset-rtd1619.h | 124 ++++
21 files changed, 2493 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/realtek,clocks.txt
create mode 100644 drivers/clk/realtek/Kconfig
create mode 100644 drivers/clk/realtek/Makefile
create mode 100644 drivers/clk/realtek/clk-pll-dif.c
create mode 100644 drivers/clk/realtek/clk-pll-psaud.c
create mode 100644 drivers/clk/realtek/clk-pll.c
create mode 100644 drivers/clk/realtek/clk-pll.h
create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
create mode 100644 drivers/clk/realtek/clk-regmap-mux.c
create mode 100644 drivers/clk/realtek/clk-regmap-mux.h
create mode 100644 drivers/clk/realtek/clk-rtd1619-cc.c
create mode 100644 drivers/clk/realtek/clk-rtd1619-ic.c
create mode 100644 drivers/clk/realtek/common.c
create mode 100644 drivers/clk/realtek/common.h
create mode 100644 drivers/clk/realtek/reset.c
create mode 100644 drivers/clk/realtek/reset.h
create mode 100644 include/dt-bindings/clock/rtk,clock-rtd1619.h
create mode 100644 include/dt-bindings/reset/rtk,reset-rtd1619.h
--
2.24.0
From: cylee12 <[email protected]>
Add devicetree binding for Realtek RTD1619 clocks.
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
include/dt-bindings/clock/rtk,clock-rtd1619.h | 88 +++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 include/dt-bindings/clock/rtk,clock-rtd1619.h
diff --git a/include/dt-bindings/clock/rtk,clock-rtd1619.h b/include/dt-bindings/clock/rtk,clock-rtd1619.h
new file mode 100644
index 000000000000..497f9b914857
--- /dev/null
+++ b/include/dt-bindings/clock/rtk,clock-rtd1619.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __DT_BINDINGS_RTK_CLOCK_RTD1619_H
+#define __DT_BINDINGS_RTK_CLOCK_RTD1619_H
+
+#define CC_PLL_SCPU 0
+#define CC_PLL_BUS 2
+#define CC_CLK_SYS 3
+#define CC_CLK_SYS_SB2 4
+#define CC_PLL_DCSB 5
+#define CC_CLK_SYSH 6
+#define CC_PLL_DDSA 7
+#define CC_PLL_DDSB 8
+#define CC_PLL_GPU 9
+#define CC_CLK_GPU 10
+#define CC_PLL_VE1 11
+#define CC_PLL_VE2 12
+#define CC_CLK_VE1 13
+#define CC_CLK_VE2 14
+#define CC_CLK_VE3 15
+#define CC_CLK_VE2_BPU 16
+#define CC_PLL_DIF 17
+#define CC_PLL_PSAUD1A 18
+#define CC_PLL_PSAUD2A 19
+
+#define CC_CKE_MISC 33
+#define CC_CKE_PCIE0 34
+#define CC_CKE_GSPI 35
+#define CC_CKE_SDS 36
+#define CC_CKE_HDMI 37
+#define CC_CKE_LSADC 38
+#define CC_CKE_SE 39
+#define CC_CKE_CP 40
+#define CC_CKE_MD 41
+#define CC_CKE_TP 42
+#define CC_CKE_RSA 43
+#define CC_CKE_NF 44
+#define CC_CKE_EMMC 45
+#define CC_CKE_SD 46
+#define CC_CKE_SDIO_IP 47
+#define CC_CKE_MIPI 48
+#define CC_CKE_EMMC_IP 49
+#define CC_CKE_SDIO 50
+#define CC_CKE_SD_IP 51
+#define CC_CKE_CABLERX 52
+#define CC_CKE_TPB 53
+#define CC_CKE_SC1 54
+#define CC_CKE_I2C3 55
+#define CC_CKE_JPEG 56
+#define CC_CKE_SC0 57
+#define CC_CKE_HDMIRX 58
+#define CC_CKE_HSE 59
+#define CC_CKE_UR2 60
+#define CC_CKE_UR1 61
+#define CC_CKE_FAN 62
+#define CC_CKE_SATA_WRAP_SYS 63
+#define CC_CKE_SATA_WRAP_SYSH 64
+#define CC_CKE_SATA_MAC_SYSH 65
+#define CC_CKE_R2RDSC 66
+#define CC_CKE_PCIE1 67
+#define CC_CKE_I2C4 68
+#define CC_CKE_I2C5 69
+#define CC_CKE_EDP 70
+#define CC_CKE_TSIO_TRX 71
+#define CC_CKE_TVE 72
+#define CC_CKE_VO 73
+
+#define CC_CLK_MAX 74
+
+
+#define IC_CKE_CEC0 2
+#define IC_CKE_CBUSRX_SYS 3
+#define IC_CKE_CBUSTX_SYS 4
+#define IC_CKE_CBUS_SYS 5
+#define IC_CKE_CBUS_OSC 6
+#define IC_CKE_IR 7
+#define IC_CKE_UR0 8
+#define IC_CKE_I2C0 9
+#define IC_CKE_I2C1 10
+#define IC_CKE_ETN_250M 11
+#define IC_CKE_ETN_SYS 12
+#define IC_CKE_USB_DRD 13
+#define IC_CKE_USB_HOST 14
+#define IC_CKE_USB_U3_HOST 15
+#define IC_CKE_USB 16
+#define IC_CLK_MAX 17
+
+#endif /* __DT_BINDINGS_RTK_CLOCK_RTD1619_H */
+
--
2.24.0
From: cylee12 <[email protected]>
This patch adds common clock support for Realtek SoCs, including PLLs,
Mux clocks and Gate clocks.
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/realtek/Kconfig | 10 +
drivers/clk/realtek/Makefile | 9 +
drivers/clk/realtek/clk-pll-dif.c | 81 ++++++
drivers/clk/realtek/clk-pll-psaud.c | 120 ++++++++
drivers/clk/realtek/clk-pll.c | 400 ++++++++++++++++++++++++++
drivers/clk/realtek/clk-pll.h | 151 ++++++++++
drivers/clk/realtek/clk-regmap-gate.c | 89 ++++++
drivers/clk/realtek/clk-regmap-gate.h | 26 ++
drivers/clk/realtek/clk-regmap-mux.c | 63 ++++
drivers/clk/realtek/clk-regmap-mux.h | 26 ++
drivers/clk/realtek/common.c | 320 +++++++++++++++++++++
drivers/clk/realtek/common.h | 123 ++++++++
14 files changed, 1420 insertions(+)
create mode 100644 drivers/clk/realtek/Kconfig
create mode 100644 drivers/clk/realtek/Makefile
create mode 100644 drivers/clk/realtek/clk-pll-dif.c
create mode 100644 drivers/clk/realtek/clk-pll-psaud.c
create mode 100644 drivers/clk/realtek/clk-pll.c
create mode 100644 drivers/clk/realtek/clk-pll.h
create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
create mode 100644 drivers/clk/realtek/clk-regmap-mux.c
create mode 100644 drivers/clk/realtek/clk-regmap-mux.h
create mode 100644 drivers/clk/realtek/common.c
create mode 100644 drivers/clk/realtek/common.h
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c44247d0b83e..8e06487440ce 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -317,6 +317,7 @@ source "drivers/clk/mediatek/Kconfig"
source "drivers/clk/meson/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
+source "drivers/clk/realtek/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sifive/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 0138fb14e6f8..71ea17f97f7d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
+obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/
obj-y += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
new file mode 100644
index 000000000000..5bca757dddfa
--- /dev/null
+++ b/drivers/clk/realtek/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config COMMON_CLK_REALTEK
+ bool "Clock driver for realtek"
+ select MFD_SYSCON
+
+config CLK_PLL_PSAUD
+ bool
+
+config CLK_PLL_DIF
+ bool
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
new file mode 100644
index 000000000000..050d450db067
--- /dev/null
+++ b/drivers/clk/realtek/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_COMMON_CLK_REALTEK) += clk-rtk.o
+
+clk-rtk-y += common.o
+clk-rtk-y += clk-regmap-mux.o
+clk-rtk-y += clk-regmap-gate.o
+clk-rtk-y += clk-pll.o
+clk-rtk-$(CONFIG_CLK_PLL_PSAUD) += clk-pll-psaud.o
+clk-rtk-$(CONFIG_CLK_PLL_DIF) += clk-pll-dif.o
diff --git a/drivers/clk/realtek/clk-pll-dif.c b/drivers/clk/realtek/clk-pll-dif.c
new file mode 100644
index 000000000000..d19efef2626e
--- /dev/null
+++ b/drivers/clk/realtek/clk-pll-dif.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include "common.h"
+#include "clk-pll.h"
+
+static int clk_pll_dif_enable(struct clk_hw *hw)
+{
+ struct clk_pll_dif *pll = to_clk_pll_dif(hw);
+
+ pr_debug("%pC: %s\n", hw->clk, __func__);
+
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x0C, 0x00000048);
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00020c00);
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x04, 0x204004ca);
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x00, 0x8000a000);
+ udelay(100);
+
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00420c00);
+ udelay(50);
+
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00420c03);
+ udelay(200);
+
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x0C, 0x00000078);
+ udelay(100);
+
+ clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x04, 0x204084ca);
+
+ /* ssc control */
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x00, 0x00000004);
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x04, 0x00006800);
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x0C, 0x00000000);
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x10, 0x00000000);
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x08, 0x001e1f98);
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x00, 0x00000005);
+ pll->status = 1;
+
+ return 0;
+}
+
+static void clk_pll_dif_disable(struct clk_hw *hw)
+{
+ struct clk_pll_dif *pll = to_clk_pll_dif(hw);
+
+ pr_debug("%pC: %s\n", hw->clk, __func__);
+ clk_regmap_update(&pll->clkr, pll->pll_ofs + 0x04, 0x00080000, 0x0);
+ clk_regmap_update(&pll->clkr, pll->pll_ofs + 0x08, 0x00400C03, 0x0);
+ clk_regmap_update(&pll->clkr, pll->pll_ofs + 0x0C, 0x00000038, 0x0);
+
+ clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x00, 0x00000004);
+ pll->status = 0;
+}
+
+static int clk_pll_dif_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pll_dif *pll = to_clk_pll_dif(hw);
+
+ return pll->status;
+}
+
+static void clk_pll_dif_disable_unused(struct clk_hw *hw)
+{
+ pr_info("%pC: %s\n", hw->clk, __func__);
+ clk_pll_dif_disable(hw);
+}
+
+const struct clk_ops clk_pll_dif_ops = {
+ .enable = clk_pll_dif_enable,
+ .disable = clk_pll_dif_disable,
+ .disable_unused = clk_pll_dif_disable_unused,
+ .is_enabled = clk_pll_dif_is_enabled,
+};
+
diff --git a/drivers/clk/realtek/clk-pll-psaud.c b/drivers/clk/realtek/clk-pll-psaud.c
new file mode 100644
index 000000000000..757a3320ebb7
--- /dev/null
+++ b/drivers/clk/realtek/clk-pll-psaud.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * clk-pll-psaud.c - PLL_PSAUDXA
+ *
+ * Copyright (c) 2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk-provider.h>
+#include "common.h"
+#include "clk-pll.h"
+
+static int clk_pll_psaud_enable(struct clk_hw *hw)
+{
+ struct clk_pll_psaud *pll = to_clk_pll_psaud(hw);
+ u32 mask = 0, val = 0;
+
+ if (pll->id == CLK_PLL_PSAUD1A) {
+ mask = 0x3;
+ val = 0x1;
+ } else {
+ mask = 0xc;
+ val = 0x4;
+ }
+ clk_regmap_update(&pll->clkr, pll->reg + 4, mask, val);
+ return 0;
+}
+
+static void clk_pll_psaud_disable(struct clk_hw *hw)
+{
+ struct clk_pll_psaud *pll = to_clk_pll_psaud(hw);
+ u32 mask = 0, val = 0;
+
+ if (pll->id == CLK_PLL_PSAUD1A) {
+ mask = 0x3;
+ val = 0x3;
+ } else {
+ mask = 0xc;
+ val = 0xc;
+ }
+ clk_regmap_update(&pll->clkr, pll->reg + 4, mask, val);
+}
+
+static void clk_pll_psaud_disable_unused(struct clk_hw *hw)
+{
+ pr_info("%pC: %s\n", hw->clk, __func__);
+ clk_pll_psaud_disable(hw);
+}
+
+static int clk_pll_psaud_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pll_psaud *pll = to_clk_pll_psaud(hw);
+ u32 val;
+
+ val = clk_regmap_read(&pll->clkr, pll->reg + 4);
+ if (pll->id == CLK_PLL_PSAUD1A)
+ val &= 0x3;
+ else
+ val >>= 2;
+ return val == 0x1;
+}
+
+static long clk_pll_psaud_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return 49192000;
+}
+
+static int clk_pll_psaud_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pll_psaud *pll = to_clk_pll_psaud(hw);
+ u32 rsel = 0;
+ u32 mask = 0, val = 0;
+
+ if (WARN_ON_ONCE(rate != 45158400 && rate != 49192000))
+ return -EINVAL;
+
+ if (rate == 45158400)
+ rsel = 1;
+ if (pll->id == CLK_PLL_PSAUD1A) {
+ val = 0x6a0 | (rsel << 8);
+ mask = 0x7e0;
+ } else {
+ val = 0x19 | (rsel << 2);
+ mask = 0x1f;
+ }
+ clk_regmap_update(&pll->clkr, pll->reg, mask, val);
+ return 0;
+}
+
+static unsigned long clk_pll_psaud_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pll_psaud *pll = to_clk_pll_psaud(hw);
+ u32 val;
+ u32 rsel = 0;
+
+ val = clk_regmap_read(&pll->clkr, pll->reg);
+
+ if (pll->id == CLK_PLL_PSAUD1A)
+ rsel = !!(val & BIT(8));
+ else
+ rsel = !!(val & BIT(2));
+
+ return rsel ? 45158400 : 49192000;
+}
+
+const struct clk_ops clk_pll_psaud_ops = {
+ .enable = clk_pll_psaud_enable,
+ .disable = clk_pll_psaud_disable,
+ .disable_unused = clk_pll_psaud_disable_unused,
+ .is_enabled = clk_pll_psaud_is_enabled,
+ .set_rate = clk_pll_psaud_set_rate,
+ .round_rate = clk_pll_psaud_round_rate,
+ .recalc_rate = clk_pll_psaud_recalc_rate,
+};
+
diff --git a/drivers/clk/realtek/clk-pll.c b/drivers/clk/realtek/clk-pll.c
new file mode 100644
index 000000000000..dd90bfc011ec
--- /dev/null
+++ b/drivers/clk/realtek/clk-pll.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017-2018 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include "common.h"
+#include "clk-pll.h"
+
+static int clk_pll_debug_rate_u64_set(void *data, u64 val)
+{
+ struct clk_hw *hw = data;
+
+ clk_set_rate(hw->clk, (unsigned long)(val));
+ return 0;
+}
+
+static int clk_pll_debug_rate_u64_get(void *data, u64 *val)
+{
+ struct clk_hw *hw = data;
+
+ *val = (u64)clk_get_rate(hw->clk);
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clk_pll_debut_rate_op, clk_pll_debug_rate_u64_get,
+ clk_pll_debug_rate_u64_set, "%llu\n");
+
+static void clk_pll_debug_init(struct clk_hw *hw, struct dentry *d)
+{
+ debugfs_create_file("debug_rate", 0644, d, hw, &clk_pll_debut_rate_op);
+}
+
+static const struct freq_table *ftbl_find_by_rate(const struct freq_table *ftbl,
+ unsigned long rate)
+{
+ unsigned long best_rate = 0;
+ const struct freq_table *best = NULL;
+
+ for ( ; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
+ if (ftbl->rate == rate)
+ return ftbl;
+
+ if (ftbl->rate > rate)
+ continue;
+
+ if ((rate - best_rate) > (rate - ftbl->rate)) {
+ best_rate = ftbl->rate;
+ best = ftbl;
+ }
+ }
+
+ return best;
+}
+
+static const struct freq_table *ftbl_find_by_val(const struct freq_table *ftbl,
+ uint32_t value)
+{
+ while (!IS_FREQ_TABLE_END(ftbl)) {
+ if (ftbl->val == (value))
+ return ftbl;
+ ftbl++;
+ }
+ return NULL;
+};
+
+static const struct div_table *dtbl_find_by_rate(const struct div_table *dtbl,
+ unsigned long rate)
+{
+ while (!IS_DIV_TABLE_END(dtbl)) {
+ if (rate >= dtbl->rate)
+ return dtbl;
+ dtbl++;
+ }
+ return NULL;
+}
+
+static const struct div_table *dtbl_find_by_val(const struct div_table *dtbl,
+ uint32_t val)
+{
+ while (!IS_DIV_TABLE_END(dtbl)) {
+ if (val == dtbl->val)
+ return dtbl;
+ dtbl++;
+ }
+ return NULL;
+}
+
+static void __clk_pll_set_pow_reg(struct clk_pll *clkp, int on)
+{
+ uint32_t pow = (clkp->pow_loc == CLK_PLL_CONF_POW_LOC_CTL3) ? 0x8 : 0x4;
+
+ if (on) {
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs + pow, 0x7, 0x3);
+ if (clkp->freq_loc == CLK_PLL_CONF_FREQ_LOC_SSC1) {
+ uint32_t val;
+
+ val = clk_regmap_read(&clkp->clkr, clkp->ssc_ofs + 0x0);
+
+ /*
+ * For those PLL with SCC used only the default
+ * freq, the oc_en would nerver to be set.
+ * Help to set it here.
+ */
+ if ((val & 0x7) != 0x5)
+ clk_regmap_update(&clkp->clkr,
+ clkp->ssc_ofs + 0x0, 0x7, 0x5);
+ }
+ udelay(200);
+ } else {
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs + pow, 0x7, 0x4);
+ }
+}
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+
+ if (clk_pll_has_pow(clkp))
+ __clk_pll_set_pow_reg(clkp, 1);
+ return 0;
+}
+
+static void clk_pll_disable(struct clk_hw *hw)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+
+ if (clk_pll_has_pow(clkp))
+ __clk_pll_set_pow_reg(clkp, 0);
+}
+
+static void clk_pll_disable_unused(struct clk_hw *hw)
+{
+ pr_info("%pC: %s\n", hw->clk, __func__);
+ clk_pll_disable(hw);
+}
+
+static int clk_pll_is_enabled(struct clk_hw *hw)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+ uint32_t pow;
+ uint32_t val;
+
+ if (!clk_pll_has_pow(clkp))
+ return -EINVAL;
+
+ pow = (clkp->pow_loc == CLK_PLL_CONF_POW_LOC_CTL3) ? 0x8 : 0x4;
+ val = clk_regmap_read(&clkp->clkr, clkp->pll_ofs + pow);
+ return !!(val & 0x1);
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+ const struct freq_table *ftblv = NULL;
+
+ ftblv = ftbl_find_by_rate(clkp->freq_tbl, rate);
+ return ftblv ? ftblv->rate : 0;
+}
+
+static uint32_t __clk_pll_freq_get(struct clk_pll *clkp)
+{
+ uint32_t val = 0;
+
+ switch (clkp->freq_loc) {
+ case CLK_PLL_CONF_FREQ_LOC_CTL1:
+ val = clk_regmap_read(&clkp->clkr, clkp->pll_ofs + 0x0);
+ break;
+
+ case CLK_PLL_CONF_FREQ_LOC_CTL2:
+ val = clk_regmap_read(&clkp->clkr, clkp->pll_ofs + 0x4);
+ break;
+
+ case CLK_PLL_CONF_FREQ_LOC_SSC1:
+ val = clk_regmap_read(&clkp->clkr, clkp->ssc_ofs + 0x4);
+ break;
+
+ default:
+ break;
+ }
+ return val & clkp->freq_mask;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+ unsigned long flags = 0;
+ const struct freq_table *fv;
+ uint32_t val;
+
+ flags = clk_pll_lock(clkp);
+ val = __clk_pll_freq_get(clkp);
+ clk_pll_unlock(clkp, flags);
+
+ fv = ftbl_find_by_val(clkp->freq_tbl, val);
+ return fv ? fv->rate : 0;
+}
+
+static inline int __clk_pll_freq_set(struct clk_pll *clkp, uint32_t val)
+{
+ struct clk_hw *hw = &clkp->clkr.hw;
+ int ret = 0;
+ uint32_t mask = clkp->freq_mask;
+ uint32_t pollval;
+
+ switch (clkp->freq_loc) {
+ case CLK_PLL_CONF_FREQ_LOC_CTL1:
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs, mask, val);
+ break;
+
+ case CLK_PLL_CONF_FREQ_LOC_CTL2:
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs + 0x4, mask, val);
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs + 0x8, 0x1, 0x0);
+ clk_regmap_update(&clkp->clkr, clkp->pll_ofs + 0x8, 0x1, 0x1);
+ break;
+
+ case CLK_PLL_CONF_FREQ_LOC_SSC1:
+ clk_regmap_update(&clkp->clkr, clkp->ssc_ofs + 0x0, 0x7, 0x4);
+ clk_regmap_update(&clkp->clkr, clkp->ssc_ofs + 0x4, mask, val);
+ clk_regmap_update(&clkp->clkr, clkp->ssc_ofs + 0x0, 0x7, 0x5);
+
+ if (clk_pll_has_pow(clkp) && !clk_pll_is_enabled(hw))
+ return 0;
+
+ ret = regmap_read_poll_timeout(clkp->clkr.regmap,
+ clkp->ssc_ofs + 0x1c,
+ pollval, pollval & BIT(20),
+ 0, 2000);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pll *clkp = to_clk_pll(hw);
+ unsigned long flags = 0;
+ const struct freq_table *fv;
+ int ret = 0;
+
+ fv = ftbl_find_by_rate(clkp->freq_tbl, rate);
+ if (!fv)
+ return -EINVAL;
+
+ pr_debug("%pC: %s: rate=%ld, val=0x%08x\n", hw->clk, __func__,
+ fv->rate, fv->val);
+
+ flags = clk_pll_lock(clkp);
+ ret = __clk_pll_freq_set(clkp, fv->val);
+ clk_pll_unlock(clkp, flags);
+ if (ret)
+ pr_warn("%pC %s: failed to set freq: %d\n", hw->clk, __func__,
+ ret);
+ return ret;
+}
+
+static void __clk_pll_div_set(struct clk_pll_div *clkpd, uint32_t val)
+{
+ uint32_t m = (BIT(clkpd->div_width) - 1) << clkpd->div_shift;
+ uint32_t s = clkpd->div_shift;
+
+ clk_regmap_update(&clkpd->clkp.clkr, clkpd->div_ofs, m, val << s);
+}
+
+static uint32_t __clk_pll_div_get(struct clk_pll_div *clkpd)
+{
+ uint32_t m = (BIT(clkpd->div_width) - 1) << clkpd->div_shift;
+ uint32_t s = clkpd->div_shift;
+
+ return (clk_regmap_read(&clkpd->clkp.clkr, clkpd->div_ofs) & m) >> s;
+}
+
+static long clk_pll_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_pll_div *clkpd = to_clk_pll_div(hw);
+ const struct div_table *dv;
+
+ /* lookup div in dtbl */
+ dv = dtbl_find_by_rate(clkpd->div_tbl, rate);
+ if (!dv)
+ return 0;
+
+ rate *= dv->div;
+ rate = clk_pll_round_rate(hw, rate, parent_rate);
+ return rate / dv->div;
+}
+
+static unsigned long clk_pll_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_pll_div *clkpd = to_clk_pll_div(hw);
+ unsigned long rate;
+ const struct div_table *dv;
+ uint32_t val;
+
+ rate = clk_pll_recalc_rate(hw, parent_rate);
+
+ val = __clk_pll_div_get(clkpd);
+ dv = dtbl_find_by_val(clkpd->div_tbl, val);
+ if (!dv)
+ return 0;
+
+ rate /= dv->div;
+ pr_debug("%pC: %s: current rate=%lu, div=%d, reg_val=0x%x\n",
+ hw->clk, __func__, rate, dv->div, val);
+
+ return rate;
+}
+
+static int clk_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk *clk = hw->clk;
+ struct clk_pll_div *clkpd = to_clk_pll_div(hw);
+ unsigned long flags;
+ const struct div_table *ndv, *cdv;
+ unsigned long target;
+ uint32_t cur_d;
+ int ret;
+
+ /* find next in the dtbl */
+ ndv = dtbl_find_by_rate(clkpd->div_tbl, rate);
+ if (!ndv)
+ return -EINVAL;
+
+ target = rate * ndv->div;
+
+ /* find current in the dtbl */
+ cur_d = __clk_pll_div_get(clkpd);
+ cdv = dtbl_find_by_val(clkpd->div_tbl, cur_d);
+ if (!cdv)
+ return -EINVAL;
+
+ pr_debug("%pC: rate=%lu, cdv={%d,0x%x}, ndv={%d,0x%x}\n",
+ clk, rate, cdv->div, cdv->val, ndv->div, ndv->val);
+
+ flags = clk_pll_div_lock(clkpd);
+
+ /* workaround to prevent glitch */
+#ifdef CONFIG_COMMON_CLK_RTD129X
+ if ((&clkpd->clkp.flags & CLK_PLL_DIV_WORKAROUND) &&
+ ndv->val != cdv->val && (ndv->val == 1 || cdv->val == 1)) {
+
+ pr_debug("%pC: apply rate=%u\n", clk, 1000000000);
+ clk_pll_set_rate(hw, 1000000000, parent_rate);
+
+ pr_debug("%pC: apply dv={%d, 0x%x}\n", clk, ndv->div, ndv->val);
+ __clk_pll_div_set(clkpd, ndv->val);
+ cdv = ndv;
+ }
+#endif
+
+ if (ndv->div > cdv->div)
+ __clk_pll_div_set(clkpd, ndv->val);
+ ret = clk_pll_set_rate(hw, target, parent_rate);
+ if (ndv->div < cdv->div)
+ __clk_pll_div_set(clkpd, ndv->val);
+
+ clk_pll_div_unlock(clkpd, flags);
+
+ return ret;
+}
+
+const struct clk_ops clk_pll_ops = {
+ .debug_init = clk_pll_debug_init,
+ .round_rate = clk_pll_round_rate,
+ .recalc_rate = clk_pll_recalc_rate,
+ .set_rate = clk_pll_set_rate,
+ .enable = clk_pll_enable,
+ .disable = clk_pll_disable,
+ .disable_unused = clk_pll_disable_unused,
+ .is_enabled = clk_pll_is_enabled,
+};
+
+const struct clk_ops clk_pll_div_ops = {
+ .debug_init = clk_pll_debug_init,
+ .round_rate = clk_pll_div_round_rate,
+ .recalc_rate = clk_pll_div_recalc_rate,
+ .set_rate = clk_pll_div_set_rate,
+ .enable = clk_pll_enable,
+ .disable = clk_pll_disable,
+ .disable_unused = clk_pll_disable_unused,
+ .is_enabled = clk_pll_is_enabled,
+};
+
diff --git a/drivers/clk/realtek/clk-pll.h b/drivers/clk/realtek/clk-pll.h
new file mode 100644
index 000000000000..03b4d0391c31
--- /dev/null
+++ b/drivers/clk/realtek/clk-pll.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017-2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#ifndef __CLK_REALTEK_CLK_PLL_H
+#define __CLK_REALTEK_CLK_PLL_H
+
+#include "common.h"
+
+struct freq_table {
+ uint32_t val;
+ unsigned long rate;
+};
+
+#define FREQ_TABLE_END { .rate = 0 }
+#define IS_FREQ_TABLE_END(_f) ((_f)->rate == 0)
+
+struct div_table {
+ unsigned long rate;
+ uint32_t div;
+ uint32_t val;
+};
+
+#define DIV_TABLE_END { .rate = 0 }
+#define IS_DIV_TABLE_END(_d) ((_d)->rate == 0)
+
+struct clk_pll {
+ struct clk_regmap clkr;
+
+
+ int pll_ofs;
+ int ssc_ofs;
+
+ const struct freq_table *freq_tbl;
+ uint32_t freq_mask;
+ uint32_t freq_loc;
+#define CLK_PLL_CONF_FREQ_LOC_CTL1 1
+#define CLK_PLL_CONF_FREQ_LOC_CTL2 2
+#define CLK_PLL_CONF_FREQ_LOC_SSC1 3
+
+ uint32_t pow_loc;
+#define CLK_PLL_CONF_NO_POW 0
+#define CLK_PLL_CONF_POW_LOC_CTL2 1
+#define CLK_PLL_CONF_POW_LOC_CTL3 2
+
+ spinlock_t *lock;
+
+ uint32_t flags;
+};
+
+#define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)
+#define __clk_pll_hw(_ptr) __clk_regmap_hw(&(_ptr)->clkr)
+
+/* clk_pll flags */
+#define CLK_PLL_DIV_WORKAROUND BIT(2)
+
+
+static inline bool clk_pll_has_pow(struct clk_pll *pll)
+{
+ if (pll->pow_loc != CLK_PLL_CONF_NO_POW)
+ return true;
+ return false;
+}
+
+static inline unsigned long clk_pll_lock(struct clk_pll *pll)
+{
+ unsigned long flags = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+ return flags;
+}
+
+static inline void clk_pll_unlock(struct clk_pll *pll, unsigned long flags)
+{
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
+struct clk_pll_div {
+ struct clk_pll clkp;
+ int div_ofs;
+ int div_shift;
+ int div_width;
+ const struct div_table *div_tbl;
+ spinlock_t *lock;
+};
+
+#define to_clk_pll_div(_hw) \
+ container_of(to_clk_pll(_hw), struct clk_pll_div, clkp)
+#define __clk_pll_div_hw(_ptr) __clk_pll_hw(&(_ptr)->clkp)
+
+/* clk_pll_div helper functions */
+static inline unsigned long clk_pll_div_lock(struct clk_pll_div *plld)
+{
+ unsigned long flags = 0;
+
+ if (plld->lock)
+ spin_lock_irqsave(plld->lock, flags);
+ return flags;
+}
+
+static inline void clk_pll_div_unlock(struct clk_pll_div *plld,
+ unsigned long flags)
+{
+ if (plld->lock)
+ spin_unlock_irqrestore(plld->lock, flags);
+}
+
+extern const struct clk_ops clk_pll_ops;
+extern const struct clk_ops clk_pll_div_ops;
+
+#ifdef CONFIG_CLK_PLL_PSAUD
+
+struct clk_pll_psaud {
+ struct clk_regmap clkr;
+ int id;
+ int reg;
+ spinlock_t *lock;
+};
+
+#define to_clk_pll_psaud(_hw) \
+ container_of(to_clk_regmap(_hw), struct clk_pll_psaud, clkr)
+#define __clk_pll_psaud_hw(_ptr) __clk_regmap_hw(&(_ptr)->clkr)
+extern const struct clk_ops clk_pll_psaud_ops;
+
+#define CLK_PLL_PSAUD1A (0x1)
+#define CLK_PLL_PSAUD2A (0x2)
+
+#endif /* CONFIG_CLK_PLL_PSAUD */
+
+#ifdef CONFIG_CLK_PLL_DIF
+
+struct clk_pll_dif {
+ struct clk_regmap clkr;
+ int pll_ofs;
+ int ssc_ofs;
+ uint32_t status;
+ spinlock_t *lock;
+};
+#define to_clk_pll_dif(_hw) \
+ container_of(to_clk_regmap(_hw), struct clk_pll_dif, clkr)
+#define __clk_pll_dif_hw(_ptr) __clk_regmap_hw(&(_ptr)->clkr)
+
+extern const struct clk_ops clk_pll_dif_ops;
+#endif /* CONFIG_CLK_PLL_DIF */
+
+
+#endif /* __CLK_REALTEK_CLK_PLL_H */
diff --git a/drivers/clk/realtek/clk-regmap-gate.c b/drivers/clk/realtek/clk-regmap-gate.c
new file mode 100644
index 000000000000..5f4a6a98da94
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-gate.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include "clk-regmap-gate.h"
+
+static int clk_regmap_gate_enable(struct clk_hw *hw)
+{
+ struct clk_regmap_gate *clkg = to_clk_regmap_gate(hw);
+ unsigned long flags = 0;
+ unsigned int mask;
+ unsigned int val;
+
+ if (clkg->lock)
+ spin_lock_irqsave(clkg->lock, flags);
+
+ mask = BIT(clkg->bit_idx);
+ val = BIT(clkg->bit_idx);
+
+ if (clkg->write_en) {
+ mask |= BIT(clkg->bit_idx + 1);
+ val |= BIT(clkg->bit_idx + 1);
+ }
+
+ clk_regmap_update(&clkg->clkr, clkg->gate_ofs, mask, val);
+
+ if (clkg->lock)
+ spin_unlock_irqrestore(clkg->lock, flags);
+
+ return 0;
+}
+
+static void clk_regmap_gate_disable(struct clk_hw *hw)
+{
+ struct clk_regmap_gate *clkg = to_clk_regmap_gate(hw);
+ unsigned long flags = 0;
+ unsigned int mask;
+ unsigned int val;
+
+ if (clkg->lock)
+ spin_lock_irqsave(clkg->lock, flags);
+
+ mask = BIT(clkg->bit_idx);
+ val = 0;
+
+ if (clkg->write_en) {
+ mask |= BIT(clkg->bit_idx + 1);
+ val |= BIT(clkg->bit_idx + 1);
+ }
+
+ clk_regmap_update(&clkg->clkr, clkg->gate_ofs, mask, val);
+
+ if (clkg->lock)
+ spin_unlock_irqrestore(clkg->lock, flags);
+}
+
+static void clk_regmap_gate_disable_unused(struct clk_hw *hw)
+{
+ pr_info("%pC: %s\n", hw->clk, __func__);
+ clk_regmap_gate_disable(hw);
+}
+
+static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
+{
+ struct clk_regmap_gate *clkg = to_clk_regmap_gate(hw);
+ int ret;
+ unsigned long flags = 0;
+
+ if (clkg->lock)
+ spin_lock_irqsave(clkg->lock, flags);
+
+ ret = clk_regmap_read(&clkg->clkr, clkg->gate_ofs) & BIT(clkg->bit_idx);
+
+ if (clkg->lock)
+ spin_unlock_irqrestore(clkg->lock, flags);
+
+ return !!ret;
+}
+
+const struct clk_ops clk_regmap_gate_ops = {
+ .enable = clk_regmap_gate_enable,
+ .disable = clk_regmap_gate_disable,
+ .disable_unused = clk_regmap_gate_disable_unused,
+ .is_enabled = clk_regmap_gate_is_enabled,
+};
diff --git a/drivers/clk/realtek/clk-regmap-gate.h b/drivers/clk/realtek/clk-regmap-gate.h
new file mode 100644
index 000000000000..7643e0193177
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-gate.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#ifndef __CLK_REALTEK_CLK_MMIO_GATE_H
+#define __CLK_REALTEK_CLK_MMIO_GATE_H
+
+#include "common.h"
+
+struct clk_regmap_gate {
+ struct clk_regmap clkr;
+ int gate_ofs;
+ uint8_t bit_idx;
+ spinlock_t *lock;
+ int write_en:1;
+};
+
+#define to_clk_regmap_gate(_hw) \
+ container_of(to_clk_regmap(_hw), struct clk_regmap_gate, clkr)
+#define __clk_regmap_gate_hw(_p) __clk_regmap_hw(&(_p)->clkr)
+
+extern const struct clk_ops clk_regmap_gate_ops;
+
+#endif
diff --git a/drivers/clk/realtek/clk-regmap-mux.c b/drivers/clk/realtek/clk-regmap-mux.c
new file mode 100644
index 000000000000..bd7eb706e12a
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-mux.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk-regmap-mux.h"
+
+static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
+{
+ struct clk_regmap_mux *clkm = to_clk_regmap_mux(hw);
+ int num_parents = clk_hw_get_num_parents(hw);
+ u32 val;
+ unsigned long flags = 0;
+
+ if (clkm->lock)
+ spin_lock_irqsave(clkm->lock, flags);
+
+ val = clk_regmap_read(&clkm->clkr, clkm->mux_ofs) >> clkm->shift;
+ if (clkm->lock)
+ spin_unlock_irqrestore(clkm->lock, flags);
+
+ val &= clkm->mask;
+ if (val >= num_parents)
+ return -EINVAL;
+
+ return val;
+}
+
+static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_regmap_mux *clkm = to_clk_regmap_mux(hw);
+ unsigned long flags = 0;
+
+ if (clkm->lock)
+ spin_lock_irqsave(clkm->lock, flags);
+
+ clk_regmap_update(&clkm->clkr, clkm->mux_ofs, clkm->mask << clkm->shift,
+ index << clkm->shift);
+
+ if (clkm->lock)
+ spin_unlock_irqrestore(clkm->lock, flags);
+ return 0;
+}
+
+const struct clk_ops clk_regmap_mux_ops = {
+ .get_parent = clk_regmap_mux_get_parent,
+ .set_parent = clk_regmap_mux_set_parent,
+ .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
+
+const struct clk_ops clk_regmap_mux_ro_ops = {
+ .get_parent = clk_regmap_mux_get_parent,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
+
diff --git a/drivers/clk/realtek/clk-regmap-mux.h b/drivers/clk/realtek/clk-regmap-mux.h
new file mode 100644
index 000000000000..36895f03c0f4
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-mux.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#ifndef __CLK_REALTEK_CLK_MMIO_MUX_H
+#define __CLK_REALTEK_CLK_MMIO_MUX_H
+
+#include "common.h"
+
+struct clk_regmap_mux {
+ struct clk_regmap clkr;
+ int mux_ofs;
+ unsigned int mask;
+ unsigned int shift;
+ spinlock_t *lock;
+};
+
+#define to_clk_regmap_mux(_hw) \
+ container_of(to_clk_regmap(_hw), struct clk_regmap_mux, clkr)
+#define __clk_regmap_mux_hw(_p) __clk_regmap_hw(&(_p)->clkr)
+
+extern const struct clk_ops clk_regmap_mux_ops;
+
+#endif
diff --git a/drivers/clk/realtek/common.c b/drivers/clk/realtek/common.c
new file mode 100644
index 000000000000..0c5dc5ce4682
--- /dev/null
+++ b/drivers/clk/realtek/common.c
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include "common.h"
+#include "clk-pll.h"
+#include "clk-regmap-gate.h"
+#include "clk-regmap-mux.h"
+
+static int rtk_clk_suspend(struct device *dev)
+{
+ struct rtk_clk_data *data = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < data->pm_data_num; i++) {
+ struct clk_pm_data *pm_data = &data->pm_data[i];
+
+ regmap_read(data->regmap, pm_data->ofs, &pm_data->val);
+ }
+ return 0;
+}
+
+static int rtk_clk_resume(struct device *dev)
+{
+ struct rtk_clk_data *data = dev_get_drvdata(dev);
+ int i;
+
+ for (i = data->pm_data_num - 1; i >= 0; i--) {
+ struct clk_pm_data *pm_data = &data->pm_data[i];
+ uint32_t val = pm_data->val;
+ uint32_t mask = ~0x0;
+
+ if (pm_data->write_en_bits)
+ val |= pm_data->write_en_bits;
+ if (pm_data->ignore_bits)
+ mask &= ~pm_data->ignore_bits;
+ dev_info(dev, "resuming: ofs=%03x, vs=%08x vr=%08x m=%08x\n",
+ pm_data->ofs, pm_data->val, val, mask);
+ regmap_update_bits(data->regmap, pm_data->ofs, mask, val);
+ }
+ return 0;
+}
+
+const struct dev_pm_ops rtk_clk_pm_ops = {
+ .suspend = rtk_clk_suspend,
+ .resume = rtk_clk_resume,
+};
+
+struct rtk_clk_data *alloc_rtk_clk_data(int clk_num)
+{
+ struct rtk_clk_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ data->clk_num = clk_num;
+ data->clk_data.clk_num = clk_num;
+ data->clk_data.clks = kcalloc(clk_num, sizeof(*data->clk_data.clks),
+ GFP_KERNEL);
+ if (!data->clk_data.clks)
+ goto free_data;
+ return data;
+
+free_data:
+ kfree(data->clk_data.clks);
+ kfree(data);
+ return NULL;
+}
+
+void free_rtk_clk_data(struct rtk_clk_data *data)
+{
+ kfree(data->clk_data.clks);
+ kfree(data);
+}
+
+static inline
+int __cell_clk_add(struct clk_onecell_data *clk_data, int i, struct clk *clk)
+{
+ if (clk_data->clks[i]) {
+ pr_err("%s: failed to add %pC, cell%d is used by %pC\n",
+ __func__, clk, i, clk_data->clks[i]);
+ return -EINVAL;
+ }
+ clk_data->clks[i] = clk;
+ return 0;
+}
+
+#define CLK_TYPE_DEFAULT (0x0)
+#define CLK_TYPE_REGMAP (0x8)
+#define CLK_TYPE_REGMAP_PLL (0x1 | CLK_TYPE_REGMAP)
+#define CLK_TYPE_REGMAP_MUX (0x2 | CLK_TYPE_REGMAP)
+#define CLK_TYPE_REGMAP_GATE (0x3 | CLK_TYPE_REGMAP)
+
+static inline int __hw_to_type(struct clk_hw *hw)
+{
+ const struct clk_ops *ops = hw->init->ops;
+
+ if (ops == &clk_pll_ops || ops == &clk_pll_div_ops)
+ return CLK_TYPE_REGMAP_PLL;
+ if (ops == &clk_regmap_mux_ops)
+ return CLK_TYPE_REGMAP_MUX;
+ if (ops == &clk_regmap_gate_ops)
+ return CLK_TYPE_REGMAP_GATE;
+#ifdef CONFIG_CLK_PLL_DIF
+ /*
+ * clk_pll_dif is not based struct clk_pll, so
+ * return as CLK_TYPE_REGMAP to setup internal
+ * clk_reg
+ */
+ if (ops == &clk_pll_dif_ops)
+ return CLK_TYPE_REGMAP;
+#endif
+#ifdef CONFIG_CLK_PLL_PSAUD
+ /*
+ * clk_pll_psaud is not based struct clk_pll, so
+ * return as CLK_TYPE_REGMAP to setup internal
+ * clk_reg
+ */
+ if (ops == &clk_pll_psaud_ops)
+ return CLK_TYPE_REGMAP;
+#endif
+
+ return CLK_TYPE_DEFAULT;
+}
+
+static
+struct clk *rtk_clk_register_hw(struct device *dev, struct regmap *regmap,
+ struct clk_hw *hw)
+{
+ int type;
+
+ type = __hw_to_type(hw);
+ if (type & CLK_TYPE_REGMAP) {
+ struct clk_regmap *clkr = to_clk_regmap(hw);
+
+ clkr->regmap = regmap;
+ }
+
+ return clk_register(dev, hw);
+}
+
+int rtk_clk_add_hws(struct device *dev, struct rtk_clk_data *data,
+ struct clk_hw **hws, int num)
+{
+ struct clk_onecell_data *clk_data = &data->clk_data;
+ struct regmap *regmap = data->regmap;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ struct clk_hw *hw = hws[i];
+ const char *name;
+ struct clk *clk;
+
+ if (IS_ERR(hw))
+ __cell_clk_add(clk_data, i, ERR_CAST(hw));
+ if (IS_ERR_OR_NULL(hw))
+ continue;
+
+ name = hw->init->name;
+ clk = rtk_clk_register_hw(dev, regmap, hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to add hw%d(%s): %ld\n", __func__,
+ i, name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_register_clkdev(clk, name, NULL);
+ __cell_clk_add(clk_data, i, clk);
+ }
+ return 0;
+}
+
+static
+struct clk *rtk_clk_register_composite(struct device *dev,
+ struct regmap *regmap,
+ struct clk_composite_data *comp)
+{
+ struct clk_regmap_mux *clkm = NULL;
+ const struct clk_ops *mux_op = NULL;
+ struct clk_hw *mux_hw = NULL;
+ struct clk_regmap_gate *clkg = NULL;
+ const struct clk_ops *gate_op = NULL;
+ struct clk_hw *gate_hw = NULL;
+ struct clk *clk;
+
+ if (comp->mux_ofs != CLK_OFS_INVALID) {
+ clkm = kzalloc(sizeof(*clkm), GFP_KERNEL);
+ if (!clkm) {
+ clk = ERR_PTR(-ENOMEM);
+ goto check_err;
+ }
+
+ clkm->mux_ofs = comp->mux_ofs;
+ clkm->mask = BIT(comp->mux_width) - 1;
+ clkm->shift = comp->mux_shift;
+ clkm->clkr.regmap = regmap;
+
+ mux_op = &clk_regmap_mux_ops;
+ mux_hw = &__clk_regmap_mux_hw(clkm);
+ }
+
+ if (comp->gate_ofs != CLK_OFS_INVALID) {
+ clkg = kzalloc(sizeof(*clkg), GFP_KERNEL);
+ if (!clkg) {
+ clk = ERR_PTR(-ENOMEM);
+ goto check_err;
+ }
+
+ clkg->gate_ofs = comp->gate_ofs;
+ clkg->bit_idx = comp->gate_shift;
+ clkg->write_en = comp->gate_write_en;
+ clkg->clkr.regmap = regmap;
+
+ gate_op = &clk_regmap_gate_ops;
+ gate_hw = &__clk_regmap_gate_hw(clkg);
+ }
+
+ clk = clk_register_composite(NULL, comp->name, comp->parent_names,
+ comp->num_parents, mux_hw, mux_op,
+ NULL, NULL, gate_hw, gate_op, comp->flags);
+check_err:
+ if (IS_ERR(clk)) {
+ kfree(clkm);
+ kfree(clkg);
+ }
+ return clk;
+}
+
+int rtk_clk_add_composites(struct device *dev, struct rtk_clk_data *data,
+ struct clk_composite_data *comps, int num)
+{
+ struct clk_onecell_data *clk_data = &data->clk_data;
+ struct regmap *regmap = data->regmap;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ struct clk_composite_data *comp = &comps[i];
+ const char *name = comp->name;
+ struct clk *clk;
+
+ clk = rtk_clk_register_composite(dev, regmap, comp);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to add composite%d(%s): %ld\n",
+ __func__, i, name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_register_clkdev(clk, name, NULL);
+ __cell_clk_add(clk_data, comp->id, clk);
+ }
+
+ return 0;
+}
+
+static
+struct clk *rtk_clk_register_gate(struct device *dev, struct regmap *regmap,
+ struct clk_gate_data *gate)
+{
+ struct clk_regmap_gate *clkg;
+ struct clk_init_data init = { 0 };
+ struct clk_hw *hw;
+
+ clkg = kzalloc(sizeof(*clkg), GFP_KERNEL);
+ if (!clkg)
+ return ERR_PTR(-ENOMEM);
+
+ clkg->gate_ofs = gate->gate_ofs;
+ clkg->bit_idx = gate->gate_shift;
+ clkg->write_en = gate->gate_write_en;
+ clkg->clkr.regmap = regmap;
+
+ init.name = gate->name;
+ init.ops = &clk_regmap_gate_ops;
+ init.flags = gate->flags;
+ if (gate->parent) {
+ init.parent_names = &gate->parent;
+ init.num_parents = 1;
+ }
+
+ hw = &__clk_regmap_gate_hw(clkg);
+ hw->init = &init;
+ return clk_register(dev, hw);
+}
+
+int rtk_clk_add_gates(struct device *dev, struct rtk_clk_data *data,
+ struct clk_gate_data *gates, int num)
+{
+ struct clk_onecell_data *clk_data = &data->clk_data;
+ struct regmap *regmap = data->regmap;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ struct clk_gate_data *gate = &gates[i];
+ const char *name = gate->name;
+ struct clk *clk;
+
+ clk = rtk_clk_register_gate(dev, regmap, gate);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to add gate%d(%s): %ld\n", __func__,
+ i, name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_register_clkdev(clk, name, NULL);
+ __cell_clk_add(clk_data, gate->id, clk);
+ }
+
+ return 0;
+}
+
diff --git a/drivers/clk/realtek/common.h b/drivers/clk/realtek/common.h
new file mode 100644
index 000000000000..c736b254852f
--- /dev/null
+++ b/drivers/clk/realtek/common.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2016-2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#ifndef __CLK_REALTEK_COMMON_H
+#define __CLK_REALTEK_COMMON_H
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+struct device;
+struct platform_device;
+
+struct clk_regmap {
+ struct clk_hw hw;
+ struct regmap *regmap;
+};
+
+#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
+#define __clk_regmap_hw(_p) ((_p)->hw)
+
+static inline
+void clk_regmap_write(struct clk_regmap *clkr, uint32_t ofs, uint32_t val)
+{
+ pr_debug("%s: ofs=%03x, val=%08x\n", __func__, ofs, val);
+ regmap_write(clkr->regmap, ofs, val);
+}
+
+static inline
+uint32_t clk_regmap_read(struct clk_regmap *clkr, uint32_t ofs)
+{
+ uint32_t val = 0;
+
+ regmap_read(clkr->regmap, ofs, &val);
+ pr_debug("%s: ofs=%03x, val=%08x\n", __func__, ofs, val);
+ return val;
+}
+
+static inline void clk_regmap_update(struct clk_regmap *clkr, uint32_t ofs,
+ uint32_t mask, uint32_t val)
+{
+ pr_debug("%s: ofs=%03x, mask=%08x, val=%08x\n", __func__, ofs,
+ mask, val);
+ regmap_update_bits(clkr->regmap, ofs, mask, val);
+}
+
+/* ofs check */
+#define CLK_OFS_INVALID (-1)
+#define CLK_OFS_IS_VALID(_ofs) ((_ofs) != CLK_OFS_INVALID)
+
+struct clk_composite_data {
+ int id;
+ const char *name;
+ unsigned long flags;
+ struct clk *clk;
+
+ int gate_ofs;
+ int gate_shift;
+ int gate_write_en;
+
+ int mux_ofs;
+ int mux_width;
+ int mux_shift;
+ const char * const *parent_names;
+ int num_parents;
+};
+
+struct clk_gate_data {
+ int id;
+ const char *name;
+ const char *parent;
+ unsigned long flags;
+ struct clk *clk;
+
+ int gate_ofs;
+ int gate_shift;
+ int gate_write_en;
+};
+
+#define CLK_GATE_DATA(_id, _name, _parent, _flags, _ofs, _shift, _write_en) \
+{ \
+ .id = _id, \
+ .name = _name, \
+ .parent = _parent, \
+ .flags = _flags, \
+ .gate_ofs = _ofs, \
+ .gate_shift = _shift, \
+ .gate_write_en = _write_en, \
+}
+
+struct clk_pm_data {
+ int ofs;
+ uint32_t ignore_bits;
+ uint32_t write_en_bits;
+ uint32_t val;
+};
+
+struct rtk_clk_data {
+ int clk_num;
+ struct regmap *regmap;
+ struct clk_onecell_data clk_data;
+ struct clk_pm_data *pm_data;
+ int pm_data_num;
+};
+
+struct rtk_clk_data *alloc_rtk_clk_data(int clk_num);
+void free_rtk_clk_data(struct rtk_clk_data *data);
+int rtk_clk_add_hws(struct device *dev, struct rtk_clk_data *data,
+ struct clk_hw **hws, int num);
+int rtk_clk_add_composites(struct device *dev, struct rtk_clk_data *data,
+ struct clk_composite_data *comps, int num);
+int rtk_clk_add_gates(struct device *dev, struct rtk_clk_data *data,
+ struct clk_gate_data *gates, int num);
+extern const struct dev_pm_ops rtk_clk_pm_ops;
+
+#endif /* __CLK_REALTEK_COMMON_H */
+
--
2.24.0
From: cylee12 <[email protected]>
This patch adds CRT controller and ISO controller for RTD1619 SoC.
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
drivers/clk/realtek/Kconfig | 10 +
drivers/clk/realtek/Makefile | 2 +
drivers/clk/realtek/clk-rtd1619-cc.c | 553 +++++++++++++++++++++++++++
drivers/clk/realtek/clk-rtd1619-ic.c | 112 ++++++
4 files changed, 677 insertions(+)
create mode 100644 drivers/clk/realtek/clk-rtd1619-cc.c
create mode 100644 drivers/clk/realtek/clk-rtd1619-ic.c
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
index 8e7e7edf64dd..43c55be25eba 100644
--- a/drivers/clk/realtek/Kconfig
+++ b/drivers/clk/realtek/Kconfig
@@ -9,3 +9,13 @@ config CLK_PLL_PSAUD
config CLK_PLL_DIF
bool
+
+config COMMON_CLK_RTD1619
+ bool "RTD1619 Clock Controller"
+ depends on ARCH_REALTEK || COMPILE_TEST
+ select COMMON_CLK_REALTEK
+ select CLK_PLL_PSAUD
+ select CLK_PLL_DIF
+ default ARCH_REALTEK
+ ---help---
+ Support for the clock controller on RTD1619
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 43f8bd71c0c8..24af3dbe2006 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -8,3 +8,5 @@ clk-rtk-y += clk-pll.o
clk-rtk-$(CONFIG_CLK_PLL_PSAUD) += clk-pll-psaud.o
clk-rtk-$(CONFIG_CLK_PLL_DIF) += clk-pll-dif.o
clk-rtk-y += reset.o
+clk-rtk-$(CONFIG_COMMON_CLK_RTD1619) += clk-rtd1619-cc.o
+clk-rtk-$(CONFIG_COMMON_CLK_RTD1619) += clk-rtd1619-ic.o
diff --git a/drivers/clk/realtek/clk-rtd1619-cc.c b/drivers/clk/realtek/clk-rtd1619-cc.c
new file mode 100644
index 000000000000..c799ffd4cc7a
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtd1619-cc.c
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2018-2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include "common.h"
+#include "clk-pll.h"
+#include "clk-regmap-gate.h"
+#include "clk-regmap-mux.h"
+#include "reset.h"
+#include <dt-bindings/clock/rtk,clock-rtd1619.h>
+#include <dt-bindings/reset/rtk,reset-rtd1619.h>
+
+#define DIV_DV(_r, _d, _v) { .rate = _r, .div = _d, .val = _v, }
+#define FREQ_NF_MASK (0x7FFFF)
+#define FREQ_NF(_r, _n, _f) { .rate = _r, .val = ((_n) << 11) | (_f), }
+#define FREQ_MNO_MASK (0x63FF0)
+#define FREQ_MNO(_r, _m, _n, _o) \
+ { .rate = _r, .val = ((_m) << 4) | ((_n) << 12) | ((_o) << 17), }
+
+static const char * const default_parent[] = { "osc27m" };
+
+static const struct div_table scpu_div_tbl[] = {
+ DIV_DV(1000000000, 1, 0),
+ DIV_DV(500000000, 2, 0x88),
+ DIV_DV(350000000, 3, 0x8C),
+ DIV_DV(250000000, 4, 0x90),
+ DIV_DV(200000000, 8, 0xA0),
+ DIV_DV(100000000, 10, 0xA8),
+ DIV_TABLE_END
+};
+
+static const struct freq_table scpu_tbl[] = {
+ FREQ_NF(1000000000, 34, 75),
+ FREQ_NF(1100000000, 37, 1517),
+ FREQ_NF(1200000000, 41, 910),
+ FREQ_NF(1300000000, 45, 303),
+ FREQ_NF(1400000000, 48, 1745),
+ FREQ_NF(1500000000, 52, 1137),
+ FREQ_NF(1600000000, 56, 530),
+ FREQ_NF(1700000000, 59, 1972),
+ FREQ_NF(1800000000, 63, 1365),
+ FREQ_NF(1900000000, 67, 758),
+ FREQ_NF(2000000000, 71, 151),
+ /* init-value mapping */
+ FREQ_NF(1000000000, 35, 0),
+ FREQ_NF(1200000000, 41, 0),
+ FREQ_NF(1800000000, 65, 0),
+ FREQ_NF(1800000000, 64, 0),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll_div pll_scpu = {
+ .div_ofs = 0x030,
+ .div_shift = 6,
+ .div_width = 8,
+ .div_tbl = scpu_div_tbl,
+ .clkp = {
+ .ssc_ofs = 0x500,
+ .pll_ofs = CLK_OFS_INVALID,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_SSC1,
+ .freq_tbl = scpu_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_scpu",
+ .ops = &clk_pll_div_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED |
+ CLK_GET_RATE_NOCACHE,
+ },
+ },
+};
+
+static const struct div_table bus_div_tbl[] = {
+ DIV_DV(257000000, 1, 0),
+ DIV_DV(129000000, 2, 2),
+ DIV_DV(65000000, 4, 3),
+ DIV_TABLE_END
+};
+
+static const struct freq_table bus_tbl[] = {
+ FREQ_NF(513000000, 35, 0),
+ FREQ_NF(400000000, 26, 1289),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll_div pll_bus = {
+ .div_ofs = 0x030,
+ .div_shift = 0,
+ .div_width = 2,
+ .div_tbl = bus_div_tbl,
+ .clkp = {
+ .ssc_ofs = 0x520,
+ .pll_ofs = CLK_OFS_INVALID,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_SSC1,
+ .freq_tbl = bus_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_bus",
+ .ops = &clk_pll_div_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED |
+ CLK_GET_RATE_NOCACHE,
+ },
+ },
+};
+
+static struct clk_fixed_factor clk_sys = {
+ .div = 1,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data) {
+ .name = "clk_sys",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "pll_bus" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct div_table dcsb_div_tbl[] = {
+ DIV_DV(550000000, 1, 0),
+ DIV_DV(275000000, 2, 2),
+ DIV_DV(1, 4, 3),
+ DIV_TABLE_END
+};
+
+static const struct freq_table dcsb_tbl[] = {
+ FREQ_NF(550000000, 38, 0),
+ FREQ_NF(550000000, 37, 1517),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll_div pll_dcsb = {
+ .div_ofs = 0x030,
+ .div_shift = 2,
+ .div_width = 2,
+ .div_tbl = dcsb_div_tbl,
+ .clkp = {
+ .ssc_ofs = 0x540,
+ .pll_ofs = CLK_OFS_INVALID,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_SSC1,
+ .freq_tbl = dcsb_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_dcsb",
+ .ops = &clk_pll_div_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED |
+ CLK_GET_RATE_NOCACHE,
+ },
+ },
+};
+
+static struct clk_fixed_factor clk_sysh = {
+ .div = 1,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data) {
+ .name = "clk_sysh",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "pll_dcsb" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct freq_table ddsx_tbl[] = {
+ FREQ_NF(432000000, 13, 0),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll pll_ddsa = {
+ .ssc_ofs = 0x560,
+ .pll_ofs = 0x120,
+ .pow_loc = CLK_PLL_CONF_POW_LOC_CTL3,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_SSC1,
+ .freq_tbl = ddsx_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_ddsa",
+ .ops = &clk_pll_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct freq_table gpu_tbl[] = {
+ FREQ_NF(300000000, 19, 455),
+ FREQ_NF(400000000, 26, 1289),
+ FREQ_NF(500000000, 34, 75),
+ FREQ_NF(600000000, 41, 910),
+ FREQ_NF(650000000, 45, 303),
+ FREQ_NF(700000000, 48, 1745),
+ FREQ_NF(750000000, 52, 1137),
+ FREQ_NF(800000000, 56, 530),
+ FREQ_NF(850000000, 59, 1971),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll pll_gpu = {
+ .ssc_ofs = 0x5A0,
+ .pll_ofs = 0x1C0,
+ .pow_loc = CLK_PLL_CONF_POW_LOC_CTL2,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_SSC1,
+ .freq_tbl = gpu_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_gpu",
+ .ops = &clk_pll_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct freq_table ve_tbl[] = {
+ FREQ_MNO(189000000, 12, 0, 1),
+ FREQ_MNO(270000000, 18, 0, 1),
+ FREQ_MNO(405000000, 13, 0, 0),
+ FREQ_MNO(432000000, 14, 0, 0),
+ FREQ_MNO(459000000, 15, 0, 0),
+ FREQ_MNO(486000000, 16, 0, 0),
+ FREQ_MNO(513000000, 17, 0, 0),
+ FREQ_MNO(540000000, 18, 0, 0),
+ FREQ_MNO(550000000, 59, 2, 0),
+ FREQ_MNO(567000000, 19, 0, 0),
+ FREQ_MNO(594000000, 20, 0, 0),
+ FREQ_MNO(648000000, 22, 0, 0),
+ FREQ_MNO(675000000, 23, 0, 0),
+ FREQ_MNO(702000000, 24, 0, 0),
+ FREQ_MNO(715000000, 51, 1, 0),
+ FREQ_TABLE_END
+};
+
+static struct clk_pll pll_ve1 = {
+ .ssc_ofs = CLK_OFS_INVALID,
+ .pll_ofs = 0x114,
+ .pow_loc = CLK_PLL_CONF_POW_LOC_CTL2,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_CTL1,
+ .freq_tbl = ve_tbl,
+ .freq_mask = FREQ_MNO_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_ve1",
+ .ops = &clk_pll_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_pll pll_ve2 = {
+ .ssc_ofs = CLK_OFS_INVALID,
+ .pll_ofs = 0x1D0,
+ .pow_loc = CLK_PLL_CONF_POW_LOC_CTL2,
+ .freq_loc = CLK_PLL_CONF_FREQ_LOC_CTL1,
+ .freq_tbl = ve_tbl,
+ .freq_mask = FREQ_MNO_MASK,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_ve2",
+ .ops = &clk_pll_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_pll_dif pll_dif = {
+ .ssc_ofs = 0x634,
+ .pll_ofs = 0x624,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_dif",
+ .ops = &clk_pll_dif_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_pll_psaud pll_psaud1a = {
+ .reg = 0x130,
+ .id = CLK_PLL_PSAUD1A,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_psaud1a",
+ .ops = &clk_pll_psaud_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED | CLK_SET_RATE_UNGATE,
+ },
+};
+
+static struct clk_pll_psaud pll_psaud2a = {
+ .reg = 0x130,
+ .id = CLK_PLL_PSAUD2A,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pll_psaud2a",
+ .ops = &clk_pll_psaud_ops,
+ .parent_names = default_parent,
+ .num_parents = 1,
+ .flags = CLK_IGNORE_UNUSED | CLK_SET_RATE_UNGATE,
+ },
+};
+
+static struct clk_hw *cc_hws[] = {
+ [CC_PLL_SCPU] = &__clk_pll_div_hw(&pll_scpu),
+ [CC_PLL_BUS] = &__clk_pll_div_hw(&pll_bus),
+ [CC_PLL_DCSB] = &__clk_pll_div_hw(&pll_dcsb),
+ [CC_PLL_DDSA] = &__clk_pll_hw(&pll_ddsa),
+ [CC_PLL_GPU] = &__clk_pll_hw(&pll_gpu),
+ [CC_PLL_VE1] = &__clk_pll_hw(&pll_ve1),
+ [CC_PLL_VE2] = &__clk_pll_hw(&pll_ve2),
+ [CC_PLL_DIF] = &__clk_pll_dif_hw(&pll_dif),
+ [CC_CLK_SYS] = &clk_sys.hw,
+ [CC_CLK_SYSH] = &clk_sysh.hw,
+ [CC_PLL_PSAUD1A] = &__clk_pll_psaud_hw(&pll_psaud1a),
+ [CC_PLL_PSAUD2A] = &__clk_pll_psaud_hw(&pll_psaud2a),
+};
+
+static const char * const ve_parents[] = {
+ "clk_sys",
+ "clk_sysh",
+ "pll_ve1",
+ "pll_ve2",
+};
+
+static struct clk_composite_data cc_composites[] = {
+ {
+ .id = CC_CLK_GPU,
+ .mux_ofs = CLK_OFS_INVALID,
+ .gate_ofs = 0x050,
+ .gate_shift = 18,
+ .gate_write_en = 1,
+ .parent_names = (const char *[]){ "pll_gpu" },
+ .num_parents = 1,
+ .name = "clk_gpu",
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ {
+ .id = CC_CLK_VE1,
+ .gate_ofs = 0x050,
+ .gate_shift = 20,
+ .gate_write_en = 1,
+ .mux_ofs = 0x04C,
+ .mux_width = 3,
+ .mux_shift = 0,
+ .parent_names = ve_parents,
+ .num_parents = ARRAY_SIZE(ve_parents),
+ .name = "clk_ve1",
+ .flags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT,
+ },
+ {
+ .id = CC_CLK_VE2,
+ .gate_ofs = 0x050,
+ .gate_shift = 22,
+ .gate_write_en = 1,
+ .mux_ofs = 0x04C,
+ .mux_width = 3,
+ .mux_shift = 3,
+ .parent_names = ve_parents,
+ .num_parents = ARRAY_SIZE(ve_parents),
+ .name = "clk_ve2",
+ .flags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT,
+ },
+ {
+ .id = CC_CLK_VE3,
+ .gate_ofs = 0x05C,
+ .gate_shift = 26,
+ .gate_write_en = 1,
+ .mux_ofs = 0x04C,
+ .mux_width = 3,
+ .mux_shift = 6,
+ .parent_names = ve_parents,
+ .num_parents = ARRAY_SIZE(ve_parents),
+ .name = "clk_ve3",
+ .flags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT,
+ },
+ {
+ .id = CC_CLK_VE2_BPU,
+ .gate_ofs = CLK_OFS_INVALID,
+ .mux_ofs = 0x04C,
+ .mux_width = 3,
+ .mux_shift = 9,
+ .parent_names = ve_parents,
+ .num_parents = ARRAY_SIZE(ve_parents),
+ .name = "clk_ve2_bpu",
+ .flags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+#define GATE(_id, _name, _parent, _ofs, _shift) \
+ CLK_GATE_DATA(_id, _name, _parent, 0, _ofs, _shift, 1)
+#define GATE_IGNORE(_id, _name, _parent, _ofs, _shift) \
+ CLK_GATE_DATA(_id, _name, _parent, CLK_IGNORE_UNUSED, _ofs, _shift, 1)
+
+static struct clk_gate_data cc_gates[] = {
+ GATE_IGNORE(CC_CKE_MISC, "misc", NULL, 0x50, 0),
+ GATE(CC_CKE_PCIE0, "pcie0", NULL, 0x50, 2),
+ GATE(CC_CKE_GSPI, "gspi", "misc", 0x50, 6),
+ GATE(CC_CKE_SDS, "sds", NULL, 0x50, 12),
+ GATE_IGNORE(CC_CKE_HDMI, "hdmi", NULL, 0x50, 14),
+ GATE_IGNORE(CC_CKE_TVE, "tve", NULL, 0x50, 24),
+ GATE_IGNORE(CC_CKE_VO, "vo", NULL, 0x50, 26),
+ GATE_IGNORE(CC_CKE_LSADC, "lsadc", NULL, 0x50, 28),
+ GATE(CC_CKE_SE, "se", NULL, 0x50, 30),
+ GATE_IGNORE(CC_CKE_CP, "cp", NULL, 0x54, 2),
+ GATE_IGNORE(CC_CKE_MD, "md", NULL, 0x54, 4),
+ GATE_IGNORE(CC_CKE_TP, "tp", NULL, 0x54, 6),
+ GATE(CC_CKE_RSA, "rsa", NULL, 0x54, 8),
+ GATE(CC_CKE_NF, "nf", NULL, 0x54, 10),
+ GATE(CC_CKE_EMMC, "emmc", NULL, 0x54, 12),
+ GATE(CC_CKE_SD, "sd", NULL, 0x54, 14),
+ GATE(CC_CKE_SDIO_IP, "sdio_ip", NULL, 0x54, 16),
+ GATE(CC_CKE_MIPI, "mipi", NULL, 0x54, 18),
+ GATE(CC_CKE_EMMC_IP, "emmc_ip", NULL, 0x54, 20),
+ GATE(CC_CKE_SDIO, "sdio", NULL, 0x54, 22),
+ GATE(CC_CKE_SD_IP, "sd_ip", NULL, 0x54, 24),
+ GATE(CC_CKE_CABLERX, "cablerx", NULL, 0x54, 26),
+ GATE(CC_CKE_TPB, "tpb", NULL, 0x54, 28),
+ GATE(CC_CKE_SC1, "sc1", "misc", 0x54, 30),
+ GATE(CC_CKE_I2C3, "i2c3", "misc", 0x58, 0),
+ GATE(CC_CKE_JPEG, "jpeg", NULL, 0x58, 4),
+ GATE(CC_CKE_SC0, "sc0", "misc", 0x58, 10),
+ GATE(CC_CKE_HDMIRX, "hdmirx", NULL, 0x58, 26),
+ GATE(CC_CKE_HSE, "hse", NULL, 0x58, 28),
+ GATE(CC_CKE_UR2, "ur2", "misc", 0x58, 30),
+ GATE(CC_CKE_UR1, "ur1", "misc", 0x5C, 0),
+ GATE(CC_CKE_FAN, "fan", "misc", 0x5C, 2),
+ GATE(CC_CKE_SATA_WRAP_SYS, "sata_wrap_sys", NULL, 0x5C, 8),
+ GATE(CC_CKE_SATA_WRAP_SYSH, "sata_wrap_sysh", NULL, 0x5C, 10),
+ GATE(CC_CKE_SATA_MAC_SYSH, "sata_mac_sysh", NULL, 0x5C, 12),
+ GATE(CC_CKE_R2RDSC, "r2rdsc", NULL, 0x5C, 14),
+ GATE(CC_CKE_PCIE1, "pcie1", NULL, 0x5C, 18),
+ GATE(CC_CKE_I2C4, "i2c4", "misc", 0x5C, 20),
+ GATE(CC_CKE_I2C5, "i2c5", "misc", 0x5C, 22),
+ GATE(CC_CKE_EDP, "edp", NULL, 0x5C, 28),
+ GATE_IGNORE(CC_CKE_TSIO_TRX, "tsio_trx", NULL, 0x5C, 30),
+};
+
+static struct rtk_reset_bank cc_reset_banks[] = {
+ { .ofs = 0x00, .write_en = 1, },
+ { .ofs = 0x04, .write_en = 1, },
+ { .ofs = 0x08, .write_en = 1, },
+ { .ofs = 0x0c, .write_en = 1, },
+ { .ofs = 0x14, .write_en = 1, },
+ { .ofs = 0x68, .write_en = 1, },
+};
+
+static struct rtk_reset_initdata cc_reset_initdata = {
+ .banks = cc_reset_banks,
+ .num_banks = ARRAY_SIZE(cc_reset_banks),
+};
+
+static struct clk_pm_data cc_pm_data[] = {
+ /* SOFT_RESET */
+ { .ofs = 0x00, .write_en_bits = 0xAAAAAAAA, },
+ { .ofs = 0x04, .write_en_bits = 0xAAAAAAAA, },
+ { .ofs = 0x08, .write_en_bits = 0x0A80AAAA, },
+ { .ofs = 0x0C, .write_en_bits = 0x2AAAAAAA, },
+ { .ofs = 0x14, .write_en_bits = 0xAA82AA82, },
+ { .ofs = 0x68, .write_en_bits = 0xAAAAAAAA, },
+ /* CLK_EN */
+ { .ofs = 0x50, .write_en_bits = 0xA0A8288A, },
+ { .ofs = 0x54, .write_en_bits = 0xAAAAAAA8, },
+ { .ofs = 0x58, .write_en_bits = 0xA800082A, },
+ { .ofs = 0x5C, .write_en_bits = 0xAAAAAA0A, },
+ /* PLL_GPU */
+ { .ofs = 0x1C4, },
+ { .ofs = 0x5A4, .ignore_bits = ~(0x7FFFF), },
+ /* PLL_VE1 */
+ { .ofs = 0x118, },
+ { .ofs = 0x114, .ignore_bits = ~(0x63FF0), },
+ /* PLL_VE2 */
+ { .ofs = 0x1D4, },
+ { .ofs = 0x1D0, .ignore_bits = ~(0x63FF0), },
+};
+
+static int rtd1619_cc_probe(struct platform_device *pdev)
+{
+ struct device *parent;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct rtk_clk_data *data;
+ struct regmap *regmap;
+ int ret;
+
+ parent = dev->parent;
+ if (!parent) {
+ dev_err(dev, "no parent crt controller\n");
+ return -ENODEV;
+ }
+
+ regmap = syscon_node_to_regmap(parent->of_node);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(dev, "failed to get regmap form %s: %d\n", np->name,
+ ret);
+ return ret;
+ }
+
+ data = alloc_rtk_clk_data(CC_CLK_MAX);
+ if (!data)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, data);
+ data->regmap = regmap;
+ data->pm_data = cc_pm_data;
+ data->pm_data_num = ARRAY_SIZE(cc_pm_data);
+
+ rtk_clk_add_hws(dev, data, cc_hws, ARRAY_SIZE(cc_hws));
+ rtk_clk_add_composites(dev, data, cc_composites,
+ ARRAY_SIZE(cc_composites));
+ rtk_clk_add_gates(dev, data, cc_gates, ARRAY_SIZE(cc_gates));
+
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, &data->clk_data);
+ if (ret)
+ dev_err(dev, "failed to add clk provider: %d\n", ret);
+
+ rtk_reset_controller_add(dev, regmap, &cc_reset_initdata);
+
+ return 0;
+}
+
+static const struct of_device_id rtd1619_cc_match[] = {
+ { .compatible = "realtek,rtd1619-cc", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rtd1619_cc_driver = {
+ .probe = rtd1619_cc_probe,
+ .driver = {
+ .name = "rtk-rtd1619-cc",
+ .of_match_table = rtd1619_cc_match,
+ .pm = &rtk_clk_pm_ops,
+ },
+};
+
+static int __init rtd1619_cc_init(void)
+{
+ return platform_driver_register(&rtd1619_cc_driver);
+}
+core_initcall(rtd1619_cc_init);
diff --git a/drivers/clk/realtek/clk-rtd1619-ic.c b/drivers/clk/realtek/clk-rtd1619-ic.c
new file mode 100644
index 000000000000..9651c9aca26d
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtd1619-ic.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include "common.h"
+#include "reset.h"
+#include <dt-bindings/clock/rtk,clock-rtd1619.h>
+
+#define GATE(_id, _name, _parent, _ofs, _shift) \
+ CLK_GATE_DATA(_id, _name, _parent, 0, _ofs, _shift, 0)
+
+static struct clk_gate_data ic_gates[] = {
+ GATE(IC_CKE_CEC0, "cec0", NULL, 0x8c, 2),
+ GATE(IC_CKE_CBUSRX_SYS, "cbusrx_sys", NULL, 0x8c, 3),
+ GATE(IC_CKE_CBUSTX_SYS, "cbustx_sys", NULL, 0x8c, 4),
+ GATE(IC_CKE_CBUS_SYS, "cbus_sys", NULL, 0x8c, 5),
+ GATE(IC_CKE_CBUS_OSC, "cbus_osc", NULL, 0x8c, 6),
+ GATE(IC_CKE_IR, "ir", NULL, 0x8c, 7),
+ GATE(IC_CKE_UR0, "ur0", NULL, 0x8c, 8),
+ GATE(IC_CKE_I2C0, "i2c0", NULL, 0x8c, 9),
+ GATE(IC_CKE_I2C1, "i2c1", NULL, 0x8c, 10),
+ GATE(IC_CKE_ETN_250M, "etn_250m", NULL, 0x8c, 11),
+ GATE(IC_CKE_ETN_SYS, "etn_sys", NULL, 0x8c, 12),
+ GATE(IC_CKE_USB_DRD, "usb_drd", NULL, 0x8c, 13),
+ GATE(IC_CKE_USB_HOST, "usb_host", NULL, 0x8c, 14),
+ GATE(IC_CKE_USB_U3_HOST, "usb_u3_host", NULL, 0x8c, 15),
+ GATE(IC_CKE_USB, "usb", NULL, 0x8c, 16),
+};
+
+static struct rtk_reset_bank ic_reset_banks[] = {
+ { .ofs = 0x88, },
+};
+
+static struct rtk_reset_initdata ic_reset_initdata = {
+ .banks = ic_reset_banks,
+ .num_banks = ARRAY_SIZE(ic_reset_banks),
+};
+
+static struct clk_pm_data ic_pm_data[] = {
+ { .ofs = 0x88, },
+ { .ofs = 0x8C, },
+};
+
+static int rtd1619_ic_probe(struct platform_device *pdev)
+{
+ struct device *parent;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct rtk_clk_data *data;
+ struct regmap *regmap;
+ int ret;
+
+ parent = dev->parent;
+ if (!parent) {
+ dev_err(dev, "no parent crt controller\n");
+ return -ENODEV;
+ }
+
+ regmap = syscon_node_to_regmap(parent->of_node);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(dev, "failed to get regmap form %s: %d\n", np->name,
+ ret);
+ return ret;
+ }
+
+ data = alloc_rtk_clk_data(IC_CLK_MAX);
+ if (!data)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, data);
+ data->regmap = regmap;
+ data->pm_data = ic_pm_data;
+ data->pm_data_num = ARRAY_SIZE(ic_pm_data);
+
+ rtk_clk_add_gates(dev, data, ic_gates, ARRAY_SIZE(ic_gates));
+
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, &data->clk_data);
+ if (ret)
+ dev_err(dev, "failed to add clk provider: %d\n", ret);
+
+ rtk_reset_controller_add(dev, regmap, &ic_reset_initdata);
+
+ return 0;
+}
+
+static const struct of_device_id rtd1619_ic_match[] = {
+ { .compatible = "realtek,rtd1619-ic", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rtd1619_ic_driver = {
+ .probe = rtd1619_ic_probe,
+ .driver = {
+ .name = "rtk-rtd1619-ic",
+ .of_match_table = rtd1619_ic_match,
+ .pm = &rtk_clk_pm_ops,
+ },
+};
+
+static int __init rtd1619_ic_init(void)
+{
+ return platform_driver_register(&rtd1619_ic_driver);
+}
+core_initcall(rtd1619_ic_init);
--
2.24.0
From: cylee12 <[email protected]>
This patch add reset control support for Realtek SoCs.
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
drivers/clk/realtek/Kconfig | 1 +
drivers/clk/realtek/Makefile | 1 +
drivers/clk/realtek/reset.c | 107 +++++++++++++++++++++++++++++++++++
drivers/clk/realtek/reset.h | 37 ++++++++++++
4 files changed, 146 insertions(+)
create mode 100644 drivers/clk/realtek/reset.c
create mode 100644 drivers/clk/realtek/reset.h
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
index 5bca757dddfa..8e7e7edf64dd 100644
--- a/drivers/clk/realtek/Kconfig
+++ b/drivers/clk/realtek/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config COMMON_CLK_REALTEK
bool "Clock driver for realtek"
+ select RESET_CONTROLLER
select MFD_SYSCON
config CLK_PLL_PSAUD
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 050d450db067..43f8bd71c0c8 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -7,3 +7,4 @@ clk-rtk-y += clk-regmap-gate.o
clk-rtk-y += clk-pll.o
clk-rtk-$(CONFIG_CLK_PLL_PSAUD) += clk-pll-psaud.o
clk-rtk-$(CONFIG_CLK_PLL_DIF) += clk-pll-dif.o
+clk-rtk-y += reset.o
diff --git a/drivers/clk/realtek/reset.c b/drivers/clk/realtek/reset.c
new file mode 100644
index 000000000000..3f4d1a723b2a
--- /dev/null
+++ b/drivers/clk/realtek/reset.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Realtek Semiconductor Corporation
+ */
+
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include "reset.h"
+
+static int rtk_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
+ struct rtk_reset_bank *bank = &data->banks[idx >> 8];
+ uint32_t id = idx & 0xff;
+ uint32_t mask = bank->write_en ? (0x3 << id) : BIT(id);
+ uint32_t val = bank->write_en ? (0x2 << id) : 0;
+
+ return regmap_update_bits(data->regmap, bank->ofs, mask, val);
+}
+
+static int rtk_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
+ struct rtk_reset_bank *bank = &data->banks[idx >> 8];
+ uint32_t id = idx & 0xff;
+ uint32_t mask = bank->write_en ? (0x3 << id) : BIT(id);
+ uint32_t val = mask;
+
+ return regmap_update_bits(data->regmap, bank->ofs, mask, val);
+}
+
+static int rtk_reset_reset(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ int ret;
+
+ ret = rtk_reset_assert(rcdev, idx);
+ if (ret)
+ return ret;
+
+ return rtk_reset_deassert(rcdev, idx);
+}
+
+static int rtk_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
+ struct rtk_reset_bank *bank = &data->banks[idx >> 8];
+ uint32_t id = idx & 0xff;
+ uint32_t val;
+
+ regmap_read(data->regmap, bank->ofs, &val);
+ return !((val >> id) & 1);
+}
+
+static struct reset_control_ops rtk_reset_ops = {
+ .assert = rtk_reset_assert,
+ .deassert = rtk_reset_deassert,
+ .reset = rtk_reset_reset,
+ .status = rtk_reset_status,
+};
+
+static int rtk_of_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
+ int val;
+
+ val = reset_spec->args[0];
+ if (val >= rcdev->nr_resets)
+ return -EINVAL;
+
+ if (data->id_xlate)
+ return data->id_xlate(val);
+ return val;
+}
+
+
+int rtk_reset_controller_add(struct device *dev, struct regmap *regmap,
+ struct rtk_reset_initdata *initdata)
+{
+ struct rtk_reset_data *data;
+ struct device_node *np = dev->of_node;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ data->regmap = regmap;
+ data->num_banks = initdata->num_banks;
+ data->banks = initdata->banks;
+ data->id_xlate = initdata->id_xlate;
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.ops = &rtk_reset_ops;
+ data->rcdev.of_node = np;
+ data->rcdev.nr_resets = initdata->num_banks * 0x100;
+ data->rcdev.of_xlate = rtk_of_reset_xlate;
+ data->rcdev.of_reset_n_cells = 1;
+
+ return reset_controller_register(&data->rcdev);
+}
+
diff --git a/drivers/clk/realtek/reset.h b/drivers/clk/realtek/reset.h
new file mode 100644
index 000000000000..f0cc7b1045ee
--- /dev/null
+++ b/drivers/clk/realtek/reset.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2019 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <[email protected]>
+ */
+
+#ifndef __CLK_REALTEK_RESET_H
+#define __CLK_REALTEK_RESET_H
+
+#include <linux/reset-controller.h>
+
+struct rtk_reset_bank {
+ uint32_t ofs;
+ uint32_t write_en;
+};
+
+struct rtk_reset_data {
+ struct reset_controller_dev rcdev;
+ struct rtk_reset_bank *banks;
+ uint32_t num_banks;
+ struct regmap *regmap;
+ unsigned long (*id_xlate)(unsigned long id);
+};
+
+#define to_rtk_reset_controller(r) \
+ container_of(r, struct rtk_reset_data, rcdev)
+
+struct rtk_reset_initdata {
+ struct rtk_reset_bank *banks;
+ uint32_t num_banks;
+ unsigned long (*id_xlate)(unsigned long id);
+};
+
+int rtk_reset_controller_add(struct device *dev, struct regmap *regmap,
+ struct rtk_reset_initdata *initdata);
+
+#endif /* __CLK_REALTEK_RESET_H */
--
2.24.0
From: cylee12 <[email protected]>
Add devicetree binding for Realtek RTD1619 SoC reset controls.
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
include/dt-bindings/reset/rtk,reset-rtd1619.h | 124 ++++++++++++++++++
1 file changed, 124 insertions(+)
create mode 100644 include/dt-bindings/reset/rtk,reset-rtd1619.h
diff --git a/include/dt-bindings/reset/rtk,reset-rtd1619.h b/include/dt-bindings/reset/rtk,reset-rtd1619.h
new file mode 100644
index 000000000000..f6fa6359ec1c
--- /dev/null
+++ b/include/dt-bindings/reset/rtk,reset-rtd1619.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __DT_BINDINGS_RTK_RESET_RTD1619_H
+#define __DT_BINDINGS_RTK_RESET_RTD1619_H
+
+#define CC_RSTN_REG_BANK_1 (0x0000)
+#define CC_RSTN_REG_BANK_2 (0x0100)
+#define CC_RSTN_REG_BANK_3 (0x0200)
+#define CC_RSTN_REG_BANK_4 (0x0300)
+#define CC_RSTN_REG_BANK_6 (0x0400)
+#define CC_RSTN_REG_BANK_7 (0x0500)
+
+#define CC_RSTN_MISC (CC_RSTN_REG_BANK_1 | 0x00)
+#define CC_RSTN_DIP (CC_RSTN_REG_BANK_1 | 0x02)
+#define CC_RSTN_GSPI (CC_RSTN_REG_BANK_1 | 0x04)
+#define CC_RSTN_SDS (CC_RSTN_REG_BANK_1 | 0x06)
+#define CC_RSTN_SDS_REG (CC_RSTN_REG_BANK_1 | 0x08)
+#define CC_RSTN_SDS_PHY (CC_RSTN_REG_BANK_1 | 0x0a)
+#define CC_RSTN_VE1 (CC_RSTN_REG_BANK_1 | 0x0c)
+#define CC_RSTN_VE2 (CC_RSTN_REG_BANK_1 | 0x0e)
+#define CC_RSTN_R2RDSC_A00 (CC_RSTN_REG_BANK_1 | 0x10)
+#define CC_RSTN_RSA (CC_RSTN_REG_BANK_1 | 0x12)
+#define CC_RSTN_GPU (CC_RSTN_REG_BANK_1 | 0x14)
+#define CC_RSTN_DC_PHY (CC_RSTN_REG_BANK_1 | 0x16)
+#define CC_RSTN_DCPHY_CRT (CC_RSTN_REG_BANK_1 | 0x18)
+#define CC_RSTN_LSADC (CC_RSTN_REG_BANK_1 | 0x1a)
+#define CC_RSTN_SE (CC_RSTN_REG_BANK_1 | 0x1c)
+#define CC_RSTN_HSE_A00 (CC_RSTN_REG_BANK_1 | 0x1e)
+
+#define CC_RSTN_JPEG (CC_RSTN_REG_BANK_2 | 0x00)
+#define CC_RSTN_SD (CC_RSTN_REG_BANK_2 | 0x02)
+#define CC_RSTN_EMMC_A00 (CC_RSTN_REG_BANK_2 | 0x04)
+#define CC_RSTN_SDIO (CC_RSTN_REG_BANK_2 | 0x06)
+#define CC_RSTN_PCR_CNT (CC_RSTN_REG_BANK_2 | 0x08)
+#define CC_RSTN_PCIE0_STITCH (CC_RSTN_REG_BANK_2 | 0x0a)
+#define CC_RSTN_PCIE0_PHY (CC_RSTN_REG_BANK_2 | 0x0c)
+#define CC_RSTN_PCIE0 (CC_RSTN_REG_BANK_2 | 0x0e)
+#define CC_RSTN_PCIE0_CORE (CC_RSTN_REG_BANK_2 | 0x10)
+#define CC_RSTN_PCIE0_POWER (CC_RSTN_REG_BANK_2 | 0x12)
+#define CC_RSTN_PCIE0_NONSTITCH (CC_RSTN_REG_BANK_2 | 0x14)
+#define CC_RSTN_PCIE0_PHY_MDIO (CC_RSTN_REG_BANK_2 | 0x16)
+#define CC_RSTN_PCIE0_SGMII_MDIO (CC_RSTN_REG_BANK_2 | 0x18)
+#define CC_RSTN_UR2 (CC_RSTN_REG_BANK_2 | 0x1a)
+#define CC_RSTN_UR1 (CC_RSTN_REG_BANK_2 | 0x1c)
+#define CC_RSTN_MISC_SC0 (CC_RSTN_REG_BANK_2 | 0x1e)
+
+#define CC_RSTN_AE (CC_RSTN_REG_BANK_3 | 0x00)
+#define CC_RSTN_CABLERX (CC_RSTN_REG_BANK_3 | 0x02)
+#define CC_RSTN_MD_A00 (CC_RSTN_REG_BANK_3 | 0x04)
+#define CC_RSTN_TP_A00 (CC_RSTN_REG_BANK_3 | 0x06)
+#define CC_RSTN_NF_A00 (CC_RSTN_REG_BANK_3 | 0x08)
+#define CC_RSTN_MISC_SC1 (CC_RSTN_REG_BANK_3 | 0x0a)
+#define CC_RSTN_I2C_3 (CC_RSTN_REG_BANK_3 | 0x0c)
+#define CC_RSTN_FAN (CC_RSTN_REG_BANK_3 | 0x0e)
+#define CC_RSTN_TVE (CC_RSTN_REG_BANK_3 | 0x10)
+#define CC_RSTN_AIO (CC_RSTN_REG_BANK_3 | 0x12)
+#define CC_RSTN_VO (CC_RSTN_REG_BANK_3 | 0x14)
+#define CC_RSTN_MIPI_A00 (CC_RSTN_REG_BANK_3 | 0x16)
+#define CC_RSTN_HDMIRX (CC_RSTN_REG_BANK_3 | 0x18)
+#define CC_RSTN_HDMIRX_WRAP (CC_RSTN_REG_BANK_3 | 0x1a)
+#define CC_RSTN_HDMI (CC_RSTN_REG_BANK_3 | 0x1c)
+#define CC_RSTN_DISP (CC_RSTN_REG_BANK_3 | 0x1e)
+
+#define CC_RSTN_SATA_PHY_POW1 (CC_RSTN_REG_BANK_4 | 0x00)
+#define CC_RSTN_SATA_PHY_POW0 (CC_RSTN_REG_BANK_4 | 0x02)
+#define CC_RSTN_SATA_MDIO1 (CC_RSTN_REG_BANK_4 | 0x04)
+#define CC_RSTN_SATA_MDIO0 (CC_RSTN_REG_BANK_4 | 0x06)
+#define CC_RSTN_SATA_WRAP (CC_RSTN_REG_BANK_4 | 0x08)
+#define CC_RSTN_SATA_MAC_P1 (CC_RSTN_REG_BANK_4 | 0x0a)
+#define CC_RSTN_SATA_MAC_P0 (CC_RSTN_REG_BANK_4 | 0x0c)
+#define CC_RSTN_SATA_MAC_COM (CC_RSTN_REG_BANK_4 | 0x0e)
+#define CC_RSTN_PCIE1_STITCH (CC_RSTN_REG_BANK_4 | 0x10)
+#define CC_RSTN_PCIE1_PHY (CC_RSTN_REG_BANK_4 | 0x12)
+#define CC_RSTN_PCIE1 (CC_RSTN_REG_BANK_4 | 0x14)
+#define CC_RSTN_PCIE1_CORE (CC_RSTN_REG_BANK_4 | 0x16)
+#define CC_RSTN_PCIE1_POWER (CC_RSTN_REG_BANK_4 | 0x18)
+#define CC_RSTN_PCIE1_NONSTITCH (CC_RSTN_REG_BANK_4 | 0x1a)
+#define CC_RSTN_PCIE1_PHY_MDIO (CC_RSTN_REG_BANK_4 | 0x1c)
+#define CC_RSTN_HDMITOP (CC_RSTN_REG_BANK_4 | 0x1e)
+
+#define CC_RSTN_HSE (CC_RSTN_REG_BANK_6 | 0x06)
+#define CC_RSTN_R2RDSC (CC_RSTN_REG_BANK_6 | 0x08)
+#define CC_RSTN_EMMC (CC_RSTN_REG_BANK_6 | 0x0a)
+#define CC_RSTN_NF (CC_RSTN_REG_BANK_6 | 0x0c)
+#define CC_RSTN_MD (CC_RSTN_REG_BANK_6 | 0x0e)
+#define CC_RSTN_TPB (CC_RSTN_REG_BANK_6 | 0x18)
+#define CC_RSTN_TP (CC_RSTN_REG_BANK_6 | 0x1a)
+#define CC_RSTN_MIPI (CC_RSTN_REG_BANK_6 | 0x1c)
+
+#define CC_RSTN_TPB_A00 (CC_RSTN_REG_BANK_7 | 0x00)
+#define CC_RSTN_I2C_4 (CC_RSTN_REG_BANK_7 | 0x02)
+#define CC_RSTN_I2C_5 (CC_RSTN_REG_BANK_7 | 0x04)
+#define CC_RSTN_TSIO (CC_RSTN_REG_BANK_7 | 0x06)
+#define CC_RSTN_VE3 (CC_RSTN_REG_BANK_7 | 0x08)
+#define CC_RSTN_EDP (CC_RSTN_REG_BANK_7 | 0x0a)
+
+/* 0x98007088 */
+#define IC_RSTN_VFD 0x0000
+#define IC_RSTN_IR 0x0001
+#define IC_RSTN_CEC0 0x0002
+#define IC_RSTN_CEC1 0x0003
+#define IC_RSTN_DP 0x0004
+#define IC_RSTN_CBUSTX 0x0005
+#define IC_RSTN_CBUSRX 0x0006
+#define IC_RSTN_EFUSE 0x0007
+#define IC_RSTN_UR0 0x0008
+#define IC_RSTN_GMAC 0x0009
+#define IC_RSTN_GPHY 0x000a
+#define IC_RSTN_I2C_0 0x000b
+#define IC_RSTN_I2C_1 0x000c
+#define IC_RSTN_CBUS 0x000d
+#define IC_RSTN_USB_DRD 0x000e
+#define IC_RSTN_USB_HOST 0x000f
+#define IC_RSTN_USB_PHY_0 0x0010
+#define IC_RSTN_USB_PHY_1 0x0011
+#define IC_RSTN_USB_PHY_2 0x0012
+#define IC_RSTN_USB 0x0013
+#define IC_RSTN_TYPE_C 0x0014
+#define IC_RSTN_USB_U3_HOST 0x0015
+#define IC_RSTN_USB3_PHY0_POW 0x0016
+#define IC_RSTN_USB3_P0_MDIO 0x0017
+#define IC_RSTN_USB3_PHY1_POW 0x0018
+#define IC_RSTN_USB3_P1_MDIO 0x0019
+
+#endif
--
2.24.0
From: cylee12 <[email protected]>
Signed-off-by: Cheng-Yu Lee <[email protected]>
Signed-off-by: James Tai <[email protected]>
---
.../bindings/clock/realtek,clocks.txt | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/realtek,clocks.txt
diff --git a/Documentation/devicetree/bindings/clock/realtek,clocks.txt b/Documentation/devicetree/bindings/clock/realtek,clocks.txt
new file mode 100644
index 000000000000..db101508ac6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/realtek,clocks.txt
@@ -0,0 +1,38 @@
+Realtek Clock/Reset Controller
+==============================
+
+Realtek CRT/ISO controller device-tree binding for Realtek Platforms.
+
+This binding uses the common clock binding[1].
+
+The controller node should be the child of a syscon node with the required
+propertise:
+
+- compatible :
+ should contain only one of the following:
+ "realtek,rtd1619-cc" for RTD1619 CRT clock controller,
+ "realtek,rtd1619-ic" for RTD1619 ISO clock controller,
+
+- #clock-cells : should be 1.
+
+- #reset-cells : should be 1.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Example:
+
+ crt@98000000 {
+ compatible = "realtek,rtd1619-crt", "simple-mfd", "syscon";
+ reg = <0x98000000 0x1000>;
+
+ cc: cc@98000000 {
+ compatible = "realtek,rtd1619-cc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+ };
+
+ consumer {
+ clocks = <&cc CC_CKE_GSPI>;
+ };
+
--
2.24.0
Hi James and Cheng-Yu,
Am 03.12.19 um 08:45 schrieb James Tai:
> From: cylee12 <[email protected]>
Please fix the author (git commit --amend --author="...") and use an
appropriate git config setting (and communication to your team) to avoid
this reoccurring for new commits - already pointed out to James.
BTW I wonder why we have so many seemingly unrelated people in CC
(Mediatek, RISC-V) that the patches and responses keep hanging in
mailing list moderation?
>
> Add devicetree binding for Realtek RTD1619 clocks.
>
> Signed-off-by: Cheng-Yu Lee <[email protected]>
> Signed-off-by: James Tai <[email protected]>
> ---
> include/dt-bindings/clock/rtk,clock-rtd1619.h | 88 +++++++++++++++++++
> 1 file changed, 88 insertions(+)
> create mode 100644 include/dt-bindings/clock/rtk,clock-rtd1619.h
>
> diff --git a/include/dt-bindings/clock/rtk,clock-rtd1619.h b/include/dt-bindings/clock/rtk,clock-rtd1619.h
> new file mode 100644
> index 000000000000..497f9b914857
> --- /dev/null
> +++ b/include/dt-bindings/clock/rtk,clock-rtd1619.h
NAK for the filename. "rtk," is not a registered vendor prefix [1], so
you cannot use it anywhere in bindings. Please use the registered prefix
"realtek," and compare the other Realtek bindings headers that got
accepted already. The order of SoC vs. name seems wrong.
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -0,0 +1,88 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
Why restrict these trivial numbers to GPLv2? Please compare the .dtsi
and .yaml files where this may get #include'd, and keep non-Linux OSes
such as BSDs in mind for any DT bindings; it's supposed to be an
OS-neutral interface contract that anyone can implement.
> +#ifndef __DT_BINDINGS_RTK_CLOCK_RTD1619_H
> +#define __DT_BINDINGS_RTK_CLOCK_RTD1619_H
May need adjustments based on the filename, same for the #endif.
> +
> +#define CC_PLL_SCPU 0
> +#define CC_PLL_BUS 2
Please tab-indent the indices for readability.
> +#define CC_CLK_SYS 3
> +#define CC_CLK_SYS_SB2 4
> +#define CC_PLL_DCSB 5
> +#define CC_CLK_SYSH 6
> +#define CC_PLL_DDSA 7
> +#define CC_PLL_DDSB 8
> +#define CC_PLL_GPU 9
> +#define CC_CLK_GPU 10
> +#define CC_PLL_VE1 11
> +#define CC_PLL_VE2 12
> +#define CC_CLK_VE1 13
> +#define CC_CLK_VE2 14
> +#define CC_CLK_VE3 15
> +#define CC_CLK_VE2_BPU 16
> +#define CC_PLL_DIF 17
> +#define CC_PLL_PSAUD1A 18
> +#define CC_PLL_PSAUD2A 19
> +
> +#define CC_CKE_MISC 33
> +#define CC_CKE_PCIE0 34
> +#define CC_CKE_GSPI 35
> +#define CC_CKE_SDS 36
> +#define CC_CKE_HDMI 37
> +#define CC_CKE_LSADC 38
> +#define CC_CKE_SE 39
> +#define CC_CKE_CP 40
> +#define CC_CKE_MD 41
> +#define CC_CKE_TP 42
> +#define CC_CKE_RSA 43
> +#define CC_CKE_NF 44
> +#define CC_CKE_EMMC 45
> +#define CC_CKE_SD 46
> +#define CC_CKE_SDIO_IP 47
> +#define CC_CKE_MIPI 48
> +#define CC_CKE_EMMC_IP 49
> +#define CC_CKE_SDIO 50
> +#define CC_CKE_SD_IP 51
> +#define CC_CKE_CABLERX 52
> +#define CC_CKE_TPB 53
> +#define CC_CKE_SC1 54
> +#define CC_CKE_I2C3 55
> +#define CC_CKE_JPEG 56
> +#define CC_CKE_SC0 57
> +#define CC_CKE_HDMIRX 58
> +#define CC_CKE_HSE 59
> +#define CC_CKE_UR2 60
> +#define CC_CKE_UR1 61
> +#define CC_CKE_FAN 62
> +#define CC_CKE_SATA_WRAP_SYS 63
> +#define CC_CKE_SATA_WRAP_SYSH 64
> +#define CC_CKE_SATA_MAC_SYSH 65
> +#define CC_CKE_R2RDSC 66
> +#define CC_CKE_PCIE1 67
> +#define CC_CKE_I2C4 68
> +#define CC_CKE_I2C5 69
> +#define CC_CKE_EDP 70
> +#define CC_CKE_TSIO_TRX 71
> +#define CC_CKE_TVE 72
> +#define CC_CKE_VO 73
> +
> +#define CC_CLK_MAX 74
> +
> +
> +#define IC_CKE_CEC0 2
> +#define IC_CKE_CBUSRX_SYS 3
> +#define IC_CKE_CBUSTX_SYS 4
> +#define IC_CKE_CBUS_SYS 5
> +#define IC_CKE_CBUS_OSC 6
> +#define IC_CKE_IR 7
> +#define IC_CKE_UR0 8
> +#define IC_CKE_I2C0 9
> +#define IC_CKE_I2C1 10
> +#define IC_CKE_ETN_250M 11
> +#define IC_CKE_ETN_SYS 12
> +#define IC_CKE_USB_DRD 13
> +#define IC_CKE_USB_HOST 14
> +#define IC_CKE_USB_U3_HOST 15
> +#define IC_CKE_USB 16
> +#define IC_CLK_MAX 17
> +
> +#endif /* __DT_BINDINGS_RTK_CLOCK_RTD1619_H */
> +
Trailing empty line.
Regards,
Andreas
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer
HRB 36809 (AG Nürnberg)
Hi James,
[dropping Palmer]
Am 03.12.19 um 08:45 schrieb James Tai:
> From: cylee12 <[email protected]>
Please fix the author name.
>
> This patch adds common clock support for Realtek SoCs, including PLLs,
> Mux clocks and Gate clocks.
Can you be more specific here, please? Is this compatible back to
RTD1195 or RTD1295 or just 1619 forward? I only see RTD1619 in 5/6. And
not a single .dtsi patch is included in this series for testing it.
>
> Signed-off-by: Cheng-Yu Lee <[email protected]>
> Signed-off-by: James Tai <[email protected]>
> ---
> drivers/clk/Kconfig | 1 +
> drivers/clk/Makefile | 1 +
> drivers/clk/realtek/Kconfig | 10 +
> drivers/clk/realtek/Makefile | 9 +
> drivers/clk/realtek/clk-pll-dif.c | 81 ++++++
> drivers/clk/realtek/clk-pll-psaud.c | 120 ++++++++
> drivers/clk/realtek/clk-pll.c | 400 ++++++++++++++++++++++++++
> drivers/clk/realtek/clk-pll.h | 151 ++++++++++
> drivers/clk/realtek/clk-regmap-gate.c | 89 ++++++
> drivers/clk/realtek/clk-regmap-gate.h | 26 ++
> drivers/clk/realtek/clk-regmap-mux.c | 63 ++++
> drivers/clk/realtek/clk-regmap-mux.h | 26 ++
> drivers/clk/realtek/common.c | 320 +++++++++++++++++++++
> drivers/clk/realtek/common.h | 123 ++++++++
> 14 files changed, 1420 insertions(+)
This patch is way too large for me to review. Please split this up
further into logically self-contained, compile-testable patches.
> create mode 100644 drivers/clk/realtek/Kconfig
> create mode 100644 drivers/clk/realtek/Makefile
> create mode 100644 drivers/clk/realtek/clk-pll-dif.c
> create mode 100644 drivers/clk/realtek/clk-pll-psaud.c
> create mode 100644 drivers/clk/realtek/clk-pll.c
> create mode 100644 drivers/clk/realtek/clk-pll.h
> create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
> create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
> create mode 100644 drivers/clk/realtek/clk-regmap-mux.c
> create mode 100644 drivers/clk/realtek/clk-regmap-mux.h
> create mode 100644 drivers/clk/realtek/common.c
> create mode 100644 drivers/clk/realtek/common.h
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c44247d0b83e..8e06487440ce 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -317,6 +317,7 @@ source "drivers/clk/mediatek/Kconfig"
> source "drivers/clk/meson/Kconfig"
> source "drivers/clk/mvebu/Kconfig"
> source "drivers/clk/qcom/Kconfig"
> +source "drivers/clk/realtek/Kconfig"
> source "drivers/clk/renesas/Kconfig"
> source "drivers/clk/samsung/Kconfig"
> source "drivers/clk/sifive/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 0138fb14e6f8..71ea17f97f7d 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -95,6 +95,7 @@ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
> obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
> obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
> obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
> +obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/
Should we take the Renesas approach here and allow for COMPILE_TEST?
> obj-y += renesas/
> obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
> obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
> diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
> new file mode 100644
> index 000000000000..5bca757dddfa
> --- /dev/null
> +++ b/drivers/clk/realtek/Kconfig
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config COMMON_CLK_REALTEK
I would personally think that it's not necessary to prefix with COMMON_
here, even if based on CONFIG_COMMON_CLK framework, since Realtek is no
longer common. Stephen/Michael?
Which brings us to the next aspect, is this really universally common
for Realtek? Are they compatible with old MIPS SoCs and Arm SoCs from
departments other than DHC? (e.g., Smart TV)
If the answer to any of these is no, then please rename the Kconfig
symbol to the oldest SoC for uniqueness, e.g., RTD1195.
> + bool "Clock driver for realtek"
Spelling.
> + select MFD_SYSCON
Please add help text and include SoC names.
> +
> +config CLK_PLL_PSAUD
Too generic name.
> + bool
> +
> +config CLK_PLL_DIF
Ditto.
> + bool
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> new file mode 100644
> index 000000000000..050d450db067
> --- /dev/null
> +++ b/drivers/clk/realtek/Makefile
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_COMMON_CLK_REALTEK) += clk-rtk.o
> +
> +clk-rtk-y += common.o
> +clk-rtk-y += clk-regmap-mux.o
> +clk-rtk-y += clk-regmap-gate.o
> +clk-rtk-y += clk-pll.o
> +clk-rtk-$(CONFIG_CLK_PLL_PSAUD) += clk-pll-psaud.o
> +clk-rtk-$(CONFIG_CLK_PLL_DIF) += clk-pll-dif.o
> diff --git a/drivers/clk/realtek/clk-pll-dif.c b/drivers/clk/realtek/clk-pll-dif.c
> new file mode 100644
> index 000000000000..d19efef2626e
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-pll-dif.c
> @@ -0,0 +1,81 @@
> +// SPDX-License-Identifier: GPL-2.0-only
Can you relicense this code as GPL-2.0-or-later? For Makefile and
Kconfig it doesn't matter, just for low-level code that could become
relevant for debuggers like OpenOCD, which is licensed GPLv2+.
> +/*
Care to elaborate here what "dif" is? :)
> + * Copyright (c) 2019 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <[email protected]>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clk.h>
> +#include <linux/spinlock.h>
> +#include <linux/delay.h>
Insert white line here?
> +#include "common.h"
> +#include "clk-pll.h"
> +
> +static int clk_pll_dif_enable(struct clk_hw *hw)
> +{
> + struct clk_pll_dif *pll = to_clk_pll_dif(hw);
> +
> + pr_debug("%pC: %s\n", hw->clk, __func__);
Please review debug and info messages for whether they are still needed
- in particular for info below I assume no.
> +
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x0C, 0x00000048);
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00020c00);
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x04, 0x204004ca);
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x00, 0x8000a000);
This is way too much dark magic!
Start with giving the offsets symbolic names, please.
Next, construct the value from symbolic constants. You will see me use
BIT() and GENMASK() macros elsewhere; please adopt those conventions.
> + udelay(100);
Is this from some internal datasheet? Otherwise, from some MCU clocks
that I've previously implemented, I would expect there to be some status
bit indicating readyness that we should poll rather than trusting a
hardcoded delay. I don't see a single read below, nor any explanatory
comment.
> +
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00420c00);
> + udelay(50);
> +
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x08, 0x00420c03);
> + udelay(200);
> +
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x0C, 0x00000078);
> + udelay(100);
> +
> + clk_regmap_write(&pll->clkr, pll->pll_ofs + 0x04, 0x204084ca);
> +
> + /* ssc control */
This lonely comment seems kind of redundant with ssc_ofs vs. pll_ofs.
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x00, 0x00000004);
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x04, 0x00006800);
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x0C, 0x00000000);
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x10, 0x00000000);
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x08, 0x001e1f98);
> + clk_regmap_write(&pll->clkr, pll->ssc_ofs + 0x00, 0x00000005);
> + pll->status = 1;
> +
> + return 0;
> +}
[snip]
I'll stop reviewing here and am waiting for a v2.
Thanks,
Andreas
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer
HRB 36809 (AG Nürnberg)
Hi James,
[dropping Palmer, adding Philipp]
$subject: I prefer to have the subject start with uppercase letter, to
clearly distinguish it from the lowercase prefixes (and because that's
how a book or newspaper headline would start, too). Applies also to
other patches in this series, e.g., "reset: Add ..." (cf. below).
Am 03.12.19 um 08:45 schrieb James Tai:
> From: cylee12 <[email protected]>
--author.
>
> This patch add reset control support for Realtek SoCs.
Please don't write "This patch" in a Git commit message. You can
elegantly avoid the patch vs. commit topic by using "This adds" (and
note the grammar for third-person presence vs. imperative in subject).
All SoCs since the beginning of time or just RTD1619 and later?
As you know, we're already using reset-simple driver for RTD1295.
>
> Signed-off-by: Cheng-Yu Lee <[email protected]>
> Signed-off-by: James Tai <[email protected]>
> ---
> drivers/clk/realtek/Kconfig | 1 +
> drivers/clk/realtek/Makefile | 1 +
> drivers/clk/realtek/reset.c | 107 +++++++++++++++++++++++++++++++++++
> drivers/clk/realtek/reset.h | 37 ++++++++++++
Why in the world under clk? I just introduced syscon nodes to cleanly
allow accessing CRT and Iso registers from multiple independent drivers,
and I have patches doing exactly that for RTD1295 and RTD1195. Please
move it into drivers/reset/, also to make sure that for v2 the reset
maintainers actually get CC'ed for review.
> 4 files changed, 146 insertions(+)
> create mode 100644 drivers/clk/realtek/reset.c
> create mode 100644 drivers/clk/realtek/reset.h
>
> diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
> index 5bca757dddfa..8e7e7edf64dd 100644
> --- a/drivers/clk/realtek/Kconfig
> +++ b/drivers/clk/realtek/Kconfig
> @@ -1,6 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-only
> config COMMON_CLK_REALTEK
> bool "Clock driver for realtek"
> + select RESET_CONTROLLER
No!
BTW if you would make this Kconfig option "depends on ARCH_REALTEK" then
it would be selected already. However, ARCH_REALTEK || COMPILE_TEST
would be preferable for noticing errors early. It doesn't make sense to
allow selecting this driver for non-Realtek systems unless COMPILE_TEST
asks for it.
> select MFD_SYSCON
>
> config CLK_PLL_PSAUD
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index 050d450db067..43f8bd71c0c8 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -7,3 +7,4 @@ clk-rtk-y += clk-regmap-gate.o
> clk-rtk-y += clk-pll.o
> clk-rtk-$(CONFIG_CLK_PLL_PSAUD) += clk-pll-psaud.o
> clk-rtk-$(CONFIG_CLK_PLL_DIF) += clk-pll-dif.o
> +clk-rtk-y += reset.o
> diff --git a/drivers/clk/realtek/reset.c b/drivers/clk/realtek/reset.c
> new file mode 100644
> index 000000000000..3f4d1a723b2a
> --- /dev/null
> +++ b/drivers/clk/realtek/reset.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0-only
Is GPL-2.0-or-later possible?
> +/*
> + * Copyright (C) 2019 Realtek Semiconductor Corporation
> + */
> +
> +#include <linux/of.h>
> +#include <linux/device.h>
Sort order.
> +#include <linux/regmap.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
White line please ...
> +#include "reset.h"
... or better try to avoid this #include by driver design.
> +
> +static int rtk_reset_assert(struct reset_controller_dev *rcdev,
rtd1619_?
> + unsigned long idx)
> +{
> + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
_controller vs. _data looks weird.
> + struct rtk_reset_bank *bank = &data->banks[idx >> 8];
> + uint32_t id = idx & 0xff;
> + uint32_t mask = bank->write_en ? (0x3 << id) : BIT(id);
> + uint32_t val = bank->write_en ? (0x2 << id) : 0;
Peeking into patch 5/6, write_en seems always 1 for CRT and 0 for a
single ISO bank.
Wouldn't it be easier to just keep two different drivers, one for
RTD1619-and-later with the new semantics, and one for the older simpler
semantics? I was really just waiting for you to post a trivial patch
that with an ack from Rob Philipp and I could apply right away. This
here is huge and I don't think you realize yet how convoluted this is
for trying to merge this into mainline within one merge window...
> +
> + return regmap_update_bits(data->regmap, bank->ofs, mask, val);
> +}
> +
> +static int rtk_reset_deassert(struct reset_controller_dev *rcdev,
> + unsigned long idx)
> +{
> + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> + struct rtk_reset_bank *bank = &data->banks[idx >> 8];
> + uint32_t id = idx & 0xff;
> + uint32_t mask = bank->write_en ? (0x3 << id) : BIT(id);
> + uint32_t val = mask;
> +
> + return regmap_update_bits(data->regmap, bank->ofs, mask, val);
> +}
The way I first read this code, there's one bit BIT(1) for writing the
new status and one bit BIT(0) for checking current status? Shouldn't
enable/disable then poll for the change to go into effect before
returning? Otherwise the caller may make wrong assumptions.
Or is this like the write_data bit for the irq mux ISR but in bit 1?
Then I am having trouble following this code and wonder why you use
regmap_update_bits() in the first place, if only some bits get written
anyway - use plain regmap_write() then. If I am puzzled, having seen the
other code, then consider it badly maintainable for the community...
You need to make the code self-documenting by using symbolic constants
instead of magic numbers, or add an inline helper. Maybe add comments.
> +
> +static int rtk_reset_reset(struct reset_controller_dev *rcdev,
> + unsigned long idx)
> +{
> + int ret;
> +
> + ret = rtk_reset_assert(rcdev, idx);
> + if (ret)
> + return ret;
> +
> + return rtk_reset_deassert(rcdev, idx);
> +}
Does the reset core not do this for us? (If not, shouldn't we fix that?)
> +
> +static int rtk_reset_status(struct reset_controller_dev *rcdev,
> + unsigned long idx)
> +{
> + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> + struct rtk_reset_bank *bank = &data->banks[idx >> 8];
> + uint32_t id = idx & 0xff;
> + uint32_t val;
> +
> + regmap_read(data->regmap, bank->ofs, &val);
> + return !((val >> id) & 1);
return !(val & BIT(id)); seems much more readable to me?
Without seeing bit 0 read here, the above enable/disable code would be
even more confusing.
Please share what the register bits are actually called, then we can
discuss what the best way of calling and using them will be.
> +}
> +
> +static struct reset_control_ops rtk_reset_ops = {
> + .assert = rtk_reset_assert,
> + .deassert = rtk_reset_deassert,
> + .reset = rtk_reset_reset,
> + .status = rtk_reset_status,
> +};
> +
> +static int rtk_of_reset_xlate(struct reset_controller_dev *rcdev,
> + const struct of_phandle_args *reset_spec)
> +{
> + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> + int val;
> +
> + val = reset_spec->args[0];
> + if (val >= rcdev->nr_resets)
> + return -EINVAL;
> +
> + if (data->id_xlate)
> + return data->id_xlate(val);
This does not appear to be used in this series - how do you envision it
to be used? That would need to be covered in the dt-binding then.
> + return val;
> +}
> +
> +
> +int rtk_reset_controller_add(struct device *dev, struct regmap *regmap,
> + struct rtk_reset_initdata *initdata)
Just get that initdata via DT compatible within this reset driver, like
I did for irqchip.
> +{
> + struct rtk_reset_data *data;
> + struct device_node *np = dev->of_node;
> +
> + data = kzalloc(sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> + data->regmap = regmap;
> + data->num_banks = initdata->num_banks;
> + data->banks = initdata->banks;
> + data->id_xlate = initdata->id_xlate;
> +
> + data->rcdev.owner = THIS_MODULE;
> + data->rcdev.ops = &rtk_reset_ops;
> + data->rcdev.of_node = np;
> + data->rcdev.nr_resets = initdata->num_banks * 0x100;
This design doesn't make much sense to me? At most a bank is going to
get you 32 resets, 16 in case of the new ones, all much smaller than 256.
The theoretical-here case of mixed sizes you could just handle by
exposing them as individual DT nodes, like we do today, which as a bonus
would make the syscon DT node nicely self-documenting. I.e.,
"realtek,rtd1619-reset" vs. "realtek,rtd1195-reset".
> + data->rcdev.of_xlate = rtk_of_reset_xlate;
> + data->rcdev.of_reset_n_cells = 1;
> +
> + return reset_controller_register(&data->rcdev);
> +}
> +
Trailing white line.
I would expect a platform_driver here, turning above _add into _probe.
> diff --git a/drivers/clk/realtek/reset.h b/drivers/clk/realtek/reset.h
> new file mode 100644
> index 000000000000..f0cc7b1045ee
> --- /dev/null
> +++ b/drivers/clk/realtek/reset.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2019 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <[email protected]>
> + */
> +
> +#ifndef __CLK_REALTEK_RESET_H
> +#define __CLK_REALTEK_RESET_H
> +
> +#include <linux/reset-controller.h>
> +
> +struct rtk_reset_bank {
> + uint32_t ofs;
> + uint32_t write_en;
If we needed this, it might as well be bool with true/false.
> +};
> +
> +struct rtk_reset_data {
> + struct reset_controller_dev rcdev;
> + struct rtk_reset_bank *banks;
const?
> + uint32_t num_banks;
> + struct regmap *regmap;
> + unsigned long (*id_xlate)(unsigned long id);
Drop until used?
> +};
> +
> +#define to_rtk_reset_controller(r) \
> + container_of(r, struct rtk_reset_data, rcdev)
> +
> +struct rtk_reset_initdata {
> + struct rtk_reset_bank *banks;
const?
> + uint32_t num_banks;
> + unsigned long (*id_xlate)(unsigned long id);
Drop until used?
> +};
> +
> +int rtk_reset_controller_add(struct device *dev, struct regmap *regmap,
> + struct rtk_reset_initdata *initdata);
> +
> +#endif /* __CLK_REALTEK_RESET_H */
Regards,
Andreas
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer
HRB 36809 (AG Nürnberg)
Hi James,
[dropping Palmer, adding Philipp]
Am 03.12.19 um 08:45 schrieb James Tai:
> From: cylee12 <[email protected]>
Author.
$subject: clk vs. clock prefix
Lacking a commit message here.
>
> Signed-off-by: Cheng-Yu Lee <[email protected]>
> Signed-off-by: James Tai <[email protected]>
> ---
> .../bindings/clock/realtek,clocks.txt | 38 +++++++++++++++++++
Please use YAML schema for any new bindings.
> 1 file changed, 38 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/realtek,clocks.txt
This patch needs to be ordered before patches using the binding in a
driver or DT. In this case it should've been squashed into 1/6.
> diff --git a/Documentation/devicetree/bindings/clock/realtek,clocks.txt b/Documentation/devicetree/bindings/clock/realtek,clocks.txt
> new file mode 100644
> index 000000000000..db101508ac6a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/realtek,clocks.txt
> @@ -0,0 +1,38 @@
> +Realtek Clock/Reset Controller
> +==============================
> +
> +Realtek CRT/ISO controller device-tree binding for Realtek Platforms.
> +
> +This binding uses the common clock binding[1].
> +
> +The controller node should be the child of a syscon node with the required
> +propertise:
> +
> +- compatible :
> + should contain only one of the following:
> + "realtek,rtd1619-cc" for RTD1619 CRT clock controller,
> + "realtek,rtd1619-ic" for RTD1619 ISO clock controller,
-ic does not strike me as the best name, can we go with -iso-something
for consistency?
> +
> +- #clock-cells : should be 1.
> +
> +- #reset-cells : should be 1.
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Example:
> +
> + crt@98000000 {
crt: syscon@...
Always prefer generic node names when possible.
> + compatible = "realtek,rtd1619-crt", "simple-mfd", "syscon";
1) You must not use undefined compatible strings in your example! If we
want to use such compatibles (which I agree with in principle), then we
need to post separate bindings patches before you do so. The big issue
there is how to name them to work across SoC families. For that reason
my syscon series did not include dt-bindings, to not hold us up with
them. Drop it here for now?
2) You must retain the valid order, here defined by the syscon binding.
Like I said for the Mjolnir .dts. If we consequently use YAML schemas,
then you can check your .dts files with make dtbs_check and hopefully
notice it yourself before I complain. .dtsi patches are sadly missing in
this series, so you could only run limited make dt_binding_check.
> + reg = <0x98000000 0x1000>;
> +
> + cc: cc@98000000 {
cc: clock-controller@...
But you must not give a unit address in absence of reg.
> + compatible = "realtek,rtd1619-cc";
reg missing. When you add it, you need #address-cells and #size-cells
above, too. Also ranges for completeness. In YAML it gets compile-tested
and should not sprout warnings.
> + #clock-cells = <1>;
> + #reset-cells = <1>;
BTW given the complex mappings that you attempt, wouldn't it be easier
to use #reset-cells = <2>? In that case one could again argue that a
per-bank node/driver will be easier.
> + };
> + };
Haven't tested this yet, but I wonder whether we could just use
"realtek,rtd1619-crt" for the clock controller directly and still use
the same node as syscon mfd? If not, it might be nice to describe in the
child node's reg what exactly is covered instead of just <0x0 0x1000>.
My point here is that the DT describes the hardware, but that does not
dictate how the Linux drivers bind to DT. clk is no platform_driver, so
you can have clk and reset drivers binding to the same DT compatible.
Did that for STM32 CRT once. However, don't hide the binding under clock
if it's really mfd - someone looking for reset bindings is going to have
a hard time finding them under clock.
> +
> + consumer {
> + clocks = <&cc CC_CKE_GSPI>;
> + };
> +
Regards,
Andreas
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer
HRB 36809 (AG Nürnberg)
Hi Andreas,
> Hi James and Cheng-Yu,
>
> Am 03.12.19 um 08:45 schrieb James Tai:
> > From: cylee12 <[email protected]>
>
> Please fix the author (git commit --amend --author="...") and use an
> appropriate git config setting (and communication to your team) to avoid this
> reoccurring for new commits - already pointed out to James.
>
> BTW I wonder why we have so many seemingly unrelated people in CC
> (Mediatek, RISC-V) that the patches and responses keep hanging in mailing list
> moderation?
I used the "get_maintainer.pl" to find the email address of maintainers. However,
I'm so sorry for mistakenly adding some unrelated people to this mail.
Regards,
James
Hi James,
[fixing Palmer]
Am 04.12.19 um 05:11 schrieb James Tai:
>> Am 03.12.19 um 08:45 schrieb James Tai:
>>> From: cylee12 <[email protected]>
>>
>> Please fix the author (git commit --amend --author="...") and use an
>> appropriate git config setting (and communication to your team) to avoid this
>> reoccurring for new commits - already pointed out to James.
>>
>> BTW I wonder why we have so many seemingly unrelated people in CC
>> (Mediatek, RISC-V) that the patches and responses keep hanging in mailing list
>> moderation?
>
> I used the "get_maintainer.pl" to find the email address of maintainers. However,
> I'm so sorry for mistakenly adding some unrelated people to this mail.
Here's my git-send-email cccmd config that I recommend:
$ git config sendemail.cccmd
scripts/get_maintainer.pl --nogit-fallback --norolestats
--nogit-fallback suppresses Git history to be checked for previous
contributors, saving time and avoiding unrelated or outdated people.
--norolestats suppresses extensive "(...)" comments for the email
addresses, which might wrap and break during transmission or when people
reply.
In addition you obviously need to configure sendemail.to, and you may
want to add multiple cc lines to [sendemail] in your .git/config to
ensure all mails including cover letters reach LKML and LAKML, too:
$ git config --get-all sendemail.to
[email protected]
$ git config --get-all sendemail.cc
[email protected]
[email protected]
Further, you need to ensure that you are sending from the right branch,
so that the latest MAINTAINERS file and scripts get used. As Paul
pointed out, Palmer's address is fixed in both linux-next and linux, so
it is really puzzling where you got that old address from...
Not understanding your setup, you'll have to debug on your own where
those addresses came from. Try git send-email --dry-run to review the CC
addresses before you send. You could also temporarily use --rolestats to
see the MAINTAINERS section they came from.
On the bright side, this time your patches arrived threaded correctly.
Regards,
Andreas
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer
HRB 36809 (AG Nürnberg)