All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-02-26 14:47 ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, sboyd, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Document that Stratix10 clock bindings, and add the clock header file. The
clock header is an enumeration of all the different clocks on the Stratix10
platform.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v6:
- no changes
v5:
- moved SPDX license header to single line comment
v4:
- remove '_' in node names
- remove stray tab
- add clock-frequency property for fixed-clocks
- put SPDX license as the very top line
v3:
- s/intc/intel for correct vendor prefix
- fixup node name to "intel,stratix10-clkmgr"
- document the required fixed-clock for oscillators
v2:
- use a single binding for the clock controller
---
 .../devicetree/bindings/clock/intc_stratix10.txt   | 51 +++++++++++++
 include/dt-bindings/clock/stratix10-clock.h        | 84 ++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/intc_stratix10.txt
 create mode 100644 include/dt-bindings/clock/stratix10-clock.h

diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
new file mode 100644
index 0000000..0652ff1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
@@ -0,0 +1,51 @@
+Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be
+	"intel,stratix10-clkmgr"
+
+- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
+
+- #clock-cells : from common clock binding, shall be set to 1.
+
+- clocks : Should contain fixed-clock sources, such as oscillators.
+
+Example:
+	clkmgr: clock-controller@ffd10000 {
+		compatible = "intel,stratix10-clkmgr";
+		reg = <0xffd10000 0x1000>;
+		#clock-cells = <1>;
+
+		clocks {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			cb_intosc_ls_clk: cb-intosc-ls-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			f2s_free_clk: f2s-free-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			osc1: osc1 {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+		};
+	};
diff --git a/include/dt-bindings/clock/stratix10-clock.h b/include/dt-bindings/clock/stratix10-clock.h
new file mode 100644
index 0000000..0ac1c90
--- /dev/null
+++ b/include/dt-bindings/clock/stratix10-clock.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier:	GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef __STRATIX10_CLOCK_H
+#define __STRATIX10_CLOCK_H
+
+/* fixed rate clocks */
+#define STRATIX10_OSC1			0
+#define STRATIX10_CB_INTOSC_HS_DIV2_CLK	1
+#define STRATIX10_CB_INTOSC_LS_CLK	2
+#define STRATIX10_F2S_FREE_CLK		3
+
+/* fixed factor clocks */
+#define STRATIX10_L4_SYS_FREE_CLK	4
+#define STRATIX10_MPU_PERIPH_CLK	5
+#define STRATIX10_MPU_L2RAM_CLK		6
+#define STRATIX10_SDMMC_CIU_CLK		7
+
+/* PLL clocks */
+#define STRATIX10_MAIN_PLL_CLK		8
+#define STRATIX10_PERIPH_PLL_CLK	9
+#define STRATIX10_BOOT_CLK		10
+
+/* Periph clocks */
+#define STRATIX10_MAIN_MPU_BASE_CLK	11
+#define STRATIX10_MAIN_NOC_BASE_CLK	12
+#define STRATIX10_MAIN_EMACA_CLK	13
+#define STRATIX10_MAIN_EMACB_CLK	14
+#define STRATIX10_MAIN_EMAC_PTP_CLK	15
+#define STRATIX10_MAIN_GPIO_DB_CLK	16
+#define STRATIX10_MAIN_SDMMC_CLK	17
+#define STRATIX10_MAIN_S2F_USR0_CLK	18
+#define STRATIX10_MAIN_S2F_USR1_CLK	19
+#define STRATIX10_MAIN_PSI_REF_CLK	20
+
+#define STRATIX10_PERI_MPU_BASE_CLK	21
+#define STRATIX10_PERI_NOC_BASE_CLK	22
+#define STRATIX10_PERI_EMACA_CLK	23
+#define STRATIX10_PERI_EMACB_CLK	24
+#define STRATIX10_PERI_EMAC_PTP_CLK	25
+#define STRATIX10_PERI_GPIO_DB_CLK	26
+#define STRATIX10_PERI_SDMMC_CLK	27
+#define STRATIX10_PERI_S2F_USR0_CLK	28
+#define STRATIX10_PERI_S2F_USR1_CLK	29
+#define STRATIX10_PERI_PSI_REF_CLK	30
+
+#define STRATIX10_MPU_FREE_CLK		31
+#define STRATIX10_NOC_FREE_CLK		32
+#define STRATIX10_S2F_USR0_CLK		33
+#define STRATIX10_NOC_CLK		34
+#define STRATIX10_EMAC_A_FREE_CLK	35
+#define STRATIX10_EMAC_B_FREE_CLK	36
+#define STRATIX10_EMAC_PTP_FREE_CLK	37
+#define STRATIX10_GPIO_DB_FREE_CLK	38
+#define STRATIX10_SDMMC_FREE_CLK	39
+#define STRATIX10_S2F_USER1_FREE_CLK	40
+#define STRATIX10_PSI_REF_FREE_CLK	41
+
+/* Gate clocks */
+#define STRATIX10_MPU_CLK		42
+#define STRATIX10_L4_MAIN_CLK		43
+#define STRATIX10_L4_MP_CLK		44
+#define STRATIX10_L4_SP_CLK		45
+#define STRATIX10_CS_AT_CLK		46
+#define STRATIX10_CS_TRACE_CLK		47
+#define STRATIX10_CS_PDBG_CLK		48
+#define STRATIX10_CS_TIMER_CLK		49
+#define STRATIX10_S2F_USER0_CLK		50
+#define STRATIX10_S2F_USER1_CLK		51
+#define STRATIX10_EMAC0_CLK		52
+#define STRATIX10_EMAC1_CLK		53
+#define STRATIX10_EMAC2_CLK		54
+#define STRATIX10_EMAC_PTP_CLK		55
+#define STRATIX10_GPIO_DB_CLK		56
+#define STRATIX10_SDMMC_CLK		57
+#define STRATIX10_PSI_REF_CLK		58
+#define STRATIX10_USB_CLK		59
+#define STRATIX10_SPI_M_CLK		60
+#define STRATIX10_NAND_CLK		61
+#define STRATIX10_NUM_CLKS		62
+
+#endif	/* __STRATIX10_CLOCK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-02-26 14:47 ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: dinguyen, mturquette, sboyd, devicetree, linux-arm-kernel,
	robh+dt, mark.rutland

Document that Stratix10 clock bindings, and add the clock header file. The
clock header is an enumeration of all the different clocks on the Stratix10
platform.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v6:
- no changes
v5:
- moved SPDX license header to single line comment
v4:
- remove '_' in node names
- remove stray tab
- add clock-frequency property for fixed-clocks
- put SPDX license as the very top line
v3:
- s/intc/intel for correct vendor prefix
- fixup node name to "intel,stratix10-clkmgr"
- document the required fixed-clock for oscillators
v2:
- use a single binding for the clock controller
---
 .../devicetree/bindings/clock/intc_stratix10.txt   | 51 +++++++++++++
 include/dt-bindings/clock/stratix10-clock.h        | 84 ++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/intc_stratix10.txt
 create mode 100644 include/dt-bindings/clock/stratix10-clock.h

diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
new file mode 100644
index 0000000..0652ff1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
@@ -0,0 +1,51 @@
+Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be
+	"intel,stratix10-clkmgr"
+
+- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
+
+- #clock-cells : from common clock binding, shall be set to 1.
+
+- clocks : Should contain fixed-clock sources, such as oscillators.
+
+Example:
+	clkmgr: clock-controller@ffd10000 {
+		compatible = "intel,stratix10-clkmgr";
+		reg = <0xffd10000 0x1000>;
+		#clock-cells = <1>;
+
+		clocks {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			cb_intosc_ls_clk: cb-intosc-ls-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			f2s_free_clk: f2s-free-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			osc1: osc1 {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+		};
+	};
diff --git a/include/dt-bindings/clock/stratix10-clock.h b/include/dt-bindings/clock/stratix10-clock.h
new file mode 100644
index 0000000..0ac1c90
--- /dev/null
+++ b/include/dt-bindings/clock/stratix10-clock.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier:	GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef __STRATIX10_CLOCK_H
+#define __STRATIX10_CLOCK_H
+
+/* fixed rate clocks */
+#define STRATIX10_OSC1			0
+#define STRATIX10_CB_INTOSC_HS_DIV2_CLK	1
+#define STRATIX10_CB_INTOSC_LS_CLK	2
+#define STRATIX10_F2S_FREE_CLK		3
+
+/* fixed factor clocks */
+#define STRATIX10_L4_SYS_FREE_CLK	4
+#define STRATIX10_MPU_PERIPH_CLK	5
+#define STRATIX10_MPU_L2RAM_CLK		6
+#define STRATIX10_SDMMC_CIU_CLK		7
+
+/* PLL clocks */
+#define STRATIX10_MAIN_PLL_CLK		8
+#define STRATIX10_PERIPH_PLL_CLK	9
+#define STRATIX10_BOOT_CLK		10
+
+/* Periph clocks */
+#define STRATIX10_MAIN_MPU_BASE_CLK	11
+#define STRATIX10_MAIN_NOC_BASE_CLK	12
+#define STRATIX10_MAIN_EMACA_CLK	13
+#define STRATIX10_MAIN_EMACB_CLK	14
+#define STRATIX10_MAIN_EMAC_PTP_CLK	15
+#define STRATIX10_MAIN_GPIO_DB_CLK	16
+#define STRATIX10_MAIN_SDMMC_CLK	17
+#define STRATIX10_MAIN_S2F_USR0_CLK	18
+#define STRATIX10_MAIN_S2F_USR1_CLK	19
+#define STRATIX10_MAIN_PSI_REF_CLK	20
+
+#define STRATIX10_PERI_MPU_BASE_CLK	21
+#define STRATIX10_PERI_NOC_BASE_CLK	22
+#define STRATIX10_PERI_EMACA_CLK	23
+#define STRATIX10_PERI_EMACB_CLK	24
+#define STRATIX10_PERI_EMAC_PTP_CLK	25
+#define STRATIX10_PERI_GPIO_DB_CLK	26
+#define STRATIX10_PERI_SDMMC_CLK	27
+#define STRATIX10_PERI_S2F_USR0_CLK	28
+#define STRATIX10_PERI_S2F_USR1_CLK	29
+#define STRATIX10_PERI_PSI_REF_CLK	30
+
+#define STRATIX10_MPU_FREE_CLK		31
+#define STRATIX10_NOC_FREE_CLK		32
+#define STRATIX10_S2F_USR0_CLK		33
+#define STRATIX10_NOC_CLK		34
+#define STRATIX10_EMAC_A_FREE_CLK	35
+#define STRATIX10_EMAC_B_FREE_CLK	36
+#define STRATIX10_EMAC_PTP_FREE_CLK	37
+#define STRATIX10_GPIO_DB_FREE_CLK	38
+#define STRATIX10_SDMMC_FREE_CLK	39
+#define STRATIX10_S2F_USER1_FREE_CLK	40
+#define STRATIX10_PSI_REF_FREE_CLK	41
+
+/* Gate clocks */
+#define STRATIX10_MPU_CLK		42
+#define STRATIX10_L4_MAIN_CLK		43
+#define STRATIX10_L4_MP_CLK		44
+#define STRATIX10_L4_SP_CLK		45
+#define STRATIX10_CS_AT_CLK		46
+#define STRATIX10_CS_TRACE_CLK		47
+#define STRATIX10_CS_PDBG_CLK		48
+#define STRATIX10_CS_TIMER_CLK		49
+#define STRATIX10_S2F_USER0_CLK		50
+#define STRATIX10_S2F_USER1_CLK		51
+#define STRATIX10_EMAC0_CLK		52
+#define STRATIX10_EMAC1_CLK		53
+#define STRATIX10_EMAC2_CLK		54
+#define STRATIX10_EMAC_PTP_CLK		55
+#define STRATIX10_GPIO_DB_CLK		56
+#define STRATIX10_SDMMC_CLK		57
+#define STRATIX10_PSI_REF_CLK		58
+#define STRATIX10_USB_CLK		59
+#define STRATIX10_SPI_M_CLK		60
+#define STRATIX10_NAND_CLK		61
+#define STRATIX10_NUM_CLKS		62
+
+#endif	/* __STRATIX10_CLOCK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-02-26 14:47 ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Document that Stratix10 clock bindings, and add the clock header file. The
clock header is an enumeration of all the different clocks on the Stratix10
platform.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v6:
- no changes
v5:
- moved SPDX license header to single line comment
v4:
- remove '_' in node names
- remove stray tab
- add clock-frequency property for fixed-clocks
- put SPDX license as the very top line
v3:
- s/intc/intel for correct vendor prefix
- fixup node name to "intel,stratix10-clkmgr"
- document the required fixed-clock for oscillators
v2:
- use a single binding for the clock controller
---
 .../devicetree/bindings/clock/intc_stratix10.txt   | 51 +++++++++++++
 include/dt-bindings/clock/stratix10-clock.h        | 84 ++++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/intc_stratix10.txt
 create mode 100644 include/dt-bindings/clock/stratix10-clock.h

diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
new file mode 100644
index 0000000..0652ff1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
@@ -0,0 +1,51 @@
+Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be
+	"intel,stratix10-clkmgr"
+
+- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
+
+- #clock-cells : from common clock binding, shall be set to 1.
+
+- clocks : Should contain fixed-clock sources, such as oscillators.
+
+Example:
+	clkmgr: clock-controller at ffd10000 {
+		compatible = "intel,stratix10-clkmgr";
+		reg = <0xffd10000 0x1000>;
+		#clock-cells = <1>;
+
+		clocks {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			cb_intosc_ls_clk: cb-intosc-ls-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			f2s_free_clk: f2s-free-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+
+			osc1: osc1 {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <25000000>;
+			};
+		};
+	};
diff --git a/include/dt-bindings/clock/stratix10-clock.h b/include/dt-bindings/clock/stratix10-clock.h
new file mode 100644
index 0000000..0ac1c90
--- /dev/null
+++ b/include/dt-bindings/clock/stratix10-clock.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier:	GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef __STRATIX10_CLOCK_H
+#define __STRATIX10_CLOCK_H
+
+/* fixed rate clocks */
+#define STRATIX10_OSC1			0
+#define STRATIX10_CB_INTOSC_HS_DIV2_CLK	1
+#define STRATIX10_CB_INTOSC_LS_CLK	2
+#define STRATIX10_F2S_FREE_CLK		3
+
+/* fixed factor clocks */
+#define STRATIX10_L4_SYS_FREE_CLK	4
+#define STRATIX10_MPU_PERIPH_CLK	5
+#define STRATIX10_MPU_L2RAM_CLK		6
+#define STRATIX10_SDMMC_CIU_CLK		7
+
+/* PLL clocks */
+#define STRATIX10_MAIN_PLL_CLK		8
+#define STRATIX10_PERIPH_PLL_CLK	9
+#define STRATIX10_BOOT_CLK		10
+
+/* Periph clocks */
+#define STRATIX10_MAIN_MPU_BASE_CLK	11
+#define STRATIX10_MAIN_NOC_BASE_CLK	12
+#define STRATIX10_MAIN_EMACA_CLK	13
+#define STRATIX10_MAIN_EMACB_CLK	14
+#define STRATIX10_MAIN_EMAC_PTP_CLK	15
+#define STRATIX10_MAIN_GPIO_DB_CLK	16
+#define STRATIX10_MAIN_SDMMC_CLK	17
+#define STRATIX10_MAIN_S2F_USR0_CLK	18
+#define STRATIX10_MAIN_S2F_USR1_CLK	19
+#define STRATIX10_MAIN_PSI_REF_CLK	20
+
+#define STRATIX10_PERI_MPU_BASE_CLK	21
+#define STRATIX10_PERI_NOC_BASE_CLK	22
+#define STRATIX10_PERI_EMACA_CLK	23
+#define STRATIX10_PERI_EMACB_CLK	24
+#define STRATIX10_PERI_EMAC_PTP_CLK	25
+#define STRATIX10_PERI_GPIO_DB_CLK	26
+#define STRATIX10_PERI_SDMMC_CLK	27
+#define STRATIX10_PERI_S2F_USR0_CLK	28
+#define STRATIX10_PERI_S2F_USR1_CLK	29
+#define STRATIX10_PERI_PSI_REF_CLK	30
+
+#define STRATIX10_MPU_FREE_CLK		31
+#define STRATIX10_NOC_FREE_CLK		32
+#define STRATIX10_S2F_USR0_CLK		33
+#define STRATIX10_NOC_CLK		34
+#define STRATIX10_EMAC_A_FREE_CLK	35
+#define STRATIX10_EMAC_B_FREE_CLK	36
+#define STRATIX10_EMAC_PTP_FREE_CLK	37
+#define STRATIX10_GPIO_DB_FREE_CLK	38
+#define STRATIX10_SDMMC_FREE_CLK	39
+#define STRATIX10_S2F_USER1_FREE_CLK	40
+#define STRATIX10_PSI_REF_FREE_CLK	41
+
+/* Gate clocks */
+#define STRATIX10_MPU_CLK		42
+#define STRATIX10_L4_MAIN_CLK		43
+#define STRATIX10_L4_MP_CLK		44
+#define STRATIX10_L4_SP_CLK		45
+#define STRATIX10_CS_AT_CLK		46
+#define STRATIX10_CS_TRACE_CLK		47
+#define STRATIX10_CS_PDBG_CLK		48
+#define STRATIX10_CS_TIMER_CLK		49
+#define STRATIX10_S2F_USER0_CLK		50
+#define STRATIX10_S2F_USER1_CLK		51
+#define STRATIX10_EMAC0_CLK		52
+#define STRATIX10_EMAC1_CLK		53
+#define STRATIX10_EMAC2_CLK		54
+#define STRATIX10_EMAC_PTP_CLK		55
+#define STRATIX10_GPIO_DB_CLK		56
+#define STRATIX10_SDMMC_CLK		57
+#define STRATIX10_PSI_REF_CLK		58
+#define STRATIX10_USB_CLK		59
+#define STRATIX10_SPI_M_CLK		60
+#define STRATIX10_NAND_CLK		61
+#define STRATIX10_NUM_CLKS		62
+
+#endif	/* __STRATIX10_CLOCK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 2/3] arm64: dts: stratix10: use clock bindings for the Stratix10 platform
  2018-02-26 14:47 ` Dinh Nguyen
  (?)
@ 2018-02-26 14:47   ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, sboyd, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Use the clock bindings for the Stratix10 SoC. This includes changing the old
binding of "intc,clk-s10-mgr" to "intel,stratix10-clkmgr". The reason that
this can be done is that there are currently no clock driver for Stratix10,
thus there are no consumers of the old binding. So changing the binding will
not break any legacy code.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- no changes
v5:
- no changes
v4:
- remove '_' in name of clock nodes
- use clock-controller in SoCDK node in dts file
v3:
- use the correct vendor prefix
- explain the binding change
v2:
- use a single clock binding for the clock controller
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi  | 50 +++++++++++++++++++++-
 .../boot/dts/altera/socfpga_stratix10_socdk.dts    | 10 +++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index c89d0c30..5a6a699 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -17,6 +17,7 @@
 /dts-v1/;
 #include <dt-bindings/reset/altr,rst-mgr-s10.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/stratix10-clock.h>
 
 / {
 	compatible = "altr,socfpga-stratix10";
@@ -92,9 +93,35 @@
 		interrupt-parent = <&intc>;
 		ranges = <0 0 0 0xffffffff>;
 
-		clkmgr@ffd1000 {
-			compatible = "altr,clk-mgr";
+		clkmgr: clock-controller@ffd10000 {
+			compatible = "intel,stratix10-clkmgr";
 			reg = <0xffd10000 0x1000>;
+			#clock-cells = <1>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				cb_intosc_ls_clk: cb-intosc-ls-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				f2s_free_clk: f2s-free-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				osc1: osc1 {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+			};
 		};
 
 		gmac0: ethernet@ff800000 {
@@ -105,6 +132,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC0_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC0_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -116,6 +145,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC1_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC1_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -127,6 +158,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC2_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC2_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -229,6 +262,9 @@
 			fifo-depth = <0x400>;
 			resets = <&rst SDMMC_RESET>;
 			reset-names = "reset";
+			clocks = <&clkmgr STRATIX10_L4_MP_CLK>,
+				 <&clkmgr STRATIX10_SDMMC_CLK>;
+			clock-names = "biu", "ciu";
 			status = "disabled";
 		};
 
@@ -288,24 +324,32 @@
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 113 4>;
 			reg = <0xffc03000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer1: timer1@ffc03100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 114 4>;
 			reg = <0xffc03100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer2: timer2@ffd00000 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 115 4>;
 			reg = <0xffd00000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer3: timer3@ffd00100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 116 4>;
 			reg = <0xffd00100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		uart0: serial0@ffc02000 {
@@ -315,6 +359,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART0_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
@@ -325,6 +370,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART1_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
index 0007564..b7f0b6b 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -50,6 +50,16 @@
 		/* We expect the bootloader to fill in the reg */
 		reg = <0 0 0 0>;
 	};
+
+	soc {
+		clock-controller@ffd10000 {
+			clocks {
+				osc1 {
+					clock-frequency = <25000000>;
+				};
+			};
+		};
+	};
 };
 
 &gpio1 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 2/3] arm64: dts: stratix10: use clock bindings for the Stratix10 platform
@ 2018-02-26 14:47   ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: dinguyen, mturquette, sboyd, devicetree, linux-arm-kernel,
	robh+dt, mark.rutland

Use the clock bindings for the Stratix10 SoC. This includes changing the old
binding of "intc,clk-s10-mgr" to "intel,stratix10-clkmgr". The reason that
this can be done is that there are currently no clock driver for Stratix10,
thus there are no consumers of the old binding. So changing the binding will
not break any legacy code.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- no changes
v5:
- no changes
v4:
- remove '_' in name of clock nodes
- use clock-controller in SoCDK node in dts file
v3:
- use the correct vendor prefix
- explain the binding change
v2:
- use a single clock binding for the clock controller
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi  | 50 +++++++++++++++++++++-
 .../boot/dts/altera/socfpga_stratix10_socdk.dts    | 10 +++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index c89d0c30..5a6a699 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -17,6 +17,7 @@
 /dts-v1/;
 #include <dt-bindings/reset/altr,rst-mgr-s10.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/stratix10-clock.h>
 
 / {
 	compatible = "altr,socfpga-stratix10";
@@ -92,9 +93,35 @@
 		interrupt-parent = <&intc>;
 		ranges = <0 0 0 0xffffffff>;
 
-		clkmgr@ffd1000 {
-			compatible = "altr,clk-mgr";
+		clkmgr: clock-controller@ffd10000 {
+			compatible = "intel,stratix10-clkmgr";
 			reg = <0xffd10000 0x1000>;
+			#clock-cells = <1>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				cb_intosc_ls_clk: cb-intosc-ls-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				f2s_free_clk: f2s-free-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				osc1: osc1 {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+			};
 		};
 
 		gmac0: ethernet@ff800000 {
@@ -105,6 +132,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC0_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC0_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -116,6 +145,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC1_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC1_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -127,6 +158,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC2_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC2_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -229,6 +262,9 @@
 			fifo-depth = <0x400>;
 			resets = <&rst SDMMC_RESET>;
 			reset-names = "reset";
+			clocks = <&clkmgr STRATIX10_L4_MP_CLK>,
+				 <&clkmgr STRATIX10_SDMMC_CLK>;
+			clock-names = "biu", "ciu";
 			status = "disabled";
 		};
 
@@ -288,24 +324,32 @@
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 113 4>;
 			reg = <0xffc03000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer1: timer1@ffc03100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 114 4>;
 			reg = <0xffc03100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer2: timer2@ffd00000 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 115 4>;
 			reg = <0xffd00000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer3: timer3@ffd00100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 116 4>;
 			reg = <0xffd00100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		uart0: serial0@ffc02000 {
@@ -315,6 +359,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART0_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
@@ -325,6 +370,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART1_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
index 0007564..b7f0b6b 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -50,6 +50,16 @@
 		/* We expect the bootloader to fill in the reg */
 		reg = <0 0 0 0>;
 	};
+
+	soc {
+		clock-controller@ffd10000 {
+			clocks {
+				osc1 {
+					clock-frequency = <25000000>;
+				};
+			};
+		};
+	};
 };
 
 &gpio1 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 2/3] arm64: dts: stratix10: use clock bindings for the Stratix10 platform
@ 2018-02-26 14:47   ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Use the clock bindings for the Stratix10 SoC. This includes changing the old
binding of "intc,clk-s10-mgr" to "intel,stratix10-clkmgr". The reason that
this can be done is that there are currently no clock driver for Stratix10,
thus there are no consumers of the old binding. So changing the binding will
not break any legacy code.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- no changes
v5:
- no changes
v4:
- remove '_' in name of clock nodes
- use clock-controller in SoCDK node in dts file
v3:
- use the correct vendor prefix
- explain the binding change
v2:
- use a single clock binding for the clock controller
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi  | 50 +++++++++++++++++++++-
 .../boot/dts/altera/socfpga_stratix10_socdk.dts    | 10 +++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index c89d0c30..5a6a699 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -17,6 +17,7 @@
 /dts-v1/;
 #include <dt-bindings/reset/altr,rst-mgr-s10.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/stratix10-clock.h>
 
 / {
 	compatible = "altr,socfpga-stratix10";
@@ -92,9 +93,35 @@
 		interrupt-parent = <&intc>;
 		ranges = <0 0 0 0xffffffff>;
 
-		clkmgr at ffd1000 {
-			compatible = "altr,clk-mgr";
+		clkmgr: clock-controller at ffd10000 {
+			compatible = "intel,stratix10-clkmgr";
 			reg = <0xffd10000 0x1000>;
+			#clock-cells = <1>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				cb_intosc_ls_clk: cb-intosc-ls-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				f2s_free_clk: f2s-free-clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+
+				osc1: osc1 {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+				};
+			};
 		};
 
 		gmac0: ethernet at ff800000 {
@@ -105,6 +132,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC0_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC0_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -116,6 +145,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC1_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC1_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -127,6 +158,8 @@
 			mac-address = [00 00 00 00 00 00];
 			resets = <&rst EMAC2_RESET>;
 			reset-names = "stmmaceth";
+			clocks = <&clkmgr STRATIX10_EMAC2_CLK>;
+			clock-names = "stmmaceth";
 			status = "disabled";
 		};
 
@@ -229,6 +262,9 @@
 			fifo-depth = <0x400>;
 			resets = <&rst SDMMC_RESET>;
 			reset-names = "reset";
+			clocks = <&clkmgr STRATIX10_L4_MP_CLK>,
+				 <&clkmgr STRATIX10_SDMMC_CLK>;
+			clock-names = "biu", "ciu";
 			status = "disabled";
 		};
 
@@ -288,24 +324,32 @@
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 113 4>;
 			reg = <0xffc03000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer1: timer1 at ffc03100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 114 4>;
 			reg = <0xffc03100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer2: timer2 at ffd00000 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 115 4>;
 			reg = <0xffd00000 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		timer3: timer3 at ffd00100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 116 4>;
 			reg = <0xffd00100 0x100>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
+			clock-names = "timer";
 		};
 
 		uart0: serial0 at ffc02000 {
@@ -315,6 +359,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART0_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
@@ -325,6 +370,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			resets = <&rst UART1_RESET>;
+			clocks = <&clkmgr STRATIX10_L4_SP_CLK>;
 			status = "disabled";
 		};
 
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
index 0007564..b7f0b6b 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -50,6 +50,16 @@
 		/* We expect the bootloader to fill in the reg */
 		reg = <0 0 0 0>;
 	};
+
+	soc {
+		clock-controller at ffd10000 {
+			clocks {
+				osc1 {
+					clock-frequency = <25000000>;
+				};
+			};
+		};
+	};
 };
 
 &gpio1 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
  2018-02-26 14:47 ` Dinh Nguyen
  (?)
@ 2018-02-26 14:47   ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, sboyd, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Add a clock driver for the Stratix10 SoC. The driver is similar to the
Cyclone5/Arria10 platforms, with the exception that this driver only uses
one single clock binding.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- minimize usage of strcmp
- use // as comment limiters for SPDX in c source file
v5:
- make SPDX license as a 1st separate first line comment
v4:
- move SPDX license first line of all files
v3:
- use fixed binding "intel,stratix10-clkmgr"
- Fix up SPDX license header
v2:
- Use a single clock binding
---
 drivers/clk/Makefile                 |   1 +
 drivers/clk/socfpga/Makefile         |   5 +
 drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
 drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
 drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
 drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
 drivers/clk/socfpga/clk.h            |   4 +
 drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
 8 files changed, 832 insertions(+)
 create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
 create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
 create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
 create mode 100644 drivers/clk/socfpga/clk-s10.c
 create mode 100644 drivers/clk/socfpga/stratix10-clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71ec41e..80ab422 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
+obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 9146c20..87ef977 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -1,6 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
+ifeq ($(CONFIG_ARCH_SOCFPGA),y)
 obj-y += clk.o
 obj-y += clk-gate.o
 obj-y += clk-pll.o
 obj-y += clk-periph.o
 obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
+else
+obj-y += clk-s10.o
+obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
+endif
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
new file mode 100644
index 0000000..5b09aef
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-s10.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= GENMASK(socfpgaclk->width - 1, 0);
+		div = (1 << val);
+	}
+	return parent_rate / div;
+}
+
+static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+	val &= GENMASK(socfpgaclk->width - 1, 0);
+	div = (1 << val);
+	div = div ? 4 : 1;
+
+	return parent_rate / div;
+}
+
+static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 mask;
+	u8 parent = 0;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			  socfpgaclk->bypass_shift);
+	}
+	return parent;
+}
+
+static struct clk_ops gateclk_ops = {
+	.recalc_rate = socfpga_gate_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+static struct clk_ops dbgclk_ops = {
+	.recalc_rate = socfpga_dbg_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+struct clk *s10_register_gate(char *name, const char *parent_name,
+			      const char * const *parent_names,
+			      u8 num_parents, unsigned long flags,
+			      void __iomem *regbase, unsigned long gate_reg,
+			      unsigned long gate_idx, unsigned long div_reg,
+			      unsigned long div_offset, u8 div_width,
+			      unsigned long bypass_reg, u8 bypass_shift,
+			      u8 fixed_div)
+{
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	struct clk_init_data init;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return NULL;
+
+	socfpga_clk->hw.reg = regbase + gate_reg;
+	socfpga_clk->hw.bit_idx = gate_idx;
+
+	gateclk_ops.enable = clk_gate_ops.enable;
+	gateclk_ops.disable = clk_gate_ops.disable;
+
+	socfpga_clk->fixed_div = fixed_div;
+
+	if (div_reg)
+		socfpga_clk->div_reg = regbase + div_reg;
+	else
+		socfpga_clk->div_reg = NULL;
+
+	socfpga_clk->width = div_width;
+	socfpga_clk->shift = div_offset;
+
+	if (bypass_reg)
+		socfpga_clk->bypass_reg = regbase + bypass_reg;
+	else
+		socfpga_clk->bypass_reg = NULL;
+	socfpga_clk->bypass_shift = bypass_shift;
+
+	if (streq(name, SOCFPGA_CS_PDBG_CLK))
+		init.ops = &dbgclk_ops;
+	else
+		init.ops = &gateclk_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return NULL;
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
new file mode 100644
index 0000000..6021ac1
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT		16
+#define CLK_MGR_FREE_MASK		0x7
+#define SWCTRLBTCLKSEN_SHIFT		8
+
+#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+	u32 val;
+
+	val = readl(socfpgaclk->hw.reg);
+	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
+	parent_rate /= val;
+
+	return parent_rate / div;
+}
+
+static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else {
+		if (!socfpgaclk->bypass_reg)
+			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+	}
+
+	return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	u32 clk_src, mask;
+	u8 parent;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			   socfpgaclk->bypass_shift);
+	} else {
+		clk_src = readl(socfpgaclk->hw.reg);
+		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
+			CLK_MGR_FREE_MASK;
+	}
+	return parent;
+}
+
+static const struct clk_ops peri_c_clk_ops = {
+	.recalc_rate = clk_peri_c_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+static const struct clk_ops peri_cnt_clk_ops = {
+	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+struct clk *s10_register_periph(char *name, const char *parent_name,
+				const char * const *parent_names,
+				u8 num_parents, unsigned long flags,
+				void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	periph_clk->hw.reg = reg + offset;
+
+	init.name = name;
+	init.ops = &peri_c_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
+
+struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
+				    const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *regbase, unsigned long offset,
+				    u8 fixed_divider, unsigned long bypass_reg,
+				    unsigned long bypass_shift)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	if (offset)
+		periph_clk->hw.reg = regbase + offset;
+	else
+		periph_clk->hw.reg = NULL;
+
+	if (bypass_reg)
+		periph_clk->bypass_reg = regbase + bypass_reg;
+	else
+		periph_clk->bypass_reg = NULL;
+	periph_clk->bypass_shift = bypass_shift;
+	periph_clk->fixed_div = fixed_divider;
+
+	init.name = name;
+	init.ops = &peri_cnt_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
new file mode 100644
index 0000000..ef24ca7
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-s10.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+/* PLL Clock enable bits */
+#define SOCFPGA_PLL_POWER		0
+#define SOCFPGA_PLL_RESET_MASK		0x2
+#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
+#define SOCFPGA_PLL_REFDIV_SHIFT	8
+#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
+#define SOCFPGA_PLL_MDIV_SHIFT		24
+#define SWCTRLBTCLKSEL_MASK		0x200
+#define SWCTRLBTCLKSEL_SHIFT		9
+
+#define SOCFPGA_BOOT_CLK		"boot_clk"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long mdiv;
+	unsigned long refdiv;
+	unsigned long reg;
+	unsigned long long vco_freq;
+
+	/* read VCO1 reg for numerator and denominator */
+	reg = readl(socfpgaclk->hw.reg);
+	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate / refdiv;
+
+	/* Read mdiv and fdiv from the fdbck register */
+	reg = readl(socfpgaclk->hw.reg + 0x4);
+	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+
+	return (unsigned long)vco_freq;
+}
+
+static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 div = 1;
+
+	div = ((readl(socfpgaclk->hw.reg) &
+		SWCTRLBTCLKSEL_MASK) >>
+		SWCTRLBTCLKSEL_SHIFT);
+	div += 1;
+	return parent_rate /= div;
+}
+
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+		CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static u8 clk_boot_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
+		SWCTRLBTCLKSEL_MASK;
+}
+
+static int clk_pll_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 reg;
+
+	/* Bring PLL out of reset */
+	reg = readl(socfpgaclk->hw.reg);
+	reg |= SOCFPGA_PLL_RESET_MASK;
+	writel(reg, socfpgaclk->hw.reg);
+
+	return 0;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+static struct clk_ops clk_boot_ops = {
+	.recalc_rate = clk_boot_clk_recalc_rate,
+	.get_parent = clk_boot_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+struct clk *s10_register_pll(const char *name, const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	struct clk_init_data init;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	pll_clk->hw.reg = reg + offset;
+
+	if (streq(name, SOCFPGA_BOOT_CLK))
+		init.ops = &clk_boot_ops;
+	else
+		init.ops = &clk_pll_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
new file mode 100644
index 0000000..31572cb
--- /dev/null
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/stratix10-clock.h>
+
+#include "stratix10-clk.h"
+
+static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
+					"f2s_free_clk",};
+static const char * const cntr_mux[] = { "main_pll", "periph_pll",
+					 "osc1", "cb_intosc_hs_div2_clk",
+					 "f2s_free_clk"};
+static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+
+static const char * const noc_free_mux[] = {"main_noc_base_clk",
+					    "peri_noc_base_clk",
+					    "osc1", "cb_intosc_hs_div2_clk",
+					    "f2s_free_clk"};
+
+static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
+static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
+static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
+static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
+static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
+static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
+static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
+static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
+
+static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
+static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
+
+/* clocks in AO (always on) controller */
+static const struct stratix10_pll_clock s10_pll_clks[] = {
+	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
+	  0x0},
+	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0x74},
+	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0xe4},
+};
+
+static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
+	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
+	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
+	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
+	  0xF4},
+	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
+	  0xF8},
+};
+
+static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
+	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	   0, 0x48, 0, 0, 0},
+	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
+	  0, 0x4C, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x50, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x54, 0, 0, 0},
+	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x58, 0, 0, 0},
+	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x5C, 0, 0, 0},
+	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x60, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0x64, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x68, 0, 0, 0},
+	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x6C, 0, 0, 0},
+	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xBC, 0, 0, 0},
+	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC0, 0, 0, 0},
+	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC4, 0, 0, 0},
+	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC8, 0, 0, 0},
+	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xCC, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD0, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xD4, 0, 0, 0},
+	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD8, 0, 0, 0},
+	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
+	  0, 4, 0, 0},
+	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
+	  0, 0, 0, 0x3C, 1},
+	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
+	  0, 0, 4, 0xB0, 0},
+	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
+	  0, 0, 4, 0xB0, 1},
+	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
+	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
+	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
+	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
+	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
+	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
+	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
+	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
+	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
+};
+
+static const struct stratix10_gate_clock s10_gate_clks[] = {
+	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
+	  0, 0, 0, 0, 0x3C, 0, 0},
+	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 2},
+	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  1, 0x70, 0, 2, 0, 0, 0},
+	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  2, 0x70, 8, 2, 0, 0, 0},
+	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
+	  3, 0x70, 16, 2, 0, 0, 0},
+	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 24, 2, 0, 0, 0},
+	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 26, 2, 0, 0, 0},
+	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 28, 1, 0, 0, 0},
+	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  5, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  0, 0, 0, 0, 0xDC, 26, 0},
+	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  1, 0, 0, 0, 0xDC, 27, 0},
+	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  2, 0, 0, 0, 0xDC, 28, 0},
+	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
+	  3, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
+	  4, 0xE0, 0, 16, 0, 0, 0},
+	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
+	  5, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
+	  7, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  8, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  9, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
+	  10, 0, 0, 0, 0, 0, 0},
+};
+
+static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
+				    int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
+					  clks[i].parent_names, clks[i].num_parents,
+					  clks[i].flags, base, clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+	return 0;
+}
+
+static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
+				      int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
+					      clks[i].parent_names,
+					      clks[i].num_parents,
+					      clks[i].flags, base,
+					      clks[i].offset,
+					      clks[i].fixed_divider,
+					      clks[i].bypass_reg,
+					      clks[i].bypass_shift);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
+					clks[i].parent_names,
+					clks[i].num_parents,
+					clks[i].flags, base,
+					clks[i].gate_reg,
+					clks[i].gate_idx, clks[i].div_reg,
+					clks[i].div_offset, clks[i].div_width,
+					clks[i].bypass_reg,
+					clks[i].bypass_shift,
+					clks[i].fixed_div);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
+				    clks[i].num_parents,
+				    clks[i].flags, base,
+				    clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
+						    int nr_clks)
+{
+	struct stratix10_clock_data *clk_data;
+	struct clk **clk_table;
+	void __iomem *base;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: failed to map clock registers\n", __func__);
+		goto err;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->base = base;
+	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
+	if (!clk_table)
+		goto err_data;
+
+	clk_data->clk_data.clks = clk_table;
+	clk_data->clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+	return clk_data;
+
+err_data:
+	kfree(clk_data);
+err:
+	return NULL;
+}
+
+
+void __init socfpga_s10_init(struct device_node *node)
+{
+	struct stratix10_clock_data *clk_data;
+
+	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
+	if (!clk_data)
+		return;
+
+	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
+
+	s10_clk_register_c_perip(s10_main_perip_c_clks,
+				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
+
+	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
+				   ARRAY_SIZE(s10_main_perip_cnt_clks),
+				   clk_data);
+
+	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
+			      clk_data);
+}
+
+CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index 9cf1230..26c3a26 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -54,9 +54,11 @@ struct socfpga_gate_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	struct regmap *sys_mgr_base_addr;
 	u32 width;	/* only valid if div_reg != 0 */
 	u32 shift;	/* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 	u32 clk_phase[2];
 };
 
@@ -65,8 +67,10 @@ struct socfpga_periph_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	u32 width;      /* only valid if div_reg != 0 */
 	u32 shift;      /* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 };
 
 #endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
new file mode 100644
index 0000000..10f1532
--- /dev/null
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier:    GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef	__STRATIX10_CLK_H
+#define	__STRATIX10_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+struct platform_device;
+
+struct stratix10_clock_data {
+	struct clk_onecell_data	clk_data;
+	void __iomem		*base;
+};
+
+struct stratix10_pll_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_c_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_cnt_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			fixed_divider;
+	unsigned long		bypass_reg;
+	unsigned long		bypass_shift;
+};
+
+struct stratix10_gate_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		gate_reg;
+	u8			gate_idx;
+	unsigned long		div_reg;
+	u8			div_offset;
+	u8			div_width;
+	unsigned long		bypass_reg;
+	u8			bypass_shift;
+	u8			fixed_div;
+};
+
+struct clk *s10_register_pll(const char *, const char *const *, u8,
+			     unsigned long, void __iomem *, unsigned long);
+
+struct clk *s10_register_periph(const char *, const char *,
+				const char * const *, u8, unsigned long,
+				void __iomem *, unsigned long);
+struct clk *s10_register_cnt_periph(const char *, const char *,
+				    const char * const *, u8,
+				    unsigned long, void __iomem *,
+				    unsigned long, u8, unsigned long,
+				    unsigned long);
+struct clk *s10_register_gate(const char *, const char *,
+			      const char * const *, u8,
+			      unsigned long, void __iomem *,
+			      unsigned long, unsigned long,
+			      unsigned long, unsigned long, u8,
+			      unsigned long, unsigned long, u8);
+#endif	/* __STRATIX10_CLK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-02-26 14:47   ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-clk
  Cc: dinguyen, mturquette, sboyd, devicetree, linux-arm-kernel,
	robh+dt, mark.rutland

Add a clock driver for the Stratix10 SoC. The driver is similar to the
Cyclone5/Arria10 platforms, with the exception that this driver only uses
one single clock binding.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- minimize usage of strcmp
- use // as comment limiters for SPDX in c source file
v5:
- make SPDX license as a 1st separate first line comment
v4:
- move SPDX license first line of all files
v3:
- use fixed binding "intel,stratix10-clkmgr"
- Fix up SPDX license header
v2:
- Use a single clock binding
---
 drivers/clk/Makefile                 |   1 +
 drivers/clk/socfpga/Makefile         |   5 +
 drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
 drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
 drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
 drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
 drivers/clk/socfpga/clk.h            |   4 +
 drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
 8 files changed, 832 insertions(+)
 create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
 create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
 create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
 create mode 100644 drivers/clk/socfpga/clk-s10.c
 create mode 100644 drivers/clk/socfpga/stratix10-clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71ec41e..80ab422 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
+obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 9146c20..87ef977 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -1,6 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
+ifeq ($(CONFIG_ARCH_SOCFPGA),y)
 obj-y += clk.o
 obj-y += clk-gate.o
 obj-y += clk-pll.o
 obj-y += clk-periph.o
 obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
+else
+obj-y += clk-s10.o
+obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
+endif
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
new file mode 100644
index 0000000..5b09aef
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-s10.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= GENMASK(socfpgaclk->width - 1, 0);
+		div = (1 << val);
+	}
+	return parent_rate / div;
+}
+
+static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+	val &= GENMASK(socfpgaclk->width - 1, 0);
+	div = (1 << val);
+	div = div ? 4 : 1;
+
+	return parent_rate / div;
+}
+
+static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 mask;
+	u8 parent = 0;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			  socfpgaclk->bypass_shift);
+	}
+	return parent;
+}
+
+static struct clk_ops gateclk_ops = {
+	.recalc_rate = socfpga_gate_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+static struct clk_ops dbgclk_ops = {
+	.recalc_rate = socfpga_dbg_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+struct clk *s10_register_gate(char *name, const char *parent_name,
+			      const char * const *parent_names,
+			      u8 num_parents, unsigned long flags,
+			      void __iomem *regbase, unsigned long gate_reg,
+			      unsigned long gate_idx, unsigned long div_reg,
+			      unsigned long div_offset, u8 div_width,
+			      unsigned long bypass_reg, u8 bypass_shift,
+			      u8 fixed_div)
+{
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	struct clk_init_data init;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return NULL;
+
+	socfpga_clk->hw.reg = regbase + gate_reg;
+	socfpga_clk->hw.bit_idx = gate_idx;
+
+	gateclk_ops.enable = clk_gate_ops.enable;
+	gateclk_ops.disable = clk_gate_ops.disable;
+
+	socfpga_clk->fixed_div = fixed_div;
+
+	if (div_reg)
+		socfpga_clk->div_reg = regbase + div_reg;
+	else
+		socfpga_clk->div_reg = NULL;
+
+	socfpga_clk->width = div_width;
+	socfpga_clk->shift = div_offset;
+
+	if (bypass_reg)
+		socfpga_clk->bypass_reg = regbase + bypass_reg;
+	else
+		socfpga_clk->bypass_reg = NULL;
+	socfpga_clk->bypass_shift = bypass_shift;
+
+	if (streq(name, SOCFPGA_CS_PDBG_CLK))
+		init.ops = &dbgclk_ops;
+	else
+		init.ops = &gateclk_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return NULL;
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
new file mode 100644
index 0000000..6021ac1
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT		16
+#define CLK_MGR_FREE_MASK		0x7
+#define SWCTRLBTCLKSEN_SHIFT		8
+
+#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+	u32 val;
+
+	val = readl(socfpgaclk->hw.reg);
+	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
+	parent_rate /= val;
+
+	return parent_rate / div;
+}
+
+static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else {
+		if (!socfpgaclk->bypass_reg)
+			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+	}
+
+	return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	u32 clk_src, mask;
+	u8 parent;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			   socfpgaclk->bypass_shift);
+	} else {
+		clk_src = readl(socfpgaclk->hw.reg);
+		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
+			CLK_MGR_FREE_MASK;
+	}
+	return parent;
+}
+
+static const struct clk_ops peri_c_clk_ops = {
+	.recalc_rate = clk_peri_c_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+static const struct clk_ops peri_cnt_clk_ops = {
+	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+struct clk *s10_register_periph(char *name, const char *parent_name,
+				const char * const *parent_names,
+				u8 num_parents, unsigned long flags,
+				void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	periph_clk->hw.reg = reg + offset;
+
+	init.name = name;
+	init.ops = &peri_c_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
+
+struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
+				    const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *regbase, unsigned long offset,
+				    u8 fixed_divider, unsigned long bypass_reg,
+				    unsigned long bypass_shift)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	if (offset)
+		periph_clk->hw.reg = regbase + offset;
+	else
+		periph_clk->hw.reg = NULL;
+
+	if (bypass_reg)
+		periph_clk->bypass_reg = regbase + bypass_reg;
+	else
+		periph_clk->bypass_reg = NULL;
+	periph_clk->bypass_shift = bypass_shift;
+	periph_clk->fixed_div = fixed_divider;
+
+	init.name = name;
+	init.ops = &peri_cnt_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
new file mode 100644
index 0000000..ef24ca7
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-s10.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+/* PLL Clock enable bits */
+#define SOCFPGA_PLL_POWER		0
+#define SOCFPGA_PLL_RESET_MASK		0x2
+#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
+#define SOCFPGA_PLL_REFDIV_SHIFT	8
+#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
+#define SOCFPGA_PLL_MDIV_SHIFT		24
+#define SWCTRLBTCLKSEL_MASK		0x200
+#define SWCTRLBTCLKSEL_SHIFT		9
+
+#define SOCFPGA_BOOT_CLK		"boot_clk"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long mdiv;
+	unsigned long refdiv;
+	unsigned long reg;
+	unsigned long long vco_freq;
+
+	/* read VCO1 reg for numerator and denominator */
+	reg = readl(socfpgaclk->hw.reg);
+	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate / refdiv;
+
+	/* Read mdiv and fdiv from the fdbck register */
+	reg = readl(socfpgaclk->hw.reg + 0x4);
+	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+
+	return (unsigned long)vco_freq;
+}
+
+static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 div = 1;
+
+	div = ((readl(socfpgaclk->hw.reg) &
+		SWCTRLBTCLKSEL_MASK) >>
+		SWCTRLBTCLKSEL_SHIFT);
+	div += 1;
+	return parent_rate /= div;
+}
+
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+		CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static u8 clk_boot_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
+		SWCTRLBTCLKSEL_MASK;
+}
+
+static int clk_pll_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 reg;
+
+	/* Bring PLL out of reset */
+	reg = readl(socfpgaclk->hw.reg);
+	reg |= SOCFPGA_PLL_RESET_MASK;
+	writel(reg, socfpgaclk->hw.reg);
+
+	return 0;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+static struct clk_ops clk_boot_ops = {
+	.recalc_rate = clk_boot_clk_recalc_rate,
+	.get_parent = clk_boot_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+struct clk *s10_register_pll(const char *name, const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	struct clk_init_data init;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	pll_clk->hw.reg = reg + offset;
+
+	if (streq(name, SOCFPGA_BOOT_CLK))
+		init.ops = &clk_boot_ops;
+	else
+		init.ops = &clk_pll_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
new file mode 100644
index 0000000..31572cb
--- /dev/null
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/stratix10-clock.h>
+
+#include "stratix10-clk.h"
+
+static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
+					"f2s_free_clk",};
+static const char * const cntr_mux[] = { "main_pll", "periph_pll",
+					 "osc1", "cb_intosc_hs_div2_clk",
+					 "f2s_free_clk"};
+static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+
+static const char * const noc_free_mux[] = {"main_noc_base_clk",
+					    "peri_noc_base_clk",
+					    "osc1", "cb_intosc_hs_div2_clk",
+					    "f2s_free_clk"};
+
+static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
+static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
+static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
+static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
+static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
+static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
+static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
+static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
+
+static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
+static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
+
+/* clocks in AO (always on) controller */
+static const struct stratix10_pll_clock s10_pll_clks[] = {
+	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
+	  0x0},
+	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0x74},
+	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0xe4},
+};
+
+static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
+	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
+	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
+	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
+	  0xF4},
+	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
+	  0xF8},
+};
+
+static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
+	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	   0, 0x48, 0, 0, 0},
+	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
+	  0, 0x4C, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x50, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x54, 0, 0, 0},
+	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x58, 0, 0, 0},
+	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x5C, 0, 0, 0},
+	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x60, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0x64, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x68, 0, 0, 0},
+	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x6C, 0, 0, 0},
+	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xBC, 0, 0, 0},
+	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC0, 0, 0, 0},
+	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC4, 0, 0, 0},
+	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC8, 0, 0, 0},
+	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xCC, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD0, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xD4, 0, 0, 0},
+	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD8, 0, 0, 0},
+	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
+	  0, 4, 0, 0},
+	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
+	  0, 0, 0, 0x3C, 1},
+	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
+	  0, 0, 4, 0xB0, 0},
+	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
+	  0, 0, 4, 0xB0, 1},
+	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
+	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
+	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
+	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
+	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
+	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
+	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
+	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
+	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
+};
+
+static const struct stratix10_gate_clock s10_gate_clks[] = {
+	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
+	  0, 0, 0, 0, 0x3C, 0, 0},
+	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 2},
+	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  1, 0x70, 0, 2, 0, 0, 0},
+	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  2, 0x70, 8, 2, 0, 0, 0},
+	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
+	  3, 0x70, 16, 2, 0, 0, 0},
+	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 24, 2, 0, 0, 0},
+	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 26, 2, 0, 0, 0},
+	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 28, 1, 0, 0, 0},
+	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  5, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  0, 0, 0, 0, 0xDC, 26, 0},
+	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  1, 0, 0, 0, 0xDC, 27, 0},
+	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  2, 0, 0, 0, 0xDC, 28, 0},
+	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
+	  3, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
+	  4, 0xE0, 0, 16, 0, 0, 0},
+	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
+	  5, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
+	  7, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  8, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  9, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
+	  10, 0, 0, 0, 0, 0, 0},
+};
+
+static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
+				    int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
+					  clks[i].parent_names, clks[i].num_parents,
+					  clks[i].flags, base, clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+	return 0;
+}
+
+static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
+				      int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
+					      clks[i].parent_names,
+					      clks[i].num_parents,
+					      clks[i].flags, base,
+					      clks[i].offset,
+					      clks[i].fixed_divider,
+					      clks[i].bypass_reg,
+					      clks[i].bypass_shift);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
+					clks[i].parent_names,
+					clks[i].num_parents,
+					clks[i].flags, base,
+					clks[i].gate_reg,
+					clks[i].gate_idx, clks[i].div_reg,
+					clks[i].div_offset, clks[i].div_width,
+					clks[i].bypass_reg,
+					clks[i].bypass_shift,
+					clks[i].fixed_div);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
+				    clks[i].num_parents,
+				    clks[i].flags, base,
+				    clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
+						    int nr_clks)
+{
+	struct stratix10_clock_data *clk_data;
+	struct clk **clk_table;
+	void __iomem *base;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: failed to map clock registers\n", __func__);
+		goto err;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->base = base;
+	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
+	if (!clk_table)
+		goto err_data;
+
+	clk_data->clk_data.clks = clk_table;
+	clk_data->clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+	return clk_data;
+
+err_data:
+	kfree(clk_data);
+err:
+	return NULL;
+}
+
+
+void __init socfpga_s10_init(struct device_node *node)
+{
+	struct stratix10_clock_data *clk_data;
+
+	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
+	if (!clk_data)
+		return;
+
+	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
+
+	s10_clk_register_c_perip(s10_main_perip_c_clks,
+				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
+
+	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
+				   ARRAY_SIZE(s10_main_perip_cnt_clks),
+				   clk_data);
+
+	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
+			      clk_data);
+}
+
+CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index 9cf1230..26c3a26 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -54,9 +54,11 @@ struct socfpga_gate_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	struct regmap *sys_mgr_base_addr;
 	u32 width;	/* only valid if div_reg != 0 */
 	u32 shift;	/* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 	u32 clk_phase[2];
 };
 
@@ -65,8 +67,10 @@ struct socfpga_periph_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	u32 width;      /* only valid if div_reg != 0 */
 	u32 shift;      /* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 };
 
 #endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
new file mode 100644
index 0000000..10f1532
--- /dev/null
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier:    GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef	__STRATIX10_CLK_H
+#define	__STRATIX10_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+struct platform_device;
+
+struct stratix10_clock_data {
+	struct clk_onecell_data	clk_data;
+	void __iomem		*base;
+};
+
+struct stratix10_pll_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_c_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_cnt_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			fixed_divider;
+	unsigned long		bypass_reg;
+	unsigned long		bypass_shift;
+};
+
+struct stratix10_gate_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		gate_reg;
+	u8			gate_idx;
+	unsigned long		div_reg;
+	u8			div_offset;
+	u8			div_width;
+	unsigned long		bypass_reg;
+	u8			bypass_shift;
+	u8			fixed_div;
+};
+
+struct clk *s10_register_pll(const char *, const char *const *, u8,
+			     unsigned long, void __iomem *, unsigned long);
+
+struct clk *s10_register_periph(const char *, const char *,
+				const char * const *, u8, unsigned long,
+				void __iomem *, unsigned long);
+struct clk *s10_register_cnt_periph(const char *, const char *,
+				    const char * const *, u8,
+				    unsigned long, void __iomem *,
+				    unsigned long, u8, unsigned long,
+				    unsigned long);
+struct clk *s10_register_gate(const char *, const char *,
+			      const char * const *, u8,
+			      unsigned long, void __iomem *,
+			      unsigned long, unsigned long,
+			      unsigned long, unsigned long, u8,
+			      unsigned long, unsigned long, u8);
+#endif	/* __STRATIX10_CLK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-02-26 14:47   ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-02-26 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Add a clock driver for the Stratix10 SoC. The driver is similar to the
Cyclone5/Arria10 platforms, with the exception that this driver only uses
one single clock binding.

Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v6:
- minimize usage of strcmp
- use // as comment limiters for SPDX in c source file
v5:
- make SPDX license as a 1st separate first line comment
v4:
- move SPDX license first line of all files
v3:
- use fixed binding "intel,stratix10-clkmgr"
- Fix up SPDX license header
v2:
- Use a single clock binding
---
 drivers/clk/Makefile                 |   1 +
 drivers/clk/socfpga/Makefile         |   5 +
 drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
 drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
 drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
 drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
 drivers/clk/socfpga/clk.h            |   4 +
 drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
 8 files changed, 832 insertions(+)
 create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
 create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
 create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
 create mode 100644 drivers/clk/socfpga/clk-s10.c
 create mode 100644 drivers/clk/socfpga/stratix10-clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71ec41e..80ab422 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
+obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 9146c20..87ef977 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -1,6 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
+ifeq ($(CONFIG_ARCH_SOCFPGA),y)
 obj-y += clk.o
 obj-y += clk-gate.o
 obj-y += clk-pll.o
 obj-y += clk-periph.o
 obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
+else
+obj-y += clk-s10.o
+obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
+endif
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
new file mode 100644
index 0000000..5b09aef
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-s10.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include "clk.h"
+
+#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= GENMASK(socfpgaclk->width - 1, 0);
+		div = (1 << val);
+	}
+	return parent_rate / div;
+}
+
+static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
+						  unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+	val &= GENMASK(socfpgaclk->width - 1, 0);
+	div = (1 << val);
+	div = div ? 4 : 1;
+
+	return parent_rate / div;
+}
+
+static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 mask;
+	u8 parent = 0;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			  socfpgaclk->bypass_shift);
+	}
+	return parent;
+}
+
+static struct clk_ops gateclk_ops = {
+	.recalc_rate = socfpga_gate_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+static struct clk_ops dbgclk_ops = {
+	.recalc_rate = socfpga_dbg_clk_recalc_rate,
+	.get_parent = socfpga_gate_get_parent,
+};
+
+struct clk *s10_register_gate(char *name, const char *parent_name,
+			      const char * const *parent_names,
+			      u8 num_parents, unsigned long flags,
+			      void __iomem *regbase, unsigned long gate_reg,
+			      unsigned long gate_idx, unsigned long div_reg,
+			      unsigned long div_offset, u8 div_width,
+			      unsigned long bypass_reg, u8 bypass_shift,
+			      u8 fixed_div)
+{
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	struct clk_init_data init;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return NULL;
+
+	socfpga_clk->hw.reg = regbase + gate_reg;
+	socfpga_clk->hw.bit_idx = gate_idx;
+
+	gateclk_ops.enable = clk_gate_ops.enable;
+	gateclk_ops.disable = clk_gate_ops.disable;
+
+	socfpga_clk->fixed_div = fixed_div;
+
+	if (div_reg)
+		socfpga_clk->div_reg = regbase + div_reg;
+	else
+		socfpga_clk->div_reg = NULL;
+
+	socfpga_clk->width = div_width;
+	socfpga_clk->shift = div_offset;
+
+	if (bypass_reg)
+		socfpga_clk->bypass_reg = regbase + bypass_reg;
+	else
+		socfpga_clk->bypass_reg = NULL;
+	socfpga_clk->bypass_shift = bypass_shift;
+
+	if (streq(name, SOCFPGA_CS_PDBG_CLK))
+		init.ops = &dbgclk_ops;
+	else
+		init.ops = &gateclk_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return NULL;
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
new file mode 100644
index 0000000..6021ac1
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT		16
+#define CLK_MGR_FREE_MASK		0x7
+#define SWCTRLBTCLKSEN_SHIFT		8
+
+#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+	u32 val;
+
+	val = readl(socfpgaclk->hw.reg);
+	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
+	parent_rate /= val;
+
+	return parent_rate / div;
+}
+
+static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	unsigned long div = 1;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else {
+		if (!socfpgaclk->bypass_reg)
+			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+	}
+
+	return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+	u32 clk_src, mask;
+	u8 parent;
+
+	if (socfpgaclk->bypass_reg) {
+		mask = (0x1 << socfpgaclk->bypass_shift);
+		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+			   socfpgaclk->bypass_shift);
+	} else {
+		clk_src = readl(socfpgaclk->hw.reg);
+		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
+			CLK_MGR_FREE_MASK;
+	}
+	return parent;
+}
+
+static const struct clk_ops peri_c_clk_ops = {
+	.recalc_rate = clk_peri_c_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+static const struct clk_ops peri_cnt_clk_ops = {
+	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+struct clk *s10_register_periph(char *name, const char *parent_name,
+				const char * const *parent_names,
+				u8 num_parents, unsigned long flags,
+				void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	periph_clk->hw.reg = reg + offset;
+
+	init.name = name;
+	init.ops = &peri_c_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
+
+struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
+				    const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *regbase, unsigned long offset,
+				    u8 fixed_divider, unsigned long bypass_reg,
+				    unsigned long bypass_shift)
+{
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	struct clk_init_data init;
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return NULL;
+
+	if (offset)
+		periph_clk->hw.reg = regbase + offset;
+	else
+		periph_clk->hw.reg = NULL;
+
+	if (bypass_reg)
+		periph_clk->bypass_reg = regbase + bypass_reg;
+	else
+		periph_clk->bypass_reg = NULL;
+	periph_clk->bypass_shift = bypass_shift;
+	periph_clk->fixed_div = fixed_divider;
+
+	init.name = name;
+	init.ops = &peri_cnt_clk_ops;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names ? parent_names : &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
new file mode 100644
index 0000000..ef24ca7
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-s10.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+/* PLL Clock enable bits */
+#define SOCFPGA_PLL_POWER		0
+#define SOCFPGA_PLL_RESET_MASK		0x2
+#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
+#define SOCFPGA_PLL_REFDIV_SHIFT	8
+#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
+#define SOCFPGA_PLL_MDIV_SHIFT		24
+#define SWCTRLBTCLKSEL_MASK		0x200
+#define SWCTRLBTCLKSEL_SHIFT		9
+
+#define SOCFPGA_BOOT_CLK		"boot_clk"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long mdiv;
+	unsigned long refdiv;
+	unsigned long reg;
+	unsigned long long vco_freq;
+
+	/* read VCO1 reg for numerator and denominator */
+	reg = readl(socfpgaclk->hw.reg);
+	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate / refdiv;
+
+	/* Read mdiv and fdiv from the fdbck register */
+	reg = readl(socfpgaclk->hw.reg + 0x4);
+	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+
+	return (unsigned long)vco_freq;
+}
+
+static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 div = 1;
+
+	div = ((readl(socfpgaclk->hw.reg) &
+		SWCTRLBTCLKSEL_MASK) >>
+		SWCTRLBTCLKSEL_SHIFT);
+	div += 1;
+	return parent_rate /= div;
+}
+
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+		CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static u8 clk_boot_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
+		SWCTRLBTCLKSEL_MASK;
+}
+
+static int clk_pll_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 reg;
+
+	/* Bring PLL out of reset */
+	reg = readl(socfpgaclk->hw.reg);
+	reg |= SOCFPGA_PLL_RESET_MASK;
+	writel(reg, socfpgaclk->hw.reg);
+
+	return 0;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+static struct clk_ops clk_boot_ops = {
+	.recalc_rate = clk_boot_clk_recalc_rate,
+	.get_parent = clk_boot_get_parent,
+	.prepare = clk_pll_prepare,
+};
+
+struct clk *s10_register_pll(const char *name, const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    void __iomem *reg, unsigned long offset)
+{
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	struct clk_init_data init;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	pll_clk->hw.reg = reg + offset;
+
+	if (streq(name, SOCFPGA_BOOT_CLK))
+		init.ops = &clk_boot_ops;
+	else
+		init.ops = &clk_pll_ops;
+
+	init.name = name;
+	init.flags = flags;
+
+	init.num_parents = num_parents;
+	init.parent_names = parent_names;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	return clk;
+}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
new file mode 100644
index 0000000..31572cb
--- /dev/null
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier:	GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/stratix10-clock.h>
+
+#include "stratix10-clk.h"
+
+static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
+					"f2s_free_clk",};
+static const char * const cntr_mux[] = { "main_pll", "periph_pll",
+					 "osc1", "cb_intosc_hs_div2_clk",
+					 "f2s_free_clk"};
+static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+
+static const char * const noc_free_mux[] = {"main_noc_base_clk",
+					    "peri_noc_base_clk",
+					    "osc1", "cb_intosc_hs_div2_clk",
+					    "f2s_free_clk"};
+
+static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
+static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
+static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
+static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
+static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
+static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
+static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
+static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
+
+static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
+static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
+
+/* clocks in AO (always on) controller */
+static const struct stratix10_pll_clock s10_pll_clks[] = {
+	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
+	  0x0},
+	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0x74},
+	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
+	  0, 0xe4},
+};
+
+static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
+	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
+	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
+	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
+	  0xF4},
+	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
+	  0xF8},
+};
+
+static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
+	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	   0, 0x48, 0, 0, 0},
+	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
+	  0, 0x4C, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x50, 0, 0, 0},
+	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x54, 0, 0, 0},
+	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x58, 0, 0, 0},
+	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x5C, 0, 0, 0},
+	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x60, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0x64, 0, 0, 0},
+	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x68, 0, 0, 0},
+	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
+	  0x6C, 0, 0, 0},
+	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xBC, 0, 0, 0},
+	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC0, 0, 0, 0},
+	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC4, 0, 0, 0},
+	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xC8, 0, 0, 0},
+	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xCC, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD0, 0, 0, 0},
+	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+	  0, 0xD4, 0, 0, 0},
+	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
+	  0xD8, 0, 0, 0},
+	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
+	  0, 4, 0, 0},
+	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
+	  0, 0, 0, 0x3C, 1},
+	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
+	  0, 0, 4, 0xB0, 0},
+	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
+	  0, 0, 4, 0xB0, 1},
+	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
+	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
+	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
+	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
+	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
+	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
+	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
+	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
+	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
+};
+
+static const struct stratix10_gate_clock s10_gate_clks[] = {
+	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
+	  0, 0, 0, 0, 0x3C, 0, 0},
+	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
+	  0, 0, 0, 0, 0, 0, 2},
+	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  1, 0x70, 0, 2, 0, 0, 0},
+	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  2, 0x70, 8, 2, 0, 0, 0},
+	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
+	  3, 0x70, 16, 2, 0, 0, 0},
+	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 24, 2, 0, 0, 0},
+	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 26, 2, 0, 0, 0},
+	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
+	  4, 0x70, 28, 1, 0, 0, 0},
+	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
+	  5, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  0, 0, 0, 0, 0xDC, 26, 0},
+	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  1, 0, 0, 0, 0xDC, 27, 0},
+	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+	  2, 0, 0, 0, 0xDC, 28, 0},
+	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
+	  3, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
+	  4, 0xE0, 0, 16, 0, 0, 0},
+	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
+	  5, 0, 0, 0, 0, 0, 4},
+	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
+	  6, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
+	  7, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  8, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+	  9, 0, 0, 0, 0, 0, 0},
+	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
+	  10, 0, 0, 0, 0, 0, 0},
+};
+
+static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
+				    int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
+					  clks[i].parent_names, clks[i].num_parents,
+					  clks[i].flags, base, clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+	return 0;
+}
+
+static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
+				      int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
+					      clks[i].parent_names,
+					      clks[i].num_parents,
+					      clks[i].flags, base,
+					      clks[i].offset,
+					      clks[i].fixed_divider,
+					      clks[i].bypass_reg,
+					      clks[i].bypass_shift);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
+					clks[i].parent_names,
+					clks[i].num_parents,
+					clks[i].flags, base,
+					clks[i].gate_reg,
+					clks[i].gate_idx, clks[i].div_reg,
+					clks[i].div_offset, clks[i].div_width,
+					clks[i].bypass_reg,
+					clks[i].bypass_shift,
+					clks[i].fixed_div);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
+				 int nums, struct stratix10_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
+				    clks[i].num_parents,
+				    clks[i].flags, base,
+				    clks[i].offset);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+
+	return 0;
+}
+
+struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
+						    int nr_clks)
+{
+	struct stratix10_clock_data *clk_data;
+	struct clk **clk_table;
+	void __iomem *base;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: failed to map clock registers\n", __func__);
+		goto err;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->base = base;
+	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
+	if (!clk_table)
+		goto err_data;
+
+	clk_data->clk_data.clks = clk_table;
+	clk_data->clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+	return clk_data;
+
+err_data:
+	kfree(clk_data);
+err:
+	return NULL;
+}
+
+
+void __init socfpga_s10_init(struct device_node *node)
+{
+	struct stratix10_clock_data *clk_data;
+
+	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
+	if (!clk_data)
+		return;
+
+	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
+
+	s10_clk_register_c_perip(s10_main_perip_c_clks,
+				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
+
+	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
+				   ARRAY_SIZE(s10_main_perip_cnt_clks),
+				   clk_data);
+
+	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
+			      clk_data);
+}
+
+CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index 9cf1230..26c3a26 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -54,9 +54,11 @@ struct socfpga_gate_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	struct regmap *sys_mgr_base_addr;
 	u32 width;	/* only valid if div_reg != 0 */
 	u32 shift;	/* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 	u32 clk_phase[2];
 };
 
@@ -65,8 +67,10 @@ struct socfpga_periph_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	void __iomem *bypass_reg;
 	u32 width;      /* only valid if div_reg != 0 */
 	u32 shift;      /* only valid if div_reg != 0 */
