From 3b2bd70f03c75d37de791b65d574a31d1e2507b0 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 20 Oct 2014 22:10:27 +0800 Subject: clk: sunxi: Add support for A80 basic bus clocks The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module. As far as I can tell, the GT bus and CCI400 bus clock must be protected. This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index ed116df9c3e7..7f1c486691e0 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23 "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates "allwinner,sun4i-a10-ahb-clk" - for the AHB clock + "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80 "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s @@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s @@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 -- cgit 1.4.1 From 0b0f08028e4e2d69edbe4bb073af26cd17505a04 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 20 Oct 2014 22:10:28 +0800 Subject: clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC This adds the gate clocks for AHB/APB busses on the A80 SoC. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 5 ++++ drivers/clk/sunxi/clk-sunxi.c | 31 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 7f1c486691e0..0455cb9caa97 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -29,6 +29,9 @@ Required properties: "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 + "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 + "allwinner,sun9i-a80-ahb1-gates-clk" - for the AHB1 gates on A80 + "allwinner,sun9i-a80-ahb2-gates-clk" - for the AHB2 gates on A80 "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 @@ -39,6 +42,7 @@ Required properties: "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 + "allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing @@ -48,6 +52,7 @@ Required properties: "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23 + "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 636b8d772d4a..20f47c68a946 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -758,6 +758,18 @@ static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = { .mask = {0x25386742, 0x2505111}, }; +static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = { + .mask = {0xF5F12B}, +}; + +static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = { + .mask = {0x1E20003}, +}; + +static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = { + .mask = {0x9B7}, +}; + static const struct gates_data sun4i_apb0_gates_data __initconst = { .mask = {0x4EF}, }; @@ -774,6 +786,10 @@ static const struct gates_data sun7i_a20_apb0_gates_data __initconst = { .mask = { 0x4ff }, }; +static const struct gates_data sun9i_a80_apb0_gates_data __initconst = { + .mask = {0xEB822}, +}; + static const struct gates_data sun4i_apb1_gates_data __initconst = { .mask = {0xFF00F7}, }; @@ -802,6 +818,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { .mask = { 0xff80ff }, }; +static const struct gates_data sun9i_a80_apb1_gates_data __initconst = { + .mask = {0x3F001F}, +}; + static const struct gates_data sun8i_a23_apb2_gates_data __initconst = { .mask = {0x1F0007}, }; @@ -1103,16 +1123,21 @@ static const struct of_device_id clk_gates_match[] __initconst = { {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,}, {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, + {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,}, {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,}, {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, @@ -1201,3 +1226,9 @@ static void __init sun6i_init_clocks(struct device_node *node) } CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); + +static void __init sun9i_init_clocks(struct device_node *node) +{ + sunxi_init_clocks(NULL, 0); +} +CLK_OF_DECLARE(sun9i_a80_clk_init, "allwinner,sun9i-a80", sun9i_init_clocks); -- cgit 1.4.1 From 6233fe38048a80a9fa111ddb166ce9e8e0f5f1b3 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 27 Oct 2014 10:11:58 +0900 Subject: clk: samsung: Document binding for Exynos4415 clock controller This patch adds DT binding documentation for Exynos4415 SoC system clock controllers. Signed-off-by: Chanwoo Choi Acked-by: Kyungmin Park Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/clock/exynos4415-clock.txt | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/exynos4415-clock.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/exynos4415-clock.txt b/Documentation/devicetree/bindings/clock/exynos4415-clock.txt new file mode 100644 index 000000000000..847d98bae8cf --- /dev/null +++ b/Documentation/devicetree/bindings/clock/exynos4415-clock.txt @@ -0,0 +1,38 @@ +* Samsung Exynos4415 Clock Controller + +The Exynos4415 clock controller generates and supplies clock to various +consumer devices within the Exynos4415 SoC. + +Required properties: + +- compatible: should be one of the following: + - "samsung,exynos4415-cmu" - for the main system clocks controller + (CMU_LEFTBUS, CMU_RIGHTBUS, CMU_TOP, CMU_CPU clock domains). + - "samsung,exynos4415-cmu-dmc" - for the Exynos4415 SoC DRAM Memory + Controller (DMC) domain clock controller. + +- reg: physical base address of the controller and length of memory mapped + region. + +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/exynos4415.h header and can be used in device +tree sources. + +Example 1: An example of a clock controller node is listed below. + + cmu: clock-controller@10030000 { + compatible = "samsung,exynos4415-cmu"; + reg = <0x10030000 0x18000>; + #clock-cells = <1>; + }; + + cmu-dmc: clock-controller@105C0000 { + compatible = "samsung,exynos4415-cmu-dmc"; + reg = <0x105C0000 0x3000>; + #clock-cells = <1>; + }; -- cgit 1.4.1 From 532abc3a4a4502e13315d246c545d7567c80b03e Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Mon, 22 Sep 2014 10:17:04 +0530 Subject: clk: samsung: add initial clock support for Exynos7 SoC Add initial clock support for Exynos7 SoC which is required to bring up platforms based on Exynos7. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/clock/exynos7-clock.txt | 67 ++++ drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-exynos7.c | 425 +++++++++++++++++++++ include/dt-bindings/clock/exynos7-clk.h | 49 +++ 4 files changed, 542 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/exynos7-clock.txt create mode 100644 drivers/clk/samsung/clk-exynos7.c create mode 100644 include/dt-bindings/clock/exynos7-clk.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt new file mode 100644 index 000000000000..789f76132a85 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt @@ -0,0 +1,67 @@ +* Samsung Exynos7 Clock Controller + +Exynos7 clock controller has various blocks which are instantiated +independently from the device-tree. These clock controllers +generate and supply clocks to various hardware blocks within +the SoC. + +Each clock is assigned an identifier and client nodes can use +this identifier to specify the clock which they consume. All +available clocks are defined as preprocessor macros in +dt-bindings/clock/exynos7-clk.h header and can be used in +device tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It +is expected that they are defined using standard clock bindings +with following clock-output-names: + + - "fin_pll" - PLL input clock from XXTI + +Required Properties for Clock Controller: + + - compatible: clock controllers will use one of the following + compatible strings to indicate the clock controller + functionality. + + - "samsung,exynos7-clock-topc" + - "samsung,exynos7-clock-top0" + - "samsung,exynos7-clock-peric0" + - "samsung,exynos7-clock-peric1" + - "samsung,exynos7-clock-peris" + + - reg: physical base address of the controller and the length of + memory mapped region. + + - #clock-cells: should be 1. + + - clocks: list of clock identifiers which are fed as the input to + the given clock controller. Please refer the next section to + find the input clocks for a given controller. + +- clock-names: list of names of clocks which are fed as the input + to the given clock controller. + +Input clocks for top0 clock controller: + - fin_pll + - dout_sclk_bus0_pll + - dout_sclk_bus1_pll + - dout_sclk_cc_pll + - dout_sclk_mfc_pll + +Input clocks for peric0 clock controller: + - fin_pll + - dout_aclk_peric0_66 + - sclk_uart0 + +Input clocks for peric1 clock controller: + - fin_pll + - dout_aclk_peric1_66 + - sclk_uart1 + - sclk_uart2 + - sclk_uart3 + +Input clocks for peris clock controller: + - fin_pll + - dout_aclk_peris_66 diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index d8535e6df1db..006c6f294310 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o +obj-$(CONFIG_ARCH_EXYNOS7) += clk-exynos7.o obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c new file mode 100644 index 000000000000..54206d4d408a --- /dev/null +++ b/drivers/clk/samsung/clk-exynos7.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Naveen Krishna Ch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include +#include +#include +#include + +#include "clk.h" +#include + +/* Register Offset definitions for CMU_TOPC (0x10570000) */ +#define CC_PLL_LOCK 0x0000 +#define BUS0_PLL_LOCK 0x0004 +#define BUS1_DPLL_LOCK 0x0008 +#define MFC_PLL_LOCK 0x000C +#define AUD_PLL_LOCK 0x0010 +#define CC_PLL_CON0 0x0100 +#define BUS0_PLL_CON0 0x0110 +#define BUS1_DPLL_CON0 0x0120 +#define MFC_PLL_CON0 0x0130 +#define AUD_PLL_CON0 0x0140 +#define MUX_SEL_TOPC0 0x0200 +#define MUX_SEL_TOPC1 0x0204 +#define MUX_SEL_TOPC3 0x020C +#define DIV_TOPC1 0x0604 +#define DIV_TOPC3 0x060C + +static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0), + FFACTOR(0, "ffac_topc_bus0_pll_div4", + "ffac_topc_bus0_pll_div2", 1, 2, 0), + FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_bus1_pll_ctrl", 1, 2, 0), + FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_cc_pll_ctrl", 1, 2, 0), + FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_mfc_pll_ctrl", 1, 2, 0), +}; + +/* List of parent clocks for Muxes in CMU_TOPC */ +PNAME(mout_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" }; +PNAME(mout_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" }; +PNAME(mout_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" }; +PNAME(mout_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" }; + +PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc", + "mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc", + "mout_sclk_mfc_pll_cmuc" }; + +PNAME(mout_sclk_bus0_pll_cmuc_p) = { "mout_bus0_pll_ctrl", + "ffac_topc_bus0_pll_div2", "ffac_topc_bus0_pll_div4"}; +PNAME(mout_sclk_bus1_pll_cmuc_p) = { "mout_bus1_pll_ctrl", + "ffac_topc_bus1_pll_div2"}; +PNAME(mout_sclk_cc_pll_cmuc_p) = { "mout_cc_pll_ctrl", + "ffac_topc_cc_pll_div2"}; +PNAME(mout_sclk_mfc_pll_cmuc_p) = { "mout_mfc_pll_ctrl", + "ffac_topc_mfc_pll_div2"}; + + +PNAME(mout_sclk_bus0_pll_out_p) = {"mout_bus0_pll_ctrl", + "ffac_topc_bus0_pll_div2"}; + +static unsigned long topc_clk_regs[] __initdata = { + CC_PLL_LOCK, + BUS0_PLL_LOCK, + BUS1_DPLL_LOCK, + MFC_PLL_LOCK, + AUD_PLL_LOCK, + CC_PLL_CON0, + BUS0_PLL_CON0, + BUS1_DPLL_CON0, + MFC_PLL_CON0, + AUD_PLL_CON0, + MUX_SEL_TOPC0, + MUX_SEL_TOPC1, + MUX_SEL_TOPC3, + DIV_TOPC1, + DIV_TOPC3, +}; + +static struct samsung_mux_clock topc_mux_clks[] __initdata = { + MUX(0, "mout_bus0_pll_ctrl", mout_bus0_pll_ctrl_p, MUX_SEL_TOPC0, 0, 1), + MUX(0, "mout_bus1_pll_ctrl", mout_bus1_pll_ctrl_p, MUX_SEL_TOPC0, 4, 1), + MUX(0, "mout_cc_pll_ctrl", mout_cc_pll_ctrl_p, MUX_SEL_TOPC0, 8, 1), + MUX(0, "mout_mfc_pll_ctrl", mout_mfc_pll_ctrl_p, MUX_SEL_TOPC0, 12, 1), + + MUX(0, "mout_sclk_bus0_pll_cmuc", mout_sclk_bus0_pll_cmuc_p, + MUX_SEL_TOPC0, 16, 2), + MUX(0, "mout_sclk_bus1_pll_cmuc", mout_sclk_bus1_pll_cmuc_p, + MUX_SEL_TOPC0, 20, 1), + MUX(0, "mout_sclk_cc_pll_cmuc", mout_sclk_cc_pll_cmuc_p, + MUX_SEL_TOPC0, 24, 1), + MUX(0, "mout_sclk_mfc_pll_cmuc", mout_sclk_mfc_pll_cmuc_p, + MUX_SEL_TOPC0, 28, 1), + + MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p, + MUX_SEL_TOPC1, 16, 1), + + MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2), +}; + +static struct samsung_div_clock topc_div_clks[] __initdata = { + DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66", + DIV_TOPC1, 24, 4), + + DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_sclk_bus0_pll_out", + DIV_TOPC3, 0, 3), + DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_bus1_pll_ctrl", + DIV_TOPC3, 8, 3), + DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_cc_pll_ctrl", + DIV_TOPC3, 12, 3), + DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_mfc_pll_ctrl", + DIV_TOPC3, 16, 3), +}; + +static struct samsung_pll_clock topc_pll_clks[] __initdata = { + PLL(pll_1451x, 0, "fout_bus0_pll", "fin_pll", BUS0_PLL_LOCK, + BUS0_PLL_CON0, NULL), + PLL(pll_1452x, 0, "fout_cc_pll", "fin_pll", CC_PLL_LOCK, + CC_PLL_CON0, NULL), + PLL(pll_1452x, 0, "fout_bus1_pll", "fin_pll", BUS1_DPLL_LOCK, + BUS1_DPLL_CON0, NULL), + PLL(pll_1452x, 0, "fout_mfc_pll", "fin_pll", MFC_PLL_LOCK, + MFC_PLL_CON0, NULL), + PLL(pll_1460x, 0, "fout_aud_pll", "fin_pll", AUD_PLL_LOCK, + AUD_PLL_CON0, NULL), +}; + +static struct samsung_cmu_info topc_cmu_info __initdata = { + .pll_clks = topc_pll_clks, + .nr_pll_clks = ARRAY_SIZE(topc_pll_clks), + .mux_clks = topc_mux_clks, + .nr_mux_clks = ARRAY_SIZE(topc_mux_clks), + .div_clks = topc_div_clks, + .nr_div_clks = ARRAY_SIZE(topc_div_clks), + .fixed_factor_clks = topc_fixed_factor_clks, + .nr_fixed_factor_clks = ARRAY_SIZE(topc_fixed_factor_clks), + .nr_clk_ids = TOPC_NR_CLK, + .clk_regs = topc_clk_regs, + .nr_clk_regs = ARRAY_SIZE(topc_clk_regs), +}; + +static void __init exynos7_clk_topc_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &topc_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc", + exynos7_clk_topc_init); + +/* Register Offset definitions for CMU_TOP0 (0x105D0000) */ +#define MUX_SEL_TOP00 0x0200 +#define MUX_SEL_TOP01 0x0204 +#define MUX_SEL_TOP03 0x020C +#define MUX_SEL_TOP0_PERIC3 0x023C +#define DIV_TOP03 0x060C +#define DIV_TOP0_PERIC3 0x063C +#define ENABLE_SCLK_TOP0_PERIC3 0x0A3C + +/* List of parent clocks for Muxes in CMU_TOP0 */ +PNAME(mout_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" }; +PNAME(mout_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll" }; +PNAME(mout_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll" }; +PNAME(mout_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll" }; + +PNAME(mout_top0_half_bus0_pll_p) = {"mout_top0_bus0_pll", + "ffac_top0_bus0_pll_div2"}; +PNAME(mout_top0_half_bus1_pll_p) = {"mout_top0_bus1_pll", + "ffac_top0_bus1_pll_div2"}; +PNAME(mout_top0_half_cc_pll_p) = {"mout_top0_cc_pll", + "ffac_top0_cc_pll_div2"}; +PNAME(mout_top0_half_mfc_pll_p) = {"mout_top0_mfc_pll", + "ffac_top0_mfc_pll_div2"}; + +PNAME(mout_top0_group1) = {"mout_top0_half_bus0_pll", + "mout_top0_half_bus1_pll", "mout_top0_half_cc_pll", + "mout_top0_half_mfc_pll"}; + +static unsigned long top0_clk_regs[] __initdata = { + MUX_SEL_TOP00, + MUX_SEL_TOP01, + MUX_SEL_TOP03, + MUX_SEL_TOP0_PERIC3, + DIV_TOP03, + DIV_TOP0_PERIC3, + ENABLE_SCLK_TOP0_PERIC3, +}; + +static struct samsung_mux_clock top0_mux_clks[] __initdata = { + MUX(0, "mout_top0_mfc_pll", mout_mfc_pll_p, MUX_SEL_TOP00, 4, 1), + MUX(0, "mout_top0_cc_pll", mout_cc_pll_p, MUX_SEL_TOP00, 8, 1), + MUX(0, "mout_top0_bus1_pll", mout_bus1_pll_p, MUX_SEL_TOP00, 12, 1), + MUX(0, "mout_top0_bus0_pll", mout_bus0_pll_p, MUX_SEL_TOP00, 16, 1), + + MUX(0, "mout_top0_half_mfc_pll", mout_top0_half_mfc_pll_p, + MUX_SEL_TOP01, 4, 1), + MUX(0, "mout_top0_half_cc_pll", mout_top0_half_cc_pll_p, + MUX_SEL_TOP01, 8, 1), + MUX(0, "mout_top0_half_bus1_pll", mout_top0_half_bus1_pll_p, + MUX_SEL_TOP01, 12, 1), + MUX(0, "mout_top0_half_bus0_pll", mout_top0_half_bus0_pll_p, + MUX_SEL_TOP01, 16, 1), + + MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2), + MUX(0, "mout_aclk_peric0_66", mout_top0_group1, MUX_SEL_TOP03, 20, 2), + + MUX(0, "mout_sclk_uart3", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 4, 2), + MUX(0, "mout_sclk_uart2", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 8, 2), + MUX(0, "mout_sclk_uart1", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 12, 2), + MUX(0, "mout_sclk_uart0", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 16, 2), +}; + +static struct samsung_div_clock top0_div_clks[] __initdata = { + DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66", + DIV_TOP03, 12, 6), + DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66", + DIV_TOP03, 20, 6), + + DIV(0, "dout_sclk_uart3", "mout_sclk_uart3", DIV_TOP0_PERIC3, 4, 4), + DIV(0, "dout_sclk_uart2", "mout_sclk_uart2", DIV_TOP0_PERIC3, 8, 4), + DIV(0, "dout_sclk_uart1", "mout_sclk_uart1", DIV_TOP0_PERIC3, 12, 4), + DIV(0, "dout_sclk_uart0", "mout_sclk_uart0", DIV_TOP0_PERIC3, 16, 4), +}; + +static struct samsung_gate_clock top0_gate_clks[] __initdata = { + GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_sclk_uart3", + ENABLE_SCLK_TOP0_PERIC3, 4, 0, 0), + GATE(CLK_SCLK_UART2, "sclk_uart2", "dout_sclk_uart2", + ENABLE_SCLK_TOP0_PERIC3, 8, 0, 0), + GATE(CLK_SCLK_UART1, "sclk_uart1", "dout_sclk_uart1", + ENABLE_SCLK_TOP0_PERIC3, 12, 0, 0), + GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_sclk_uart0", + ENABLE_SCLK_TOP0_PERIC3, 16, 0, 0), +}; + +static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll", 1, 2, 0), + FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll", 1, 2, 0), + FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll", 1, 2, 0), + FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll", 1, 2, 0), +}; + +static struct samsung_cmu_info top0_cmu_info __initdata = { + .mux_clks = top0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(top0_mux_clks), + .div_clks = top0_div_clks, + .nr_div_clks = ARRAY_SIZE(top0_div_clks), + .gate_clks = top0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(top0_gate_clks), + .fixed_factor_clks = top0_fixed_factor_clks, + .nr_fixed_factor_clks = ARRAY_SIZE(top0_fixed_factor_clks), + .nr_clk_ids = TOP0_NR_CLK, + .clk_regs = top0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(top0_clk_regs), +}; + +static void __init exynos7_clk_top0_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &top0_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_top0, "samsung,exynos7-clock-top0", + exynos7_clk_top0_init); + +/* Register Offset definitions for CMU_PERIC0 (0x13610000) */ +#define MUX_SEL_PERIC0 0x0200 +#define ENABLE_PCLK_PERIC0 0x0900 +#define ENABLE_SCLK_PERIC0 0x0A00 + +/* List of parent clocks for Muxes in CMU_PERIC0 */ +PNAME(mout_aclk_peric0_66_p) = { "fin_pll", "dout_aclk_peric0_66" }; +PNAME(mout_sclk_uart0_p) = { "fin_pll", "sclk_uart0" }; + +static unsigned long peric0_clk_regs[] __initdata = { + MUX_SEL_PERIC0, + ENABLE_PCLK_PERIC0, + ENABLE_SCLK_PERIC0, +}; + +static struct samsung_mux_clock peric0_mux_clks[] __initdata = { + MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_p, + MUX_SEL_PERIC0, 0, 1), + MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_p, + MUX_SEL_PERIC0, 16, 1), +}; + +static struct samsung_gate_clock peric0_gate_clks[] __initdata = { + GATE(PCLK_UART0, "pclk_uart0", "mout_aclk_peric0_66_user", + ENABLE_PCLK_PERIC0, 16, 0, 0), + + GATE(SCLK_UART0, "sclk_uart0_user", "mout_sclk_uart0_user", + ENABLE_SCLK_PERIC0, 16, 0, 0), +}; + +static struct samsung_cmu_info peric0_cmu_info __initdata = { + .mux_clks = peric0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peric0_mux_clks), + .gate_clks = peric0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peric0_gate_clks), + .nr_clk_ids = PERIC0_NR_CLK, + .clk_regs = peric0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peric0_clk_regs), +}; + +static void __init exynos7_clk_peric0_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &peric0_cmu_info); +} + +/* Register Offset definitions for CMU_PERIC1 (0x14C80000) */ +#define MUX_SEL_PERIC10 0x0200 +#define MUX_SEL_PERIC11 0x0204 +#define ENABLE_PCLK_PERIC1 0x0900 +#define ENABLE_SCLK_PERIC10 0x0A00 + +CLK_OF_DECLARE(exynos7_clk_peric0, "samsung,exynos7-clock-peric0", + exynos7_clk_peric0_init); + +/* List of parent clocks for Muxes in CMU_PERIC1 */ +PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" }; +PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" }; +PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" }; +PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" }; + +static unsigned long peric1_clk_regs[] __initdata = { + MUX_SEL_PERIC10, + MUX_SEL_PERIC11, + ENABLE_PCLK_PERIC1, + ENABLE_SCLK_PERIC10, +}; + +static struct samsung_mux_clock peric1_mux_clks[] __initdata = { + MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p, + MUX_SEL_PERIC10, 0, 1), + + MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p, + MUX_SEL_PERIC11, 20, 1), + MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p, + MUX_SEL_PERIC11, 24, 1), + MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_p, + MUX_SEL_PERIC11, 28, 1), +}; + +static struct samsung_gate_clock peric1_gate_clks[] __initdata = { + GATE(PCLK_UART1, "pclk_uart1", "mout_aclk_peric1_66_user", + ENABLE_PCLK_PERIC1, 9, 0, 0), + GATE(PCLK_UART2, "pclk_uart2", "mout_aclk_peric1_66_user", + ENABLE_PCLK_PERIC1, 10, 0, 0), + GATE(PCLK_UART3, "pclk_uart3", "mout_aclk_peric1_66_user", + ENABLE_PCLK_PERIC1, 11, 0, 0), + + GATE(SCLK_UART1, "sclk_uart1_user", "mout_sclk_uart1_user", + ENABLE_SCLK_PERIC10, 9, 0, 0), + GATE(SCLK_UART2, "sclk_uart2_user", "mout_sclk_uart2_user", + ENABLE_SCLK_PERIC10, 10, 0, 0), + GATE(SCLK_UART3, "sclk_uart3_user", "mout_sclk_uart3_user", + ENABLE_SCLK_PERIC10, 11, 0, 0), +}; + +static struct samsung_cmu_info peric1_cmu_info __initdata = { + .mux_clks = peric1_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks), + .gate_clks = peric1_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peric1_gate_clks), + .nr_clk_ids = PERIC1_NR_CLK, + .clk_regs = peric1_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peric1_clk_regs), +}; + +static void __init exynos7_clk_peric1_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &peric1_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1", + exynos7_clk_peric1_init); + +/* Register Offset definitions for CMU_PERIS (0x10040000) */ +#define MUX_SEL_PERIS 0x0200 +#define ENABLE_PCLK_PERIS_SECURE_CHIPID 0x0910 +#define ENABLE_SCLK_PERIS_SECURE_CHIPID 0x0A10 + +/* List of parent clocks for Muxes in CMU_PERIS */ +PNAME(mout_aclk_peris_66_p) = { "fin_pll", "dout_aclk_peris_66" }; + +static unsigned long peris_clk_regs[] __initdata = { + MUX_SEL_PERIS, + ENABLE_PCLK_PERIS_SECURE_CHIPID, + ENABLE_SCLK_PERIS_SECURE_CHIPID, +}; + +static struct samsung_mux_clock peris_mux_clks[] __initdata = { + MUX(0, "mout_aclk_peris_66_user", + mout_aclk_peris_66_p, MUX_SEL_PERIS, 0, 1), +}; + +static struct samsung_gate_clock peris_gate_clks[] __initdata = { + GATE(PCLK_CHIPID, "pclk_chipid", "mout_aclk_peris_66_user", + ENABLE_PCLK_PERIS_SECURE_CHIPID, 0, 0, 0), + GATE(SCLK_CHIPID, "sclk_chipid", "fin_pll", + ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0), +}; + +static struct samsung_cmu_info peris_cmu_info __initdata = { + .mux_clks = peris_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peris_mux_clks), + .gate_clks = peris_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peris_gate_clks), + .nr_clk_ids = PERIS_NR_CLK, + .clk_regs = peris_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peris_clk_regs), +}; + +static void __init exynos7_clk_peris_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &peris_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris", + exynos7_clk_peris_init); diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h new file mode 100644 index 000000000000..00fd6de1cb25 --- /dev/null +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Naveen Krishna Ch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef _DT_BINDINGS_CLOCK_EXYNOS7_H +#define _DT_BINDINGS_CLOCK_EXYNOS7_H + +/* TOPC */ +#define DOUT_ACLK_PERIS 1 +#define DOUT_SCLK_BUS0_PLL 2 +#define DOUT_SCLK_BUS1_PLL 3 +#define DOUT_SCLK_CC_PLL 4 +#define DOUT_SCLK_MFC_PLL 5 +#define TOPC_NR_CLK 6 + +/* TOP0 */ +#define DOUT_ACLK_PERIC1 1 +#define DOUT_ACLK_PERIC0 2 +#define CLK_SCLK_UART0 3 +#define CLK_SCLK_UART1 4 +#define CLK_SCLK_UART2 5 +#define CLK_SCLK_UART3 6 +#define TOP0_NR_CLK 7 + +/* PERIC0 */ +#define PCLK_UART0 1 +#define SCLK_UART0 2 +#define PERIC0_NR_CLK 3 + +/* PERIC1 */ +#define PCLK_UART1 1 +#define PCLK_UART2 2 +#define PCLK_UART3 3 +#define SCLK_UART1 4 +#define SCLK_UART2 5 +#define SCLK_UART3 6 +#define PERIC1_NR_CLK 7 + +/* PERIS */ +#define PCLK_CHIPID 1 +#define SCLK_CHIPID 2 +#define PERIS_NR_CLK 3 + +#endif /* _DT_BINDINGS_CLOCK_EXYNOS7_H */ -- cgit 1.4.1 From 6d0c8c723f0b886f58263c089831fd2bee0b3b57 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Tue, 21 Oct 2014 11:13:52 +0530 Subject: clk: samsung: exynos7: add clocks for MMC block Exynos7 supports 3 MMC channels, add the MMC gate clocks to support them. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/clock/exynos7-clock.txt | 21 ++ drivers/clk/samsung/clk-exynos7.c | 224 +++++++++++++++++++++ include/dt-bindings/clock/exynos7-clk.h | 20 ++ 3 files changed, 265 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt index 789f76132a85..b29cb50048c6 100644 --- a/Documentation/devicetree/bindings/clock/exynos7-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt @@ -27,9 +27,12 @@ Required Properties for Clock Controller: - "samsung,exynos7-clock-topc" - "samsung,exynos7-clock-top0" + - "samsung,exynos7-clock-top1" - "samsung,exynos7-clock-peric0" - "samsung,exynos7-clock-peric1" - "samsung,exynos7-clock-peris" + - "samsung,exynos7-clock-fsys0" + - "samsung,exynos7-clock-fsys1" - reg: physical base address of the controller and the length of memory mapped region. @@ -50,6 +53,13 @@ Input clocks for top0 clock controller: - dout_sclk_cc_pll - dout_sclk_mfc_pll +Input clocks for top1 clock controller: + - fin_pll + - dout_sclk_bus0_pll + - dout_sclk_bus1_pll + - dout_sclk_cc_pll + - dout_sclk_mfc_pll + Input clocks for peric0 clock controller: - fin_pll - dout_aclk_peric0_66 @@ -65,3 +75,14 @@ Input clocks for peric1 clock controller: Input clocks for peris clock controller: - fin_pll - dout_aclk_peris_66 + +Input clocks for fsys0 clock controller: + - fin_pll + - dout_aclk_fsys0_200 + - dout_sclk_mmc2 + +Input clocks for fsys1 clock controller: + - fin_pll + - dout_aclk_fsys1_200 + - dout_sclk_mmc0 + - dout_sclk_mmc1 diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index c700f654289e..f5e43fab1951 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -267,6 +267,132 @@ static void __init exynos7_clk_top0_init(struct device_node *np) CLK_OF_DECLARE(exynos7_clk_top0, "samsung,exynos7-clock-top0", exynos7_clk_top0_init); +/* Register Offset definitions for CMU_TOP1 (0x105E0000) */ +#define MUX_SEL_TOP10 0x0200 +#define MUX_SEL_TOP11 0x0204 +#define MUX_SEL_TOP13 0x020C +#define MUX_SEL_TOP1_FSYS0 0x0224 +#define MUX_SEL_TOP1_FSYS1 0x0228 +#define DIV_TOP13 0x060C +#define DIV_TOP1_FSYS0 0x0624 +#define DIV_TOP1_FSYS1 0x0628 +#define ENABLE_ACLK_TOP13 0x080C +#define ENABLE_SCLK_TOP1_FSYS0 0x0A24 +#define ENABLE_SCLK_TOP1_FSYS1 0x0A28 + +/* List of parent clocks for Muxes in CMU_TOP1 */ +PNAME(mout_top1_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" }; +PNAME(mout_top1_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll_b" }; +PNAME(mout_top1_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll_b" }; +PNAME(mout_top1_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll_b" }; + +PNAME(mout_top1_half_bus0_pll_p) = {"mout_top1_bus0_pll", + "ffac_top1_bus0_pll_div2"}; +PNAME(mout_top1_half_bus1_pll_p) = {"mout_top1_bus1_pll", + "ffac_top1_bus1_pll_div2"}; +PNAME(mout_top1_half_cc_pll_p) = {"mout_top1_cc_pll", + "ffac_top1_cc_pll_div2"}; +PNAME(mout_top1_half_mfc_pll_p) = {"mout_top1_mfc_pll", + "ffac_top1_mfc_pll_div2"}; + +PNAME(mout_top1_group1) = {"mout_top1_half_bus0_pll", + "mout_top1_half_bus1_pll", "mout_top1_half_cc_pll", + "mout_top1_half_mfc_pll"}; + +static unsigned long top1_clk_regs[] __initdata = { + MUX_SEL_TOP10, + MUX_SEL_TOP11, + MUX_SEL_TOP13, + MUX_SEL_TOP1_FSYS0, + MUX_SEL_TOP1_FSYS1, + DIV_TOP13, + DIV_TOP1_FSYS0, + DIV_TOP1_FSYS1, + ENABLE_ACLK_TOP13, + ENABLE_SCLK_TOP1_FSYS0, + ENABLE_SCLK_TOP1_FSYS1, +}; + +static struct samsung_mux_clock top1_mux_clks[] __initdata = { + MUX(0, "mout_top1_mfc_pll", mout_top1_mfc_pll_p, MUX_SEL_TOP10, 4, 1), + MUX(0, "mout_top1_cc_pll", mout_top1_cc_pll_p, MUX_SEL_TOP10, 8, 1), + MUX(0, "mout_top1_bus1_pll", mout_top1_bus1_pll_p, + MUX_SEL_TOP10, 12, 1), + MUX(0, "mout_top1_bus0_pll", mout_top1_bus0_pll_p, + MUX_SEL_TOP10, 16, 1), + + MUX(0, "mout_top1_half_mfc_pll", mout_top1_half_mfc_pll_p, + MUX_SEL_TOP11, 4, 1), + MUX(0, "mout_top1_half_cc_pll", mout_top1_half_cc_pll_p, + MUX_SEL_TOP11, 8, 1), + MUX(0, "mout_top1_half_bus1_pll", mout_top1_half_bus1_pll_p, + MUX_SEL_TOP11, 12, 1), + MUX(0, "mout_top1_half_bus0_pll", mout_top1_half_bus0_pll_p, + MUX_SEL_TOP11, 16, 1), + + MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2), + MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2), + + MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 24, 2), + + MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 24, 2), + MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 28, 2), +}; + +static struct samsung_div_clock top1_div_clks[] __initdata = { + DIV(DOUT_ACLK_FSYS1_200, "dout_aclk_fsys1_200", "mout_aclk_fsys1_200", + DIV_TOP13, 24, 4), + DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200", + DIV_TOP13, 28, 4), + + DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2", + DIV_TOP1_FSYS0, 24, 4), + + DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1", + DIV_TOP1_FSYS1, 24, 4), + DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0", + DIV_TOP1_FSYS1, 28, 4), +}; + +static struct samsung_gate_clock top1_gate_clks[] __initdata = { + GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2", + ENABLE_SCLK_TOP1_FSYS0, 24, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1", + ENABLE_SCLK_TOP1_FSYS1, 24, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0", + ENABLE_SCLK_TOP1_FSYS1, 28, CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll", 1, 2, 0), + FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll", 1, 2, 0), + FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll", 1, 2, 0), + FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll", 1, 2, 0), +}; + +static struct samsung_cmu_info top1_cmu_info __initdata = { + .mux_clks = top1_mux_clks, + .nr_mux_clks = ARRAY_SIZE(top1_mux_clks), + .div_clks = top1_div_clks, + .nr_div_clks = ARRAY_SIZE(top1_div_clks), + .gate_clks = top1_gate_clks, + .nr_gate_clks = ARRAY_SIZE(top1_gate_clks), + .fixed_factor_clks = top1_fixed_factor_clks, + .nr_fixed_factor_clks = ARRAY_SIZE(top1_fixed_factor_clks), + .nr_clk_ids = TOP1_NR_CLK, + .clk_regs = top1_clk_regs, + .nr_clk_regs = ARRAY_SIZE(top1_clk_regs), +}; + +static void __init exynos7_clk_top1_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &top1_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1", + exynos7_clk_top1_init); + /* Register Offset definitions for CMU_PERIC0 (0x13610000) */ #define MUX_SEL_PERIC0 0x0200 #define ENABLE_PCLK_PERIC0 0x0900 @@ -447,3 +573,101 @@ static void __init exynos7_clk_peris_init(struct device_node *np) CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris", exynos7_clk_peris_init); + +/* Register Offset definitions for CMU_FSYS0 (0x10E90000) */ +#define MUX_SEL_FSYS00 0x0200 +#define MUX_SEL_FSYS01 0x0204 +#define ENABLE_ACLK_FSYS01 0x0804 + +/* + * List of parent clocks for Muxes in CMU_FSYS0 + */ +PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" }; +PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" }; + +static unsigned long fsys0_clk_regs[] __initdata = { + MUX_SEL_FSYS00, + MUX_SEL_FSYS01, + ENABLE_ACLK_FSYS01, +}; + +static struct samsung_mux_clock fsys0_mux_clks[] __initdata = { + MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_p, + MUX_SEL_FSYS00, 24, 1), + + MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1), +}; + +static struct samsung_gate_clock fsys0_gate_clks[] __initdata = { + GATE(ACLK_MMC2, "aclk_mmc2", "mout_aclk_fsys0_200_user", + ENABLE_ACLK_FSYS01, 31, 0, 0), +}; + +static struct samsung_cmu_info fsys0_cmu_info __initdata = { + .mux_clks = fsys0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks), + .gate_clks = fsys0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks), + .nr_clk_ids = TOP1_NR_CLK, + .clk_regs = fsys0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs), +}; + +static void __init exynos7_clk_fsys0_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &fsys0_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0", + exynos7_clk_fsys0_init); + +/* Register Offset definitions for CMU_FSYS1 (0x156E0000) */ +#define MUX_SEL_FSYS10 0x0200 +#define MUX_SEL_FSYS11 0x0204 +#define ENABLE_ACLK_FSYS1 0x0800 + +/* + * List of parent clocks for Muxes in CMU_FSYS1 + */ +PNAME(mout_aclk_fsys1_200_p) = { "fin_pll", "dout_aclk_fsys1_200" }; +PNAME(mout_sclk_mmc0_p) = { "fin_pll", "sclk_mmc0" }; +PNAME(mout_sclk_mmc1_p) = { "fin_pll", "sclk_mmc1" }; + +static unsigned long fsys1_clk_regs[] __initdata = { + MUX_SEL_FSYS10, + MUX_SEL_FSYS11, + ENABLE_ACLK_FSYS1, +}; + +static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { + MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_p, + MUX_SEL_FSYS10, 28, 1), + + MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_p, MUX_SEL_FSYS11, 24, 1), + MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_p, MUX_SEL_FSYS11, 28, 1), +}; + +static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { + GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user", + ENABLE_ACLK_FSYS1, 29, 0, 0), + GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user", + ENABLE_ACLK_FSYS1, 30, 0, 0), +}; + +static struct samsung_cmu_info fsys1_cmu_info __initdata = { + .mux_clks = fsys1_mux_clks, + .nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks), + .gate_clks = fsys1_gate_clks, + .nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks), + .nr_clk_ids = TOP1_NR_CLK, + .clk_regs = fsys1_clk_regs, + .nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs), +}; + +static void __init exynos7_clk_fsys1_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &fsys1_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1", + exynos7_clk_fsys1_init); diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index 6d07b6f1d615..ff63c4e15cc5 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -27,6 +27,17 @@ #define CLK_SCLK_UART3 6 #define TOP0_NR_CLK 7 +/* TOP1 */ +#define DOUT_ACLK_FSYS1_200 1 +#define DOUT_ACLK_FSYS0_200 2 +#define DOUT_SCLK_MMC2 3 +#define DOUT_SCLK_MMC1 4 +#define DOUT_SCLK_MMC0 5 +#define CLK_SCLK_MMC2 6 +#define CLK_SCLK_MMC1 7 +#define CLK_SCLK_MMC0 8 +#define TOP1_NR_CLK 9 + /* PERIC0 */ #define PCLK_UART0 1 #define SCLK_UART0 2 @@ -58,4 +69,13 @@ #define SCLK_CHIPID 2 #define PERIS_NR_CLK 3 +/* FSYS0 */ +#define ACLK_MMC2 1 +#define FSYS0_NR_CLK 2 + +/* FSYS1 */ +#define ACLK_MMC1 1 +#define ACLK_MMC0 2 +#define FSYS1_NR_CLK 3 + #endif /* _DT_BINDINGS_CLOCK_EXYNOS7_H */ -- cgit 1.4.1 From f5e127cd5ee52b3f0edaeeb7a40c0b9599f4e691 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Tue, 28 Oct 2014 16:48:53 +0530 Subject: clk: samsung: exynos7: add clocks for RTC block Add clock support for the RTC block in Exynos7. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/clock/exynos7-clock.txt | 5 ++ drivers/clk/samsung/clk-exynos7.c | 54 ++++++++++++++++++++++ include/dt-bindings/clock/exynos7-clk.h | 7 ++- 3 files changed, 65 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt index b29cb50048c6..6d3d5f80c1c3 100644 --- a/Documentation/devicetree/bindings/clock/exynos7-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt @@ -28,6 +28,7 @@ Required Properties for Clock Controller: - "samsung,exynos7-clock-topc" - "samsung,exynos7-clock-top0" - "samsung,exynos7-clock-top1" + - "samsung,exynos7-clock-ccore" - "samsung,exynos7-clock-peric0" - "samsung,exynos7-clock-peric1" - "samsung,exynos7-clock-peris" @@ -60,6 +61,10 @@ Input clocks for top1 clock controller: - dout_sclk_cc_pll - dout_sclk_mfc_pll +Input clocks for ccore clock controller: + - fin_pll + - dout_aclk_ccore_133 + Input clocks for peric0 clock controller: - fin_pll - dout_aclk_peric0_66 diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index f5e43fab1951..3a30f43fa925 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -29,7 +29,9 @@ #define AUD_PLL_CON0 0x0140 #define MUX_SEL_TOPC0 0x0200 #define MUX_SEL_TOPC1 0x0204 +#define MUX_SEL_TOPC2 0x0208 #define MUX_SEL_TOPC3 0x020C +#define DIV_TOPC0 0x0600 #define DIV_TOPC1 0x0604 #define DIV_TOPC3 0x060C @@ -78,7 +80,9 @@ static unsigned long topc_clk_regs[] __initdata = { AUD_PLL_CON0, MUX_SEL_TOPC0, MUX_SEL_TOPC1, + MUX_SEL_TOPC2, MUX_SEL_TOPC3, + DIV_TOPC0, DIV_TOPC1, DIV_TOPC3, }; @@ -101,10 +105,15 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = { MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p, MUX_SEL_TOPC1, 16, 1), + MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2), + MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2), }; static struct samsung_div_clock topc_div_clks[] __initdata = { + DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133", + DIV_TOPC0, 4, 4), + DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66", DIV_TOPC1, 24, 4), @@ -393,6 +402,51 @@ static void __init exynos7_clk_top1_init(struct device_node *np) CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1", exynos7_clk_top1_init); +/* Register Offset definitions for CMU_CCORE (0x105B0000) */ +#define MUX_SEL_CCORE 0x0200 +#define DIV_CCORE 0x0600 +#define ENABLE_ACLK_CCORE0 0x0800 +#define ENABLE_ACLK_CCORE1 0x0804 +#define ENABLE_PCLK_CCORE 0x0900 + +/* + * List of parent clocks for Muxes in CMU_CCORE + */ +PNAME(mout_aclk_ccore_133_p) = { "fin_pll", "dout_aclk_ccore_133" }; + +static unsigned long ccore_clk_regs[] __initdata = { + MUX_SEL_CCORE, + ENABLE_PCLK_CCORE, +}; + +static struct samsung_mux_clock ccore_mux_clks[] __initdata = { + MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_p, + MUX_SEL_CCORE, 1, 1), +}; + +static struct samsung_gate_clock ccore_gate_clks[] __initdata = { + GATE(PCLK_RTC, "pclk_rtc", "mout_aclk_ccore_133_user", + ENABLE_PCLK_CCORE, 8, 0, 0), +}; + +static struct samsung_cmu_info ccore_cmu_info __initdata = { + .mux_clks = ccore_mux_clks, + .nr_mux_clks = ARRAY_SIZE(ccore_mux_clks), + .gate_clks = ccore_gate_clks, + .nr_gate_clks = ARRAY_SIZE(ccore_gate_clks), + .nr_clk_ids = CCORE_NR_CLK, + .clk_regs = ccore_clk_regs, + .nr_clk_regs = ARRAY_SIZE(ccore_clk_regs), +}; + +static void __init exynos7_clk_ccore_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &ccore_cmu_info); +} + +CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore", + exynos7_clk_ccore_init); + /* Register Offset definitions for CMU_PERIC0 (0x13610000) */ #define MUX_SEL_PERIC0 0x0200 #define ENABLE_PCLK_PERIC0 0x0900 diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index ff63c4e15cc5..dd89aa0f84e1 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -16,7 +16,8 @@ #define DOUT_SCLK_BUS1_PLL 3 #define DOUT_SCLK_CC_PLL 4 #define DOUT_SCLK_MFC_PLL 5 -#define TOPC_NR_CLK 6 +#define DOUT_ACLK_CCORE_133 6 +#define TOPC_NR_CLK 7 /* TOP0 */ #define DOUT_ACLK_PERIC1 1 @@ -38,6 +39,10 @@ #define CLK_SCLK_MMC0 8 #define TOP1_NR_CLK 9 +/* CCORE */ +#define PCLK_RTC 1 +#define CCORE_NR_CLK 2 + /* PERIC0 */ #define PCLK_UART0 1 #define SCLK_UART0 2 -- cgit 1.4.1 From 93746e70be83a3f113134a16065957b324af50f7 Mon Sep 17 00:00:00 2001 From: Emilio López Date: Thu, 6 Nov 2014 11:40:29 +0800 Subject: clk: sunxi: unify APB1 clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit unifies the APB1 mux with the APB1 clock, using the new factors infrastructure. Signed-off-by: Emilio López [wens@csie.org: Add mux mask bits] Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 - drivers/clk/sunxi/clk-sunxi.c | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 0455cb9caa97..6ddcf6e10eb8 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -45,7 +45,6 @@ Required properties: "allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 - "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 20f47c68a946..4133e278212b 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -507,6 +507,8 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = { }; static const struct factors_data sun4i_apb1_data __initconst = { + .mux = 24, + .muxmask = BIT(1) | BIT(0), .table = &sun4i_apb1_config, .getter = sun4i_get_apb1_factors, }; @@ -545,10 +547,6 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { .shift = 12, }; -static const struct mux_data sun4i_apb1_mux_data __initconst = { - .shift = 24, -}; - static void __init sunxi_mux_clk_setup(struct device_node *node, struct mux_data *data) { @@ -1109,7 +1107,6 @@ static const struct of_device_id clk_divs_match[] __initconst = { /* Matches for mux clocks */ static const struct of_device_id clk_mux_match[] __initconst = { {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, - {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, {} }; -- cgit 1.4.1 From bfadcadf03a63bc841f69ed1c47e930b2ba2273d Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Fri, 7 Nov 2014 16:51:08 +0100 Subject: clk: shmobile: document DIV6 clock parent bindings Describes how to specify the parents for clocks with EXSRC bits. Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,cpg-div6-clocks.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt index 952e373178d2..054f65f9319c 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt @@ -7,11 +7,16 @@ to 64. Required Properties: - compatible: Must be one of the following + - "renesas,r8a73a4-div6-clock" for R8A73A4 (R-Mobile APE6) DIV6 clocks + - "renesas,r8a7740-div6-clock" for R8A7740 (R-Mobile A1) DIV6 clocks - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks + - "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks - "renesas,cpg-div6-clock" for generic DIV6 clocks - reg: Base address and length of the memory resource used by the DIV6 clock - - clocks: Reference to the parent clock + - clocks: Reference to the parent clock(s); either one, four, or eight + clocks must be specified. For clocks with multiple parents, invalid + settings must be specified as "<0>". - #clock-cells: Must be 0 - clock-output-names: The name of the clock as a free-form string @@ -19,10 +24,11 @@ Required Properties: Example ------- - sd2_clk: sd2_clk@e6150078 { - compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; - reg = <0 0xe6150078 0 4>; - clocks = <&pll1_div2_clk>; + sdhi2_clk: sdhi2_clk@e615007c { + compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615007c 0 4>; + clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, + <0>, <&extal2_clk>; #clock-cells = <0>; - clock-output-names = "sd2"; + clock-output-names = "sdhi2ck"; }; -- cgit 1.4.1 From ab08aefcd12d4e21abb28264ca77a430dcce7ebd Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 31 Oct 2014 10:13:49 +0800 Subject: clk: mmp: add pxa168 DT support for clock driver It adds the DT support for pxa168 clock subsystem. Signed-off-by: Chao Xie Acked-by: Haojian Zhuang Signed-off-by: Michael Turquette --- .../devicetree/bindings/clock/marvell,pxa168.txt | 21 ++ drivers/clk/mmp/Makefile | 2 + drivers/clk/mmp/clk-of-pxa168.c | 279 +++++++++++++++++++++ include/dt-bindings/clock/marvell,pxa168.h | 57 +++++ 4 files changed, 359 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa168.txt create mode 100644 drivers/clk/mmp/clk-of-pxa168.c create mode 100644 include/dt-bindings/clock/marvell,pxa168.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa168.txt b/Documentation/devicetree/bindings/clock/marvell,pxa168.txt new file mode 100644 index 000000000000..c62eb1d173a6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,pxa168.txt @@ -0,0 +1,21 @@ +* Marvell PXA168 Clock Controller + +The PXA168 clock subsystem generates and supplies clock to various +controllers within the PXA168 SoC. + +Required Properties: + +- compatible: should be one of the following. + - "marvell,pxa168-clock" - controller compatible with PXA168 SoC. + +- reg: physical base address of the clock subsystem and length of memory mapped + region. There are 3 places in SOC has clock control logic: + "mpmu", "apmu", "apbc". So three reg spaces need to be defined. + +- #clock-cells: should be 1. +- #reset-cells: should be 1. + +Each clock is assigned an identifier and client nodes use this identifier +to specify the clock which they consume. + +All these identifier could be found in . diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile index 2573d7c6198e..733acc7aa484 100644 --- a/drivers/clk/mmp/Makefile +++ b/drivers/clk/mmp/Makefile @@ -6,6 +6,8 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o +obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o + obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c new file mode 100644 index 000000000000..5b1810dc4bd2 --- /dev/null +++ b/drivers/clk/mmp/clk-of-pxa168.c @@ -0,0 +1,279 @@ +/* + * pxa168 clock framework source file + * + * Copyright (C) 2012 Marvell + * Chao Xie + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "reset.h" + +#define APBC_RTC 0x28 +#define APBC_TWSI0 0x2c +#define APBC_KPC 0x30 +#define APBC_UART0 0x0 +#define APBC_UART1 0x4 +#define APBC_GPIO 0x8 +#define APBC_PWM0 0xc +#define APBC_PWM1 0x10 +#define APBC_PWM2 0x14 +#define APBC_PWM3 0x18 +#define APBC_SSP0 0x81c +#define APBC_SSP1 0x820 +#define APBC_SSP2 0x84c +#define APBC_SSP3 0x858 +#define APBC_SSP4 0x85c +#define APBC_TWSI1 0x6c +#define APBC_UART2 0x70 +#define APMU_SDH0 0x54 +#define APMU_SDH1 0x58 +#define APMU_USB 0x5c +#define APMU_DISP0 0x4c +#define APMU_CCIC0 0x50 +#define APMU_DFC 0x60 +#define MPMU_UART_PLL 0x14 + +struct pxa168_clk_unit { + struct mmp_clk_unit unit; + void __iomem *mpmu_base; + void __iomem *apmu_base; + void __iomem *apbc_base; +}; + +static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { + {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, + {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, + {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, +}; + +static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { + {PXA168_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, + {PXA168_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, + {PXA168_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, + {PXA168_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, + {PXA168_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0}, + {PXA168_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, + {PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0}, + {PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0}, + {PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0}, + {PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0}, + {PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0}, + {PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0}, + {PXA168_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0}, +}; + +static struct mmp_clk_factor_masks uart_factor_masks = { + .factor = 2, + .num_mask = 0x1fff, + .den_mask = 0x1fff, + .num_shift = 16, + .den_shift = 0, +}; + +static struct mmp_clk_factor_tbl uart_factor_tbl[] = { + {.num = 8125, .den = 1536}, /*14.745MHZ */ +}; + +static void pxa168_pll_init(struct pxa168_clk_unit *pxa_unit) +{ + struct clk *clk; + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_fixed_rate_clks(unit, fixed_rate_clks, + ARRAY_SIZE(fixed_rate_clks)); + + mmp_register_fixed_factor_clks(unit, fixed_factor_clks, + ARRAY_SIZE(fixed_factor_clks)); + + clk = mmp_clk_register_factor("uart_pll", "pll1_4", + CLK_SET_RATE_PARENT, + pxa_unit->mpmu_base + MPMU_UART_PLL, + &uart_factor_masks, uart_factor_tbl, + ARRAY_SIZE(uart_factor_tbl), NULL); + mmp_clk_add(unit, PXA168_CLK_UART_PLL, clk); +} + +static DEFINE_SPINLOCK(uart0_lock); +static DEFINE_SPINLOCK(uart1_lock); +static DEFINE_SPINLOCK(uart2_lock); +static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"}; + +static DEFINE_SPINLOCK(ssp0_lock); +static DEFINE_SPINLOCK(ssp1_lock); +static DEFINE_SPINLOCK(ssp2_lock); +static DEFINE_SPINLOCK(ssp3_lock); +static DEFINE_SPINLOCK(ssp4_lock); +static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; + +static DEFINE_SPINLOCK(reset_lock); + +static struct mmp_param_mux_clk apbc_mux_clks[] = { + {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, + {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, + {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART2, 4, 3, 0, &uart2_lock}, + {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, + {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, + {0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock}, + {0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock}, + {0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock}, +}; + +static struct mmp_param_gate_clk apbc_gate_clks[] = { + {PXA168_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, + {PXA168_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, + {PXA168_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA168_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x3, 0x3, 0x0, 0, &reset_lock}, + /* The gate clocks has mux parent. */ + {PXA168_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x3, 0x3, 0x0, 0, &uart0_lock}, + {PXA168_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock}, + {PXA168_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBC_UART2, 0x3, 0x3, 0x0, 0, &uart2_lock}, + {PXA168_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock}, + {PXA168_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock}, + {PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock}, + {PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock}, + {PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock}, +}; + +static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit) +{ + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_mux_clks)); + + mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_gate_clks)); + +} + +static DEFINE_SPINLOCK(sdh0_lock); +static DEFINE_SPINLOCK(sdh1_lock); +static const char *sdh_parent_names[] = {"pll1_12", "pll1_13"}; + +static DEFINE_SPINLOCK(usb_lock); + +static DEFINE_SPINLOCK(disp0_lock); +static const char *disp_parent_names[] = {"pll1_2", "pll1_12"}; + +static DEFINE_SPINLOCK(ccic0_lock); +static const char *ccic_parent_names[] = {"pll1_2", "pll1_12"}; +static const char *ccic_phy_parent_names[] = {"pll1_6", "pll1_12"}; + +static struct mmp_param_mux_clk apmu_mux_clks[] = { + {0, "sdh0_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH0, 6, 1, 0, &sdh0_lock}, + {0, "sdh1_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH1, 6, 1, 0, &sdh1_lock}, + {0, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 1, 0, &disp0_lock}, + {0, "ccic0_mux", ccic_parent_names, ARRAY_SIZE(ccic_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 6, 1, 0, &ccic0_lock}, + {0, "ccic0_phy_mux", ccic_phy_parent_names, ARRAY_SIZE(ccic_phy_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 7, 1, 0, &ccic0_lock}, +}; + +static struct mmp_param_div_clk apmu_div_clks[] = { + {0, "ccic0_sphy_div", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, +}; + +static struct mmp_param_gate_clk apmu_gate_clks[] = { + {PXA168_CLK_DFC, "dfc_clk", "pll1_4", CLK_SET_RATE_PARENT, APMU_DFC, 0x19b, 0x19b, 0x0, 0, NULL}, + {PXA168_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, + {PXA168_CLK_SPH, "sph_clk", "usb_pll", 0, APMU_USB, 0x12, 0x12, 0x0, 0, &usb_lock}, + /* The gate clocks has mux parent. */ + {PXA168_CLK_SDH0, "sdh0_clk", "sdh0_mux", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh0_lock}, + {PXA168_CLK_SDH1, "sdh1_clk", "sdh1_mux", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh1_lock}, + {PXA168_CLK_DISP0, "disp0_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, + {PXA168_CLK_CCIC0, "ccic0_clk", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, + {PXA168_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_phy_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, + {PXA168_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, +}; + +static void pxa168_axi_periph_clk_init(struct pxa168_clk_unit *pxa_unit) +{ + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_mux_clks)); + + mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_div_clks)); + + mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_gate_clks)); +} + +static void pxa168_clk_reset_init(struct device_node *np, + struct pxa168_clk_unit *pxa_unit) +{ + struct mmp_clk_reset_cell *cells; + int i, nr_resets; + + nr_resets = ARRAY_SIZE(apbc_gate_clks); + cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); + if (!cells) + return; + + for (i = 0; i < nr_resets; i++) { + cells[i].clk_id = apbc_gate_clks[i].id; + cells[i].reg = pxa_unit->apbc_base + apbc_gate_clks[i].offset; + cells[i].flags = 0; + cells[i].lock = apbc_gate_clks[i].lock; + cells[i].bits = 0x4; + } + + mmp_clk_reset_register(np, cells, nr_resets); +} + +static void __init pxa168_clk_init(struct device_node *np) +{ + struct pxa168_clk_unit *pxa_unit; + + pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); + if (!pxa_unit) + return; + + pxa_unit->mpmu_base = of_iomap(np, 0); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map mpmu registers\n"); + return; + } + + pxa_unit->apmu_base = of_iomap(np, 1); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map apmu registers\n"); + return; + } + + pxa_unit->apbc_base = of_iomap(np, 2); + if (!pxa_unit->apbc_base) { + pr_err("failed to map apbc registers\n"); + return; + } + + mmp_clk_init(np, &pxa_unit->unit, PXA168_NR_CLKS); + + pxa168_pll_init(pxa_unit); + + pxa168_apb_periph_clk_init(pxa_unit); + + pxa168_axi_periph_clk_init(pxa_unit); + + pxa168_clk_reset_init(np, pxa_unit); +} + +CLK_OF_DECLARE(pxa168_clk, "marvell,pxa168-clock", pxa168_clk_init); diff --git a/include/dt-bindings/clock/marvell,pxa168.h b/include/dt-bindings/clock/marvell,pxa168.h new file mode 100644 index 000000000000..79630b9d74b8 --- /dev/null +++ b/include/dt-bindings/clock/marvell,pxa168.h @@ -0,0 +1,57 @@ +#ifndef __DTS_MARVELL_PXA168_CLOCK_H +#define __DTS_MARVELL_PXA168_CLOCK_H + +/* fixed clocks and plls */ +#define PXA168_CLK_CLK32 1 +#define PXA168_CLK_VCTCXO 2 +#define PXA168_CLK_PLL1 3 +#define PXA168_CLK_PLL1_2 8 +#define PXA168_CLK_PLL1_4 9 +#define PXA168_CLK_PLL1_8 10 +#define PXA168_CLK_PLL1_16 11 +#define PXA168_CLK_PLL1_6 12 +#define PXA168_CLK_PLL1_12 13 +#define PXA168_CLK_PLL1_24 14 +#define PXA168_CLK_PLL1_48 15 +#define PXA168_CLK_PLL1_96 16 +#define PXA168_CLK_PLL1_13 17 +#define PXA168_CLK_PLL1_13_1_5 18 +#define PXA168_CLK_PLL1_2_1_5 19 +#define PXA168_CLK_PLL1_3_16 20 +#define PXA168_CLK_UART_PLL 27 + +/* apb periphrals */ +#define PXA168_CLK_TWSI0 60 +#define PXA168_CLK_TWSI1 61 +#define PXA168_CLK_TWSI2 62 +#define PXA168_CLK_TWSI3 63 +#define PXA168_CLK_GPIO 64 +#define PXA168_CLK_KPC 65 +#define PXA168_CLK_RTC 66 +#define PXA168_CLK_PWM0 67 +#define PXA168_CLK_PWM1 68 +#define PXA168_CLK_PWM2 69 +#define PXA168_CLK_PWM3 70 +#define PXA168_CLK_UART0 71 +#define PXA168_CLK_UART1 72 +#define PXA168_CLK_UART2 73 +#define PXA168_CLK_SSP0 74 +#define PXA168_CLK_SSP1 75 +#define PXA168_CLK_SSP2 76 +#define PXA168_CLK_SSP3 77 +#define PXA168_CLK_SSP4 78 + +/* axi periphrals */ +#define PXA168_CLK_DFC 100 +#define PXA168_CLK_SDH0 101 +#define PXA168_CLK_SDH1 102 +#define PXA168_CLK_SDH2 103 +#define PXA168_CLK_USB 104 +#define PXA168_CLK_SPH 105 +#define PXA168_CLK_DISP0 106 +#define PXA168_CLK_CCIC0 107 +#define PXA168_CLK_CCIC0_PHY 108 +#define PXA168_CLK_CCIC0_SPHY 109 + +#define PXA168_NR_CLKS 200 +#endif -- cgit 1.4.1 From 2bc61da9f7ff422117a68bef0d309a29affd023a Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 31 Oct 2014 10:13:50 +0800 Subject: clk: mmp: add pxa910 DT support for clock driver It adds the DT support for pxa910 clock subsystem. Signed-off-by: Chao Xie Acked-by: Haojian Zhuang Signed-off-by: Michael Turquette --- .../devicetree/bindings/clock/marvell,pxa910.txt | 21 ++ drivers/clk/mmp/Makefile | 2 +- drivers/clk/mmp/clk-of-pxa910.c | 301 +++++++++++++++++++++ include/dt-bindings/clock/marvell,pxa910.h | 54 ++++ 4 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa910.txt create mode 100644 drivers/clk/mmp/clk-of-pxa910.c create mode 100644 include/dt-bindings/clock/marvell,pxa910.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa910.txt b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt new file mode 100644 index 000000000000..d9f41f3c03a0 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt @@ -0,0 +1,21 @@ +* Marvell PXA910 Clock Controller + +The PXA910 clock subsystem generates and supplies clock to various +controllers within the PXA910 SoC. + +Required Properties: + +- compatible: should be one of the following. + - "marvell,pxa910-clock" - controller compatible with PXA910 SoC. + +- reg: physical base address of the clock subsystem and length of memory mapped + region. There are 4 places in SOC has clock control logic: + "mpmu", "apmu", "apbc", "apbcp". So four reg spaces need to be defined. + +- #clock-cells: should be 1. +- #reset-cells: should be 1. + +Each clock is assigned an identifier and client nodes use this identifier +to specify the clock which they consume. + +All these identifier could be found in . diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile index 733acc7aa484..947cd74a82a7 100644 --- a/drivers/clk/mmp/Makefile +++ b/drivers/clk/mmp/Makefile @@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o -obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o +obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c new file mode 100644 index 000000000000..5e3c80dad336 --- /dev/null +++ b/drivers/clk/mmp/clk-of-pxa910.c @@ -0,0 +1,301 @@ +/* + * pxa910 clock framework source file + * + * Copyright (C) 2012 Marvell + * Chao Xie + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "reset.h" + +#define APBC_RTC 0x28 +#define APBC_TWSI0 0x2c +#define APBC_KPC 0x18 +#define APBC_UART0 0x0 +#define APBC_UART1 0x4 +#define APBC_GPIO 0x8 +#define APBC_PWM0 0xc +#define APBC_PWM1 0x10 +#define APBC_PWM2 0x14 +#define APBC_PWM3 0x18 +#define APBC_SSP0 0x1c +#define APBC_SSP1 0x20 +#define APBC_SSP2 0x4c +#define APBCP_TWSI1 0x28 +#define APBCP_UART2 0x1c +#define APMU_SDH0 0x54 +#define APMU_SDH1 0x58 +#define APMU_USB 0x5c +#define APMU_DISP0 0x4c +#define APMU_CCIC0 0x50 +#define APMU_DFC 0x60 +#define MPMU_UART_PLL 0x14 + +struct pxa910_clk_unit { + struct mmp_clk_unit unit; + void __iomem *mpmu_base; + void __iomem *apmu_base; + void __iomem *apbc_base; + void __iomem *apbcp_base; +}; + +static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { + {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, + {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, + {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, +}; + +static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { + {PXA910_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, + {PXA910_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, + {PXA910_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, + {PXA910_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, + {PXA910_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0}, + {PXA910_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, + {PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0}, + {PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0}, + {PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0}, + {PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0}, + {PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0}, + {PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0}, + {PXA910_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0}, +}; + +static struct mmp_clk_factor_masks uart_factor_masks = { + .factor = 2, + .num_mask = 0x1fff, + .den_mask = 0x1fff, + .num_shift = 16, + .den_shift = 0, +}; + +static struct mmp_clk_factor_tbl uart_factor_tbl[] = { + {.num = 8125, .den = 1536}, /*14.745MHZ */ +}; + +static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit) +{ + struct clk *clk; + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_fixed_rate_clks(unit, fixed_rate_clks, + ARRAY_SIZE(fixed_rate_clks)); + + mmp_register_fixed_factor_clks(unit, fixed_factor_clks, + ARRAY_SIZE(fixed_factor_clks)); + + clk = mmp_clk_register_factor("uart_pll", "pll1_4", + CLK_SET_RATE_PARENT, + pxa_unit->mpmu_base + MPMU_UART_PLL, + &uart_factor_masks, uart_factor_tbl, + ARRAY_SIZE(uart_factor_tbl), NULL); + mmp_clk_add(unit, PXA910_CLK_UART_PLL, clk); +} + +static DEFINE_SPINLOCK(uart0_lock); +static DEFINE_SPINLOCK(uart1_lock); +static DEFINE_SPINLOCK(uart2_lock); +static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"}; + +static DEFINE_SPINLOCK(ssp0_lock); +static DEFINE_SPINLOCK(ssp1_lock); +static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; + +static DEFINE_SPINLOCK(reset_lock); + +static struct mmp_param_mux_clk apbc_mux_clks[] = { + {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, + {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, + {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, + {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, +}; + +static struct mmp_param_mux_clk apbcp_mux_clks[] = { + {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBCP_UART2, 4, 3, 0, &uart2_lock}, +}; + +static struct mmp_param_gate_clk apbc_gate_clks[] = { + {PXA910_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA910_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA910_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, + {PXA910_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, + {PXA910_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA910_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA910_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x3, 0x3, 0x0, 0, &reset_lock}, + {PXA910_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x3, 0x3, 0x0, 0, &reset_lock}, + /* The gate clocks has mux parent. */ + {PXA910_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x3, 0x3, 0x0, 0, &uart0_lock}, + {PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock}, + {PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock}, + {PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock}, +}; + +static struct mmp_param_gate_clk apbcp_gate_clks[] = { + {PXA910_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBCP_TWSI1, 0x3, 0x3, 0x0, 0, &reset_lock}, + /* The gate clocks has mux parent. */ + {PXA910_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBCP_UART2, 0x3, 0x3, 0x0, 0, &uart2_lock}, +}; + +static void pxa910_apb_periph_clk_init(struct pxa910_clk_unit *pxa_unit) +{ + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_mux_clks)); + + mmp_register_mux_clks(unit, apbcp_mux_clks, pxa_unit->apbcp_base, + ARRAY_SIZE(apbcp_mux_clks)); + + mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_gate_clks)); + + mmp_register_gate_clks(unit, apbcp_gate_clks, pxa_unit->apbcp_base, + ARRAY_SIZE(apbcp_gate_clks)); +} + +static DEFINE_SPINLOCK(sdh0_lock); +static DEFINE_SPINLOCK(sdh1_lock); +static const char *sdh_parent_names[] = {"pll1_12", "pll1_13"}; + +static DEFINE_SPINLOCK(usb_lock); + +static DEFINE_SPINLOCK(disp0_lock); +static const char *disp_parent_names[] = {"pll1_2", "pll1_12"}; + +static DEFINE_SPINLOCK(ccic0_lock); +static const char *ccic_parent_names[] = {"pll1_2", "pll1_12"}; +static const char *ccic_phy_parent_names[] = {"pll1_6", "pll1_12"}; + +static struct mmp_param_mux_clk apmu_mux_clks[] = { + {0, "sdh0_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH0, 6, 1, 0, &sdh0_lock}, + {0, "sdh1_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH1, 6, 1, 0, &sdh1_lock}, + {0, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 1, 0, &disp0_lock}, + {0, "ccic0_mux", ccic_parent_names, ARRAY_SIZE(ccic_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 6, 1, 0, &ccic0_lock}, + {0, "ccic0_phy_mux", ccic_phy_parent_names, ARRAY_SIZE(ccic_phy_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 7, 1, 0, &ccic0_lock}, +}; + +static struct mmp_param_div_clk apmu_div_clks[] = { + {0, "ccic0_sphy_div", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, +}; + +static struct mmp_param_gate_clk apmu_gate_clks[] = { + {PXA910_CLK_DFC, "dfc_clk", "pll1_4", CLK_SET_RATE_PARENT, APMU_DFC, 0x19b, 0x19b, 0x0, 0, NULL}, + {PXA910_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, + {PXA910_CLK_SPH, "sph_clk", "usb_pll", 0, APMU_USB, 0x12, 0x12, 0x0, 0, &usb_lock}, + /* The gate clocks has mux parent. */ + {PXA910_CLK_SDH0, "sdh0_clk", "sdh0_mux", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh0_lock}, + {PXA910_CLK_SDH1, "sdh1_clk", "sdh1_mux", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh1_lock}, + {PXA910_CLK_DISP0, "disp0_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, + {PXA910_CLK_CCIC0, "ccic0_clk", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, + {PXA910_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_phy_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, + {PXA910_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, +}; + +static void pxa910_axi_periph_clk_init(struct pxa910_clk_unit *pxa_unit) +{ + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_mux_clks)); + + mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_div_clks)); + + mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_gate_clks)); +} + +static void pxa910_clk_reset_init(struct device_node *np, + struct pxa910_clk_unit *pxa_unit) +{ + struct mmp_clk_reset_cell *cells; + int i, base, nr_resets_apbc, nr_resets_apbcp, nr_resets; + + nr_resets_apbc = ARRAY_SIZE(apbc_gate_clks); + nr_resets_apbcp = ARRAY_SIZE(apbcp_gate_clks); + nr_resets = nr_resets_apbc + nr_resets_apbcp; + cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); + if (!cells) + return; + + base = 0; + for (i = 0; i < nr_resets_apbc; i++) { + cells[base + i].clk_id = apbc_gate_clks[i].id; + cells[base + i].reg = + pxa_unit->apbc_base + apbc_gate_clks[i].offset; + cells[base + i].flags = 0; + cells[base + i].lock = apbc_gate_clks[i].lock; + cells[base + i].bits = 0x4; + } + + base = nr_resets_apbc; + for (i = 0; i < nr_resets_apbcp; i++) { + cells[base + i].clk_id = apbcp_gate_clks[i].id; + cells[base + i].reg = + pxa_unit->apbc_base + apbc_gate_clks[i].offset; + cells[base + i].flags = 0; + cells[base + i].lock = apbc_gate_clks[i].lock; + cells[base + i].bits = 0x4; + } + + mmp_clk_reset_register(np, cells, nr_resets); +} + +static void __init pxa910_clk_init(struct device_node *np) +{ + struct pxa910_clk_unit *pxa_unit; + + pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); + if (!pxa_unit) + return; + + pxa_unit->mpmu_base = of_iomap(np, 0); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map mpmu registers\n"); + return; + } + + pxa_unit->apmu_base = of_iomap(np, 1); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map apmu registers\n"); + return; + } + + pxa_unit->apbc_base = of_iomap(np, 2); + if (!pxa_unit->apbc_base) { + pr_err("failed to map apbc registers\n"); + return; + } + + pxa_unit->apbcp_base = of_iomap(np, 3); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map apbcp registers\n"); + return; + } + + mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS); + + pxa910_pll_init(pxa_unit); + + pxa910_apb_periph_clk_init(pxa_unit); + + pxa910_axi_periph_clk_init(pxa_unit); + + pxa910_clk_reset_init(np, pxa_unit); +} + +CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init); diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h new file mode 100644 index 000000000000..719cffb2bea2 --- /dev/null +++ b/include/dt-bindings/clock/marvell,pxa910.h @@ -0,0 +1,54 @@ +#ifndef __DTS_MARVELL_PXA910_CLOCK_H +#define __DTS_MARVELL_PXA910_CLOCK_H + +/* fixed clocks and plls */ +#define PXA910_CLK_CLK32 1 +#define PXA910_CLK_VCTCXO 2 +#define PXA910_CLK_PLL1 3 +#define PXA910_CLK_PLL1_2 8 +#define PXA910_CLK_PLL1_4 9 +#define PXA910_CLK_PLL1_8 10 +#define PXA910_CLK_PLL1_16 11 +#define PXA910_CLK_PLL1_6 12 +#define PXA910_CLK_PLL1_12 13 +#define PXA910_CLK_PLL1_24 14 +#define PXA910_CLK_PLL1_48 15 +#define PXA910_CLK_PLL1_96 16 +#define PXA910_CLK_PLL1_13 17 +#define PXA910_CLK_PLL1_13_1_5 18 +#define PXA910_CLK_PLL1_2_1_5 19 +#define PXA910_CLK_PLL1_3_16 20 +#define PXA910_CLK_UART_PLL 27 + +/* apb periphrals */ +#define PXA910_CLK_TWSI0 60 +#define PXA910_CLK_TWSI1 61 +#define PXA910_CLK_TWSI2 62 +#define PXA910_CLK_TWSI3 63 +#define PXA910_CLK_GPIO 64 +#define PXA910_CLK_KPC 65 +#define PXA910_CLK_RTC 66 +#define PXA910_CLK_PWM0 67 +#define PXA910_CLK_PWM1 68 +#define PXA910_CLK_PWM2 69 +#define PXA910_CLK_PWM3 70 +#define PXA910_CLK_UART0 71 +#define PXA910_CLK_UART1 72 +#define PXA910_CLK_UART2 73 +#define PXA910_CLK_SSP0 74 +#define PXA910_CLK_SSP1 75 + +/* axi periphrals */ +#define PXA910_CLK_DFC 100 +#define PXA910_CLK_SDH0 101 +#define PXA910_CLK_SDH1 102 +#define PXA910_CLK_SDH2 103 +#define PXA910_CLK_USB 104 +#define PXA910_CLK_SPH 105 +#define PXA910_CLK_DISP0 106 +#define PXA910_CLK_CCIC0 107 +#define PXA910_CLK_CCIC0_PHY 108 +#define PXA910_CLK_CCIC0_SPHY 109 + +#define PXA910_NR_CLKS 200 +#endif -- cgit 1.4.1 From 1ec770d92a62582ac1f7e0969d6a0ddc54d5f49e Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 31 Oct 2014 10:13:51 +0800 Subject: clk: mmp: add mmp2 DT support for clock driver It adds the DT support for mmp2 clock subsystem. Signed-off-by: Chao Xie Acked-by: Haojian Zhuang Signed-off-by: Michael Turquette --- .../devicetree/bindings/clock/marvell,mmp2.txt | 21 ++ drivers/clk/mmp/Makefile | 1 + drivers/clk/mmp/clk-of-mmp2.c | 334 +++++++++++++++++++++ include/dt-bindings/clock/marvell,mmp2.h | 74 +++++ 4 files changed, 430 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/marvell,mmp2.txt create mode 100644 drivers/clk/mmp/clk-of-mmp2.c create mode 100644 include/dt-bindings/clock/marvell,mmp2.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/marvell,mmp2.txt b/Documentation/devicetree/bindings/clock/marvell,mmp2.txt new file mode 100644 index 000000000000..af376a01f2b7 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,mmp2.txt @@ -0,0 +1,21 @@ +* Marvell MMP2 Clock Controller + +The MMP2 clock subsystem generates and supplies clock to various +controllers within the MMP2 SoC. + +Required Properties: + +- compatible: should be one of the following. + - "marvell,mmp2-clock" - controller compatible with MMP2 SoC. + +- reg: physical base address of the clock subsystem and length of memory mapped + region. There are 3 places in SOC has clock control logic: + "mpmu", "apmu", "apbc". So three reg spaces need to be defined. + +- #clock-cells: should be 1. +- #reset-cells: should be 1. + +Each clock is assigned an identifier and client nodes use this identifier +to specify the clock which they consume. + +All these identifier could be found in . diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile index 947cd74a82a7..3caaf7cc169c 100644 --- a/drivers/clk/mmp/Makefile +++ b/drivers/clk/mmp/Makefile @@ -7,6 +7,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o +obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c new file mode 100644 index 000000000000..2cbc2b43ae52 --- /dev/null +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -0,0 +1,334 @@ +/* + * mmp2 clock framework source file + * + * Copyright (C) 2012 Marvell + * Chao Xie + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "reset.h" + +#define APBC_RTC 0x0 +#define APBC_TWSI0 0x4 +#define APBC_TWSI1 0x8 +#define APBC_TWSI2 0xc +#define APBC_TWSI3 0x10 +#define APBC_TWSI4 0x7c +#define APBC_TWSI5 0x80 +#define APBC_KPC 0x18 +#define APBC_UART0 0x2c +#define APBC_UART1 0x30 +#define APBC_UART2 0x34 +#define APBC_UART3 0x88 +#define APBC_GPIO 0x38 +#define APBC_PWM0 0x3c +#define APBC_PWM1 0x40 +#define APBC_PWM2 0x44 +#define APBC_PWM3 0x48 +#define APBC_SSP0 0x50 +#define APBC_SSP1 0x54 +#define APBC_SSP2 0x58 +#define APBC_SSP3 0x5c +#define APMU_SDH0 0x54 +#define APMU_SDH1 0x58 +#define APMU_SDH2 0xe8 +#define APMU_SDH3 0xec +#define APMU_USB 0x5c +#define APMU_DISP0 0x4c +#define APMU_DISP1 0x110 +#define APMU_CCIC0 0x50 +#define APMU_CCIC1 0xf4 +#define MPMU_UART_PLL 0x14 + +struct mmp2_clk_unit { + struct mmp_clk_unit unit; + void __iomem *mpmu_base; + void __iomem *apmu_base; + void __iomem *apbc_base; +}; + +static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { + {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, + {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, + {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 800000000}, + {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 960000000}, + {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, +}; + +static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { + {MMP2_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, + {MMP2_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, + {MMP2_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, + {MMP2_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, + {MMP2_CLK_PLL1_20, "pll1_20", "pll1_4", 1, 5, 0}, + {MMP2_CLK_PLL1_3, "pll1_3", "pll1", 1, 3, 0}, + {MMP2_CLK_PLL1_6, "pll1_6", "pll1_3", 1, 2, 0}, + {MMP2_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, + {MMP2_CLK_PLL2_2, "pll2_2", "pll2", 1, 2, 0}, + {MMP2_CLK_PLL2_4, "pll2_4", "pll2_2", 1, 2, 0}, + {MMP2_CLK_PLL2_8, "pll2_8", "pll2_4", 1, 2, 0}, + {MMP2_CLK_PLL2_16, "pll2_16", "pll2_8", 1, 2, 0}, + {MMP2_CLK_PLL2_3, "pll2_3", "pll2", 1, 3, 0}, + {MMP2_CLK_PLL2_6, "pll2_6", "pll2_3", 1, 2, 0}, + {MMP2_CLK_PLL2_12, "pll2_12", "pll2_6", 1, 2, 0}, + {MMP2_CLK_VCTCXO_2, "vctcxo_2", "vctcxo", 1, 2, 0}, + {MMP2_CLK_VCTCXO_4, "vctcxo_4", "vctcxo_2", 1, 2, 0}, +}; + +static struct mmp_clk_factor_masks uart_factor_masks = { + .factor = 2, + .num_mask = 0x1fff, + .den_mask = 0x1fff, + .num_shift = 16, + .den_shift = 0, +}; + +static struct mmp_clk_factor_tbl uart_factor_tbl[] = { + {.num = 14634, .den = 2165}, /*14.745MHZ */ + {.num = 3521, .den = 689}, /*19.23MHZ */ + {.num = 9679, .den = 5728}, /*58.9824MHZ */ + {.num = 15850, .den = 9451}, /*59.429MHZ */ +}; + +static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit) +{ + struct clk *clk; + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_fixed_rate_clks(unit, fixed_rate_clks, + ARRAY_SIZE(fixed_rate_clks)); + + mmp_register_fixed_factor_clks(unit, fixed_factor_clks, + ARRAY_SIZE(fixed_factor_clks)); + + clk = mmp_clk_register_factor("uart_pll", "pll1_4", + CLK_SET_RATE_PARENT, + pxa_unit->mpmu_base + MPMU_UART_PLL, + &uart_factor_masks, uart_factor_tbl, + ARRAY_SIZE(uart_factor_tbl), NULL); + mmp_clk_add(unit, MMP2_CLK_UART_PLL, clk); +} + +static DEFINE_SPINLOCK(uart0_lock); +static DEFINE_SPINLOCK(uart1_lock); +static DEFINE_SPINLOCK(uart2_lock); +static const char *uart_parent_names[] = {"uart_pll", "vctcxo"}; + +static DEFINE_SPINLOCK(ssp0_lock); +static DEFINE_SPINLOCK(ssp1_lock); +static DEFINE_SPINLOCK(ssp2_lock); +static DEFINE_SPINLOCK(ssp3_lock); +static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"}; + +static DEFINE_SPINLOCK(reset_lock); + +static struct mmp_param_mux_clk apbc_mux_clks[] = { + {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, + {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, + {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART2, 4, 3, 0, &uart2_lock}, + {0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART3, 4, 3, 0, &uart2_lock}, + {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, + {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, + {0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock}, + {0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock}, +}; + +static struct mmp_param_gate_clk apbc_gate_clks[] = { + {MMP2_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI2, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI3, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI4, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI5, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x7, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, &reset_lock}, + {MMP2_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x87, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, &reset_lock}, + {MMP2_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x7, 0x3, 0x0, 0, &reset_lock}, + {MMP2_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x7, 0x3, 0x0, 0, &reset_lock}, + /* The gate clocks has mux parent. */ + {MMP2_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x7, 0x3, 0x0, 0, &uart0_lock}, + {MMP2_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x7, 0x3, 0x0, 0, &uart1_lock}, + {MMP2_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBC_UART2, 0x7, 0x3, 0x0, 0, &uart2_lock}, + {MMP2_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, APBC_UART3, 0x7, 0x3, 0x0, 0, &uart2_lock}, + {MMP2_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x7, 0x3, 0x0, 0, &ssp0_lock}, + {MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock}, + {MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock}, + {MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock}, +}; + +static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit) +{ + struct mmp_clk_unit *unit = &pxa_unit->unit; + + mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_mux_clks)); + + mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, + ARRAY_SIZE(apbc_gate_clks)); +} + +static DEFINE_SPINLOCK(sdh_lock); +static const char *sdh_parent_names[] = {"pll1_4", "pll2", "usb_pll", "pll1"}; +static struct mmp_clk_mix_config sdh_mix_config = { + .reg_info = DEFINE_MIX_REG_INFO(4, 10, 2, 8, 32), +}; + +static DEFINE_SPINLOCK(usb_lock); + +static DEFINE_SPINLOCK(disp0_lock); +static DEFINE_SPINLOCK(disp1_lock); +static const char *disp_parent_names[] = {"pll1", "pll1_16", "pll2", "vctcxo"}; + +static DEFINE_SPINLOCK(ccic0_lock); +static DEFINE_SPINLOCK(ccic1_lock); +static const char *ccic_parent_names[] = {"pll1_2", "pll1_16", "vctcxo"}; +static struct mmp_clk_mix_config ccic0_mix_config = { + .reg_info = DEFINE_MIX_REG_INFO(4, 17, 2, 6, 32), +}; +static struct mmp_clk_mix_config ccic1_mix_config = { + .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32), +}; + +static struct mmp_param_mux_clk apmu_mux_clks[] = { + {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock}, + {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock}, +}; + +static struct mmp_param_div_clk apmu_div_clks[] = { + {0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, 0, &disp0_lock}, + {0, "disp0_sphy_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 15, 5, 0, &disp0_lock}, + {0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, 0, &disp1_lock}, + {0, "ccic0_sphy_div", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, + {0, "ccic1_sphy_div", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 10, 5, 0, &ccic1_lock}, +}; + +static struct mmp_param_gate_clk apmu_gate_clks[] = { + {MMP2_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, + /* The gate clocks has mux parent. */ + {MMP2_CLK_SDH0, "sdh0_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, + {MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, + {MMP2_CLK_SDH1, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, + {MMP2_CLK_SDH1, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, + {MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, + {MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock}, + {MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock}, + {MMP2_CLK_CCIC_ARBITER, "ccic_arbiter", "vctcxo", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1800, 0x1800, 0x0, 0, &ccic0_lock}, + {MMP2_CLK_CCIC0, "ccic0_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, + {MMP2_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, + {MMP2_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, + {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock}, + {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock}, + {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock}, +}; + +static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit) +{ + struct clk *clk; + struct mmp_clk_unit *unit = &pxa_unit->unit; + + sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH0; + clk = mmp_clk_register_mix(NULL, "sdh_mix_clk", sdh_parent_names, + ARRAY_SIZE(sdh_parent_names), + CLK_SET_RATE_PARENT, + &sdh_mix_config, &sdh_lock); + + ccic0_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC0; + clk = mmp_clk_register_mix(NULL, "ccic0_mix_clk", ccic_parent_names, + ARRAY_SIZE(ccic_parent_names), + CLK_SET_RATE_PARENT, + &ccic0_mix_config, &ccic0_lock); + mmp_clk_add(unit, MMP2_CLK_CCIC0_MIX, clk); + + ccic1_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC1; + clk = mmp_clk_register_mix(NULL, "ccic1_mix_clk", ccic_parent_names, + ARRAY_SIZE(ccic_parent_names), + CLK_SET_RATE_PARENT, + &ccic1_mix_config, &ccic1_lock); + mmp_clk_add(unit, MMP2_CLK_CCIC1_MIX, clk); + + mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_mux_clks)); + + mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_div_clks)); + + mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, + ARRAY_SIZE(apmu_gate_clks)); +} + +static void mmp2_clk_reset_init(struct device_node *np, + struct mmp2_clk_unit *pxa_unit) +{ + struct mmp_clk_reset_cell *cells; + int i, nr_resets; + + nr_resets = ARRAY_SIZE(apbc_gate_clks); + cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); + if (!cells) + return; + + for (i = 0; i < nr_resets; i++) { + cells[i].clk_id = apbc_gate_clks[i].id; + cells[i].reg = pxa_unit->apbc_base + apbc_gate_clks[i].offset; + cells[i].flags = 0; + cells[i].lock = apbc_gate_clks[i].lock; + cells[i].bits = 0x4; + } + + mmp_clk_reset_register(np, cells, nr_resets); +} + +static void __init mmp2_clk_init(struct device_node *np) +{ + struct mmp2_clk_unit *pxa_unit; + + pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); + if (!pxa_unit) + return; + + pxa_unit->mpmu_base = of_iomap(np, 0); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map mpmu registers\n"); + return; + } + + pxa_unit->apmu_base = of_iomap(np, 1); + if (!pxa_unit->mpmu_base) { + pr_err("failed to map apmu registers\n"); + return; + } + + pxa_unit->apbc_base = of_iomap(np, 2); + if (!pxa_unit->apbc_base) { + pr_err("failed to map apbc registers\n"); + return; + } + + mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS); + + mmp2_pll_init(pxa_unit); + + mmp2_apb_periph_clk_init(pxa_unit); + + mmp2_axi_periph_clk_init(pxa_unit); + + mmp2_clk_reset_init(np, pxa_unit); +} + +CLK_OF_DECLARE(mmp2_clk, "marvell,mmp2-clock", mmp2_clk_init); diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h new file mode 100644 index 000000000000..591f7fba89e2 --- /dev/null +++ b/include/dt-bindings/clock/marvell,mmp2.h @@ -0,0 +1,74 @@ +#ifndef __DTS_MARVELL_MMP2_CLOCK_H +#define __DTS_MARVELL_MMP2_CLOCK_H + +/* fixed clocks and plls */ +#define MMP2_CLK_CLK32 1 +#define MMP2_CLK_VCTCXO 2 +#define MMP2_CLK_PLL1 3 +#define MMP2_CLK_PLL1_2 8 +#define MMP2_CLK_PLL1_4 9 +#define MMP2_CLK_PLL1_8 10 +#define MMP2_CLK_PLL1_16 11 +#define MMP2_CLK_PLL1_3 12 +#define MMP2_CLK_PLL1_6 13 +#define MMP2_CLK_PLL1_12 14 +#define MMP2_CLK_PLL1_20 15 +#define MMP2_CLK_PLL2 16 +#define MMP2_CLK_PLL2_2 17 +#define MMP2_CLK_PLL2_4 18 +#define MMP2_CLK_PLL2_8 19 +#define MMP2_CLK_PLL2_16 20 +#define MMP2_CLK_PLL2_3 21 +#define MMP2_CLK_PLL2_6 22 +#define MMP2_CLK_PLL2_12 23 +#define MMP2_CLK_VCTCXO_2 24 +#define MMP2_CLK_VCTCXO_4 25 +#define MMP2_CLK_UART_PLL 26 +#define MMP2_CLK_USB_PLL 27 + +/* apb periphrals */ +#define MMP2_CLK_TWSI0 60 +#define MMP2_CLK_TWSI1 61 +#define MMP2_CLK_TWSI2 62 +#define MMP2_CLK_TWSI3 63 +#define MMP2_CLK_TWSI4 64 +#define MMP2_CLK_TWSI5 65 +#define MMP2_CLK_GPIO 66 +#define MMP2_CLK_KPC 67 +#define MMP2_CLK_RTC 68 +#define MMP2_CLK_PWM0 69 +#define MMP2_CLK_PWM1 70 +#define MMP2_CLK_PWM2 71 +#define MMP2_CLK_PWM3 72 +#define MMP2_CLK_UART0 73 +#define MMP2_CLK_UART1 74 +#define MMP2_CLK_UART2 75 +#define MMP2_CLK_UART3 76 +#define MMP2_CLK_SSP0 77 +#define MMP2_CLK_SSP1 78 +#define MMP2_CLK_SSP2 79 +#define MMP2_CLK_SSP3 80 + +/* axi periphrals */ +#define MMP2_CLK_SDH0 101 +#define MMP2_CLK_SDH1 102 +#define MMP2_CLK_SDH2 103 +#define MMP2_CLK_SDH3 104 +#define MMP2_CLK_USB 105 +#define MMP2_CLK_DISP0 106 +#define MMP2_CLK_DISP0_MUX 107 +#define MMP2_CLK_DISP0_SPHY 108 +#define MMP2_CLK_DISP1 109 +#define MMP2_CLK_DISP1_MUX 110 +#define MMP2_CLK_CCIC_ARBITER 111 +#define MMP2_CLK_CCIC0 112 +#define MMP2_CLK_CCIC0_MIX 113 +#define MMP2_CLK_CCIC0_PHY 114 +#define MMP2_CLK_CCIC0_SPHY 115 +#define MMP2_CLK_CCIC1 116 +#define MMP2_CLK_CCIC1_MIX 117 +#define MMP2_CLK_CCIC1_PHY 118 +#define MMP2_CLK_CCIC1_SPHY 119 + +#define MMP2_NR_CLKS 200 +#endif -- cgit 1.4.1 From 29a77b8a04e794c6c34d45ea10a300b117a68e08 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:34 +0100 Subject: clk: shmobile: Deprecate renesas,clock-indices Commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices") forgot to replace all occurrences of "renesas,clock-indices" in the driver-specific binding documentation. Signed-off-by: Geert Uytterhoeven Acked-by: Simon Horman Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Signed-off-by: Michael Turquette --- .../devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt index a5f52238c80d..2e18676bd4b5 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -26,11 +26,11 @@ Required Properties: must appear in the same order as the output clocks. - #clock-cells: Must be 1 - clock-output-names: The name of the clocks as free-form strings - - renesas,clock-indices: Indices of the gate clocks into the group (0 to 31) + - clock-indices: Indices of the gate clocks into the group (0 to 31) -The clocks, clock-output-names and renesas,clock-indices properties contain one -entry per gate clock. The MSTP groups are sparsely populated. Unimplemented -gate clocks must not be declared. +The clocks, clock-output-names and clock-indices properties contain one entry +per gate clock. The MSTP groups are sparsely populated. Unimplemented gate +clocks must not be declared. Example -- cgit 1.4.1 From eaa2e9804e9cbd0b46f74e39ca6f92e4834547db Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 6 Nov 2014 11:40:32 +0800 Subject: clk: sunxi: Removed unused/incorrect sun6i-a31-apb2-clk driver This driver does not match the hardware, which is actually compatible to sun4i-a10-apb1-clk. Since we've switch to the correct one, drop this driver. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 - drivers/clk/sunxi/clk-sunxi.c | 7 ------- 2 files changed, 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 6ddcf6e10eb8..d199f9153e04 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -52,7 +52,6 @@ Required properties: "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23 "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 - "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 4133e278212b..46d98e3b98ba 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -632,12 +632,6 @@ static const struct div_data sun4i_apb0_data __initconst = { .table = sun4i_apb0_table, }; -static const struct div_data sun6i_a31_apb2_div_data __initconst = { - .shift = 0, - .pow = 0, - .width = 4, -}; - static void __init sunxi_divider_clk_setup(struct device_node *node, struct div_data *data) { @@ -1093,7 +1087,6 @@ static const struct of_device_id clk_div_match[] __initconst = { {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,}, {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, - {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, {} }; -- cgit 1.4.1 From 95e94c1fadcd1959857db45c2e11810a893badd0 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 13 Nov 2014 02:08:31 +0800 Subject: clk: sunxi: Implement A31 PLL6 as a divs clock for 2x output Some clock modules on the A31 use PLL6x2 as one of their inputs. This patch changes the PLL6 implementation for A31 to a divs clock, i.e. clock with multiple outputs that have different dividers. The first output will be the normal PLL6 output, and the second will be PLL6x2. This patch fixes the PLL6 N factor in the clock driver, and removes any /2 dividers in the PLL6 factors clock part. The N factor counts from 1 to 32, mapping to values 0 to 31, as shown in the A31 manual. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 19 +++++++++++++-- drivers/clk/sunxi/clk-sunxi.c | 28 +++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index d199f9153e04..67b2b99f2b33 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -71,8 +71,9 @@ Required properties for all clocks: multiplexed clocks, the list order must match the hardware programming order. - #clock-cells : from common clock binding; shall be set to 0 except for - "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and - "allwinner,sun4i-pll6-clk" where it shall be set to 1 + the following compatibles where it shall be set to 1: + "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk", + "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk" - clock-output-names : shall be the corresponding names of the outputs. If the clock module only has one output, the name shall be the module name. @@ -87,6 +88,12 @@ Clock consumers should specify the desired clocks they use with a "clocks" phandle cell. Consumers that are using a gated clock should provide an additional ID in their clock property. This ID is the offset of the bit controlling this particular gate in the register. +For the other clocks with "#clock-cells" = 1, the additional ID shall +refer to the index of the output. + +For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output +is the normal PLL6 output, or "pll6". The second output is rate doubled +PLL6, or "pll6x2". For example: @@ -114,6 +121,14 @@ pll5: clk@01c20020 { clock-output-names = "pll5_ddr", "pll5_other"; }; +pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6", "pll6x2"; +}; + cpu: cpu@01c20054 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-cpu-clk"; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index d46949372762..570202582dcf 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -245,9 +245,9 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, } /** - * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 - * PLL6 rate is calculated as follows - * rate = parent_rate * n * (k + 1) / 2 + * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2 + * PLL6x2 rate is calculated as follows + * rate = parent_rate * (n + 1) * (k + 1) * parent_rate is always 24Mhz */ @@ -256,13 +256,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, { u8 div; - /* - * We always have 24MHz / 2, so we can just say that our - * parent clock is 12MHz. - */ - parent_rate = parent_rate / 2; - - /* Normalize value to a parent_rate multiple (24M / 2) */ + /* Normalize value to a parent_rate multiple (24M) */ div = *freq / parent_rate; *freq = parent_rate * div; @@ -274,7 +268,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, if (*k > 3) *k = 3; - *n = DIV_ROUND_UP(div, (*k+1)); + *n = DIV_ROUND_UP(div, (*k+1)) - 1; } /** @@ -445,6 +439,7 @@ static struct clk_factors_config sun6i_a31_pll6_config = { .nwidth = 5, .kshift = 4, .kwidth = 2, + .n_start = 1, }; static struct clk_factors_config sun4i_apb1_config = { @@ -504,6 +499,7 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = { .enable = 31, .table = &sun6i_a31_pll6_config, .getter = sun6i_a31_get_pll6_factors, + .name = "pll6x2", }; static const struct factors_data sun4i_apb1_data __initconst = { @@ -942,6 +938,14 @@ static const struct divs_data pll6_divs_data __initconst = { } }; +static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { + .factors = &sun6i_a31_pll6_data, + .ndivs = 1, + .div = { + { .fixed = 2 }, /* normal output */ + } +}; + /** * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks * @@ -1082,7 +1086,6 @@ static const struct of_device_id clk_factors_match[] __initconst = { {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, - {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, {} @@ -1101,6 +1104,7 @@ static const struct of_device_id clk_div_match[] __initconst = { static const struct of_device_id clk_divs_match[] __initconst = { {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, + {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,}, {} }; -- cgit 1.4.1 From 646cafc6aa4d6004d189de1cdc267ab562069ba9 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 2 Dec 2014 08:54:22 +0100 Subject: clk: Change clk_ops->determine_rate to return a clk_hw as the best parent This is in preparation for clock providers to not have to deal with struct clk. Signed-off-by: Tomeu Vizoso Reviewed-by: Stephen Boyd Signed-off-by: Michael Turquette --- Documentation/clk.txt | 2 +- arch/mips/alchemy/common/clock.c | 10 +++++----- drivers/clk/at91/clk-programmable.c | 4 ++-- drivers/clk/bcm/clk-kona.c | 4 ++-- drivers/clk/clk-composite.c | 9 +++++---- drivers/clk/clk.c | 17 +++++++++++------ drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/mmp/clk-mix.c | 4 ++-- drivers/clk/qcom/clk-pll.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 ++++++++++++-------- drivers/clk/qcom/clk-rcg2.c | 28 +++++++++++++++++----------- drivers/clk/sunxi/clk-factors.c | 4 ++-- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 ++-- include/linux/clk-provider.h | 4 ++-- 14 files changed, 65 insertions(+), 49 deletions(-) (limited to 'Documentation') diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 1fee72f4d331..4ff84623d5e1 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -74,7 +74,7 @@ the operations defined in clk.h: long (*determine_rate)(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk); + struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index d7557cde271a..f42dd0a4af20 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -375,7 +375,7 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk, + struct clk_hw **best_parent_clk, int scale, int maxdiv) { struct clk *pc, *bpc, *free; @@ -454,7 +454,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, } *best_parent_rate = bpr; - *best_parent_clk = bpc; + *best_parent_clk = __clk_get_hw(bpc); return br; } @@ -548,7 +548,7 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw, static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate, best_parent_clk, 2, 512); @@ -680,7 +680,7 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw, static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { struct alchemy_fgcs_clk *c = to_fgcs_clk(hw); int scale, maxdiv; @@ -899,7 +899,7 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate, static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { struct alchemy_fgcs_clk *c = to_fgcs_clk(hw); int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */ diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 62e2509f9df1..bbdb1b985c91 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -57,7 +57,7 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, static long clk_programmable_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_hw) { struct clk *parent = NULL; long best_rate = -EINVAL; @@ -84,7 +84,7 @@ static long clk_programmable_determine_rate(struct clk_hw *hw, if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) { best_rate = tmp_rate; *best_parent_rate = parent_rate; - *best_parent_clk = parent; + *best_parent_hw = __clk_get_hw(parent); } if (!best_rate) diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index 95af2e665dd3..1c06f6f3a8c5 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c @@ -1032,7 +1032,7 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, } static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *best_parent_rate, struct clk **best_parent) + unsigned long *best_parent_rate, struct clk_hw **best_parent) { struct kona_clk *bcm_clk = to_kona_clk(hw); struct clk *clk = hw->clk; @@ -1075,7 +1075,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, if (delta < best_delta) { best_delta = delta; best_rate = other_rate; - *best_parent = parent; + *best_parent = __clk_get_hw(parent); *best_parent_rate = parent_rate; } } diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index b9355daf8065..4386697236a7 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -57,7 +57,7 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_p) + struct clk_hw **best_parent_p) { struct clk_composite *composite = to_clk_composite(hw); const struct clk_ops *rate_ops = composite->rate_ops; @@ -80,8 +80,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, *best_parent_p = NULL; if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) { - *best_parent_p = clk_get_parent(mux_hw->clk); - *best_parent_rate = __clk_get_rate(*best_parent_p); + parent = clk_get_parent(mux_hw->clk); + *best_parent_p = __clk_get_hw(parent); + *best_parent_rate = __clk_get_rate(parent); return rate_ops->round_rate(rate_hw, rate, best_parent_rate); @@ -103,7 +104,7 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, if (!rate_diff || !*best_parent_p || best_rate_diff > rate_diff) { - *best_parent_p = parent; + *best_parent_p = __clk_get_hw(parent); *best_parent_rate = parent_rate; best_rate_diff = rate_diff; best_rate = tmp_rate; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f549e8b1d5ed..44cdc47a6cc5 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -702,7 +702,7 @@ struct clk *__clk_lookup(const char *name) */ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_p) + struct clk_hw **best_parent_p) { struct clk *clk = hw->clk, *parent, *best_parent = NULL; int i, num_parents; @@ -738,7 +738,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, out: if (best_parent) - *best_parent_p = best_parent; + *best_parent_p = best_parent->hw; *best_parent_rate = best; return best; @@ -946,6 +946,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) { unsigned long parent_rate = 0; struct clk *parent; + struct clk_hw *parent_hw; if (!clk) return 0; @@ -954,10 +955,11 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) if (parent) parent_rate = parent->rate; - if (clk->ops->determine_rate) + if (clk->ops->determine_rate) { + parent_hw = parent ? parent->hw : NULL; return clk->ops->determine_rate(clk->hw, rate, &parent_rate, - &parent); - else if (clk->ops->round_rate) + &parent_hw); + } else if (clk->ops->round_rate) return clk->ops->round_rate(clk->hw, rate, &parent_rate); else if (clk->flags & CLK_SET_RATE_PARENT) return __clk_round_rate(clk->parent, rate); @@ -1345,6 +1347,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) { struct clk *top = clk; struct clk *old_parent, *parent; + struct clk_hw *parent_hw; unsigned long best_parent_rate = 0; unsigned long new_rate; int p_index = 0; @@ -1360,9 +1363,11 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) /* find the closest rate and parent clk/rate */ if (clk->ops->determine_rate) { + parent_hw = parent ? parent->hw : NULL; new_rate = clk->ops->determine_rate(clk->hw, rate, &best_parent_rate, - &parent); + &parent_hw); + parent = parent_hw->clk; } else if (clk->ops->round_rate) { new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index 640ea3327c3e..007144f81f50 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -296,7 +296,7 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw, static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_p) + struct clk_hw **best_parent_p) { struct clk_mmc *mclk = to_mmc(hw); unsigned long best = 0; diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c index b79742c47d53..48fa53c7ce5e 100644 --- a/drivers/clk/mmp/clk-mix.c +++ b/drivers/clk/mmp/clk-mix.c @@ -203,7 +203,7 @@ error: static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { struct mmp_clk_mix *mix = to_clk_mix(hw); struct mmp_clk_mix_clk_table *item; @@ -264,7 +264,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate, found: *best_parent_rate = parent_rate_best; - *best_parent_clk = parent_best; + *best_parent_clk = __clk_get_hw(parent_best); return mix_rate_best; } diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index b823bc3b6250..60873a7f45d9 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c @@ -141,7 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate) static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_pll *pll = to_clk_pll(hw); const struct pll_freq_tbl *f; diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index b6e6959e89aa..0b93972c8807 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c @@ -368,16 +368,17 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) static long _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p_hw) { unsigned long clk_flags; + struct clk *p; f = qcom_find_freq(f, rate); if (!f) return -EINVAL; clk_flags = __clk_get_flags(hw->clk); - *p = clk_get_parent_by_index(hw->clk, f->src); + p = clk_get_parent_by_index(hw->clk, f->src); if (clk_flags & CLK_SET_RATE_PARENT) { rate = rate * f->pre_div; if (f->n) { @@ -387,15 +388,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw, rate = tmp; } } else { - rate = __clk_get_rate(*p); + rate = __clk_get_rate(p); } + *p_hw = __clk_get_hw(p); *p_rate = rate; return f->freq; } static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_rcg *rcg = to_clk_rcg(hw); @@ -403,7 +405,7 @@ static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, } static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); @@ -411,13 +413,15 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, } static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p_hw) { struct clk_rcg *rcg = to_clk_rcg(hw); const struct freq_tbl *f = rcg->freq_tbl; + struct clk *p; - *p = clk_get_parent_by_index(hw->clk, f->src); - *p_rate = __clk_round_rate(*p, rate); + p = clk_get_parent_by_index(hw->clk, f->src); + *p_hw = __clk_get_hw(p); + *p_rate = __clk_round_rate(p, rate); return *p_rate; } diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index cfa9eb4fe9ca..08b8b3729f53 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -175,16 +175,17 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) static long _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p_hw) { unsigned long clk_flags; + struct clk *p; f = qcom_find_freq(f, rate); if (!f) return -EINVAL; clk_flags = __clk_get_flags(hw->clk); - *p = clk_get_parent_by_index(hw->clk, f->src); + p = clk_get_parent_by_index(hw->clk, f->src); if (clk_flags & CLK_SET_RATE_PARENT) { if (f->pre_div) { rate /= 2; @@ -198,15 +199,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw, rate = tmp; } } else { - rate = __clk_get_rate(*p); + rate = __clk_get_rate(p); } + *p_hw = __clk_get_hw(p); *p_rate = rate; return f->freq; } static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); @@ -359,7 +361,7 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw, } static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); const struct freq_tbl *f = rcg->freq_tbl; @@ -371,7 +373,7 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, u32 hid_div; /* Force the correct parent */ - *p = clk_get_parent_by_index(hw->clk, f->src); + *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, f->src)); if (src_rate == 810000000) frac = frac_table_810m; @@ -410,18 +412,20 @@ const struct clk_ops clk_edp_pixel_ops = { EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p_hw) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); const struct freq_tbl *f = rcg->freq_tbl; unsigned long parent_rate, div; u32 mask = BIT(rcg->hid_width) - 1; + struct clk *p; if (rate == 0) return -EINVAL; - *p = clk_get_parent_by_index(hw->clk, f->src); - *p_rate = parent_rate = __clk_round_rate(*p, rate); + p = clk_get_parent_by_index(hw->clk, f->src); + *p_hw = __clk_get_hw(p); + *p_rate = parent_rate = __clk_round_rate(p, rate); div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; div = min_t(u32, div, mask); @@ -472,14 +476,16 @@ static const struct frac_entry frac_table_pixel[] = { }; static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *p_rate, struct clk **p) + unsigned long *p_rate, struct clk_hw **p) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); unsigned long request, src_rate; int delta = 100000; const struct freq_tbl *f = rcg->freq_tbl; const struct frac_entry *frac = frac_table_pixel; - struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src); + struct clk *parent = clk_get_parent_by_index(hw->clk, f->src); + + *p = __clk_get_hw(parent); for (; frac->num; frac++) { request = (rate * frac->den) / frac->num; diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 5521e866fa5e..62e08fb58554 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -81,7 +81,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_p) + struct clk_hw **best_parent_p) { struct clk *clk = hw->clk, *parent, *best_parent = NULL; int i, num_parents; @@ -108,7 +108,7 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, } if (best_parent) - *best_parent_p = best_parent; + *best_parent_p = __clk_get_hw(best_parent); *best_parent_rate = best; return best_child_rate; diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index acca53290be2..3d282fb8f85c 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c @@ -46,7 +46,7 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw, static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { int nparents = __clk_get_num_parents(hw->clk); long best_rate = -EINVAL; @@ -100,7 +100,7 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, tmp_rate = (parent_rate >> shift) / div; if (!*best_parent_clk || tmp_rate > best_rate) { - *best_parent_clk = parent; + *best_parent_clk = __clk_get_hw(parent); *best_parent_rate = parent_rate; best_rate = tmp_rate; } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5e06f23eed41..d936409520f8 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -176,7 +176,7 @@ struct clk_ops { unsigned long *parent_rate); long (*determine_rate)(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk); + struct clk_hw **best_parent_hw); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long rate, @@ -551,7 +551,7 @@ bool __clk_is_enabled(struct clk *clk); struct clk *__clk_lookup(const char *name); long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_p); + struct clk_hw **best_parent_p); /* * FIXME clock api without lock protection -- cgit 1.4.1