+	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 };
 
 #endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
new file mode 100644
index 0000000..10f1532
--- /dev/null
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier:    GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef	__STRATIX10_CLK_H
+#define	__STRATIX10_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+struct platform_device;
+
+struct stratix10_clock_data {
+	struct clk_onecell_data	clk_data;
+	void __iomem		*base;
+};
+
+struct stratix10_pll_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_c_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+};
+
+struct stratix10_perip_cnt_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			fixed_divider;
+	unsigned long		bypass_reg;
+	unsigned long		bypass_shift;
+};
+
+struct stratix10_gate_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	const char		*const *parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		gate_reg;
+	u8			gate_idx;
+	unsigned long		div_reg;
+	u8			div_offset;
+	u8			div_width;
+	unsigned long		bypass_reg;
+	u8			bypass_shift;
+	u8			fixed_div;
+};
+
+struct clk *s10_register_pll(const char *, const char *const *, u8,
+			     unsigned long, void __iomem *, unsigned long);
+
+struct clk *s10_register_periph(const char *, const char *,
+				const char * const *, u8, unsigned long,
+				void __iomem *, unsigned long);
+struct clk *s10_register_cnt_periph(const char *, const char *,
+				    const char * const *, u8,
+				    unsigned long, void __iomem *,
+				    unsigned long, u8, unsigned long,
+				    unsigned long);
+struct clk *s10_register_gate(const char *, const char *,
+			      const char * const *, u8,
+			      unsigned long, void __iomem *,
+			      unsigned long, unsigned long,
+			      unsigned long, unsigned long, u8,
+			      unsigned long, unsigned long, u8);
+#endif	/* __STRATIX10_CLK_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
  2018-02-26 14:47   ` Dinh Nguyen
  (?)
@ 2018-03-05 15:16     ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-05 15:16 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, sboyd, mturquette, robh+dt, linux-arm-kernel

Hi Mike and Stephen,

Was wondering if you can review this patch when you get a chance?

Thanks so much,

Dinh

On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
> Add a clock driver for the Stratix10 SoC. The driver is similar to the
> Cyclone5/Arria10 platforms, with the exception that this driver only uses
> one single clock binding.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
> ---
> v6:
> - minimize usage of strcmp
> - use // as comment limiters for SPDX in c source file
> v5:
> - make SPDX license as a 1st separate first line comment
> v4:
> - move SPDX license first line of all files
> v3:
> - use fixed binding "intel,stratix10-clkmgr"
> - Fix up SPDX license header
> v2:
> - Use a single clock binding
> ---
>  drivers/clk/Makefile                 |   1 +
>  drivers/clk/socfpga/Makefile         |   5 +
>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>  drivers/clk/socfpga/clk.h            |   4 +
>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>  8 files changed, 832 insertions(+)
>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71ec41e..80ab422 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>  obj-$(CONFIG_ARCH_STI)			+= st/
> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>  obj-y += clk.o
>  obj-y += clk-gate.o
>  obj-y += clk-pll.o
>  obj-y += clk-periph.o
>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y += clk-s10.o
> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else if (socfpgaclk->div_reg) {
> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +		val &= GENMASK(socfpgaclk->width - 1, 0);
> +		div = (1 << val);
> +	}
> +	return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +	val &= GENMASK(socfpgaclk->width - 1, 0);
> +	div = (1 << val);
> +	div = div ? 4 : 1;
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 mask;
> +	u8 parent = 0;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			  socfpgaclk->bypass_shift);
> +	}
> +	return parent;
> +}
> +
> +static struct clk_ops gateclk_ops = {
> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops = {
> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +			      const char * const *parent_names,
> +			      u8 num_parents, unsigned long flags,
> +			      void __iomem *regbase, unsigned long gate_reg,
> +			      unsigned long gate_idx, unsigned long div_reg,
> +			      unsigned long div_offset, u8 div_width,
> +			      unsigned long bypass_reg, u8 bypass_shift,
> +			      u8 fixed_div)
> +{
> +	struct clk *clk;
> +	struct socfpga_gate_clk *socfpga_clk;
> +	struct clk_init_data init;
> +
> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +	if (WARN_ON(!socfpga_clk))
> +		return NULL;
> +
> +	socfpga_clk->hw.reg = regbase + gate_reg;
> +	socfpga_clk->hw.bit_idx = gate_idx;
> +
> +	gateclk_ops.enable = clk_gate_ops.enable;
> +	gateclk_ops.disable = clk_gate_ops.disable;
> +
> +	socfpga_clk->fixed_div = fixed_div;
> +
> +	if (div_reg)
> +		socfpga_clk->div_reg = regbase + div_reg;
> +	else
> +		socfpga_clk->div_reg = NULL;
> +
> +	socfpga_clk->width = div_width;
> +	socfpga_clk->shift = div_offset;
> +
> +	if (bypass_reg)
> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		socfpga_clk->bypass_reg = NULL;
> +	socfpga_clk->bypass_shift = bypass_shift;
> +
> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +		init.ops = &dbgclk_ops;
> +	else
> +		init.ops = &gateclk_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +	socfpga_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(socfpga_clk);
> +		return NULL;
> +	}
> +
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
> new file mode 100644
> index 0000000..6021ac1
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-periph-s10.c
> @@ -0,0 +1,148 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +#define CLK_MGR_FREE_SHIFT		16
> +#define CLK_MGR_FREE_MASK		0x7
> +#define SWCTRLBTCLKSEN_SHIFT		8
> +
> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
> +
> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +	u32 val;
> +
> +	val = readl(socfpgaclk->hw.reg);
> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
> +	parent_rate /= val;
> +
> +	return parent_rate / div;
> +}
> +
> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else {
> +		if (!socfpgaclk->bypass_reg)
> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
> +	}
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	u32 clk_src, mask;
> +	u8 parent;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			   socfpgaclk->bypass_shift);
> +	} else {
> +		clk_src = readl(socfpgaclk->hw.reg);
> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
> +			CLK_MGR_FREE_MASK;
> +	}
> +	return parent;
> +}
> +
> +static const struct clk_ops peri_c_clk_ops = {
> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +static const struct clk_ops peri_cnt_clk_ops = {
> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +struct clk *s10_register_periph(char *name, const char *parent_name,
> +				const char * const *parent_names,
> +				u8 num_parents, unsigned long flags,
> +				void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	periph_clk->hw.reg = reg + offset;
> +
> +	init.name = name;
> +	init.ops = &peri_c_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> +
> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
> +				    const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *regbase, unsigned long offset,
> +				    u8 fixed_divider, unsigned long bypass_reg,
> +				    unsigned long bypass_shift)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	if (offset)
> +		periph_clk->hw.reg = regbase + offset;
> +	else
> +		periph_clk->hw.reg = NULL;
> +
> +	if (bypass_reg)
> +		periph_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		periph_clk->bypass_reg = NULL;
> +	periph_clk->bypass_shift = bypass_shift;
> +	periph_clk->fixed_div = fixed_divider;
> +
> +	init.name = name;
> +	init.ops = &peri_cnt_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
> new file mode 100644
> index 0000000..ef24ca7
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-pll-s10.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +/* Clock Manager offsets */
> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
> +
> +/* PLL Clock enable bits */
> +#define SOCFPGA_PLL_POWER		0
> +#define SOCFPGA_PLL_RESET_MASK		0x2
> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
> +#define SOCFPGA_PLL_MDIV_SHIFT		24
> +#define SWCTRLBTCLKSEL_MASK		0x200
> +#define SWCTRLBTCLKSEL_SHIFT		9
> +
> +#define SOCFPGA_BOOT_CLK		"boot_clk"
> +
> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	unsigned long mdiv;
> +	unsigned long refdiv;
> +	unsigned long reg;
> +	unsigned long long vco_freq;
> +
> +	/* read VCO1 reg for numerator and denominator */
> +	reg = readl(socfpgaclk->hw.reg);
> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate / refdiv;
> +
> +	/* Read mdiv and fdiv from the fdbck register */
> +	reg = readl(socfpgaclk->hw.reg + 0x4);
> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
> +
> +	return (unsigned long)vco_freq;
> +}
> +
> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 div = 1;
> +
> +	div = ((readl(socfpgaclk->hw.reg) &
> +		SWCTRLBTCLKSEL_MASK) >>
> +		SWCTRLBTCLKSEL_SHIFT);
> +	div += 1;
> +	return parent_rate /= div;
> +}
> +
> +
> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
> +		CLK_MGR_PLL_CLK_SRC_MASK;
> +}
> +
> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
> +		SWCTRLBTCLKSEL_MASK;
> +}
> +
> +static int clk_pll_prepare(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 reg;
> +
> +	/* Bring PLL out of reset */
> +	reg = readl(socfpgaclk->hw.reg);
> +	reg |= SOCFPGA_PLL_RESET_MASK;
> +	writel(reg, socfpgaclk->hw.reg);
> +
> +	return 0;
> +}
> +
> +static struct clk_ops clk_pll_ops = {
> +	.recalc_rate = clk_pll_recalc_rate,
> +	.get_parent = clk_pll_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +static struct clk_ops clk_boot_ops = {
> +	.recalc_rate = clk_boot_clk_recalc_rate,
> +	.get_parent = clk_boot_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_pll *pll_clk;
> +	struct clk_init_data init;
> +
> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
> +	if (WARN_ON(!pll_clk))
> +		return NULL;
> +
> +	pll_clk->hw.reg = reg + offset;
> +
> +	if (streq(name, SOCFPGA_BOOT_CLK))
> +		init.ops = &clk_boot_ops;
> +	else
> +		init.ops = &clk_pll_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names;
> +	pll_clk->hw.hw.init = &init;
> +
> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
> +	clk_pll_ops.enable = clk_gate_ops.enable;
> +	clk_pll_ops.disable = clk_gate_ops.disable;
> +
> +	clk = clk_register(NULL, &pll_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(pll_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <dt-bindings/clock/stratix10-clock.h>
> +
> +#include "stratix10-clk.h"
> +
> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
> +					"f2s_free_clk",};
> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
> +					 "osc1", "cb_intosc_hs_div2_clk",
> +					 "f2s_free_clk"};
> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
> +
> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
> +					    "peri_noc_base_clk",
> +					    "osc1", "cb_intosc_hs_div2_clk",
> +					    "f2s_free_clk"};
> +
> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
> +
> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
> +
> +/* clocks in AO (always on) controller */
> +static const struct stratix10_pll_clock s10_pll_clks[] = {
> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
> +	  0x0},
> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0x74},
> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0xe4},
> +};
> +
> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF4},
> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF8},
> +};
> +
> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	   0, 0x48, 0, 0, 0},
> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
> +	  0, 0x4C, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x50, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x54, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x58, 0, 0, 0},
> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x5C, 0, 0, 0},
> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x60, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0x64, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x68, 0, 0, 0},
> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x6C, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xBC, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC0, 0, 0, 0},
> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC4, 0, 0, 0},
> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC8, 0, 0, 0},
> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xCC, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD0, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xD4, 0, 0, 0},
> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD8, 0, 0, 0},
> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
> +	  0, 4, 0, 0},
> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
> +	  0, 0, 0, 0x3C, 1},
> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
> +	  0, 0, 4, 0xB0, 0},
> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
> +	  0, 0, 4, 0xB0, 1},
> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
> +};
> +
> +static const struct stratix10_gate_clock s10_gate_clks[] = {
> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
> +	  0, 0, 0, 0, 0x3C, 0, 0},
> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 2},
> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  1, 0x70, 0, 2, 0, 0, 0},
> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  2, 0x70, 8, 2, 0, 0, 0},
> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
> +	  3, 0x70, 16, 2, 0, 0, 0},
> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 24, 2, 0, 0, 0},
> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 26, 2, 0, 0, 0},
> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 28, 1, 0, 0, 0},
> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  5, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  0, 0, 0, 0, 0xDC, 26, 0},
> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  1, 0, 0, 0, 0xDC, 27, 0},
> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  2, 0, 0, 0, 0xDC, 28, 0},
> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
> +	  3, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
> +	  4, 0xE0, 0, 16, 0, 0, 0},
> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
> +	  5, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
> +	  7, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  8, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  9, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
> +	  10, 0, 0, 0, 0, 0, 0},
> +};
> +
> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
> +				    int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
> +					  clks[i].parent_names, clks[i].num_parents,
> +					  clks[i].flags, base, clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +	return 0;
> +}
> +
> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
> +				      int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
> +					      clks[i].parent_names,
> +					      clks[i].num_parents,
> +					      clks[i].flags, base,
> +					      clks[i].offset,
> +					      clks[i].fixed_divider,
> +					      clks[i].bypass_reg,
> +					      clks[i].bypass_shift);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
> +					clks[i].parent_names,
> +					clks[i].num_parents,
> +					clks[i].flags, base,
> +					clks[i].gate_reg,
> +					clks[i].gate_idx, clks[i].div_reg,
> +					clks[i].div_offset, clks[i].div_width,
> +					clks[i].bypass_reg,
> +					clks[i].bypass_shift,
> +					clks[i].fixed_div);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
> +				    clks[i].num_parents,
> +				    clks[i].flags, base,
> +				    clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
> +						    int nr_clks)
> +{
> +	struct stratix10_clock_data *clk_data;
> +	struct clk **clk_table;
> +	void __iomem *base;
> +
> +	base = of_iomap(np, 0);
> +	if (!base) {
> +		pr_err("%s: failed to map clock registers\n", __func__);
> +		goto err;
> +	}
> +
> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +	if (!clk_data)
> +		goto err;
> +
> +	clk_data->base = base;
> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +	if (!clk_table)
> +		goto err_data;
> +
> +	clk_data->clk_data.clks = clk_table;
> +	clk_data->clk_data.clk_num = nr_clks;
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> +	return clk_data;
> +
> +err_data:
> +	kfree(clk_data);
> +err:
> +	return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)
> +{
> +	struct stratix10_clock_data *clk_data;
> +
> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +	if (!clk_data)
> +		return;
> +
> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
> +
> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
> +
> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
> +				   clk_data);
> +
> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +			      clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
> index 9cf1230..26c3a26 100644
> --- a/drivers/clk/socfpga/clk.h
> +++ b/drivers/clk/socfpga/clk.h
> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	struct regmap *sys_mgr_base_addr;
>  	u32 width;	/* only valid if div_reg != 0 */
>  	u32 shift;	/* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  	u32 clk_phase[2];
>  };
>  
> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	u32 width;      /* only valid if div_reg != 0 */
>  	u32 shift;      /* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  };
>  
>  #endif /* SOCFPGA_CLK_H */
> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef	__STRATIX10_CLK_H
> +#define	__STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +
> +struct platform_device;
> +
> +struct stratix10_clock_data {
> +	struct clk_onecell_data	clk_data;
> +	void __iomem		*base;
> +};
> +
> +struct stratix10_pll_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_c_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_cnt_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +	u8			fixed_divider;
> +	unsigned long		bypass_reg;
> +	unsigned long		bypass_shift;
> +};
> +
> +struct stratix10_gate_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		gate_reg;
> +	u8			gate_idx;
> +	unsigned long		div_reg;
> +	u8			div_offset;
> +	u8			div_width;
> +	unsigned long		bypass_reg;
> +	u8			bypass_shift;
> +	u8			fixed_div;
> +};
> +
> +struct clk *s10_register_pll(const char *, const char *const *, u8,
> +			     unsigned long, void __iomem *, unsigned long);
> +
> +struct clk *s10_register_periph(const char *, const char *,
> +				const char * const *, u8, unsigned long,
> +				void __iomem *, unsigned long);
> +struct clk *s10_register_cnt_periph(const char *, const char *,
> +				    const char * const *, u8,
> +				    unsigned long, void __iomem *,
> +				    unsigned long, u8, unsigned long,
> +				    unsigned long);
> +struct clk *s10_register_gate(const char *, const char *,
> +			      const char * const *, u8,
> +			      unsigned long, void __iomem *,
> +			      unsigned long, unsigned long,
> +			      unsigned long, unsigned long, u8,
> +			      unsigned long, unsigned long, u8);
> +#endif	/* __STRATIX10_CLK_H */
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-05 15:16     ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-05 15:16 UTC (permalink / raw)
  To: linux-clk
  Cc: mturquette, sboyd, devicetree, linux-arm-kernel, robh+dt, mark.rutland

Hi Mike and Stephen,

Was wondering if you can review this patch when you get a chance?

Thanks so much,

Dinh

On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
> Add a clock driver for the Stratix10 SoC. The driver is similar to the
> Cyclone5/Arria10 platforms, with the exception that this driver only uses
> one single clock binding.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
> ---
> v6:
> - minimize usage of strcmp
> - use // as comment limiters for SPDX in c source file
> v5:
> - make SPDX license as a 1st separate first line comment
> v4:
> - move SPDX license first line of all files
> v3:
> - use fixed binding "intel,stratix10-clkmgr"
> - Fix up SPDX license header
> v2:
> - Use a single clock binding
> ---
>  drivers/clk/Makefile                 |   1 +
>  drivers/clk/socfpga/Makefile         |   5 +
>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>  drivers/clk/socfpga/clk.h            |   4 +
>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>  8 files changed, 832 insertions(+)
>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71ec41e..80ab422 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>  obj-$(CONFIG_ARCH_STI)			+= st/
> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>  obj-y += clk.o
>  obj-y += clk-gate.o
>  obj-y += clk-pll.o
>  obj-y += clk-periph.o
>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y += clk-s10.o
> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else if (socfpgaclk->div_reg) {
> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +		val &= GENMASK(socfpgaclk->width - 1, 0);
> +		div = (1 << val);
> +	}
> +	return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +	val &= GENMASK(socfpgaclk->width - 1, 0);
> +	div = (1 << val);
> +	div = div ? 4 : 1;
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 mask;
> +	u8 parent = 0;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			  socfpgaclk->bypass_shift);
> +	}
> +	return parent;
> +}
> +
> +static struct clk_ops gateclk_ops = {
> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops = {
> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +			      const char * const *parent_names,
> +			      u8 num_parents, unsigned long flags,
> +			      void __iomem *regbase, unsigned long gate_reg,
> +			      unsigned long gate_idx, unsigned long div_reg,
> +			      unsigned long div_offset, u8 div_width,
> +			      unsigned long bypass_reg, u8 bypass_shift,
> +			      u8 fixed_div)
> +{
> +	struct clk *clk;
> +	struct socfpga_gate_clk *socfpga_clk;
> +	struct clk_init_data init;
> +
> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +	if (WARN_ON(!socfpga_clk))
> +		return NULL;
> +
> +	socfpga_clk->hw.reg = regbase + gate_reg;
> +	socfpga_clk->hw.bit_idx = gate_idx;
> +
> +	gateclk_ops.enable = clk_gate_ops.enable;
> +	gateclk_ops.disable = clk_gate_ops.disable;
> +
> +	socfpga_clk->fixed_div = fixed_div;
> +
> +	if (div_reg)
> +		socfpga_clk->div_reg = regbase + div_reg;
> +	else
> +		socfpga_clk->div_reg = NULL;
> +
> +	socfpga_clk->width = div_width;
> +	socfpga_clk->shift = div_offset;
> +
> +	if (bypass_reg)
> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		socfpga_clk->bypass_reg = NULL;
> +	socfpga_clk->bypass_shift = bypass_shift;
> +
> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +		init.ops = &dbgclk_ops;
> +	else
> +		init.ops = &gateclk_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +	socfpga_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(socfpga_clk);
> +		return NULL;
> +	}
> +
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
> new file mode 100644
> index 0000000..6021ac1
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-periph-s10.c
> @@ -0,0 +1,148 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +#define CLK_MGR_FREE_SHIFT		16
> +#define CLK_MGR_FREE_MASK		0x7
> +#define SWCTRLBTCLKSEN_SHIFT		8
> +
> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
> +
> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +	u32 val;
> +
> +	val = readl(socfpgaclk->hw.reg);
> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
> +	parent_rate /= val;
> +
> +	return parent_rate / div;
> +}
> +
> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else {
> +		if (!socfpgaclk->bypass_reg)
> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
> +	}
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	u32 clk_src, mask;
> +	u8 parent;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			   socfpgaclk->bypass_shift);
> +	} else {
> +		clk_src = readl(socfpgaclk->hw.reg);
> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
> +			CLK_MGR_FREE_MASK;
> +	}
> +	return parent;
> +}
> +
> +static const struct clk_ops peri_c_clk_ops = {
> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +static const struct clk_ops peri_cnt_clk_ops = {
> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +struct clk *s10_register_periph(char *name, const char *parent_name,
> +				const char * const *parent_names,
> +				u8 num_parents, unsigned long flags,
> +				void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	periph_clk->hw.reg = reg + offset;
> +
> +	init.name = name;
> +	init.ops = &peri_c_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> +
> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
> +				    const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *regbase, unsigned long offset,
> +				    u8 fixed_divider, unsigned long bypass_reg,
> +				    unsigned long bypass_shift)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	if (offset)
> +		periph_clk->hw.reg = regbase + offset;
> +	else
> +		periph_clk->hw.reg = NULL;
> +
> +	if (bypass_reg)
> +		periph_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		periph_clk->bypass_reg = NULL;
> +	periph_clk->bypass_shift = bypass_shift;
> +	periph_clk->fixed_div = fixed_divider;
> +
> +	init.name = name;
> +	init.ops = &peri_cnt_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
> new file mode 100644
> index 0000000..ef24ca7
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-pll-s10.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +/* Clock Manager offsets */
> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
> +
> +/* PLL Clock enable bits */
> +#define SOCFPGA_PLL_POWER		0
> +#define SOCFPGA_PLL_RESET_MASK		0x2
> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
> +#define SOCFPGA_PLL_MDIV_SHIFT		24
> +#define SWCTRLBTCLKSEL_MASK		0x200
> +#define SWCTRLBTCLKSEL_SHIFT		9
> +
> +#define SOCFPGA_BOOT_CLK		"boot_clk"
> +
> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	unsigned long mdiv;
> +	unsigned long refdiv;
> +	unsigned long reg;
> +	unsigned long long vco_freq;
> +
> +	/* read VCO1 reg for numerator and denominator */
> +	reg = readl(socfpgaclk->hw.reg);
> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate / refdiv;
> +
> +	/* Read mdiv and fdiv from the fdbck register */
> +	reg = readl(socfpgaclk->hw.reg + 0x4);
> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
> +
> +	return (unsigned long)vco_freq;
> +}
> +
> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 div = 1;
> +
> +	div = ((readl(socfpgaclk->hw.reg) &
> +		SWCTRLBTCLKSEL_MASK) >>
> +		SWCTRLBTCLKSEL_SHIFT);
> +	div += 1;
> +	return parent_rate /= div;
> +}
> +
> +
> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
> +		CLK_MGR_PLL_CLK_SRC_MASK;
> +}
> +
> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
> +		SWCTRLBTCLKSEL_MASK;
> +}
> +
> +static int clk_pll_prepare(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 reg;
> +
> +	/* Bring PLL out of reset */
> +	reg = readl(socfpgaclk->hw.reg);
> +	reg |= SOCFPGA_PLL_RESET_MASK;
> +	writel(reg, socfpgaclk->hw.reg);
> +
> +	return 0;
> +}
> +
> +static struct clk_ops clk_pll_ops = {
> +	.recalc_rate = clk_pll_recalc_rate,
> +	.get_parent = clk_pll_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +static struct clk_ops clk_boot_ops = {
> +	.recalc_rate = clk_boot_clk_recalc_rate,
> +	.get_parent = clk_boot_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_pll *pll_clk;
> +	struct clk_init_data init;
> +
> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
> +	if (WARN_ON(!pll_clk))
> +		return NULL;
> +
> +	pll_clk->hw.reg = reg + offset;
> +
> +	if (streq(name, SOCFPGA_BOOT_CLK))
> +		init.ops = &clk_boot_ops;
> +	else
> +		init.ops = &clk_pll_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names;
> +	pll_clk->hw.hw.init = &init;
> +
> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
> +	clk_pll_ops.enable = clk_gate_ops.enable;
> +	clk_pll_ops.disable = clk_gate_ops.disable;
> +
> +	clk = clk_register(NULL, &pll_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(pll_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <dt-bindings/clock/stratix10-clock.h>
> +
> +#include "stratix10-clk.h"
> +
> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
> +					"f2s_free_clk",};
> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
> +					 "osc1", "cb_intosc_hs_div2_clk",
> +					 "f2s_free_clk"};
> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
> +
> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
> +					    "peri_noc_base_clk",
> +					    "osc1", "cb_intosc_hs_div2_clk",
> +					    "f2s_free_clk"};
> +
> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
> +
> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
> +
> +/* clocks in AO (always on) controller */
> +static const struct stratix10_pll_clock s10_pll_clks[] = {
> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
> +	  0x0},
> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0x74},
> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0xe4},
> +};
> +
> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF4},
> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF8},
> +};
> +
> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	   0, 0x48, 0, 0, 0},
> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
> +	  0, 0x4C, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x50, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x54, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x58, 0, 0, 0},
> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x5C, 0, 0, 0},
> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x60, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0x64, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x68, 0, 0, 0},
> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x6C, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xBC, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC0, 0, 0, 0},
> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC4, 0, 0, 0},
> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC8, 0, 0, 0},
> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xCC, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD0, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xD4, 0, 0, 0},
> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD8, 0, 0, 0},
> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
> +	  0, 4, 0, 0},
> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
> +	  0, 0, 0, 0x3C, 1},
> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
> +	  0, 0, 4, 0xB0, 0},
> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
> +	  0, 0, 4, 0xB0, 1},
> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
> +};
> +
> +static const struct stratix10_gate_clock s10_gate_clks[] = {
> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
> +	  0, 0, 0, 0, 0x3C, 0, 0},
> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 2},
> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  1, 0x70, 0, 2, 0, 0, 0},
> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  2, 0x70, 8, 2, 0, 0, 0},
> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
> +	  3, 0x70, 16, 2, 0, 0, 0},
> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 24, 2, 0, 0, 0},
> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 26, 2, 0, 0, 0},
> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 28, 1, 0, 0, 0},
> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  5, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  0, 0, 0, 0, 0xDC, 26, 0},
> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  1, 0, 0, 0, 0xDC, 27, 0},
> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  2, 0, 0, 0, 0xDC, 28, 0},
> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
> +	  3, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
> +	  4, 0xE0, 0, 16, 0, 0, 0},
> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
> +	  5, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
> +	  7, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  8, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  9, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
> +	  10, 0, 0, 0, 0, 0, 0},
> +};
> +
> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
> +				    int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
> +					  clks[i].parent_names, clks[i].num_parents,
> +					  clks[i].flags, base, clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +	return 0;
> +}
> +
> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
> +				      int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
> +					      clks[i].parent_names,
> +					      clks[i].num_parents,
> +					      clks[i].flags, base,
> +					      clks[i].offset,
> +					      clks[i].fixed_divider,
> +					      clks[i].bypass_reg,
> +					      clks[i].bypass_shift);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
> +					clks[i].parent_names,
> +					clks[i].num_parents,
> +					clks[i].flags, base,
> +					clks[i].gate_reg,
> +					clks[i].gate_idx, clks[i].div_reg,
> +					clks[i].div_offset, clks[i].div_width,
> +					clks[i].bypass_reg,
> +					clks[i].bypass_shift,
> +					clks[i].fixed_div);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
> +				    clks[i].num_parents,
> +				    clks[i].flags, base,
> +				    clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
> +						    int nr_clks)
> +{
> +	struct stratix10_clock_data *clk_data;
> +	struct clk **clk_table;
> +	void __iomem *base;
> +
> +	base = of_iomap(np, 0);
> +	if (!base) {
> +		pr_err("%s: failed to map clock registers\n", __func__);
> +		goto err;
> +	}
> +
> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +	if (!clk_data)
> +		goto err;
> +
> +	clk_data->base = base;
> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +	if (!clk_table)
> +		goto err_data;
> +
> +	clk_data->clk_data.clks = clk_table;
> +	clk_data->clk_data.clk_num = nr_clks;
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> +	return clk_data;
> +
> +err_data:
> +	kfree(clk_data);
> +err:
> +	return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)
> +{
> +	struct stratix10_clock_data *clk_data;
> +
> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +	if (!clk_data)
> +		return;
> +
> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
> +
> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
> +
> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
> +				   clk_data);
> +
> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +			      clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
> index 9cf1230..26c3a26 100644
> --- a/drivers/clk/socfpga/clk.h
> +++ b/drivers/clk/socfpga/clk.h
> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	struct regmap *sys_mgr_base_addr;
>  	u32 width;	/* only valid if div_reg != 0 */
>  	u32 shift;	/* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  	u32 clk_phase[2];
>  };
>  
> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	u32 width;      /* only valid if div_reg != 0 */
>  	u32 shift;      /* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  };
>  
>  #endif /* SOCFPGA_CLK_H */
> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef	__STRATIX10_CLK_H
> +#define	__STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +
> +struct platform_device;
> +
> +struct stratix10_clock_data {
> +	struct clk_onecell_data	clk_data;
> +	void __iomem		*base;
> +};
> +
> +struct stratix10_pll_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_c_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_cnt_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +	u8			fixed_divider;
> +	unsigned long		bypass_reg;
> +	unsigned long		bypass_shift;
> +};
> +
> +struct stratix10_gate_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		gate_reg;
> +	u8			gate_idx;
> +	unsigned long		div_reg;
> +	u8			div_offset;
> +	u8			div_width;
> +	unsigned long		bypass_reg;
> +	u8			bypass_shift;
> +	u8			fixed_div;
> +};
> +
> +struct clk *s10_register_pll(const char *, const char *const *, u8,
> +			     unsigned long, void __iomem *, unsigned long);
> +
> +struct clk *s10_register_periph(const char *, const char *,
> +				const char * const *, u8, unsigned long,
> +				void __iomem *, unsigned long);
> +struct clk *s10_register_cnt_periph(const char *, const char *,
> +				    const char * const *, u8,
> +				    unsigned long, void __iomem *,
> +				    unsigned long, u8, unsigned long,
> +				    unsigned long);
> +struct clk *s10_register_gate(const char *, const char *,
> +			      const char * const *, u8,
> +			      unsigned long, void __iomem *,
> +			      unsigned long, unsigned long,
> +			      unsigned long, unsigned long, u8,
> +			      unsigned long, unsigned long, u8);
> +#endif	/* __STRATIX10_CLK_H */
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-05 15:16     ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-05 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike and Stephen,

Was wondering if you can review this patch when you get a chance?

Thanks so much,

Dinh

On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
> Add a clock driver for the Stratix10 SoC. The driver is similar to the
> Cyclone5/Arria10 platforms, with the exception that this driver only uses
> one single clock binding.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
> ---
> v6:
> - minimize usage of strcmp
> - use // as comment limiters for SPDX in c source file
> v5:
> - make SPDX license as a 1st separate first line comment
> v4:
> - move SPDX license first line of all files
> v3:
> - use fixed binding "intel,stratix10-clkmgr"
> - Fix up SPDX license header
> v2:
> - Use a single clock binding
> ---
>  drivers/clk/Makefile                 |   1 +
>  drivers/clk/socfpga/Makefile         |   5 +
>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>  drivers/clk/socfpga/clk.h            |   4 +
>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>  8 files changed, 832 insertions(+)
>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71ec41e..80ab422 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>  obj-$(CONFIG_ARCH_STI)			+= st/
> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>  obj-y += clk.o
>  obj-y += clk-gate.o
>  obj-y += clk-pll.o
>  obj-y += clk-periph.o
>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y += clk-s10.o
> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else if (socfpgaclk->div_reg) {
> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +		val &= GENMASK(socfpgaclk->width - 1, 0);
> +		div = (1 << val);
> +	}
> +	return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +						  unsigned long parent_rate)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 div = 1, val;
> +
> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +	val &= GENMASK(socfpgaclk->width - 1, 0);
> +	div = (1 << val);
> +	div = div ? 4 : 1;
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +	u32 mask;
> +	u8 parent = 0;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			  socfpgaclk->bypass_shift);
> +	}
> +	return parent;
> +}
> +
> +static struct clk_ops gateclk_ops = {
> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops = {
> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
> +	.get_parent = socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +			      const char * const *parent_names,
> +			      u8 num_parents, unsigned long flags,
> +			      void __iomem *regbase, unsigned long gate_reg,
> +			      unsigned long gate_idx, unsigned long div_reg,
> +			      unsigned long div_offset, u8 div_width,
> +			      unsigned long bypass_reg, u8 bypass_shift,
> +			      u8 fixed_div)
> +{
> +	struct clk *clk;
> +	struct socfpga_gate_clk *socfpga_clk;
> +	struct clk_init_data init;
> +
> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +	if (WARN_ON(!socfpga_clk))
> +		return NULL;
> +
> +	socfpga_clk->hw.reg = regbase + gate_reg;
> +	socfpga_clk->hw.bit_idx = gate_idx;
> +
> +	gateclk_ops.enable = clk_gate_ops.enable;
> +	gateclk_ops.disable = clk_gate_ops.disable;
> +
> +	socfpga_clk->fixed_div = fixed_div;
> +
> +	if (div_reg)
> +		socfpga_clk->div_reg = regbase + div_reg;
> +	else
> +		socfpga_clk->div_reg = NULL;
> +
> +	socfpga_clk->width = div_width;
> +	socfpga_clk->shift = div_offset;
> +
> +	if (bypass_reg)
> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		socfpga_clk->bypass_reg = NULL;
> +	socfpga_clk->bypass_shift = bypass_shift;
> +
> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +		init.ops = &dbgclk_ops;
> +	else
> +		init.ops = &gateclk_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +	socfpga_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(socfpga_clk);
> +		return NULL;
> +	}
> +
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
> new file mode 100644
> index 0000000..6021ac1
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-periph-s10.c
> @@ -0,0 +1,148 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +#define CLK_MGR_FREE_SHIFT		16
> +#define CLK_MGR_FREE_MASK		0x7
> +#define SWCTRLBTCLKSEN_SHIFT		8
> +
> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
> +
> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +	u32 val;
> +
> +	val = readl(socfpgaclk->hw.reg);
> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
> +	parent_rate /= val;
> +
> +	return parent_rate / div;
> +}
> +
> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
> +					     unsigned long parent_rate)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	unsigned long div = 1;
> +
> +	if (socfpgaclk->fixed_div) {
> +		div = socfpgaclk->fixed_div;
> +	} else {
> +		if (!socfpgaclk->bypass_reg)
> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
> +	}
> +
> +	return parent_rate / div;
> +}
> +
> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
> +	u32 clk_src, mask;
> +	u8 parent;
> +
> +	if (socfpgaclk->bypass_reg) {
> +		mask = (0x1 << socfpgaclk->bypass_shift);
> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +			   socfpgaclk->bypass_shift);
> +	} else {
> +		clk_src = readl(socfpgaclk->hw.reg);
> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
> +			CLK_MGR_FREE_MASK;
> +	}
> +	return parent;
> +}
> +
> +static const struct clk_ops peri_c_clk_ops = {
> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +static const struct clk_ops peri_cnt_clk_ops = {
> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
> +	.get_parent = clk_periclk_get_parent,
> +};
> +
> +struct clk *s10_register_periph(char *name, const char *parent_name,
> +				const char * const *parent_names,
> +				u8 num_parents, unsigned long flags,
> +				void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	periph_clk->hw.reg = reg + offset;
> +
> +	init.name = name;
> +	init.ops = &peri_c_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> +
> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
> +				    const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *regbase, unsigned long offset,
> +				    u8 fixed_divider, unsigned long bypass_reg,
> +				    unsigned long bypass_shift)
> +{
> +	struct clk *clk;
> +	struct socfpga_periph_clk *periph_clk;
> +	struct clk_init_data init;
> +
> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
> +	if (WARN_ON(!periph_clk))
> +		return NULL;
> +
> +	if (offset)
> +		periph_clk->hw.reg = regbase + offset;
> +	else
> +		periph_clk->hw.reg = NULL;
> +
> +	if (bypass_reg)
> +		periph_clk->bypass_reg = regbase + bypass_reg;
> +	else
> +		periph_clk->bypass_reg = NULL;
> +	periph_clk->bypass_shift = bypass_shift;
> +	periph_clk->fixed_div = fixed_divider;
> +
> +	init.name = name;
> +	init.ops = &peri_cnt_clk_ops;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names ? parent_names : &parent_name;
> +
> +	periph_clk->hw.hw.init = &init;
> +
> +	clk = clk_register(NULL, &periph_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(periph_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
> new file mode 100644
> index 0000000..ef24ca7
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-pll-s10.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +
> +#include "clk.h"
> +
> +/* Clock Manager offsets */
> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
> +
> +/* PLL Clock enable bits */
> +#define SOCFPGA_PLL_POWER		0
> +#define SOCFPGA_PLL_RESET_MASK		0x2
> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
> +#define SOCFPGA_PLL_MDIV_SHIFT		24
> +#define SWCTRLBTCLKSEL_MASK		0x200
> +#define SWCTRLBTCLKSEL_SHIFT		9
> +
> +#define SOCFPGA_BOOT_CLK		"boot_clk"
> +
> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	unsigned long mdiv;
> +	unsigned long refdiv;
> +	unsigned long reg;
> +	unsigned long long vco_freq;
> +
> +	/* read VCO1 reg for numerator and denominator */
> +	reg = readl(socfpgaclk->hw.reg);
> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate / refdiv;
> +
> +	/* Read mdiv and fdiv from the fdbck register */
> +	reg = readl(socfpgaclk->hw.reg + 0x4);
> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
> +
> +	return (unsigned long)vco_freq;
> +}
> +
> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
> +					 unsigned long parent_rate)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 div = 1;
> +
> +	div = ((readl(socfpgaclk->hw.reg) &
> +		SWCTRLBTCLKSEL_MASK) >>
> +		SWCTRLBTCLKSEL_SHIFT);
> +	div += 1;
> +	return parent_rate /= div;
> +}
> +
> +
> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
> +		CLK_MGR_PLL_CLK_SRC_MASK;
> +}
> +
> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 pll_src;
> +
> +	pll_src = readl(socfpgaclk->hw.reg);
> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
> +		SWCTRLBTCLKSEL_MASK;
> +}
> +
> +static int clk_pll_prepare(struct clk_hw *hwclk)
> +{
> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
> +	u32 reg;
> +
> +	/* Bring PLL out of reset */
> +	reg = readl(socfpgaclk->hw.reg);
> +	reg |= SOCFPGA_PLL_RESET_MASK;
> +	writel(reg, socfpgaclk->hw.reg);
> +
> +	return 0;
> +}
> +
> +static struct clk_ops clk_pll_ops = {
> +	.recalc_rate = clk_pll_recalc_rate,
> +	.get_parent = clk_pll_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +static struct clk_ops clk_boot_ops = {
> +	.recalc_rate = clk_boot_clk_recalc_rate,
> +	.get_parent = clk_boot_get_parent,
> +	.prepare = clk_pll_prepare,
> +};
> +
> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
> +				    u8 num_parents, unsigned long flags,
> +				    void __iomem *reg, unsigned long offset)
> +{
> +	struct clk *clk;
> +	struct socfpga_pll *pll_clk;
> +	struct clk_init_data init;
> +
> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
> +	if (WARN_ON(!pll_clk))
> +		return NULL;
> +
> +	pll_clk->hw.reg = reg + offset;
> +
> +	if (streq(name, SOCFPGA_BOOT_CLK))
> +		init.ops = &clk_boot_ops;
> +	else
> +		init.ops = &clk_pll_ops;
> +
> +	init.name = name;
> +	init.flags = flags;
> +
> +	init.num_parents = num_parents;
> +	init.parent_names = parent_names;
> +	pll_clk->hw.hw.init = &init;
> +
> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
> +	clk_pll_ops.enable = clk_gate_ops.enable;
> +	clk_pll_ops.disable = clk_gate_ops.disable;
> +
> +	clk = clk_register(NULL, &pll_clk->hw.hw);
> +	if (WARN_ON(IS_ERR(clk))) {
> +		kfree(pll_clk);
> +		return NULL;
> +	}
> +	return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
> +// SPDX-License-Identifier:	GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <dt-bindings/clock/stratix10-clock.h>
> +
> +#include "stratix10-clk.h"
> +
> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
> +					"f2s_free_clk",};
> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
> +					 "osc1", "cb_intosc_hs_div2_clk",
> +					 "f2s_free_clk"};
> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
> +
> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
> +					    "peri_noc_base_clk",
> +					    "osc1", "cb_intosc_hs_div2_clk",
> +					    "f2s_free_clk"};
> +
> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
> +
> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
> +
> +/* clocks in AO (always on) controller */
> +static const struct stratix10_pll_clock s10_pll_clks[] = {
> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
> +	  0x0},
> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0x74},
> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
> +	  0, 0xe4},
> +};
> +
> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF4},
> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
> +	  0xF8},
> +};
> +
> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	   0, 0x48, 0, 0, 0},
> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
> +	  0, 0x4C, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x50, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x54, 0, 0, 0},
> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x58, 0, 0, 0},
> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x5C, 0, 0, 0},
> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x60, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0x64, 0, 0, 0},
> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x68, 0, 0, 0},
> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
> +	  0x6C, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xBC, 0, 0, 0},
> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC0, 0, 0, 0},
> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC4, 0, 0, 0},
> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xC8, 0, 0, 0},
> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xCC, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD0, 0, 0, 0},
> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
> +	  0, 0xD4, 0, 0, 0},
> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
> +	  0xD8, 0, 0, 0},
> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
> +	  0, 4, 0, 0},
> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
> +	  0, 0, 0, 0x3C, 1},
> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
> +	  0, 0, 4, 0xB0, 0},
> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
> +	  0, 0, 4, 0xB0, 1},
> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
> +};
> +
> +static const struct stratix10_gate_clock s10_gate_clks[] = {
> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
> +	  0, 0, 0, 0, 0x3C, 0, 0},
> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
> +	  0, 0, 0, 0, 0, 0, 2},
> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  1, 0x70, 0, 2, 0, 0, 0},
> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  2, 0x70, 8, 2, 0, 0, 0},
> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
> +	  3, 0x70, 16, 2, 0, 0, 0},
> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 24, 2, 0, 0, 0},
> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 26, 2, 0, 0, 0},
> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
> +	  4, 0x70, 28, 1, 0, 0, 0},
> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
> +	  5, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  0, 0, 0, 0, 0xDC, 26, 0},
> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  1, 0, 0, 0, 0xDC, 27, 0},
> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
> +	  2, 0, 0, 0, 0xDC, 28, 0},
> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
> +	  3, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
> +	  4, 0xE0, 0, 16, 0, 0, 0},
> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
> +	  5, 0, 0, 0, 0, 0, 4},
> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
> +	  6, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
> +	  7, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  8, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
> +	  9, 0, 0, 0, 0, 0, 0},
> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
> +	  10, 0, 0, 0, 0, 0, 0},
> +};
> +
> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
> +				    int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
> +					  clks[i].parent_names, clks[i].num_parents,
> +					  clks[i].flags, base, clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +	return 0;
> +}
> +
> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
> +				      int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
> +					      clks[i].parent_names,
> +					      clks[i].num_parents,
> +					      clks[i].flags, base,
> +					      clks[i].offset,
> +					      clks[i].fixed_divider,
> +					      clks[i].bypass_reg,
> +					      clks[i].bypass_shift);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
> +					clks[i].parent_names,
> +					clks[i].num_parents,
> +					clks[i].flags, base,
> +					clks[i].gate_reg,
> +					clks[i].gate_idx, clks[i].div_reg,
> +					clks[i].div_offset, clks[i].div_width,
> +					clks[i].bypass_reg,
> +					clks[i].bypass_shift,
> +					clks[i].fixed_div);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +				 int nums, struct stratix10_clock_data *data)
> +{
> +	struct clk *clk;
> +	void __iomem *base = data->base;
> +	int i;
> +
> +	for (i = 0; i < nums; i++) {
> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
> +				    clks[i].num_parents,
> +				    clks[i].flags, base,
> +				    clks[i].offset);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n",
> +			       __func__, clks[i].name);
> +			continue;
> +		}
> +		data->clk_data.clks[clks[i].id] = clk;
> +	}
> +
> +	return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
> +						    int nr_clks)
> +{
> +	struct stratix10_clock_data *clk_data;
> +	struct clk **clk_table;
> +	void __iomem *base;
> +
> +	base = of_iomap(np, 0);
> +	if (!base) {
> +		pr_err("%s: failed to map clock registers\n", __func__);
> +		goto err;
> +	}
> +
> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +	if (!clk_data)
> +		goto err;
> +
> +	clk_data->base = base;
> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +	if (!clk_table)
> +		goto err_data;
> +
> +	clk_data->clk_data.clks = clk_table;
> +	clk_data->clk_data.clk_num = nr_clks;
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> +	return clk_data;
> +
> +err_data:
> +	kfree(clk_data);
> +err:
> +	return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)
> +{
> +	struct stratix10_clock_data *clk_data;
> +
> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +	if (!clk_data)
> +		return;
> +
> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
> +
> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
> +
> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
> +				   clk_data);
> +
> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +			      clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
> index 9cf1230..26c3a26 100644
> --- a/drivers/clk/socfpga/clk.h
> +++ b/drivers/clk/socfpga/clk.h
> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	struct regmap *sys_mgr_base_addr;
>  	u32 width;	/* only valid if div_reg != 0 */
>  	u32 shift;	/* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  	u32 clk_phase[2];
>  };
>  
> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>  	char *parent_name;
>  	u32 fixed_div;
>  	void __iomem *div_reg;
> +	void __iomem *bypass_reg;
>  	u32 width;      /* only valid if div_reg != 0 */
>  	u32 shift;      /* only valid if div_reg != 0 */
> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>  };
>  
>  #endif /* SOCFPGA_CLK_H */
> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef	__STRATIX10_CLK_H
> +#define	__STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +
> +struct platform_device;
> +
> +struct stratix10_clock_data {
> +	struct clk_onecell_data	clk_data;
> +	void __iomem		*base;
> +};
> +
> +struct stratix10_pll_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_c_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +};
> +
> +struct stratix10_perip_cnt_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		offset;
> +	u8			fixed_divider;
> +	unsigned long		bypass_reg;
> +	unsigned long		bypass_shift;
> +};
> +
> +struct stratix10_gate_clock {
> +	unsigned int		id;
> +	const char		*name;
> +	const char		*parent_name;
> +	const char		*const *parent_names;
> +	u8			num_parents;
> +	unsigned long		flags;
> +	unsigned long		gate_reg;
> +	u8			gate_idx;
> +	unsigned long		div_reg;
> +	u8			div_offset;
> +	u8			div_width;
> +	unsigned long		bypass_reg;
> +	u8			bypass_shift;
> +	u8			fixed_div;
> +};
> +
> +struct clk *s10_register_pll(const char *, const char *const *, u8,
> +			     unsigned long, void __iomem *, unsigned long);
> +
> +struct clk *s10_register_periph(const char *, const char *,
> +				const char * const *, u8, unsigned long,
> +				void __iomem *, unsigned long);
> +struct clk *s10_register_cnt_periph(const char *, const char *,
> +				    const char * const *, u8,
> +				    unsigned long, void __iomem *,
> +				    unsigned long, u8, unsigned long,
> +				    unsigned long);
> +struct clk *s10_register_gate(const char *, const char *,
> +			      const char * const *, u8,
> +			      unsigned long, void __iomem *,
> +			      unsigned long, unsigned long,
> +			      unsigned long, unsigned long, u8,
> +			      unsigned long, unsigned long, u8);
> +#endif	/* __STRATIX10_CLK_H */
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
  2018-03-05 15:16     ` Dinh Nguyen
  (?)
@ 2018-03-12 14:38       ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-12 14:38 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, sboyd, mturquette, robh+dt, linux-arm-kernel

Hi,

Another gentle ping on this patch?

Thanks,
Dinh

On 03/05/2018 09:16 AM, Dinh Nguyen wrote:
> Hi Mike and Stephen,
> 
> Was wondering if you can review this patch when you get a chance?
> 
> Thanks so much,
> 
> Dinh
> 
> On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
>> Add a clock driver for the Stratix10 SoC. The driver is similar to the
>> Cyclone5/Arria10 platforms, with the exception that this driver only uses
>> one single clock binding.
>>
>> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
>> ---
>> v6:
>> - minimize usage of strcmp
>> - use // as comment limiters for SPDX in c source file
>> v5:
>> - make SPDX license as a 1st separate first line comment
>> v4:
>> - move SPDX license first line of all files
>> v3:
>> - use fixed binding "intel,stratix10-clkmgr"
>> - Fix up SPDX license header
>> v2:
>> - Use a single clock binding
>> ---
>>  drivers/clk/Makefile                 |   1 +
>>  drivers/clk/socfpga/Makefile         |   5 +
>>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>>  drivers/clk/socfpga/clk.h            |   4 +
>>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>>  8 files changed, 832 insertions(+)
>>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 71ec41e..80ab422 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>>  obj-$(CONFIG_ARCH_STI)			+= st/
>> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
>> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
>> index 9146c20..87ef977 100644
>> --- a/drivers/clk/socfpga/Makefile
>> +++ b/drivers/clk/socfpga/Makefile
>> @@ -1,6 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0
>> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>>  obj-y += clk.o
>>  obj-y += clk-gate.o
>>  obj-y += clk-pll.o
>>  obj-y += clk-periph.o
>>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
>> +else
>> +obj-y += clk-s10.o
>> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
>> +endif
>> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
>> new file mode 100644
>> index 0000000..5b09aef
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-gate-s10.c
>> @@ -0,0 +1,124 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include "clk.h"
>> +
>> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
>> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
>> +
>> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else if (socfpgaclk->div_reg) {
>> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +		val &= GENMASK(socfpgaclk->width - 1, 0);
>> +		div = (1 << val);
>> +	}
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +	val &= GENMASK(socfpgaclk->width - 1, 0);
>> +	div = (1 << val);
>> +	div = div ? 4 : 1;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 mask;
>> +	u8 parent = 0;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			  socfpgaclk->bypass_shift);
>> +	}
>> +	return parent;
>> +}
>> +
>> +static struct clk_ops gateclk_ops = {
>> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +static struct clk_ops dbgclk_ops = {
>> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +struct clk *s10_register_gate(char *name, const char *parent_name,
>> +			      const char * const *parent_names,
>> +			      u8 num_parents, unsigned long flags,
>> +			      void __iomem *regbase, unsigned long gate_reg,
>> +			      unsigned long gate_idx, unsigned long div_reg,
>> +			      unsigned long div_offset, u8 div_width,
>> +			      unsigned long bypass_reg, u8 bypass_shift,
>> +			      u8 fixed_div)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_gate_clk *socfpga_clk;
>> +	struct clk_init_data init;
>> +
>> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
>> +	if (WARN_ON(!socfpga_clk))
>> +		return NULL;
>> +
>> +	socfpga_clk->hw.reg = regbase + gate_reg;
>> +	socfpga_clk->hw.bit_idx = gate_idx;
>> +
>> +	gateclk_ops.enable = clk_gate_ops.enable;
>> +	gateclk_ops.disable = clk_gate_ops.disable;
>> +
>> +	socfpga_clk->fixed_div = fixed_div;
>> +
>> +	if (div_reg)
>> +		socfpga_clk->div_reg = regbase + div_reg;
>> +	else
>> +		socfpga_clk->div_reg = NULL;
>> +
>> +	socfpga_clk->width = div_width;
>> +	socfpga_clk->shift = div_offset;
>> +
>> +	if (bypass_reg)
>> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		socfpga_clk->bypass_reg = NULL;
>> +	socfpga_clk->bypass_shift = bypass_shift;
>> +
>> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
>> +		init.ops = &dbgclk_ops;
>> +	else
>> +		init.ops = &gateclk_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +	socfpga_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(socfpga_clk);
>> +		return NULL;
>> +	}
>> +
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
>> new file mode 100644
>> index 0000000..6021ac1
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-periph-s10.c
>> @@ -0,0 +1,148 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +#define CLK_MGR_FREE_SHIFT		16
>> +#define CLK_MGR_FREE_MASK		0x7
>> +#define SWCTRLBTCLKSEN_SHIFT		8
>> +
>> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
>> +
>> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +	u32 val;
>> +
>> +	val = readl(socfpgaclk->hw.reg);
>> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
>> +	parent_rate /= val;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else {
>> +		if (!socfpgaclk->bypass_reg)
>> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
>> +	}
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	u32 clk_src, mask;
>> +	u8 parent;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			   socfpgaclk->bypass_shift);
>> +	} else {
>> +		clk_src = readl(socfpgaclk->hw.reg);
>> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
>> +			CLK_MGR_FREE_MASK;
>> +	}
>> +	return parent;
>> +}
>> +
>> +static const struct clk_ops peri_c_clk_ops = {
>> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +static const struct clk_ops peri_cnt_clk_ops = {
>> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +struct clk *s10_register_periph(char *name, const char *parent_name,
>> +				const char * const *parent_names,
>> +				u8 num_parents, unsigned long flags,
>> +				void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	periph_clk->hw.reg = reg + offset;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_c_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> +
>> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
>> +				    const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *regbase, unsigned long offset,
>> +				    u8 fixed_divider, unsigned long bypass_reg,
>> +				    unsigned long bypass_shift)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	if (offset)
>> +		periph_clk->hw.reg = regbase + offset;
>> +	else
>> +		periph_clk->hw.reg = NULL;
>> +
>> +	if (bypass_reg)
>> +		periph_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		periph_clk->bypass_reg = NULL;
>> +	periph_clk->bypass_shift = bypass_shift;
>> +	periph_clk->fixed_div = fixed_divider;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_cnt_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
>> new file mode 100644
>> index 0000000..ef24ca7
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-pll-s10.c
>> @@ -0,0 +1,145 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +/* Clock Manager offsets */
>> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
>> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
>> +
>> +/* PLL Clock enable bits */
>> +#define SOCFPGA_PLL_POWER		0
>> +#define SOCFPGA_PLL_RESET_MASK		0x2
>> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
>> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
>> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
>> +#define SOCFPGA_PLL_MDIV_SHIFT		24
>> +#define SWCTRLBTCLKSEL_MASK		0x200
>> +#define SWCTRLBTCLKSEL_SHIFT		9
>> +
>> +#define SOCFPGA_BOOT_CLK		"boot_clk"
>> +
>> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
>> +
>> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	unsigned long mdiv;
>> +	unsigned long refdiv;
>> +	unsigned long reg;
>> +	unsigned long long vco_freq;
>> +
>> +	/* read VCO1 reg for numerator and denominator */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate / refdiv;
>> +
>> +	/* Read mdiv and fdiv from the fdbck register */
>> +	reg = readl(socfpgaclk->hw.reg + 0x4);
>> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
>> +
>> +	return (unsigned long)vco_freq;
>> +}
>> +
>> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 div = 1;
>> +
>> +	div = ((readl(socfpgaclk->hw.reg) &
>> +		SWCTRLBTCLKSEL_MASK) >>
>> +		SWCTRLBTCLKSEL_SHIFT);
>> +	div += 1;
>> +	return parent_rate /= div;
>> +}
>> +
>> +
>> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
>> +		CLK_MGR_PLL_CLK_SRC_MASK;
>> +}
>> +
>> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
>> +		SWCTRLBTCLKSEL_MASK;
>> +}
>> +
>> +static int clk_pll_prepare(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 reg;
>> +
>> +	/* Bring PLL out of reset */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	reg |= SOCFPGA_PLL_RESET_MASK;
>> +	writel(reg, socfpgaclk->hw.reg);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct clk_ops clk_pll_ops = {
>> +	.recalc_rate = clk_pll_recalc_rate,
>> +	.get_parent = clk_pll_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +static struct clk_ops clk_boot_ops = {
>> +	.recalc_rate = clk_boot_clk_recalc_rate,
>> +	.get_parent = clk_boot_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_pll *pll_clk;
>> +	struct clk_init_data init;
>> +
>> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
>> +	if (WARN_ON(!pll_clk))
>> +		return NULL;
>> +
>> +	pll_clk->hw.reg = reg + offset;
>> +
>> +	if (streq(name, SOCFPGA_BOOT_CLK))
>> +		init.ops = &clk_boot_ops;
>> +	else
>> +		init.ops = &clk_pll_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names;
>> +	pll_clk->hw.hw.init = &init;
>> +
>> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
>> +	clk_pll_ops.enable = clk_gate_ops.enable;
>> +	clk_pll_ops.disable = clk_gate_ops.disable;
>> +
>> +	clk = clk_register(NULL, &pll_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(pll_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
>> new file mode 100644
>> index 0000000..31572cb
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-s10.c
>> @@ -0,0 +1,319 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +
>> +#include <dt-bindings/clock/stratix10-clock.h>
>> +
>> +#include "stratix10-clk.h"
>> +
>> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
>> +					"f2s_free_clk",};
>> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
>> +					 "osc1", "cb_intosc_hs_div2_clk",
>> +					 "f2s_free_clk"};
>> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
>> +
>> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
>> +					    "peri_noc_base_clk",
>> +					    "osc1", "cb_intosc_hs_div2_clk",
>> +					    "f2s_free_clk"};
>> +
>> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
>> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
>> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
>> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
>> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
>> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
>> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
>> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
>> +
>> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
>> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
>> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
>> +
>> +/* clocks in AO (always on) controller */
>> +static const struct stratix10_pll_clock s10_pll_clks[] = {
>> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
>> +	  0x0},
>> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0x74},
>> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0xe4},
>> +};
>> +
>> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
>> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
>> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
>> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF4},
>> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF8},
>> +};
>> +
>> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
>> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	   0, 0x48, 0, 0, 0},
>> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
>> +	  0, 0x4C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x50, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x54, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x58, 0, 0, 0},
>> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x5C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x60, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0x64, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x68, 0, 0, 0},
>> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x6C, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xBC, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC0, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC4, 0, 0, 0},
>> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC8, 0, 0, 0},
>> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xCC, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD0, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xD4, 0, 0, 0},
>> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD8, 0, 0, 0},
>> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
>> +	  0, 4, 0, 0},
>> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
>> +	  0, 0, 0, 0x3C, 1},
>> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
>> +	  0, 0, 4, 0xB0, 0},
>> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
>> +	  0, 0, 4, 0xB0, 1},
>> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
>> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
>> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
>> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
>> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
>> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
>> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
>> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
>> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
>> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
>> +};
>> +
>> +static const struct stratix10_gate_clock s10_gate_clks[] = {
>> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
>> +	  0, 0, 0, 0, 0x3C, 0, 0},
>> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 2},
>> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  1, 0x70, 0, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  2, 0x70, 8, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
>> +	  3, 0x70, 16, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 24, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 26, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 28, 1, 0, 0, 0},
>> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  5, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  0, 0, 0, 0, 0xDC, 26, 0},
>> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  1, 0, 0, 0, 0xDC, 27, 0},
>> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  2, 0, 0, 0, 0xDC, 28, 0},
>> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
>> +	  3, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
>> +	  4, 0xE0, 0, 16, 0, 0, 0},
>> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
>> +	  5, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
>> +	  7, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  8, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  9, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
>> +	  10, 0, 0, 0, 0, 0, 0},
>> +};
>> +
>> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
>> +				    int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
>> +					  clks[i].parent_names, clks[i].num_parents,
>> +					  clks[i].flags, base, clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
>> +				      int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
>> +					      clks[i].parent_names,
>> +					      clks[i].num_parents,
>> +					      clks[i].flags, base,
>> +					      clks[i].offset,
>> +					      clks[i].fixed_divider,
>> +					      clks[i].bypass_reg,
>> +					      clks[i].bypass_shift);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
>> +					clks[i].parent_names,
>> +					clks[i].num_parents,
>> +					clks[i].flags, base,
>> +					clks[i].gate_reg,
>> +					clks[i].gate_idx, clks[i].div_reg,
>> +					clks[i].div_offset, clks[i].div_width,
>> +					clks[i].bypass_reg,
>> +					clks[i].bypass_shift,
>> +					clks[i].fixed_div);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
>> +				    clks[i].num_parents,
>> +				    clks[i].flags, base,
>> +				    clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
>> +						    int nr_clks)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +	struct clk **clk_table;
>> +	void __iomem *base;
>> +
>> +	base = of_iomap(np, 0);
>> +	if (!base) {
>> +		pr_err("%s: failed to map clock registers\n", __func__);
>> +		goto err;
>> +	}
>> +
>> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
>> +	if (!clk_data)
>> +		goto err;
>> +
>> +	clk_data->base = base;
>> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
>> +	if (!clk_table)
>> +		goto err_data;
>> +
>> +	clk_data->clk_data.clks = clk_table;
>> +	clk_data->clk_data.clk_num = nr_clks;
>> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
>> +	return clk_data;
>> +
>> +err_data:
>> +	kfree(clk_data);
>> +err:
>> +	return NULL;
>> +}
>> +
>> +
>> +void __init socfpga_s10_init(struct device_node *node)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +
>> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
>> +
>> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
>> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
>> +
>> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
>> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
>> +				   clk_data);
>> +
>> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
>> +			      clk_data);
>> +}
>> +
>> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
>> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
>> index 9cf1230..26c3a26 100644
>> --- a/drivers/clk/socfpga/clk.h
>> +++ b/drivers/clk/socfpga/clk.h
>> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	struct regmap *sys_mgr_base_addr;
>>  	u32 width;	/* only valid if div_reg != 0 */
>>  	u32 shift;	/* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  	u32 clk_phase[2];
>>  };
>>  
>> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	u32 width;      /* only valid if div_reg != 0 */
>>  	u32 shift;      /* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  };
>>  
>>  #endif /* SOCFPGA_CLK_H */
>> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
>> new file mode 100644
>> index 0000000..10f1532
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/stratix10-clk.h
>> @@ -0,0 +1,86 @@
>> +/* SPDX-License-Identifier:    GPL-2.0 */
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +
>> +#ifndef	__STRATIX10_CLK_H
>> +#define	__STRATIX10_CLK_H
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/spinlock.h>
>> +
>> +struct platform_device;
>> +
>> +struct stratix10_clock_data {
>> +	struct clk_onecell_data	clk_data;
>> +	void __iomem		*base;
>> +};
>> +
>> +struct stratix10_pll_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_c_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_cnt_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +	u8			fixed_divider;
>> +	unsigned long		bypass_reg;
>> +	unsigned long		bypass_shift;
>> +};
>> +
>> +struct stratix10_gate_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		gate_reg;
>> +	u8			gate_idx;
>> +	unsigned long		div_reg;
>> +	u8			div_offset;
>> +	u8			div_width;
>> +	unsigned long		bypass_reg;
>> +	u8			bypass_shift;
>> +	u8			fixed_div;
>> +};
>> +
>> +struct clk *s10_register_pll(const char *, const char *const *, u8,
>> +			     unsigned long, void __iomem *, unsigned long);
>> +
>> +struct clk *s10_register_periph(const char *, const char *,
>> +				const char * const *, u8, unsigned long,
>> +				void __iomem *, unsigned long);
>> +struct clk *s10_register_cnt_periph(const char *, const char *,
>> +				    const char * const *, u8,
>> +				    unsigned long, void __iomem *,
>> +				    unsigned long, u8, unsigned long,
>> +				    unsigned long);
>> +struct clk *s10_register_gate(const char *, const char *,
>> +			      const char * const *, u8,
>> +			      unsigned long, void __iomem *,
>> +			      unsigned long, unsigned long,
>> +			      unsigned long, unsigned long, u8,
>> +			      unsigned long, unsigned long, u8);
>> +#endif	/* __STRATIX10_CLK_H */
>>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-12 14:38       ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-12 14:38 UTC (permalink / raw)
  To: linux-clk
  Cc: mturquette, sboyd, devicetree, linux-arm-kernel, robh+dt, mark.rutland

Hi,

Another gentle ping on this patch?

Thanks,
Dinh

On 03/05/2018 09:16 AM, Dinh Nguyen wrote:
> Hi Mike and Stephen,
> 
> Was wondering if you can review this patch when you get a chance?
> 
> Thanks so much,
> 
> Dinh
> 
> On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
>> Add a clock driver for the Stratix10 SoC. The driver is similar to the
>> Cyclone5/Arria10 platforms, with the exception that this driver only uses
>> one single clock binding.
>>
>> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
>> ---
>> v6:
>> - minimize usage of strcmp
>> - use // as comment limiters for SPDX in c source file
>> v5:
>> - make SPDX license as a 1st separate first line comment
>> v4:
>> - move SPDX license first line of all files
>> v3:
>> - use fixed binding "intel,stratix10-clkmgr"
>> - Fix up SPDX license header
>> v2:
>> - Use a single clock binding
>> ---
>>  drivers/clk/Makefile                 |   1 +
>>  drivers/clk/socfpga/Makefile         |   5 +
>>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>>  drivers/clk/socfpga/clk.h            |   4 +
>>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>>  8 files changed, 832 insertions(+)
>>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 71ec41e..80ab422 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>>  obj-$(CONFIG_ARCH_STI)			+= st/
>> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
>> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
>> index 9146c20..87ef977 100644
>> --- a/drivers/clk/socfpga/Makefile
>> +++ b/drivers/clk/socfpga/Makefile
>> @@ -1,6 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0
>> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>>  obj-y += clk.o
>>  obj-y += clk-gate.o
>>  obj-y += clk-pll.o
>>  obj-y += clk-periph.o
>>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
>> +else
>> +obj-y += clk-s10.o
>> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
>> +endif
>> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
>> new file mode 100644
>> index 0000000..5b09aef
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-gate-s10.c
>> @@ -0,0 +1,124 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include "clk.h"
>> +
>> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
>> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
>> +
>> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else if (socfpgaclk->div_reg) {
>> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +		val &= GENMASK(socfpgaclk->width - 1, 0);
>> +		div = (1 << val);
>> +	}
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +	val &= GENMASK(socfpgaclk->width - 1, 0);
>> +	div = (1 << val);
>> +	div = div ? 4 : 1;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 mask;
>> +	u8 parent = 0;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			  socfpgaclk->bypass_shift);
>> +	}
>> +	return parent;
>> +}
>> +
>> +static struct clk_ops gateclk_ops = {
>> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +static struct clk_ops dbgclk_ops = {
>> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +struct clk *s10_register_gate(char *name, const char *parent_name,
>> +			      const char * const *parent_names,
>> +			      u8 num_parents, unsigned long flags,
>> +			      void __iomem *regbase, unsigned long gate_reg,
>> +			      unsigned long gate_idx, unsigned long div_reg,
>> +			      unsigned long div_offset, u8 div_width,
>> +			      unsigned long bypass_reg, u8 bypass_shift,
>> +			      u8 fixed_div)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_gate_clk *socfpga_clk;
>> +	struct clk_init_data init;
>> +
>> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
>> +	if (WARN_ON(!socfpga_clk))
>> +		return NULL;
>> +
>> +	socfpga_clk->hw.reg = regbase + gate_reg;
>> +	socfpga_clk->hw.bit_idx = gate_idx;
>> +
>> +	gateclk_ops.enable = clk_gate_ops.enable;
>> +	gateclk_ops.disable = clk_gate_ops.disable;
>> +
>> +	socfpga_clk->fixed_div = fixed_div;
>> +
>> +	if (div_reg)
>> +		socfpga_clk->div_reg = regbase + div_reg;
>> +	else
>> +		socfpga_clk->div_reg = NULL;
>> +
>> +	socfpga_clk->width = div_width;
>> +	socfpga_clk->shift = div_offset;
>> +
>> +	if (bypass_reg)
>> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		socfpga_clk->bypass_reg = NULL;
>> +	socfpga_clk->bypass_shift = bypass_shift;
>> +
>> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
>> +		init.ops = &dbgclk_ops;
>> +	else
>> +		init.ops = &gateclk_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +	socfpga_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(socfpga_clk);
>> +		return NULL;
>> +	}
>> +
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
>> new file mode 100644
>> index 0000000..6021ac1
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-periph-s10.c
>> @@ -0,0 +1,148 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +#define CLK_MGR_FREE_SHIFT		16
>> +#define CLK_MGR_FREE_MASK		0x7
>> +#define SWCTRLBTCLKSEN_SHIFT		8
>> +
>> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
>> +
>> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +	u32 val;
>> +
>> +	val = readl(socfpgaclk->hw.reg);
>> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
>> +	parent_rate /= val;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else {
>> +		if (!socfpgaclk->bypass_reg)
>> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
>> +	}
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	u32 clk_src, mask;
>> +	u8 parent;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			   socfpgaclk->bypass_shift);
>> +	} else {
>> +		clk_src = readl(socfpgaclk->hw.reg);
>> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
>> +			CLK_MGR_FREE_MASK;
>> +	}
>> +	return parent;
>> +}
>> +
>> +static const struct clk_ops peri_c_clk_ops = {
>> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +static const struct clk_ops peri_cnt_clk_ops = {
>> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +struct clk *s10_register_periph(char *name, const char *parent_name,
>> +				const char * const *parent_names,
>> +				u8 num_parents, unsigned long flags,
>> +				void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	periph_clk->hw.reg = reg + offset;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_c_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> +
>> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
>> +				    const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *regbase, unsigned long offset,
>> +				    u8 fixed_divider, unsigned long bypass_reg,
>> +				    unsigned long bypass_shift)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	if (offset)
>> +		periph_clk->hw.reg = regbase + offset;
>> +	else
>> +		periph_clk->hw.reg = NULL;
>> +
>> +	if (bypass_reg)
>> +		periph_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		periph_clk->bypass_reg = NULL;
>> +	periph_clk->bypass_shift = bypass_shift;
>> +	periph_clk->fixed_div = fixed_divider;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_cnt_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
>> new file mode 100644
>> index 0000000..ef24ca7
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-pll-s10.c
>> @@ -0,0 +1,145 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +/* Clock Manager offsets */
>> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
>> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
>> +
>> +/* PLL Clock enable bits */
>> +#define SOCFPGA_PLL_POWER		0
>> +#define SOCFPGA_PLL_RESET_MASK		0x2
>> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
>> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
>> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
>> +#define SOCFPGA_PLL_MDIV_SHIFT		24
>> +#define SWCTRLBTCLKSEL_MASK		0x200
>> +#define SWCTRLBTCLKSEL_SHIFT		9
>> +
>> +#define SOCFPGA_BOOT_CLK		"boot_clk"
>> +
>> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
>> +
>> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	unsigned long mdiv;
>> +	unsigned long refdiv;
>> +	unsigned long reg;
>> +	unsigned long long vco_freq;
>> +
>> +	/* read VCO1 reg for numerator and denominator */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate / refdiv;
>> +
>> +	/* Read mdiv and fdiv from the fdbck register */
>> +	reg = readl(socfpgaclk->hw.reg + 0x4);
>> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
>> +
>> +	return (unsigned long)vco_freq;
>> +}
>> +
>> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 div = 1;
>> +
>> +	div = ((readl(socfpgaclk->hw.reg) &
>> +		SWCTRLBTCLKSEL_MASK) >>
>> +		SWCTRLBTCLKSEL_SHIFT);
>> +	div += 1;
>> +	return parent_rate /= div;
>> +}
>> +
>> +
>> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
>> +		CLK_MGR_PLL_CLK_SRC_MASK;
>> +}
>> +
>> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
>> +		SWCTRLBTCLKSEL_MASK;
>> +}
>> +
>> +static int clk_pll_prepare(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 reg;
>> +
>> +	/* Bring PLL out of reset */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	reg |= SOCFPGA_PLL_RESET_MASK;
>> +	writel(reg, socfpgaclk->hw.reg);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct clk_ops clk_pll_ops = {
>> +	.recalc_rate = clk_pll_recalc_rate,
>> +	.get_parent = clk_pll_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +static struct clk_ops clk_boot_ops = {
>> +	.recalc_rate = clk_boot_clk_recalc_rate,
>> +	.get_parent = clk_boot_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_pll *pll_clk;
>> +	struct clk_init_data init;
>> +
>> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
>> +	if (WARN_ON(!pll_clk))
>> +		return NULL;
>> +
>> +	pll_clk->hw.reg = reg + offset;
>> +
>> +	if (streq(name, SOCFPGA_BOOT_CLK))
>> +		init.ops = &clk_boot_ops;
>> +	else
>> +		init.ops = &clk_pll_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names;
>> +	pll_clk->hw.hw.init = &init;
>> +
>> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
>> +	clk_pll_ops.enable = clk_gate_ops.enable;
>> +	clk_pll_ops.disable = clk_gate_ops.disable;
>> +
>> +	clk = clk_register(NULL, &pll_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(pll_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
>> new file mode 100644
>> index 0000000..31572cb
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-s10.c
>> @@ -0,0 +1,319 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +
>> +#include <dt-bindings/clock/stratix10-clock.h>
>> +
>> +#include "stratix10-clk.h"
>> +
>> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
>> +					"f2s_free_clk",};
>> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
>> +					 "osc1", "cb_intosc_hs_div2_clk",
>> +					 "f2s_free_clk"};
>> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
>> +
>> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
>> +					    "peri_noc_base_clk",
>> +					    "osc1", "cb_intosc_hs_div2_clk",
>> +					    "f2s_free_clk"};
>> +
>> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
>> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
>> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
>> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
>> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
>> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
>> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
>> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
>> +
>> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
>> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
>> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
>> +
>> +/* clocks in AO (always on) controller */
>> +static const struct stratix10_pll_clock s10_pll_clks[] = {
>> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
>> +	  0x0},
>> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0x74},
>> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0xe4},
>> +};
>> +
>> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
>> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
>> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
>> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF4},
>> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF8},
>> +};
>> +
>> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
>> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	   0, 0x48, 0, 0, 0},
>> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
>> +	  0, 0x4C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x50, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x54, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x58, 0, 0, 0},
>> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x5C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x60, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0x64, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x68, 0, 0, 0},
>> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x6C, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xBC, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC0, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC4, 0, 0, 0},
>> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC8, 0, 0, 0},
>> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xCC, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD0, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xD4, 0, 0, 0},
>> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD8, 0, 0, 0},
>> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
>> +	  0, 4, 0, 0},
>> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
>> +	  0, 0, 0, 0x3C, 1},
>> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
>> +	  0, 0, 4, 0xB0, 0},
>> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
>> +	  0, 0, 4, 0xB0, 1},
>> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
>> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
>> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
>> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
>> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
>> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
>> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
>> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
>> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
>> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
>> +};
>> +
>> +static const struct stratix10_gate_clock s10_gate_clks[] = {
>> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
>> +	  0, 0, 0, 0, 0x3C, 0, 0},
>> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 2},
>> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  1, 0x70, 0, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  2, 0x70, 8, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
>> +	  3, 0x70, 16, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 24, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 26, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 28, 1, 0, 0, 0},
>> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  5, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  0, 0, 0, 0, 0xDC, 26, 0},
>> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  1, 0, 0, 0, 0xDC, 27, 0},
>> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  2, 0, 0, 0, 0xDC, 28, 0},
>> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
>> +	  3, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
>> +	  4, 0xE0, 0, 16, 0, 0, 0},
>> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
>> +	  5, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
>> +	  7, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  8, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  9, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
>> +	  10, 0, 0, 0, 0, 0, 0},
>> +};
>> +
>> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
>> +				    int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
>> +					  clks[i].parent_names, clks[i].num_parents,
>> +					  clks[i].flags, base, clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
>> +				      int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
>> +					      clks[i].parent_names,
>> +					      clks[i].num_parents,
>> +					      clks[i].flags, base,
>> +					      clks[i].offset,
>> +					      clks[i].fixed_divider,
>> +					      clks[i].bypass_reg,
>> +					      clks[i].bypass_shift);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
>> +					clks[i].parent_names,
>> +					clks[i].num_parents,
>> +					clks[i].flags, base,
>> +					clks[i].gate_reg,
>> +					clks[i].gate_idx, clks[i].div_reg,
>> +					clks[i].div_offset, clks[i].div_width,
>> +					clks[i].bypass_reg,
>> +					clks[i].bypass_shift,
>> +					clks[i].fixed_div);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
>> +				    clks[i].num_parents,
>> +				    clks[i].flags, base,
>> +				    clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
>> +						    int nr_clks)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +	struct clk **clk_table;
>> +	void __iomem *base;
>> +
>> +	base = of_iomap(np, 0);
>> +	if (!base) {
>> +		pr_err("%s: failed to map clock registers\n", __func__);
>> +		goto err;
>> +	}
>> +
>> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
>> +	if (!clk_data)
>> +		goto err;
>> +
>> +	clk_data->base = base;
>> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
>> +	if (!clk_table)
>> +		goto err_data;
>> +
>> +	clk_data->clk_data.clks = clk_table;
>> +	clk_data->clk_data.clk_num = nr_clks;
>> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
>> +	return clk_data;
>> +
>> +err_data:
>> +	kfree(clk_data);
>> +err:
>> +	return NULL;
>> +}
>> +
>> +
>> +void __init socfpga_s10_init(struct device_node *node)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +
>> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
>> +
>> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
>> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
>> +
>> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
>> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
>> +				   clk_data);
>> +
>> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
>> +			      clk_data);
>> +}
>> +
>> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
>> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
>> index 9cf1230..26c3a26 100644
>> --- a/drivers/clk/socfpga/clk.h
>> +++ b/drivers/clk/socfpga/clk.h
>> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	struct regmap *sys_mgr_base_addr;
>>  	u32 width;	/* only valid if div_reg != 0 */
>>  	u32 shift;	/* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  	u32 clk_phase[2];
>>  };
>>  
>> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	u32 width;      /* only valid if div_reg != 0 */
>>  	u32 shift;      /* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  };
>>  
>>  #endif /* SOCFPGA_CLK_H */
>> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
>> new file mode 100644
>> index 0000000..10f1532
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/stratix10-clk.h
>> @@ -0,0 +1,86 @@
>> +/* SPDX-License-Identifier:    GPL-2.0 */
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +
>> +#ifndef	__STRATIX10_CLK_H
>> +#define	__STRATIX10_CLK_H
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/spinlock.h>
>> +
>> +struct platform_device;
>> +
>> +struct stratix10_clock_data {
>> +	struct clk_onecell_data	clk_data;
>> +	void __iomem		*base;
>> +};
>> +
>> +struct stratix10_pll_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_c_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_cnt_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +	u8			fixed_divider;
>> +	unsigned long		bypass_reg;
>> +	unsigned long		bypass_shift;
>> +};
>> +
>> +struct stratix10_gate_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		gate_reg;
>> +	u8			gate_idx;
>> +	unsigned long		div_reg;
>> +	u8			div_offset;
>> +	u8			div_width;
>> +	unsigned long		bypass_reg;
>> +	u8			bypass_shift;
>> +	u8			fixed_div;
>> +};
>> +
>> +struct clk *s10_register_pll(const char *, const char *const *, u8,
>> +			     unsigned long, void __iomem *, unsigned long);
>> +
>> +struct clk *s10_register_periph(const char *, const char *,
>> +				const char * const *, u8, unsigned long,
>> +				void __iomem *, unsigned long);
>> +struct clk *s10_register_cnt_periph(const char *, const char *,
>> +				    const char * const *, u8,
>> +				    unsigned long, void __iomem *,
>> +				    unsigned long, u8, unsigned long,
>> +				    unsigned long);
>> +struct clk *s10_register_gate(const char *, const char *,
>> +			      const char * const *, u8,
>> +			      unsigned long, void __iomem *,
>> +			      unsigned long, unsigned long,
>> +			      unsigned long, unsigned long, u8,
>> +			      unsigned long, unsigned long, u8);
>> +#endif	/* __STRATIX10_CLK_H */
>>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-12 14:38       ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-12 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Another gentle ping on this patch?

Thanks,
Dinh

On 03/05/2018 09:16 AM, Dinh Nguyen wrote:
> Hi Mike and Stephen,
> 
> Was wondering if you can review this patch when you get a chance?
> 
> Thanks so much,
> 
> Dinh
> 
> On 02/26/2018 08:47 AM, Dinh Nguyen wrote:
>> Add a clock driver for the Stratix10 SoC. The driver is similar to the
>> Cyclone5/Arria10 platforms, with the exception that this driver only uses
>> one single clock binding.
>>
>> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
>> ---
>> v6:
>> - minimize usage of strcmp
>> - use // as comment limiters for SPDX in c source file
>> v5:
>> - make SPDX license as a 1st separate first line comment
>> v4:
>> - move SPDX license first line of all files
>> v3:
>> - use fixed binding "intel,stratix10-clkmgr"
>> - Fix up SPDX license header
>> v2:
>> - Use a single clock binding
>> ---
>>  drivers/clk/Makefile                 |   1 +
>>  drivers/clk/socfpga/Makefile         |   5 +
>>  drivers/clk/socfpga/clk-gate-s10.c   | 124 ++++++++++++++
>>  drivers/clk/socfpga/clk-periph-s10.c | 148 ++++++++++++++++
>>  drivers/clk/socfpga/clk-pll-s10.c    | 145 ++++++++++++++++
>>  drivers/clk/socfpga/clk-s10.c        | 319 +++++++++++++++++++++++++++++++++++
>>  drivers/clk/socfpga/clk.h            |   4 +
>>  drivers/clk/socfpga/stratix10-clk.h  |  86 ++++++++++
>>  8 files changed, 832 insertions(+)
>>  create mode 100644 drivers/clk/socfpga/clk-gate-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-periph-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-pll-s10.c
>>  create mode 100644 drivers/clk/socfpga/clk-s10.c
>>  create mode 100644 drivers/clk/socfpga/stratix10-clk.h
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 71ec41e..80ab422 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -88,6 +88,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
>>  obj-$(CONFIG_PLAT_SPEAR)		+= spear/
>>  obj-$(CONFIG_ARCH_SPRD)			+= sprd/
>>  obj-$(CONFIG_ARCH_STI)			+= st/
>> +obj-$(CONFIG_ARCH_STRATIX10)		+= socfpga/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
>>  obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
>>  obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
>> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
>> index 9146c20..87ef977 100644
>> --- a/drivers/clk/socfpga/Makefile
>> +++ b/drivers/clk/socfpga/Makefile
>> @@ -1,6 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0
>> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
>>  obj-y += clk.o
>>  obj-y += clk-gate.o
>>  obj-y += clk-pll.o
>>  obj-y += clk-periph.o
>>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
>> +else
>> +obj-y += clk-s10.o
>> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
>> +endif
>> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
>> new file mode 100644
>> index 0000000..5b09aef
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-gate-s10.c
>> @@ -0,0 +1,124 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include "clk.h"
>> +
>> +#define SOCFPGA_CS_PDBG_CLK	"cs_pdbg_clk"
>> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
>> +
>> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else if (socfpgaclk->div_reg) {
>> +		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +		val &= GENMASK(socfpgaclk->width - 1, 0);
>> +		div = (1 << val);
>> +	}
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
>> +						  unsigned long parent_rate)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 div = 1, val;
>> +
>> +	val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
>> +	val &= GENMASK(socfpgaclk->width - 1, 0);
>> +	div = (1 << val);
>> +	div = div ? 4 : 1;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
>> +	u32 mask;
>> +	u8 parent = 0;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			  socfpgaclk->bypass_shift);
>> +	}
>> +	return parent;
>> +}
>> +
>> +static struct clk_ops gateclk_ops = {
>> +	.recalc_rate = socfpga_gate_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +static struct clk_ops dbgclk_ops = {
>> +	.recalc_rate = socfpga_dbg_clk_recalc_rate,
>> +	.get_parent = socfpga_gate_get_parent,
>> +};
>> +
>> +struct clk *s10_register_gate(char *name, const char *parent_name,
>> +			      const char * const *parent_names,
>> +			      u8 num_parents, unsigned long flags,
>> +			      void __iomem *regbase, unsigned long gate_reg,
>> +			      unsigned long gate_idx, unsigned long div_reg,
>> +			      unsigned long div_offset, u8 div_width,
>> +			      unsigned long bypass_reg, u8 bypass_shift,
>> +			      u8 fixed_div)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_gate_clk *socfpga_clk;
>> +	struct clk_init_data init;
>> +
>> +	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
>> +	if (WARN_ON(!socfpga_clk))
>> +		return NULL;
>> +
>> +	socfpga_clk->hw.reg = regbase + gate_reg;
>> +	socfpga_clk->hw.bit_idx = gate_idx;
>> +
>> +	gateclk_ops.enable = clk_gate_ops.enable;
>> +	gateclk_ops.disable = clk_gate_ops.disable;
>> +
>> +	socfpga_clk->fixed_div = fixed_div;
>> +
>> +	if (div_reg)
>> +		socfpga_clk->div_reg = regbase + div_reg;
>> +	else
>> +		socfpga_clk->div_reg = NULL;
>> +
>> +	socfpga_clk->width = div_width;
>> +	socfpga_clk->shift = div_offset;
>> +
>> +	if (bypass_reg)
>> +		socfpga_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		socfpga_clk->bypass_reg = NULL;
>> +	socfpga_clk->bypass_shift = bypass_shift;
>> +
>> +	if (streq(name, SOCFPGA_CS_PDBG_CLK))
>> +		init.ops = &dbgclk_ops;
>> +	else
>> +		init.ops = &gateclk_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +	socfpga_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &socfpga_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(socfpga_clk);
>> +		return NULL;
>> +	}
>> +
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
>> new file mode 100644
>> index 0000000..6021ac1
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-periph-s10.c
>> @@ -0,0 +1,148 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +#define CLK_MGR_FREE_SHIFT		16
>> +#define CLK_MGR_FREE_MASK		0x7
>> +#define SWCTRLBTCLKSEN_SHIFT		8
>> +
>> +#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
>> +
>> +static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +	u32 val;
>> +
>> +	val = readl(socfpgaclk->hw.reg);
>> +	val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
>> +	parent_rate /= val;
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
>> +					     unsigned long parent_rate)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	unsigned long div = 1;
>> +
>> +	if (socfpgaclk->fixed_div) {
>> +		div = socfpgaclk->fixed_div;
>> +	} else {
>> +		if (!socfpgaclk->bypass_reg)
>> +			div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
>> +	}
>> +
>> +	return parent_rate / div;
>> +}
>> +
>> +static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
>> +	u32 clk_src, mask;
>> +	u8 parent;
>> +
>> +	if (socfpgaclk->bypass_reg) {
>> +		mask = (0x1 << socfpgaclk->bypass_shift);
>> +		parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
>> +			   socfpgaclk->bypass_shift);
>> +	} else {
>> +		clk_src = readl(socfpgaclk->hw.reg);
>> +		parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
>> +			CLK_MGR_FREE_MASK;
>> +	}
>> +	return parent;
>> +}
>> +
>> +static const struct clk_ops peri_c_clk_ops = {
>> +	.recalc_rate = clk_peri_c_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +static const struct clk_ops peri_cnt_clk_ops = {
>> +	.recalc_rate = clk_peri_cnt_clk_recalc_rate,
>> +	.get_parent = clk_periclk_get_parent,
>> +};
>> +
>> +struct clk *s10_register_periph(char *name, const char *parent_name,
>> +				const char * const *parent_names,
>> +				u8 num_parents, unsigned long flags,
>> +				void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	periph_clk->hw.reg = reg + offset;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_c_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> +
>> +struct clk *s10_register_cnt_periph(char *name, const char *parent_name,
>> +				    const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *regbase, unsigned long offset,
>> +				    u8 fixed_divider, unsigned long bypass_reg,
>> +				    unsigned long bypass_shift)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_periph_clk *periph_clk;
>> +	struct clk_init_data init;
>> +
>> +	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
>> +	if (WARN_ON(!periph_clk))
>> +		return NULL;
>> +
>> +	if (offset)
>> +		periph_clk->hw.reg = regbase + offset;
>> +	else
>> +		periph_clk->hw.reg = NULL;
>> +
>> +	if (bypass_reg)
>> +		periph_clk->bypass_reg = regbase + bypass_reg;
>> +	else
>> +		periph_clk->bypass_reg = NULL;
>> +	periph_clk->bypass_shift = bypass_shift;
>> +	periph_clk->fixed_div = fixed_divider;
>> +
>> +	init.name = name;
>> +	init.ops = &peri_cnt_clk_ops;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names ? parent_names : &parent_name;
>> +
>> +	periph_clk->hw.hw.init = &init;
>> +
>> +	clk = clk_register(NULL, &periph_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(periph_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
>> new file mode 100644
>> index 0000000..ef24ca7
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-pll-s10.c
>> @@ -0,0 +1,145 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include "clk.h"
>> +
>> +/* Clock Manager offsets */
>> +#define CLK_MGR_PLL_CLK_SRC_SHIFT	16
>> +#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
>> +
>> +/* PLL Clock enable bits */
>> +#define SOCFPGA_PLL_POWER		0
>> +#define SOCFPGA_PLL_RESET_MASK		0x2
>> +#define SOCFPGA_PLL_REFDIV_MASK		0x00003F00
>> +#define SOCFPGA_PLL_REFDIV_SHIFT	8
>> +#define SOCFPGA_PLL_MDIV_MASK		0xFF000000
>> +#define SOCFPGA_PLL_MDIV_SHIFT		24
>> +#define SWCTRLBTCLKSEL_MASK		0x200
>> +#define SWCTRLBTCLKSEL_SHIFT		9
>> +
>> +#define SOCFPGA_BOOT_CLK		"boot_clk"
>> +
>> +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
>> +
>> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	unsigned long mdiv;
>> +	unsigned long refdiv;
>> +	unsigned long reg;
>> +	unsigned long long vco_freq;
>> +
>> +	/* read VCO1 reg for numerator and denominator */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate / refdiv;
>> +
>> +	/* Read mdiv and fdiv from the fdbck register */
>> +	reg = readl(socfpgaclk->hw.reg + 0x4);
>> +	mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
>> +	vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
>> +
>> +	return (unsigned long)vco_freq;
>> +}
>> +
>> +static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
>> +					 unsigned long parent_rate)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 div = 1;
>> +
>> +	div = ((readl(socfpgaclk->hw.reg) &
>> +		SWCTRLBTCLKSEL_MASK) >>
>> +		SWCTRLBTCLKSEL_SHIFT);
>> +	div += 1;
>> +	return parent_rate /= div;
>> +}
>> +
>> +
>> +static u8 clk_pll_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
>> +		CLK_MGR_PLL_CLK_SRC_MASK;
>> +}
>> +
>> +static u8 clk_boot_get_parent(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 pll_src;
>> +
>> +	pll_src = readl(socfpgaclk->hw.reg);
>> +	return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
>> +		SWCTRLBTCLKSEL_MASK;
>> +}
>> +
>> +static int clk_pll_prepare(struct clk_hw *hwclk)
>> +{
>> +	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
>> +	u32 reg;
>> +
>> +	/* Bring PLL out of reset */
>> +	reg = readl(socfpgaclk->hw.reg);
>> +	reg |= SOCFPGA_PLL_RESET_MASK;
>> +	writel(reg, socfpgaclk->hw.reg);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct clk_ops clk_pll_ops = {
>> +	.recalc_rate = clk_pll_recalc_rate,
>> +	.get_parent = clk_pll_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +static struct clk_ops clk_boot_ops = {
>> +	.recalc_rate = clk_boot_clk_recalc_rate,
>> +	.get_parent = clk_boot_get_parent,
>> +	.prepare = clk_pll_prepare,
>> +};
>> +
>> +struct clk *s10_register_pll(const char *name, const char * const *parent_names,
>> +				    u8 num_parents, unsigned long flags,
>> +				    void __iomem *reg, unsigned long offset)
>> +{
>> +	struct clk *clk;
>> +	struct socfpga_pll *pll_clk;
>> +	struct clk_init_data init;
>> +
>> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
>> +	if (WARN_ON(!pll_clk))
>> +		return NULL;
>> +
>> +	pll_clk->hw.reg = reg + offset;
>> +
>> +	if (streq(name, SOCFPGA_BOOT_CLK))
>> +		init.ops = &clk_boot_ops;
>> +	else
>> +		init.ops = &clk_pll_ops;
>> +
>> +	init.name = name;
>> +	init.flags = flags;
>> +
>> +	init.num_parents = num_parents;
>> +	init.parent_names = parent_names;
>> +	pll_clk->hw.hw.init = &init;
>> +
>> +	pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
>> +	clk_pll_ops.enable = clk_gate_ops.enable;
>> +	clk_pll_ops.disable = clk_gate_ops.disable;
>> +
>> +	clk = clk_register(NULL, &pll_clk->hw.hw);
>> +	if (WARN_ON(IS_ERR(clk))) {
>> +		kfree(pll_clk);
>> +		return NULL;
>> +	}
>> +	return clk;
>> +}
>> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
>> new file mode 100644
>> index 0000000..31572cb
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/clk-s10.c
>> @@ -0,0 +1,319 @@
>> +// SPDX-License-Identifier:	GPL-2.0
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +
>> +#include <dt-bindings/clock/stratix10-clock.h>
>> +
>> +#include "stratix10-clk.h"
>> +
>> +static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
>> +					"f2s_free_clk",};
>> +static const char * const cntr_mux[] = { "main_pll", "periph_pll",
>> +					 "osc1", "cb_intosc_hs_div2_clk",
>> +					 "f2s_free_clk"};
>> +static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
>> +
>> +static const char * const noc_free_mux[] = {"main_noc_base_clk",
>> +					    "peri_noc_base_clk",
>> +					    "osc1", "cb_intosc_hs_div2_clk",
>> +					    "f2s_free_clk"};
>> +
>> +static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
>> +static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
>> +static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
>> +static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
>> +static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
>> +static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
>> +static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
>> +static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
>> +
>> +static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
>> +static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
>> +static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
>> +
>> +/* clocks in AO (always on) controller */
>> +static const struct stratix10_pll_clock s10_pll_clks[] = {
>> +	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
>> +	  0x0},
>> +	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0x74},
>> +	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
>> +	  0, 0xe4},
>> +};
>> +
>> +static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
>> +	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", 0, 1, 0, 0x84},
>> +	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", 0, 1, 0, 0x88},
>> +	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF4},
>> +	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", 0, 1, 0,
>> +	  0xF8},
>> +};
>> +
>> +static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
>> +	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	   0, 0x48, 0, 0, 0},
>> +	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
>> +	  0, 0x4C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x50, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x54, 0, 0, 0},
>> +	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x58, 0, 0, 0},
>> +	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x5C, 0, 0, 0},
>> +	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x60, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0x64, 0, 0, 0},
>> +	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x68, 0, 0, 0},
>> +	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
>> +	  0x6C, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xBC, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC0, 0, 0, 0},
>> +	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC4, 0, 0, 0},
>> +	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xC8, 0, 0, 0},
>> +	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xCC, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD0, 0, 0, 0},
>> +	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
>> +	  0, 0xD4, 0, 0, 0},
>> +	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
>> +	  0xD8, 0, 0, 0},
>> +	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
>> +	  0, 4, 0, 0},
>> +	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
>> +	  0, 0, 0, 0x3C, 1},
>> +	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
>> +	  0, 0, 4, 0xB0, 0},
>> +	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
>> +	  0, 0, 4, 0xB0, 1},
>> +	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
>> +	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
>> +	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
>> +	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
>> +	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
>> +	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
>> +	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
>> +	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
>> +	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
>> +	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
>> +};
>> +
>> +static const struct stratix10_gate_clock s10_gate_clks[] = {
>> +	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
>> +	  0, 0, 0, 0, 0x3C, 0, 0},
>> +	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
>> +	  0, 0, 0, 0, 0, 0, 2},
>> +	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  1, 0x70, 0, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  2, 0x70, 8, 2, 0, 0, 0},
>> +	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
>> +	  3, 0x70, 16, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 24, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 26, 2, 0, 0, 0},
>> +	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
>> +	  4, 0x70, 28, 1, 0, 0, 0},
>> +	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
>> +	  5, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  0, 0, 0, 0, 0xDC, 26, 0},
>> +	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  1, 0, 0, 0, 0xDC, 27, 0},
>> +	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
>> +	  2, 0, 0, 0, 0xDC, 28, 0},
>> +	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
>> +	  3, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
>> +	  4, 0xE0, 0, 16, 0, 0, 0},
>> +	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
>> +	  5, 0, 0, 0, 0, 0, 4},
>> +	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
>> +	  6, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
>> +	  7, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  8, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
>> +	  9, 0, 0, 0, 0, 0, 0},
>> +	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
>> +	  10, 0, 0, 0, 0, 0, 0},
>> +};
>> +
>> +static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
>> +				    int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
>> +					  clks[i].parent_names, clks[i].num_parents,
>> +					  clks[i].flags, base, clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
>> +				      int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
>> +					      clks[i].parent_names,
>> +					      clks[i].num_parents,
>> +					      clks[i].flags, base,
>> +					      clks[i].offset,
>> +					      clks[i].fixed_divider,
>> +					      clks[i].bypass_reg,
>> +					      clks[i].bypass_shift);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
>> +					clks[i].parent_names,
>> +					clks[i].num_parents,
>> +					clks[i].flags, base,
>> +					clks[i].gate_reg,
>> +					clks[i].gate_idx, clks[i].div_reg,
>> +					clks[i].div_offset, clks[i].div_width,
>> +					clks[i].bypass_reg,
>> +					clks[i].bypass_shift,
>> +					clks[i].fixed_div);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
>> +				 int nums, struct stratix10_clock_data *data)
>> +{
>> +	struct clk *clk;
>> +	void __iomem *base = data->base;
>> +	int i;
>> +
>> +	for (i = 0; i < nums; i++) {
>> +		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
>> +				    clks[i].num_parents,
>> +				    clks[i].flags, base,
>> +				    clks[i].offset);
>> +		if (IS_ERR(clk)) {
>> +			pr_err("%s: failed to register clock %s\n",
>> +			       __func__, clks[i].name);
>> +			continue;
>> +		}
>> +		data->clk_data.clks[clks[i].id] = clk;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
>> +						    int nr_clks)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +	struct clk **clk_table;
>> +	void __iomem *base;
>> +
>> +	base = of_iomap(np, 0);
>> +	if (!base) {
>> +		pr_err("%s: failed to map clock registers\n", __func__);
>> +		goto err;
>> +	}
>> +
>> +	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
>> +	if (!clk_data)
>> +		goto err;
>> +
>> +	clk_data->base = base;
>> +	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
>> +	if (!clk_table)
>> +		goto err_data;
>> +
>> +	clk_data->clk_data.clks = clk_table;
>> +	clk_data->clk_data.clk_num = nr_clks;
>> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
>> +	return clk_data;
>> +
>> +err_data:
>> +	kfree(clk_data);
>> +err:
>> +	return NULL;
>> +}
>> +
>> +
>> +void __init socfpga_s10_init(struct device_node *node)
>> +{
>> +	struct stratix10_clock_data *clk_data;
>> +
>> +	clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
>> +
>> +	s10_clk_register_c_perip(s10_main_perip_c_clks,
>> +				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
>> +
>> +	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
>> +				   ARRAY_SIZE(s10_main_perip_cnt_clks),
>> +				   clk_data);
>> +
>> +	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
>> +			      clk_data);
>> +}
>> +
>> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
>> diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
>> index 9cf1230..26c3a26 100644
>> --- a/drivers/clk/socfpga/clk.h
>> +++ b/drivers/clk/socfpga/clk.h
>> @@ -54,9 +54,11 @@ struct socfpga_gate_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	struct regmap *sys_mgr_base_addr;
>>  	u32 width;	/* only valid if div_reg != 0 */
>>  	u32 shift;	/* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  	u32 clk_phase[2];
>>  };
>>  
>> @@ -65,8 +67,10 @@ struct socfpga_periph_clk {
>>  	char *parent_name;
>>  	u32 fixed_div;
>>  	void __iomem *div_reg;
>> +	void __iomem *bypass_reg;
>>  	u32 width;      /* only valid if div_reg != 0 */
>>  	u32 shift;      /* only valid if div_reg != 0 */
>> +	u32 bypass_shift;      /* only valid if bypass_reg != 0 */
>>  };
>>  
>>  #endif /* SOCFPGA_CLK_H */
>> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
>> new file mode 100644
>> index 0000000..10f1532
>> --- /dev/null
>> +++ b/drivers/clk/socfpga/stratix10-clk.h
>> @@ -0,0 +1,86 @@
>> +/* SPDX-License-Identifier:    GPL-2.0 */
>> +/*
>> + * Copyright (C) 2017, Intel Corporation
>> + */
>> +
>> +#ifndef	__STRATIX10_CLK_H
>> +#define	__STRATIX10_CLK_H
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/spinlock.h>
>> +
>> +struct platform_device;
>> +
>> +struct stratix10_clock_data {
>> +	struct clk_onecell_data	clk_data;
>> +	void __iomem		*base;
>> +};
>> +
>> +struct stratix10_pll_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_c_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +};
>> +
>> +struct stratix10_perip_cnt_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		offset;
>> +	u8			fixed_divider;
>> +	unsigned long		bypass_reg;
>> +	unsigned long		bypass_shift;
>> +};
>> +
>> +struct stratix10_gate_clock {
>> +	unsigned int		id;
>> +	const char		*name;
>> +	const char		*parent_name;
>> +	const char		*const *parent_names;
>> +	u8			num_parents;
>> +	unsigned long		flags;
>> +	unsigned long		gate_reg;
>> +	u8			gate_idx;
>> +	unsigned long		div_reg;
>> +	u8			div_offset;
>> +	u8			div_width;
>> +	unsigned long		bypass_reg;
>> +	u8			bypass_shift;
>> +	u8			fixed_div;
>> +};
>> +
>> +struct clk *s10_register_pll(const char *, const char *const *, u8,
>> +			     unsigned long, void __iomem *, unsigned long);
>> +
>> +struct clk *s10_register_periph(const char *, const char *,
>> +				const char * const *, u8, unsigned long,
>> +				void __iomem *, unsigned long);
>> +struct clk *s10_register_cnt_periph(const char *, const char *,
>> +				    const char * const *, u8,
>> +				    unsigned long, void __iomem *,
>> +				    unsigned long, u8, unsigned long,
>> +				    unsigned long);
>> +struct clk *s10_register_gate(const char *, const char *,
>> +			      const char * const *, u8,
>> +			      unsigned long, void __iomem *,
>> +			      unsigned long, unsigned long,
>> +			      unsigned long, unsigned long, u8,
>> +			      unsigned long, unsigned long, u8);
>> +#endif	/* __STRATIX10_CLK_H */
>>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
  2018-02-26 14:47 ` Dinh Nguyen
  (?)
@ 2018-03-19 18:08   ` Stephen Boyd
  -1 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:08 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:33)
> diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> new file mode 100644
> index 0000000..0652ff1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> @@ -0,0 +1,51 @@
> +Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible : shall be
> +       "intel,stratix10-clkmgr"
> +
> +- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
> +
> +- #clock-cells : from common clock binding, shall be set to 1.
> +
> +- clocks : Should contain fixed-clock sources, such as oscillators.
> +
> +Example:
> +       clkmgr: clock-controller@ffd10000 {
> +               compatible = "intel,stratix10-clkmgr";
> +               reg = <0xffd10000 0x1000>;
> +               #clock-cells = <1>;
> +
> +               clocks {

Why do we need a subnode for clocks inside of a clock controller node?

> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;

What is this for? I would think oscillators go into the root of the DT
because they're on the board, not inside the clock controller.

> +                       };
> +
> +                       cb_intosc_ls_clk: cb-intosc-ls-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +
> +                       f2s_free_clk: f2s-free-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +
> +                       osc1: osc1 {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +               };
> +       };

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-03-19 18:08   ` Stephen Boyd
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:08 UTC (permalink / raw)
  To: Dinh Nguyen, linux-clk
  Cc: mark.rutland, devicetree, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:33)
> diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b=
/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> new file mode 100644
> index 0000000..0652ff1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> @@ -0,0 +1,51 @@
> +Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible : shall be
> +       "intel,stratix10-clkmgr"
> +
> +- reg : shall be the control register offset from CLOCK_MANAGER's base f=
or the clock.
> +
> +- #clock-cells : from common clock binding, shall be set to 1.
> +
> +- clocks : Should contain fixed-clock sources, such as oscillators.
> +
> +Example:
> +       clkmgr: clock-controller@ffd10000 {
> +               compatible =3D "intel,stratix10-clkmgr";
> +               reg =3D <0xffd10000 0x1000>;
> +               #clock-cells =3D <1>;
> +
> +               clocks {

Why do we need a subnode for clocks inside of a clock controller node?

> +                       #address-cells =3D <1>;
> +                       #size-cells =3D <0>;
> +
> +                       cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
> +                               #clock-cells =3D <0>;
> +                               compatible =3D "fixed-clock";
> +                               clock-frequency =3D <25000000>;

What is this for? I would think oscillators go into the root of the DT
because they're on the board, not inside the clock controller.

> +                       };
> +
> +                       cb_intosc_ls_clk: cb-intosc-ls-clk {
> +                               #clock-cells =3D <0>;
> +                               compatible =3D "fixed-clock";
> +                               clock-frequency =3D <25000000>;
> +                       };
> +
> +                       f2s_free_clk: f2s-free-clk {
> +                               #clock-cells =3D <0>;
> +                               compatible =3D "fixed-clock";
> +                               clock-frequency =3D <25000000>;
> +                       };
> +
> +                       osc1: osc1 {
> +                               #clock-cells =3D <0>;
> +                               compatible =3D "fixed-clock";
> +                               clock-frequency =3D <25000000>;
> +                       };
> +               };
> +       };

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-03-19 18:08   ` Stephen Boyd
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:08 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:33)
> diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> new file mode 100644
> index 0000000..0652ff1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
> @@ -0,0 +1,51 @@
> +Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible : shall be
> +       "intel,stratix10-clkmgr"
> +
> +- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
> +
> +- #clock-cells : from common clock binding, shall be set to 1.
> +
> +- clocks : Should contain fixed-clock sources, such as oscillators.
> +
> +Example:
> +       clkmgr: clock-controller at ffd10000 {
> +               compatible = "intel,stratix10-clkmgr";
> +               reg = <0xffd10000 0x1000>;
> +               #clock-cells = <1>;
> +
> +               clocks {

Why do we need a subnode for clocks inside of a clock controller node?

> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;

What is this for? I would think oscillators go into the root of the DT
because they're on the board, not inside the clock controller.

> +                       };
> +
> +                       cb_intosc_ls_clk: cb-intosc-ls-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +
> +                       f2s_free_clk: f2s-free-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +
> +                       osc1: osc1 {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                               clock-frequency = <25000000>;
> +                       };
> +               };
> +       };

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
  2018-02-26 14:47   ` Dinh Nguyen
  (?)
@ 2018-03-19 18:17     ` Stephen Boyd
  -1 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:17 UTC (permalink / raw)
  To: linux-clk
  Cc: mark.rutland, devicetree, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:35)
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)

Ugh, any chance to make this better if we get three?

>  obj-y += clk.o
>  obj-y += clk-gate.o
>  obj-y += clk-pll.o
>  obj-y += clk-periph.o
>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y += clk-s10.o
> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:    GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK    "cs_pdbg_clk"

Drop the define? It's used once.

> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_rate)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 div = 1, val;
> +
> +       if (socfpgaclk->fixed_div) {
> +               div = socfpgaclk->fixed_div;
> +       } else if (socfpgaclk->div_reg) {
> +               val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +               val &= GENMASK(socfpgaclk->width - 1, 0);
> +               div = (1 << val);
> +       }
> +       return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_rate)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 div = 1, val;
> +
> +       val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +       val &= GENMASK(socfpgaclk->width - 1, 0);
> +       div = (1 << val);
> +       div = div ? 4 : 1;
> +
> +       return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 mask;
> +       u8 parent = 0;
> +
> +       if (socfpgaclk->bypass_reg) {
> +               mask = (0x1 << socfpgaclk->bypass_shift);
> +               parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +                         socfpgaclk->bypass_shift);
> +       }
> +       return parent;
> +}
> +
> +static struct clk_ops gateclk_ops = {

const?

> +       .recalc_rate = socfpga_gate_clk_recalc_rate,
> +       .get_parent = socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops = {

const?

> +       .recalc_rate = socfpga_dbg_clk_recalc_rate,
> +       .get_parent = socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +                             const char * const *parent_names,
> +                             u8 num_parents, unsigned long flags,
> +                             void __iomem *regbase, unsigned long gate_reg,
> +                             unsigned long gate_idx, unsigned long div_reg,
> +                             unsigned long div_offset, u8 div_width,
> +                             unsigned long bypass_reg, u8 bypass_shift,
> +                             u8 fixed_div)
> +{
> +       struct clk *clk;
> +       struct socfpga_gate_clk *socfpga_clk;
> +       struct clk_init_data init;
> +
> +       socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +       if (WARN_ON(!socfpga_clk))

Allocation failures already print a nice stack so maybe just return NULL
if nothing allocates.

> +               return NULL;
> +
> +       socfpga_clk->hw.reg = regbase + gate_reg;
> +       socfpga_clk->hw.bit_idx = gate_idx;
> +
> +       gateclk_ops.enable = clk_gate_ops.enable;
> +       gateclk_ops.disable = clk_gate_ops.disable;
> +
> +       socfpga_clk->fixed_div = fixed_div;
> +
> +       if (div_reg)
> +               socfpga_clk->div_reg = regbase + div_reg;
> +       else
> +               socfpga_clk->div_reg = NULL;
> +
> +       socfpga_clk->width = div_width;
> +       socfpga_clk->shift = div_offset;
> +
> +       if (bypass_reg)
> +               socfpga_clk->bypass_reg = regbase + bypass_reg;
> +       else
> +               socfpga_clk->bypass_reg = NULL;
> +       socfpga_clk->bypass_shift = bypass_shift;
> +
> +       if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +               init.ops = &dbgclk_ops;
> +       else
> +               init.ops = &gateclk_ops;
> +
> +       init.name = name;
> +       init.flags = flags;
> +
> +       init.num_parents = num_parents;
> +       init.parent_names = parent_names ? parent_names : &parent_name;
> +       socfpga_clk->hw.hw.init = &init;
> +
> +       clk = clk_register(NULL, &socfpga_clk->hw.hw);
> +       if (WARN_ON(IS_ERR(clk))) {
> +               kfree(socfpga_clk);
> +               return NULL;
> +       }
> +
> +       return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
[...]
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +                                int nums, struct stratix10_clock_data *data)
> +{
> +       struct clk *clk;
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               clk = s10_register_pll(clks[i].name, clks[i].parent_names,
> +                                   clks[i].num_parents,
> +                                   clks[i].flags, base,
> +                                   clks[i].offset);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +
> +       return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,

static?

> +                                                   int nr_clks)
> +{
> +       struct stratix10_clock_data *clk_data;
> +       struct clk **clk_table;
> +       void __iomem *base;
> +
> +       base = of_iomap(np, 0);
> +       if (!base) {
> +               pr_err("%s: failed to map clock registers\n", __func__);
> +               goto err;
> +       }
> +
> +       clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +       if (!clk_data)
> +               goto err;
> +
> +       clk_data->base = base;
> +       clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +       if (!clk_table)
> +               goto err_data;
> +
> +       clk_data->clk_data.clks = clk_table;
> +       clk_data->clk_data.clk_num = nr_clks;
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> +       return clk_data;
> +
> +err_data:
> +       kfree(clk_data);
> +err:
> +       return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)

static?

> +{
> +       struct stratix10_clock_data *clk_data;
> +
> +       clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
> +
> +       s10_clk_register_c_perip(s10_main_perip_c_clks,
> +                                ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
> +
> +       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
> +                                  clk_data);
> +
> +       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +                             clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);

Can it be a platform device? We prefer those over the CLK_OF_DECLARE
style.

> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef        __STRATIX10_CLK_H
> +#define        __STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>

Why include this? And why clk-provider.h?

> +
> +struct platform_device;

Why?

> +
> +struct stratix10_clock_data {
> +       struct clk_onecell_data clk_data;
> +       void __iomem            *base;
> +};

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-19 18:17     ` Stephen Boyd
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:17 UTC (permalink / raw)
  To: Dinh Nguyen, linux-clk
  Cc: mark.rutland, devicetree, mturquette, dinguyen, robh+dt,
	linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:35)
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)

Ugh, any chance to make this better if we get three?

>  obj-y +=3D clk.o
>  obj-y +=3D clk-gate.o
>  obj-y +=3D clk-pll.o
>  obj-y +=3D clk-periph.o
>  obj-y +=3D clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y +=3D clk-s10.o
> +obj-y +=3D clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk=
-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:    GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK    "cs_pdbg_clk"

Drop the define? It's used once.

> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, =
hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_ra=
te)
> +{
> +       struct socfpga_gate_clk *socfpgaclk =3D to_socfpga_gate_clk(hwclk=
);
> +       u32 div =3D 1, val;
> +
> +       if (socfpgaclk->fixed_div) {
> +               div =3D socfpgaclk->fixed_div;
> +       } else if (socfpgaclk->div_reg) {
> +               val =3D readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +               val &=3D GENMASK(socfpgaclk->width - 1, 0);
> +               div =3D (1 << val);
> +       }
> +       return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_ra=
te)
> +{
> +       struct socfpga_gate_clk *socfpgaclk =3D to_socfpga_gate_clk(hwclk=
);
> +       u32 div =3D 1, val;
> +
> +       val =3D readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +       val &=3D GENMASK(socfpgaclk->width - 1, 0);
> +       div =3D (1 << val);
> +       div =3D div ? 4 : 1;
> +
> +       return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +       struct socfpga_gate_clk *socfpgaclk =3D to_socfpga_gate_clk(hwclk=
);
> +       u32 mask;
> +       u8 parent =3D 0;
> +
> +       if (socfpgaclk->bypass_reg) {
> +               mask =3D (0x1 << socfpgaclk->bypass_shift);
> +               parent =3D ((readl(socfpgaclk->bypass_reg) & mask) >>
> +                         socfpgaclk->bypass_shift);
> +       }
> +       return parent;
> +}
> +
> +static struct clk_ops gateclk_ops =3D {

const?

> +       .recalc_rate =3D socfpga_gate_clk_recalc_rate,
> +       .get_parent =3D socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops =3D {

const?

> +       .recalc_rate =3D socfpga_dbg_clk_recalc_rate,
> +       .get_parent =3D socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +                             const char * const *parent_names,
> +                             u8 num_parents, unsigned long flags,
> +                             void __iomem *regbase, unsigned long gate_r=
eg,
> +                             unsigned long gate_idx, unsigned long div_r=
eg,
> +                             unsigned long div_offset, u8 div_width,
> +                             unsigned long bypass_reg, u8 bypass_shift,
> +                             u8 fixed_div)
> +{
> +       struct clk *clk;
> +       struct socfpga_gate_clk *socfpga_clk;
> +       struct clk_init_data init;
> +
> +       socfpga_clk =3D kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +       if (WARN_ON(!socfpga_clk))

Allocation failures already print a nice stack so maybe just return NULL
if nothing allocates.

> +               return NULL;
> +
> +       socfpga_clk->hw.reg =3D regbase + gate_reg;
> +       socfpga_clk->hw.bit_idx =3D gate_idx;
> +
> +       gateclk_ops.enable =3D clk_gate_ops.enable;
> +       gateclk_ops.disable =3D clk_gate_ops.disable;
> +
> +       socfpga_clk->fixed_div =3D fixed_div;
> +
> +       if (div_reg)
> +               socfpga_clk->div_reg =3D regbase + div_reg;
> +       else
> +               socfpga_clk->div_reg =3D NULL;
> +
> +       socfpga_clk->width =3D div_width;
> +       socfpga_clk->shift =3D div_offset;
> +
> +       if (bypass_reg)
> +               socfpga_clk->bypass_reg =3D regbase + bypass_reg;
> +       else
> +               socfpga_clk->bypass_reg =3D NULL;
> +       socfpga_clk->bypass_shift =3D bypass_shift;
> +
> +       if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +               init.ops =3D &dbgclk_ops;
> +       else
> +               init.ops =3D &gateclk_ops;
> +
> +       init.name =3D name;
> +       init.flags =3D flags;
> +
> +       init.num_parents =3D num_parents;
> +       init.parent_names =3D parent_names ? parent_names : &parent_name;
> +       socfpga_clk->hw.hw.init =3D &init;
> +
> +       clk =3D clk_register(NULL, &socfpga_clk->hw.hw);
> +       if (WARN_ON(IS_ERR(clk))) {
> +               kfree(socfpga_clk);
> +               return NULL;
> +       }
> +
> +       return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
[...]
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +                                int nums, struct stratix10_clock_data *d=
ata)
> +{
> +       struct clk *clk;
> +       void __iomem *base =3D data->base;
> +       int i;
> +
> +       for (i =3D 0; i < nums; i++) {
> +               clk =3D s10_register_pll(clks[i].name, clks[i].parent_nam=
es,
> +                                   clks[i].num_parents,
> +                                   clks[i].flags, base,
> +                                   clks[i].offset);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +               data->clk_data.clks[clks[i].id] =3D clk;
> +       }
> +
> +       return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *=
np,

static?

> +                                                   int nr_clks)
> +{
> +       struct stratix10_clock_data *clk_data;
> +       struct clk **clk_table;
> +       void __iomem *base;
> +
> +       base =3D of_iomap(np, 0);
> +       if (!base) {
> +               pr_err("%s: failed to map clock registers\n", __func__);
> +               goto err;
> +       }
> +
> +       clk_data =3D kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +       if (!clk_data)
> +               goto err;
> +
> +       clk_data->base =3D base;
> +       clk_table =3D kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +       if (!clk_table)
> +               goto err_data;
> +
> +       clk_data->clk_data.clks =3D clk_table;
> +       clk_data->clk_data.clk_num =3D nr_clks;
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_da=
ta);
> +       return clk_data;
> +
> +err_data:
> +       kfree(clk_data);
> +err:
> +       return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)

static?

> +{
> +       struct stratix10_clock_data *clk_data;
> +
> +       clk_data =3D __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_=
data);
> +
> +       s10_clk_register_c_perip(s10_main_perip_c_clks,
> +                                ARRAY_SIZE(s10_main_perip_c_clks), clk_d=
ata);
> +
> +       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
> +                                  clk_data);
> +
> +       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +                             clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_in=
it);

Can it be a platform device? We prefer those over the CLK_OF_DECLARE
style.

> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/st=
ratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef        __STRATIX10_CLK_H
> +#define        __STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>

Why include this? And why clk-provider.h?

> +
> +struct platform_device;

Why?

> +
> +struct stratix10_clock_data {
> +       struct clk_onecell_data clk_data;
> +       void __iomem            *base;
> +};

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-19 18:17     ` Stephen Boyd
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Boyd @ 2018-03-19 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Dinh Nguyen (2018-02-26 06:47:35)
> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
> index 9146c20..87ef977 100644
> --- a/drivers/clk/socfpga/Makefile
> +++ b/drivers/clk/socfpga/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0
> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)

Ugh, any chance to make this better if we get three?

>  obj-y += clk.o
>  obj-y += clk-gate.o
>  obj-y += clk-pll.o
>  obj-y += clk-periph.o
>  obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
> +else
> +obj-y += clk-s10.o
> +obj-y += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
> +endif
> diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
> new file mode 100644
> index 0000000..5b09aef
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-gate-s10.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier:    GPL-2.0
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include "clk.h"
> +
> +#define SOCFPGA_CS_PDBG_CLK    "cs_pdbg_clk"

Drop the define? It's used once.

> +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
> +
> +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_rate)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 div = 1, val;
> +
> +       if (socfpgaclk->fixed_div) {
> +               div = socfpgaclk->fixed_div;
> +       } else if (socfpgaclk->div_reg) {
> +               val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +               val &= GENMASK(socfpgaclk->width - 1, 0);
> +               div = (1 << val);
> +       }
> +       return parent_rate / div;
> +}
> +
> +static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
> +                                                 unsigned long parent_rate)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 div = 1, val;
> +
> +       val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
> +       val &= GENMASK(socfpgaclk->width - 1, 0);
> +       div = (1 << val);
> +       div = div ? 4 : 1;
> +
> +       return parent_rate / div;
> +}
> +
> +static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
> +{
> +       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
> +       u32 mask;
> +       u8 parent = 0;
> +
> +       if (socfpgaclk->bypass_reg) {
> +               mask = (0x1 << socfpgaclk->bypass_shift);
> +               parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
> +                         socfpgaclk->bypass_shift);
> +       }
> +       return parent;
> +}
> +
> +static struct clk_ops gateclk_ops = {

const?

> +       .recalc_rate = socfpga_gate_clk_recalc_rate,
> +       .get_parent = socfpga_gate_get_parent,
> +};
> +
> +static struct clk_ops dbgclk_ops = {

const?

> +       .recalc_rate = socfpga_dbg_clk_recalc_rate,
> +       .get_parent = socfpga_gate_get_parent,
> +};
> +
> +struct clk *s10_register_gate(char *name, const char *parent_name,
> +                             const char * const *parent_names,
> +                             u8 num_parents, unsigned long flags,
> +                             void __iomem *regbase, unsigned long gate_reg,
> +                             unsigned long gate_idx, unsigned long div_reg,
> +                             unsigned long div_offset, u8 div_width,
> +                             unsigned long bypass_reg, u8 bypass_shift,
> +                             u8 fixed_div)
> +{
> +       struct clk *clk;
> +       struct socfpga_gate_clk *socfpga_clk;
> +       struct clk_init_data init;
> +
> +       socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
> +       if (WARN_ON(!socfpga_clk))

Allocation failures already print a nice stack so maybe just return NULL
if nothing allocates.

> +               return NULL;
> +
> +       socfpga_clk->hw.reg = regbase + gate_reg;
> +       socfpga_clk->hw.bit_idx = gate_idx;
> +
> +       gateclk_ops.enable = clk_gate_ops.enable;
> +       gateclk_ops.disable = clk_gate_ops.disable;
> +
> +       socfpga_clk->fixed_div = fixed_div;
> +
> +       if (div_reg)
> +               socfpga_clk->div_reg = regbase + div_reg;
> +       else
> +               socfpga_clk->div_reg = NULL;
> +
> +       socfpga_clk->width = div_width;
> +       socfpga_clk->shift = div_offset;
> +
> +       if (bypass_reg)
> +               socfpga_clk->bypass_reg = regbase + bypass_reg;
> +       else
> +               socfpga_clk->bypass_reg = NULL;
> +       socfpga_clk->bypass_shift = bypass_shift;
> +
> +       if (streq(name, SOCFPGA_CS_PDBG_CLK))
> +               init.ops = &dbgclk_ops;
> +       else
> +               init.ops = &gateclk_ops;
> +
> +       init.name = name;
> +       init.flags = flags;
> +
> +       init.num_parents = num_parents;
> +       init.parent_names = parent_names ? parent_names : &parent_name;
> +       socfpga_clk->hw.hw.init = &init;
> +
> +       clk = clk_register(NULL, &socfpga_clk->hw.hw);
> +       if (WARN_ON(IS_ERR(clk))) {
> +               kfree(socfpga_clk);
> +               return NULL;
> +       }
> +
> +       return clk;
> +}
> diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
> new file mode 100644
> index 0000000..31572cb
> --- /dev/null
> +++ b/drivers/clk/socfpga/clk-s10.c
> @@ -0,0 +1,319 @@
[...]
> +
> +static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
> +                                int nums, struct stratix10_clock_data *data)
> +{
> +       struct clk *clk;
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               clk = s10_register_pll(clks[i].name, clks[i].parent_names,
> +                                   clks[i].num_parents,
> +                                   clks[i].flags, base,
> +                                   clks[i].offset);
> +               if (IS_ERR(clk)) {
> +                       pr_err("%s: failed to register clock %s\n",
> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +
> +       return 0;
> +}
> +
> +struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,

static?

> +                                                   int nr_clks)
> +{
> +       struct stratix10_clock_data *clk_data;
> +       struct clk **clk_table;
> +       void __iomem *base;
> +
> +       base = of_iomap(np, 0);
> +       if (!base) {
> +               pr_err("%s: failed to map clock registers\n", __func__);
> +               goto err;
> +       }
> +
> +       clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> +       if (!clk_data)
> +               goto err;
> +
> +       clk_data->base = base;
> +       clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
> +       if (!clk_table)
> +               goto err_data;
> +
> +       clk_data->clk_data.clks = clk_table;
> +       clk_data->clk_data.clk_num = nr_clks;
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
> +       return clk_data;
> +
> +err_data:
> +       kfree(clk_data);
> +err:
> +       return NULL;
> +}
> +
> +
> +void __init socfpga_s10_init(struct device_node *node)

static?

> +{
> +       struct stratix10_clock_data *clk_data;
> +
> +       clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
> +       if (!clk_data)
> +               return;
> +
> +       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
> +
> +       s10_clk_register_c_perip(s10_main_perip_c_clks,
> +                                ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
> +
> +       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
> +                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
> +                                  clk_data);
> +
> +       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
> +                             clk_data);
> +}
> +
> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);

Can it be a platform device? We prefer those over the CLK_OF_DECLARE
style.

> diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
> new file mode 100644
> index 0000000..10f1532
> --- /dev/null
> +++ b/drivers/clk/socfpga/stratix10-clk.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier:    GPL-2.0 */
> +/*
> + * Copyright (C) 2017, Intel Corporation
> + */
> +
> +#ifndef        __STRATIX10_CLK_H
> +#define        __STRATIX10_CLK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>

Why include this? And why clk-provider.h?

> +
> +struct platform_device;

Why?

> +
> +struct stratix10_clock_data {
> +       struct clk_onecell_data clk_data;
> +       void __iomem            *base;
> +};

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
  2018-03-19 18:17     ` Stephen Boyd
@ 2018-03-21  4:09       ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-21  4:09 UTC (permalink / raw)
  To: Stephen Boyd, linux-clk
  Cc: mark.rutland, devicetree, mturquette, robh+dt, linux-arm-kernel



On 03/19/2018 01:17 PM, Stephen Boyd wrote:
> Quoting Dinh Nguyen (2018-02-26 06:47:35)
>> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
>> index 9146c20..87ef977 100644
>> --- a/drivers/clk/socfpga/Makefile
>> +++ b/drivers/clk/socfpga/Makefile
>> @@ -1,6 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0
>> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
> 
> Ugh, any chance to make this better if we get three?
> 

I'll try.

...

> 
>> +{
>> +       struct stratix10_clock_data *clk_data;
>> +
>> +       clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
>> +
>> +       s10_clk_register_c_perip(s10_main_perip_c_clks,
>> +                                ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
>> +
>> +       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
>> +                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
>> +                                  clk_data);
>> +
>> +       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
>> +                             clk_data);
>> +}
>> +
>> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
> 
> Can it be a platform device? We prefer those over the CLK_OF_DECLARE
> style.
> 

Thanks for the review! I'll change it to a platform device and address
your other comments in v7.

Dinh

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for Stratix10 platform
@ 2018-03-21  4:09       ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-21  4:09 UTC (permalink / raw)
  To: linux-arm-kernel



On 03/19/2018 01:17 PM, Stephen Boyd wrote:
> Quoting Dinh Nguyen (2018-02-26 06:47:35)
>> diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
>> index 9146c20..87ef977 100644
>> --- a/drivers/clk/socfpga/Makefile
>> +++ b/drivers/clk/socfpga/Makefile
>> @@ -1,6 +1,11 @@
>>  # SPDX-License-Identifier: GPL-2.0
>> +ifeq ($(CONFIG_ARCH_SOCFPGA),y)
> 
> Ugh, any chance to make this better if we get three?
> 

I'll try.

...

> 
>> +{
>> +       struct stratix10_clock_data *clk_data;
>> +
>> +       clk_data = __socfpga_s10_clk_init(node, STRATIX10_NUM_CLKS);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
>> +
>> +       s10_clk_register_c_perip(s10_main_perip_c_clks,
>> +                                ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
>> +
>> +       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
>> +                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
>> +                                  clk_data);
>> +
>> +       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
>> +                             clk_data);
>> +}
>> +
>> +CLK_OF_DECLARE(stratix10_clock, "intel,stratix10-clkmgr", socfpga_s10_init);
> 
> Can it be a platform device? We prefer those over the CLK_OF_DECLARE
> style.
> 

Thanks for the review! I'll change it to a platform device and address
your other comments in v7.

Dinh

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
  2018-03-19 18:08   ` Stephen Boyd
@ 2018-03-21  4:10     ` Dinh Nguyen
  -1 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-21  4:10 UTC (permalink / raw)
  To: Stephen Boyd, linux-clk
  Cc: mark.rutland, devicetree, mturquette, robh+dt, linux-arm-kernel



On 03/19/2018 01:08 PM, Stephen Boyd wrote:
> Quoting Dinh Nguyen (2018-02-26 06:47:33)
>> diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
>> new file mode 100644
>> index 0000000..0652ff1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
>> @@ -0,0 +1,51 @@
>> +Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible : shall be
>> +       "intel,stratix10-clkmgr"
>> +
>> +- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
>> +
>> +- #clock-cells : from common clock binding, shall be set to 1.
>> +
>> +- clocks : Should contain fixed-clock sources, such as oscillators.
>> +
>> +Example:
>> +       clkmgr: clock-controller@ffd10000 {
>> +               compatible = "intel,stratix10-clkmgr";
>> +               reg = <0xffd10000 0x1000>;
>> +               #clock-cells = <1>;
>> +
>> +               clocks {
> 
> Why do we need a subnode for clocks inside of a clock controller node?
> 
>> +                       #address-cells = <1>;
>> +                       #size-cells = <0>;
>> +
>> +                       cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
>> +                               #clock-cells = <0>;
>> +                               compatible = "fixed-clock";
>> +                               clock-frequency = <25000000>;
> 
> What is this for? I would think oscillators go into the root of the DT
> because they're on the board, not inside the clock controller.
> 

Thanks for the review! I'll move the PLLs into the root of the DT.

Dinh

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10
@ 2018-03-21  4:10     ` Dinh Nguyen
  0 siblings, 0 replies; 25+ messages in thread
From: Dinh Nguyen @ 2018-03-21  4:10 UTC (permalink / raw)
  To: linux-arm-kernel



On 03/19/2018 01:08 PM, Stephen Boyd wrote:
> Quoting Dinh Nguyen (2018-02-26 06:47:33)
>> diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
>> new file mode 100644
>> index 0000000..0652ff1
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
>> @@ -0,0 +1,51 @@
>> +Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible : shall be
>> +       "intel,stratix10-clkmgr"
>> +
>> +- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
>> +
>> +- #clock-cells : from common clock binding, shall be set to 1.
>> +
>> +- clocks : Should contain fixed-clock sources, such as oscillators.
>> +
>> +Example:
>> +       clkmgr: clock-controller at ffd10000 {
>> +               compatible = "intel,stratix10-clkmgr";
>> +               reg = <0xffd10000 0x1000>;
>> +               #clock-cells = <1>;
>> +
>> +               clocks {
> 
> Why do we need a subnode for clocks inside of a clock controller node?
> 
>> +                       #address-cells = <1>;
>> +                       #size-cells = <0>;
>> +
>> +                       cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk {
>> +                               #clock-cells = <0>;
>> +                               compatible = "fixed-clock";
>> +                               clock-frequency = <25000000>;
> 
> What is this for? I would think oscillators go into the root of the DT
> because they're on the board, not inside the clock controller.
> 

Thanks for the review! I'll move the PLLs into the root of the DT.

Dinh

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2018-03-21  4:10 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-26 14:47 [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10 Dinh Nguyen
2018-02-26 14:47 ` Dinh Nguyen
2018-02-26 14:47 ` Dinh Nguyen
2018-02-26 14:47 ` [PATCHv6 2/3] arm64: dts: stratix10: use clock bindings for the Stratix10 platform Dinh Nguyen
2018-02-26 14:47   ` Dinh Nguyen
2018-02-26 14:47   ` Dinh Nguyen
2018-02-26 14:47 ` [PATCHv6 3/3] clk: socfpga: stratix10: add clock driver for " Dinh Nguyen
2018-02-26 14:47   ` Dinh Nguyen
2018-02-26 14:47   ` Dinh Nguyen
2018-03-05 15:16   ` Dinh Nguyen
2018-03-05 15:16     ` Dinh Nguyen
2018-03-05 15:16     ` Dinh Nguyen
2018-03-12 14:38     ` Dinh Nguyen
2018-03-12 14:38       ` Dinh Nguyen
2018-03-12 14:38       ` Dinh Nguyen
2018-03-19 18:17   ` Stephen Boyd
2018-03-19 18:17     ` Stephen Boyd
2018-03-19 18:17     ` Stephen Boyd
2018-03-21  4:09     ` Dinh Nguyen
2018-03-21  4:09       ` Dinh Nguyen
2018-03-19 18:08 ` [PATCHv6 1/3] dt-bindings: documentation: add clock bindings information for Stratix10 Stephen Boyd
2018-03-19 18:08   ` Stephen Boyd
2018-03-19 18:08   ` Stephen Boyd
2018-03-21  4:10   ` Dinh Nguyen
2018-03-21  4:10     ` Dinh Nguyen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.