From 373d4e6bb8e9611e56cfbefa8d9246b004276791 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 3 Feb 2014 09:51:38 +0800 Subject: clk: sunxi: update clock-output-names dt binding documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clock-output-names is now required for most of sunxi clock nodes, to provide the name of the corresponding clock. Add the new requirements, exceptions, as well as examples. Signed-off-by: Chen-Yu Tsai Signed-off-by: Emilio López --- Documentation/devicetree/bindings/clock/sunxi.txt | 32 ++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index c2cb7621ad2d..0cf679b8384f 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -44,10 +44,11 @@ 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" where it shall be set to 1 - -Additionally, "allwinner,*-gates-clk" clocks require: -- clock-output-names : the corresponding gate names that the clock controls + "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and + "allwinner,sun4i-pll6-clk" where it shall be set to 1 +- 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. Clock consumers should specify the desired clocks they use with a "clocks" phandle cell. Consumers that are using a gated clock should @@ -56,18 +57,28 @@ offset of the bit controlling this particular gate in the register. For example: -osc24M: osc24M@01c20050 { +osc24M: clk@01c20050 { #clock-cells = <0>; compatible = "allwinner,sun4i-osc-clk"; reg = <0x01c20050 0x4>; clocks = <&osc24M_fixed>; + clock-output-names = "osc24M"; }; -pll1: pll1@01c20000 { +pll1: clk@01c20000 { #clock-cells = <0>; compatible = "allwinner,sun4i-pll1-clk"; reg = <0x01c20000 0x4>; clocks = <&osc24M>; + clock-output-names = "pll1"; +}; + +pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; }; cpu: cpu@01c20054 { @@ -75,4 +86,13 @@ cpu: cpu@01c20054 { compatible = "allwinner,sun4i-cpu-clk"; reg = <0x01c20054 0x4>; clocks = <&osc32k>, <&osc24M>, <&pll1>; + clock-output-names = "cpu"; +}; + +mmc0_clk: clk@01c20088 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0"; }; -- cgit v1.2.3-58-ga151 From dc04f2b2f7700c5f7a2a8978cdf97015a1e60902 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 10 Feb 2014 18:32:45 +0100 Subject: dt: Update binding information for mvebu core clocks with Armada 375 Add the binding information for the core clocks of the Armada 375 SoCs Signed-off-by: Gregory CLEMENT Reviewed-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/clock/mvebu-core-clock.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt index 1e662948661e..62fc34a1506d 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt @@ -11,6 +11,12 @@ The following is a list of provided IDs and clock names on Armada 370/XP: 3 = hclk (DRAM control clock) 4 = dramclk (DDR clock) +The following is a list of provided IDs and clock names on Armada 375: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = l2clk (L2 Cache clock) + 3 = ddrclk (DDR clock) + The following is a list of provided IDs and clock names on Kirkwood and Dove: 0 = tclk (Internal Bus clock) 1 = cpuclk (CPU0 clock) @@ -20,6 +26,7 @@ The following is a list of provided IDs and clock names on Kirkwood and Dove: Required properties: - compatible : shall be one of the following: "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks + "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks "marvell,dove-core-clock" - for Dove SoC core clocks "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180) -- cgit v1.2.3-58-ga151 From bac18c75a22e1706a5da0598eb577bbfe11a15ed Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 10 Feb 2014 18:32:46 +0100 Subject: dt: Update binding information for mvebu gating clocks with Armada 375 Add the binding information for the gating clocks of the Armada 375 SoCs Signed-off-by: Gregory CLEMENT Reviewed-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- .../bindings/clock/mvebu-gated-clock.txt | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt index fc2910fa7e45..cbecec1f64fa 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt @@ -1,6 +1,6 @@ * Gated Clock bindings for Marvell EBU SoCs -Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be +Marvell Armada 370/375/XP, Dove and Kirkwood allow some peripheral clocks to be gated to save some power. The clock consumer should specify the desired clock by having the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to the corresponding clock gating control bit in HW to ease manual clock @@ -22,6 +22,34 @@ ID Clock Peripheral 28 ddr DDR Cntrl 30 sata1 SATA Host 0 +The following is a list of provided IDs for Armada 375: +ID Clock Peripheral +----------------------------------- +2 mu Management Unit +3 pp Packet Processor +4 ptp PTP +5 pex0 PCIe 0 Clock out +6 pex1 PCIe 1 Clock out +8 audio Audio Cntrl +11 nd_clk Nand Flash Cntrl +14 sata0_link SATA 0 Link +15 sata0_core SATA 0 Core +16 usb3 USB3 Host +17 sdio SDHCI Host +18 usb USB Host +19 gop Gigabit Ethernet MAC +20 sata1_link SATA 1 Link +21 sata1_core SATA 1 Core +22 xor0 XOR DMA 0 +23 xor1 XOR DMA 0 +24 copro Coprocessor +25 tdm Time Division Mplx +28 crypto0_enc Cryptographic Unit Port 0 Encryption +29 crypto0_core Cryptographic Unit Port 0 Core +30 crypto1_enc Cryptographic Unit Port 1 Encryption +31 crypto1_core Cryptographic Unit Port 1 Core + + The following is a list of provided IDs for Armada XP: ID Clock Peripheral ----------------------------------- @@ -95,6 +123,7 @@ ID Clock Peripheral Required properties: - compatible : shall be one of the following: "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating + "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating "marvell,dove-gating-clock" - for Dove SoC clock gating "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating -- cgit v1.2.3-58-ga151 From 3e8947aeba06d8cf59a6193d88ebaf02b5144f5f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 10 Feb 2014 18:32:48 +0100 Subject: dt: Update binding information for mvebu core clocks with Armada 380/385 Add the binding information for the core clocks of the Armada 380 and Armada 385 SoCs Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/clock/mvebu-core-clock.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt index 62fc34a1506d..307a503c5db8 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt @@ -17,6 +17,12 @@ The following is a list of provided IDs and clock names on Armada 375: 2 = l2clk (L2 Cache clock) 3 = ddrclk (DDR clock) +The following is a list of provided IDs and clock names on Armada 380/385: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = l2clk (L2 Cache clock) + 3 = ddrclk (DDR clock) + The following is a list of provided IDs and clock names on Kirkwood and Dove: 0 = tclk (Internal Bus clock) 1 = cpuclk (CPU0 clock) @@ -27,6 +33,7 @@ Required properties: - compatible : shall be one of the following: "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks + "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks "marvell,dove-core-clock" - for Dove SoC core clocks "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180) -- cgit v1.2.3-58-ga151 From e9646fe1169de0162d461472df7ed19e0c729b61 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 10 Feb 2014 18:32:49 +0100 Subject: dt: Update binding information for mvebu gating clocks with Armada 380/385 Add the binding information for the gating clocks of the Armada 380 SoCs and the Armada 385 SoCs. Signed-off-by: Thomas Petazzoni Signed-off-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- .../bindings/clock/mvebu-gated-clock.txt | 36 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt index cbecec1f64fa..76477be742b2 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt @@ -1,9 +1,10 @@ * Gated Clock bindings for Marvell EBU SoCs -Marvell Armada 370/375/XP, Dove and Kirkwood allow some peripheral clocks to be -gated to save some power. The clock consumer should specify the desired clock -by having the clock ID in its "clocks" phandle cell. The clock ID is directly -mapped to the corresponding clock gating control bit in HW to ease manual clock +Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some +peripheral clocks to be gated to save some power. The clock consumer +should specify the desired clock by having the clock ID in its +"clocks" phandle cell. The clock ID is directly mapped to the +corresponding clock gating control bit in HW to ease manual clock lookup in datasheet. The following is a list of provided IDs for Armada 370: @@ -49,6 +50,32 @@ ID Clock Peripheral 30 crypto1_enc Cryptographic Unit Port 1 Encryption 31 crypto1_core Cryptographic Unit Port 1 Core +The following is a list of provided IDs for Armada 380/385: +ID Clock Peripheral +----------------------------------- +0 audio Audio +2 ge2 Gigabit Ethernet 2 +3 ge1 Gigabit Ethernet 1 +4 ge0 Gigabit Ethernet 0 +5 pex1 PCIe 1 +6 pex2 PCIe 2 +7 pex3 PCIe 3 +8 pex0 PCIe 0 +9 usb3h0 USB3 Host 0 +10 usb3h1 USB3 Host 1 +11 usb3d USB3 Device +13 bm Buffer Management +14 crypto0z Cryptographic 0 Z +15 sata0 SATA 0 +16 crypto1z Cryptographic 1 Z +17 sdio SDIO +18 usb2 USB 2 +21 crypto1 Cryptographic 1 +22 xor0 XOR 0 +23 crypto0 Cryptographic 0 +25 tdm Time Division Multiplexing +28 xor1 XOR 1 +30 sata1 SATA 1 The following is a list of provided IDs for Armada XP: ID Clock Peripheral @@ -124,6 +151,7 @@ Required properties: - compatible : shall be one of the following: "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating + "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating "marvell,dove-gating-clock" - for Dove SoC clock gating "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating -- cgit v1.2.3-58-ga151 From 5abdbf2f497c1769aa9df284ad125d40641207c7 Mon Sep 17 00:00:00 2001 From: Roman Byshko Date: Fri, 7 Feb 2014 16:21:50 +0100 Subject: clk: sunxi: Add USB clock register defintions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add register definitions for the usb-clk register found on sun4i, sun5i and sun7i SoCs. Signed-off-by: Roman Byshko Signed-off-by: Hans de Goede Acked-by: Maxime Ripard Signed-off-by: Emilio López --- Documentation/devicetree/bindings/clock/sunxi.txt | 5 +++++ drivers/clk/sunxi/clk-sunxi.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 0cf679b8384f..ca2b6920fca4 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -37,6 +37,8 @@ Required properties: "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks "allwinner,sun7i-a20-out-clk" - for the external output clocks + "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 + "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 Required properties for all clocks: - reg : shall be the control register address for the clock. @@ -50,6 +52,9 @@ Required properties for all clocks: If the clock module only has one output, the name shall be the module name. +And "allwinner,*-usb-clk" clocks also require: +- reset-cells : shall be set to 1 + 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 diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 23beb6e89558..a779c31b0de9 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -816,6 +816,16 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { .mask = { 0xff80ff }, }; +static const struct gates_data sun4i_a10_usb_gates_data __initconst = { + .mask = {0x1C0}, + .reset_mask = 0x07, +}; + +static const struct gates_data sun5i_a13_usb_gates_data __initconst = { + .mask = {0x140}, + .reset_mask = 0x03, +}; + static void __init sunxi_gates_clk_setup(struct device_node *node, struct gates_data *data) { @@ -1107,6 +1117,8 @@ static const struct of_device_id clk_gates_match[] __initconst = { {.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,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, + {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, + {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, {} }; -- cgit v1.2.3-58-ga151 From 92ef67c53ad92487c3c8de75e7940384c2edd793 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 5 Feb 2014 14:05:03 +0100 Subject: clk: sunxi: Add support for PLL6 on the A31 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The A31 has a slightly different PLL6 clock. Add support for this new clock in our driver. Signed-off-by: Maxime Ripard Signed-off-by: Emilio López --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/clk-sunxi.c | 45 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index ca2b6920fca4..c37c764cbbc5 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -11,6 +11,7 @@ Required properties: "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun4i-pll5-clk" - for the PLL5 clock "allwinner,sun4i-pll6-clk" - for the PLL6 clock + "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-axi-clk" - for the AXI clock "allwinner,sun4i-axi-gates-clk" - for the AXI gates diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index a779c31b0de9..d4cf297e8fac 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -252,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, *n = DIV_ROUND_UP(div, (*k+1)); } +/** + * 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 + * parent_rate is always 24Mhz + */ + +static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, + u8 *n, u8 *k, u8 *m, u8 *p) +{ + 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) */ + div = *freq / parent_rate; + *freq = parent_rate * div; + + /* we were called to round the frequency, we can now return */ + if (n == NULL) + return; + + *k = div / 32; + if (*k > 3) + *k = 3; + *n = DIV_ROUND_UP(div, (*k+1)); +} /** * sun4i_get_apb1_factors() - calculates m, p factors for APB1 @@ -420,6 +451,13 @@ static struct clk_factors_config sun4i_pll5_config = { .kwidth = 2, }; +static struct clk_factors_config sun6i_a31_pll6_config = { + .nshift = 8, + .nwidth = 5, + .kshift = 4, + .kwidth = 2, +}; + static struct clk_factors_config sun4i_apb1_config = { .mshift = 0, .mwidth = 5, @@ -469,6 +507,12 @@ static const struct factors_data sun4i_pll6_data __initconst = { .name = "pll6", }; +static const struct factors_data sun6i_a31_pll6_data __initconst = { + .enable = 31, + .table = &sun6i_a31_pll6_config, + .getter = sun6i_a31_get_pll6_factors, +}; + static const struct factors_data sun4i_apb1_data __initconst = { .table = &sun4i_apb1_config, .getter = sun4i_get_apb1_factors, @@ -1069,6 +1113,7 @@ free_clkdata: static const struct of_device_id clk_factors_match[] __initconst = { {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, + {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, -- cgit v1.2.3-58-ga151 From e4c6d6c11bee5ff11feb837a0a76103b3eba252f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 10 Feb 2014 18:35:47 +0800 Subject: clk: sunxi: Add Allwinner A20/A31 GMAC clock unit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Allwinner A20/A31 clock module controls the transmit clock source and interface type of the GMAC ethernet controller. Model this as a single clock for GMAC drivers to use. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Emilio López --- Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++ drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++ 2 files changed, 126 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index c37c764cbbc5..256a9089f677 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -38,6 +38,7 @@ Required properties: "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks "allwinner,sun7i-a20-out-clk" - for the external output clocks + "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 @@ -56,6 +57,9 @@ Required properties for all clocks: And "allwinner,*-usb-clk" clocks also require: - reset-cells : shall be set to 1 +For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate +dummy clocks at 25 MHz and 125 MHz, respectively. See example. + 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 @@ -102,3 +106,29 @@ mmc0_clk: clk@01c20088 { clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; clock-output-names = "mmc0"; }; + +mii_phy_tx_clk: clk@2 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + clock-output-names = "mii_phy_tx"; +}; + +gmac_int_tx_clk: clk@3 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_int_tx"; +}; + +gmac_clk: clk@01c20164 { + #clock-cells = <0>; + compatible = "allwinner,sun7i-a20-gmac-clk"; + reg = <0x01c20164 0x4>; + /* + * The first clock must be fixed at 25MHz; + * the second clock must be fixed at 125MHz + */ + clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; + clock-output-names = "gmac"; +}; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index d4cf297e8fac..335c98721218 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -410,6 +410,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, +/** + * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module + * + * This clock looks something like this + * ________________________ + * MII TX clock from PHY >-----|___________ _________|----> to GMAC core + * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY + * Ext. 125MHz RGMII TX clk >--|__divider__/ | + * |________________________| + * + * The external 125 MHz reference is optional, i.e. GMAC can use its + * internal TX clock just fine. The A31 GMAC clock module does not have + * the divider controls for the external reference. + * + * To keep it simple, let the GMAC use either the MII TX clock for MII mode, + * and its internal TX clock for GMII and RGMII modes. The GMAC driver should + * select the appropriate source and gate/ungate the output to the PHY. + * + * Only the GMAC should use this clock. Altering the clock so that it doesn't + * match the GMAC's operation parameters will result in the GMAC not being + * able to send traffic out. The GMAC driver should set the clock rate and + * enable/disable this clock to configure the required state. The clock + * driver then responds by auto-reparenting the clock. + */ + +#define SUN7I_A20_GMAC_GPIT 2 +#define SUN7I_A20_GMAC_MASK 0x3 +#define SUN7I_A20_GMAC_PARENTS 2 + +static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) +{ + struct clk *clk; + struct clk_mux *mux; + struct clk_gate *gate; + const char *clk_name = node->name; + const char *parents[SUN7I_A20_GMAC_PARENTS]; + void *reg; + + if (of_property_read_string(node, "clock-output-names", &clk_name)) + return; + + /* allocate mux and gate clock structs */ + mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); + if (!mux) + return; + + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); + if (!gate) + goto free_mux; + + /* gmac clock requires exactly 2 parents */ + parents[0] = of_clk_get_parent_name(node, 0); + parents[1] = of_clk_get_parent_name(node, 1); + if (!parents[0] || !parents[1]) + goto free_gate; + + reg = of_iomap(node, 0); + if (!reg) + goto free_gate; + + /* set up gate and fixed rate properties */ + gate->reg = reg; + gate->bit_idx = SUN7I_A20_GMAC_GPIT; + gate->lock = &clk_lock; + mux->reg = reg; + mux->mask = SUN7I_A20_GMAC_MASK; + mux->flags = CLK_MUX_INDEX_BIT; + mux->lock = &clk_lock; + + clk = clk_register_composite(NULL, clk_name, + parents, SUN7I_A20_GMAC_PARENTS, + &mux->hw, &clk_mux_ops, + NULL, NULL, + &gate->hw, &clk_gate_ops, + 0); + + if (IS_ERR(clk)) + goto iounmap_reg; + + of_clk_add_provider(node, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, clk_name, NULL); + + return; + +iounmap_reg: + iounmap(reg); +free_gate: + kfree(gate); +free_mux: + kfree(mux); +} +CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", + sun7i_a20_gmac_clk_setup); + + + /** * sunxi_factors_clk_setup() - Setup function for factor clocks */ -- cgit v1.2.3-58-ga151 From fd1b22f6fb3b31980b80505ac9d86521569ed2ee Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Feb 2014 09:55:57 +0100 Subject: clk: sunxi: Add new clock compatibles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Allwinner A10 compatibles were following a slightly different compatible patterns than the rest of the SoCs for historical reasons. Add compatibles matching the other pattern to the clock driver for consistency, and keep the older one for backward compatibility. Signed-off-by: Maxime Ripard Signed-off-by: Emilio López --- Documentation/devicetree/bindings/clock/sunxi.txt | 36 +++++++++++------------ drivers/clk/sunxi/clk-sunxi.c | 30 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 256a9089f677..a5160d8cbb5f 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -6,37 +6,37 @@ This binding uses the common clock binding[1]. Required properties: - compatible : shall be one of the following: - "allwinner,sun4i-osc-clk" - for a gatable oscillator - "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4 + "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator + "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,sun4i-pll5-clk" - for the PLL5 clock - "allwinner,sun4i-pll6-clk" - for the PLL6 clock + "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,sun4i-cpu-clk" - for the CPU multiplexer clock - "allwinner,sun4i-axi-clk" - for the AXI clock - "allwinner,sun4i-axi-gates-clk" - for the AXI gates - "allwinner,sun4i-ahb-clk" - for the AHB clock - "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 + "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock + "allwinner,sun4i-a10-axi-clk" - for the AXI clock + "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates + "allwinner,sun4i-a10-ahb-clk" - for the AHB clock + "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 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 "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,sun4i-apb0-clk" - for the APB0 clock - "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 + "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock + "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 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 - "allwinner,sun4i-apb1-clk" - for the APB1 clock - "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing - "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 + "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "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 "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,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 - "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks + "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks "allwinner,sun7i-a20-out-clk" - for the external output clocks "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 @@ -69,7 +69,7 @@ For example: osc24M: clk@01c20050 { #clock-cells = <0>; - compatible = "allwinner,sun4i-osc-clk"; + compatible = "allwinner,sun4i-a10-osc-clk"; reg = <0x01c20050 0x4>; clocks = <&osc24M_fixed>; clock-output-names = "osc24M"; @@ -77,7 +77,7 @@ osc24M: clk@01c20050 { pll1: clk@01c20000 { #clock-cells = <0>; - compatible = "allwinner,sun4i-pll1-clk"; + compatible = "allwinner,sun4i-a10-pll1-clk"; reg = <0x01c20000 0x4>; clocks = <&osc24M>; clock-output-names = "pll1"; @@ -93,7 +93,7 @@ pll5: clk@01c20020 { cpu: cpu@01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-cpu-clk"; + compatible = "allwinner,sun4i-a10-cpu-clk"; reg = <0x01c20054 0x4>; clocks = <&osc32k>, <&osc24M>, <&pll1>; clock-output-names = "cpu"; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 335c98721218..23baad9d934a 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -80,7 +80,7 @@ err_free_gate: err_free_fixed: kfree(fixed); } -CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); +CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup); @@ -1207,52 +1207,52 @@ free_clkdata: /* Matches for factors clocks */ static const struct of_device_id clk_factors_match[] __initconst = { - {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, + {.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,}, {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, - {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, - {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, + {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, + {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,}, {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, {} }; /* Matches for divider clocks */ static const struct of_device_id clk_div_match[] __initconst = { - {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, - {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, - {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, + {.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_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,}, {} }; /* Matches for divided outputs */ static const struct of_device_id clk_divs_match[] __initconst = { - {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,}, - {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,}, + {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, + {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, {} }; /* Matches for mux clocks */ static const struct of_device_id clk_mux_match[] __initconst = { - {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, - {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, + {.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,}, {} }; /* Matches for gate clocks */ static const struct of_device_id clk_gates_match[] __initconst = { - {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, - {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, + {.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,}, + {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, {.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,sun4i-apb0-gates-clk", .data = &sun4i_apb0_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,sun4i-apb1-gates-clk", .data = &sun4i_apb1_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,}, -- cgit v1.2.3-58-ga151 From 044abbde7bef2726489b5e11ec3fcdc012a4de4a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 6 Jan 2014 12:17:24 -0600 Subject: clk: socfpga: Add a clk-phase property to the "altr,socfpga-gate-clk" The clk-phase property is used to represent the 2 clock phase values that is needed for the SD/MMC driver. Add a prepare function to the clk_ops, that will use the syscon driver to set sdmmc_clk's phase shift that is located in the system manager. Signed-off-by: Dinh Nguyen Acked-by: Zhangfei Gao Acked-by: Jaehoon Chung --- v9: none v8: Use degrees in the clk-phase binding property v7: Add dts property to represent the clk phase of the sdmmc_clk. Add a prepare function to the gate clk that will toggle clock phase setting. Remove the "altr,socfpga-sdmmc-sdr-clk" clock type. v6: Add a new clock type "altr,socfpga-sdmmc-sdr-clk" that will be used to set the phase shift settings. v5: Use the "snps,dw-mshc" binding v4: Use the sdmmc_clk prepare function to set the phase shift settings v3: Not use the syscon driver because as of 3.13-rc1, the syscon driver is loaded after the clock driver. v2: Use the syscon driver --- .../devicetree/bindings/clock/altr_socfpga.txt | 5 ++ arch/arm/boot/dts/socfpga.dtsi | 1 + drivers/clk/socfpga/clk-gate.c | 68 ++++++++++++++++++++++ 3 files changed, 74 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/altr_socfpga.txt b/Documentation/devicetree/bindings/clock/altr_socfpga.txt index 0045433eae1f..5dfd145d3ccf 100644 --- a/Documentation/devicetree/bindings/clock/altr_socfpga.txt +++ b/Documentation/devicetree/bindings/clock/altr_socfpga.txt @@ -23,3 +23,8 @@ Optional properties: and the bit index. - div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift, and width. +- clk-phase : For the sdmmc_clk, contains the value of the clock phase that controls + the SDMMC CIU clock. The first value is the clk_sample(smpsel), and the second + value is the cclk_in_drv(drvsel). The clk-phase is used to enable the correct + hold/delay times that is needed for the SD/MMC CIU clock. The values of both + can be 0-315 degrees, in 45 degree increments. diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 537f1a5c07f5..3d62f47bead2 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -415,6 +415,7 @@ compatible = "altr,socfpga-gate-clk"; clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>; clk-gate = <0xa0 8>; + clk-phase = <0 135>; }; nand_x_clk: nand_x_clk { diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c index 4efcf4e33a82..501d513bf890 100644 --- a/drivers/clk/socfpga/clk-gate.c +++ b/drivers/clk/socfpga/clk-gate.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include "clk.h" @@ -35,6 +37,11 @@ #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) +/* SDMMC Group for System Manager defines */ +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ + ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) + static u8 socfpga_clk_get_parent(struct clk_hw *hwclk) { u32 l4_src; @@ -115,7 +122,61 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, return parent_rate / div; } +static int socfpga_clk_prepare(struct clk_hw *hwclk) +{ + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); + struct regmap *sys_mgr_base_addr; + int i; + u32 hs_timing; + u32 clk_phase[2]; + + if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) { + sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); + if (IS_ERR(sys_mgr_base_addr)) { + pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__); + return -EINVAL; + } + + for (i = 0; i < 2; i++) { + switch (socfpgaclk->clk_phase[i]) { + case 0: + clk_phase[i] = 0; + break; + case 45: + clk_phase[i] = 1; + break; + case 90: + clk_phase[i] = 2; + break; + case 135: + clk_phase[i] = 3; + break; + case 180: + clk_phase[i] = 4; + break; + case 225: + clk_phase[i] = 5; + break; + case 270: + clk_phase[i] = 6; + break; + case 315: + clk_phase[i] = 7; + break; + default: + clk_phase[i] = 0; + break; + } + } + hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]); + regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET, + hs_timing); + } + return 0; +} + static struct clk_ops gateclk_ops = { + .prepare = socfpga_clk_prepare, .recalc_rate = socfpga_clk_recalc_rate, .get_parent = socfpga_clk_get_parent, .set_parent = socfpga_clk_set_parent, @@ -126,6 +187,7 @@ static void __init __socfpga_gate_init(struct device_node *node, { u32 clk_gate[2]; u32 div_reg[3]; + u32 clk_phase[2]; u32 fixed_div; struct clk *clk; struct socfpga_gate_clk *socfpga_clk; @@ -166,6 +228,12 @@ static void __init __socfpga_gate_init(struct device_node *node, socfpga_clk->div_reg = 0; } + rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2); + if (!rc) { + socfpga_clk->clk_phase[0] = clk_phase[0]; + socfpga_clk->clk_phase[1] = clk_phase[1]; + } + of_property_read_string(node, "clock-output-names", &clk_name); init.name = clk_name; -- cgit v1.2.3-58-ga151 From 7a0fc1a3df82d29e00b4c9f88a6b37450d6711f1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 13 Feb 2014 18:02:49 +0000 Subject: clk: add clock-indices support Add a property called clock-indices to allow clock-output-names to be used where the index used to lookup a clock is not a 1:1 mapping to the array position in the clock-output-names Signed-off-by: Ben Dooks Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/clock-bindings.txt | 17 +++++++++++++++++ drivers/clk/clk.c | 20 +++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt index 7c52c29d99fa..700e7aac3717 100644 --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -44,6 +44,23 @@ For example: clocks by index. The names should reflect the clock output signal names for the device. +clock-indices: If the identifyng number for the clocks in the node + is not linear from zero, then the this mapping allows + the mapping of identifiers into the clock-output-names + array. + +For example, if we have two clocks <&oscillator 1> and <&oscillator 3>: + + oscillator { + compatible = "myclocktype"; + #clock-cells = <1>; + clock-indices = <1>, <3>; + clock-output-names = "clka", "clkb"; + } + + This ensures we do not have any empty nodes in clock-output-names + + ==Clock consumers== Required properties: diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ea2ca9ff2677..a6f079d23eaa 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2496,8 +2496,12 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_count); const char *of_clk_get_parent_name(struct device_node *np, int index) { struct of_phandle_args clkspec; + struct property *prop; const char *clk_name; + const __be32 *vp; + u32 pv; int rc; + int count; if (index < 0) return NULL; @@ -2507,8 +2511,22 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) if (rc) return NULL; + index = clkspec.args_count ? clkspec.args[0] : 0; + count = 0; + + /* if there is an indices property, use it to transfer the index + * specified into an array offset for the clock-output-names property. + */ + of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) { + if (index == pv) { + index = count; + break; + } + count++; + } + if (of_property_read_string_index(clkspec.np, "clock-output-names", - clkspec.args_count ? clkspec.args[0] : 0, + index, &clk_name) < 0) clk_name = clkspec.np->name; -- cgit v1.2.3-58-ga151 From 62ac983b614149db5a98f333dbb13848cb6b7524 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Mon, 13 Jan 2014 17:37:32 +0800 Subject: clk: hisilicon: add hi3620_mmc_clks Suggest by Arnd: abstract mmc tuning as clock behavior, also because different soc have different tuning method and registers. hi3620_mmc_clks is added to handle mmc clock specifically on hi3620. Signed-off-by: Zhangfei Gao Acked-by: Arnd Bergmann Acked-by: Jaehoon Chung Signed-off-by: Mike Turquette --- .../bindings/arm/hisilicon/hisilicon.txt | 14 ++ .../devicetree/bindings/clock/hi3620-clock.txt | 1 + drivers/clk/hisilicon/clk-hi3620.c | 274 +++++++++++++++++++++ include/dt-bindings/clock/hi3620-clock.h | 5 + 4 files changed, 294 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt index 8c7a4653508d..df0a452b8526 100644 --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt @@ -30,3 +30,17 @@ Example: resume-offset = <0x308>; reboot-offset = <0x4>; }; + +PCTRL: Peripheral misc control register + +Required Properties: +- compatible: "hisilicon,pctrl" +- reg: Address and size of pctrl. + +Example: + + /* for Hi3620 */ + pctrl: pctrl@fca09000 { + compatible = "hisilicon,pctrl"; + reg = <0xfca09000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt index 4b71ab41be53..dad6269f52c5 100644 --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: should be one of the following. - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC. + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc. - reg: physical base address of the controller and length of memory mapped region. diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index f24ad6a3a797..38faa469d288 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np) base); } CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); + +struct hisi_mmc_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + u32 clken_reg; + u32 clken_bit; + u32 div_reg; + u32 div_off; + u32 div_bits; + u32 drv_reg; + u32 drv_off; + u32 drv_bits; + u32 sam_reg; + u32 sam_off; + u32 sam_bits; +}; + +struct clk_mmc { + struct clk_hw hw; + u32 id; + void __iomem *clken_reg; + u32 clken_bit; + void __iomem *div_reg; + u32 div_off; + u32 div_bits; + void __iomem *drv_reg; + u32 drv_off; + u32 drv_bits; + void __iomem *sam_reg; + u32 sam_off; + u32 sam_bits; +}; + +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw) + +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = { + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4}, + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4}, + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4}, + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4}, +}; + +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + switch (parent_rate) { + case 26000000: + return 13000000; + case 180000000: + return 25000000; + case 360000000: + return 50000000; + case 720000000: + return 100000000; + case 1440000000: + return 180000000; + default: + return parent_rate; + } +} + +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_mmc *mclk = to_mmc(hw); + unsigned long best = 0; + + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) { + rate = 13000000; + best = 26000000; + } else if (rate <= 26000000) { + rate = 25000000; + best = 180000000; + } else if (rate <= 52000000) { + rate = 50000000; + best = 360000000; + } else if (rate <= 100000000) { + rate = 100000000; + best = 720000000; + } else { + /* max is 180M */ + rate = 180000000; + best = 1440000000; + } + *best_parent_rate = best; + return rate; +} + +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len) +{ + u32 i; + + if (para >= 0) { + for (i = 0; i < len; i++) { + if (para % 2) + val |= 1 << (off + i); + else + val &= ~(1 << (off + i)); + para = para >> 1; + } + } + return val; +} + +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate) +{ + struct clk_mmc *mclk = to_mmc(hw); + unsigned long flags; + u32 sam, drv, div, val; + static DEFINE_SPINLOCK(mmc_clk_lock); + + switch (rate) { + case 13000000: + sam = 3; + drv = 1; + div = 1; + break; + case 25000000: + sam = 13; + drv = 6; + div = 6; + break; + case 50000000: + sam = 3; + drv = 6; + div = 6; + break; + case 100000000: + sam = 6; + drv = 4; + div = 6; + break; + case 180000000: + sam = 6; + drv = 4; + div = 7; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&mmc_clk_lock, flags); + + val = readl_relaxed(mclk->clken_reg); + val &= ~(1 << mclk->clken_bit); + writel_relaxed(val, mclk->clken_reg); + + val = readl_relaxed(mclk->sam_reg); + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits); + writel_relaxed(val, mclk->sam_reg); + + val = readl_relaxed(mclk->drv_reg); + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits); + writel_relaxed(val, mclk->drv_reg); + + val = readl_relaxed(mclk->div_reg); + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits); + writel_relaxed(val, mclk->div_reg); + + val = readl_relaxed(mclk->clken_reg); + val |= 1 << mclk->clken_bit; + writel_relaxed(val, mclk->clken_reg); + + spin_unlock_irqrestore(&mmc_clk_lock, flags); + + return 0; +} + +static int mmc_clk_prepare(struct clk_hw *hw) +{ + struct clk_mmc *mclk = to_mmc(hw); + unsigned long rate; + + if (mclk->id == HI3620_MMC_CIUCLK1) + rate = 13000000; + else + rate = 25000000; + + return mmc_clk_set_timing(hw, rate); +} + +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return mmc_clk_set_timing(hw, rate); +} + +static struct clk_ops clk_mmc_ops = { + .prepare = mmc_clk_prepare, + .determine_rate = mmc_clk_determine_rate, + .set_rate = mmc_clk_set_rate, + .recalc_rate = mmc_clk_recalc_rate, +}; + +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk, + void __iomem *base, struct device_node *np) +{ + struct clk_mmc *mclk; + struct clk *clk; + struct clk_init_data init; + + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL); + if (!mclk) { + pr_err("%s: fail to allocate mmc clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = mmc_clk->name; + init.ops = &clk_mmc_ops; + init.flags = mmc_clk->flags | CLK_IS_BASIC; + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL); + init.num_parents = (mmc_clk->parent_name ? 1 : 0); + mclk->hw.init = &init; + + mclk->id = mmc_clk->id; + mclk->clken_reg = base + mmc_clk->clken_reg; + mclk->clken_bit = mmc_clk->clken_bit; + mclk->div_reg = base + mmc_clk->div_reg; + mclk->div_off = mmc_clk->div_off; + mclk->div_bits = mmc_clk->div_bits; + mclk->drv_reg = base + mmc_clk->drv_reg; + mclk->drv_off = mmc_clk->drv_off; + mclk->drv_bits = mmc_clk->drv_bits; + mclk->sam_reg = base + mmc_clk->sam_reg; + mclk->sam_off = mmc_clk->sam_off; + mclk->sam_bits = mmc_clk->sam_bits; + + clk = clk_register(NULL, &mclk->hw); + if (WARN_ON(IS_ERR(clk))) + kfree(mclk); + return clk; +} + +static void __init hi3620_mmc_clk_init(struct device_node *node) +{ + void __iomem *base; + int i, num = ARRAY_SIZE(hi3620_mmc_clks); + struct clk_onecell_data *clk_data; + + if (!node) { + pr_err("failed to find pctrl node in DTS\n"); + return; + } + + base = of_iomap(node, 0); + if (!base) { + pr_err("failed to map pctrl\n"); + return; + } + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (WARN_ON(!clk_data)) + return; + + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL); + if (!clk_data->clks) { + pr_err("%s: fail to allocate mmc clk\n", __func__); + return; + } + + for (i = 0; i < num; i++) { + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i]; + clk_data->clks[mmc_clk->id] = + hisi_register_clk_mmc(mmc_clk, base, node); + } + + clk_data->clk_num = num; + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init); diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h index 6eaa6a45e110..21b9d0e2eb0c 100644 --- a/include/dt-bindings/clock/hi3620-clock.h +++ b/include/dt-bindings/clock/hi3620-clock.h @@ -147,6 +147,11 @@ #define HI3620_MMC_CLK3 217 #define HI3620_MCU_CLK 218 +#define HI3620_SD_CIUCLK 0 +#define HI3620_MMC_CIUCLK1 1 +#define HI3620_MMC_CIUCLK2 2 +#define HI3620_MMC_CIUCLK3 3 + #define HI3620_NR_CLKS 219 #endif /* __DTS_HI3620_CLOCK_H */ -- cgit v1.2.3-58-ga151 From 1887c3a64fab8300a5be3fb5fd8d6474a63b50a0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 10:31:53 +0100 Subject: clk: axi-clkgen: Add support for v2 This patch adds support for the new v2 version of the axi-clkgen core. Unfortunately the method of accessing the registers is quite different on v2, while the content still stays largely the same. So the patch adds a small abstraction layer which implements the specific read and write functions for v1 and v2 in callback functions. Signed-off-by: Lars-Peter Clausen --- .../devicetree/bindings/clock/axi-clkgen.txt | 2 +- drivers/clk/clk-axi-clkgen.c | 312 ++++++++++++++++++--- 2 files changed, 270 insertions(+), 44 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt index 028b493e97ff..20e1704e7df2 100644 --- a/Documentation/devicetree/bindings/clock/axi-clkgen.txt +++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt @@ -5,7 +5,7 @@ This binding uses the common clock binding[1]. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt Required properties: -- compatible : shall be "adi,axi-clkgen". +- compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a". - #clock-cells : from common clock binding; Should always be set to 0. - reg : Address and length of the axi-clkgen register set. - clocks : Phandle and clock specifier for the parent clock. diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 8137327847c3..1127ee46b802 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -17,23 +17,75 @@ #include #include -#define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 -#define AXI_CLKGEN_REG_CLK_OUT1 0x08 -#define AXI_CLKGEN_REG_CLK_OUT2 0x0c -#define AXI_CLKGEN_REG_CLK_DIV 0x10 -#define AXI_CLKGEN_REG_CLK_FB1 0x14 -#define AXI_CLKGEN_REG_CLK_FB2 0x18 -#define AXI_CLKGEN_REG_LOCK1 0x1c -#define AXI_CLKGEN_REG_LOCK2 0x20 -#define AXI_CLKGEN_REG_LOCK3 0x24 -#define AXI_CLKGEN_REG_FILTER1 0x28 -#define AXI_CLKGEN_REG_FILTER2 0x2c +#define AXI_CLKGEN_V1_REG_UPDATE_ENABLE 0x04 +#define AXI_CLKGEN_V1_REG_CLK_OUT1 0x08 +#define AXI_CLKGEN_V1_REG_CLK_OUT2 0x0c +#define AXI_CLKGEN_V1_REG_CLK_DIV 0x10 +#define AXI_CLKGEN_V1_REG_CLK_FB1 0x14 +#define AXI_CLKGEN_V1_REG_CLK_FB2 0x18 +#define AXI_CLKGEN_V1_REG_LOCK1 0x1c +#define AXI_CLKGEN_V1_REG_LOCK2 0x20 +#define AXI_CLKGEN_V1_REG_LOCK3 0x24 +#define AXI_CLKGEN_V1_REG_FILTER1 0x28 +#define AXI_CLKGEN_V1_REG_FILTER2 0x2c + +#define AXI_CLKGEN_V2_REG_RESET 0x40 +#define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 +#define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 + +#define AXI_CLKGEN_V2_RESET_MMCM_ENABLE BIT(1) +#define AXI_CLKGEN_V2_RESET_ENABLE BIT(0) + +#define AXI_CLKGEN_V2_DRP_CNTRL_SEL BIT(29) +#define AXI_CLKGEN_V2_DRP_CNTRL_READ BIT(28) + +#define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) + +#define MMCM_REG_CLKOUT0_1 0x08 +#define MMCM_REG_CLKOUT0_2 0x09 +#define MMCM_REG_CLK_FB1 0x14 +#define MMCM_REG_CLK_FB2 0x15 +#define MMCM_REG_CLK_DIV 0x16 +#define MMCM_REG_LOCK1 0x18 +#define MMCM_REG_LOCK2 0x19 +#define MMCM_REG_LOCK3 0x1a +#define MMCM_REG_FILTER1 0x4e +#define MMCM_REG_FILTER2 0x4f + +struct axi_clkgen; + +struct axi_clkgen_mmcm_ops { + void (*enable)(struct axi_clkgen *axi_clkgen, bool enable); + int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg, + unsigned int val, unsigned int mask); + int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg, + unsigned int *val); +}; struct axi_clkgen { void __iomem *base; + const struct axi_clkgen_mmcm_ops *mmcm_ops; struct clk_hw clk_hw; }; +static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, + bool enable) +{ + axi_clkgen->mmcm_ops->enable(axi_clkgen, enable); +} + +static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int val, unsigned int mask) +{ + return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask); +} + +static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int *val) +{ + return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val); +} + static uint32_t axi_clkgen_lookup_filter(unsigned int m) { switch (m) { @@ -156,6 +208,148 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, *val = readl(axi_clkgen->base + reg); } +static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg) +{ + switch (reg) { + case MMCM_REG_CLKOUT0_1: + return AXI_CLKGEN_V1_REG_CLK_OUT1; + case MMCM_REG_CLKOUT0_2: + return AXI_CLKGEN_V1_REG_CLK_OUT2; + case MMCM_REG_CLK_FB1: + return AXI_CLKGEN_V1_REG_CLK_FB1; + case MMCM_REG_CLK_FB2: + return AXI_CLKGEN_V1_REG_CLK_FB2; + case MMCM_REG_CLK_DIV: + return AXI_CLKGEN_V1_REG_CLK_DIV; + case MMCM_REG_LOCK1: + return AXI_CLKGEN_V1_REG_LOCK1; + case MMCM_REG_LOCK2: + return AXI_CLKGEN_V1_REG_LOCK2; + case MMCM_REG_LOCK3: + return AXI_CLKGEN_V1_REG_LOCK3; + case MMCM_REG_FILTER1: + return AXI_CLKGEN_V1_REG_FILTER1; + case MMCM_REG_FILTER2: + return AXI_CLKGEN_V1_REG_FILTER2; + default: + return 0; + } +} + +static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int val, unsigned int mask) +{ + reg = axi_clkgen_v1_map_mmcm_reg(reg); + if (reg == 0) + return -EINVAL; + + axi_clkgen_write(axi_clkgen, reg, val); + + return 0; +} + +static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int *val) +{ + reg = axi_clkgen_v1_map_mmcm_reg(reg); + if (reg == 0) + return -EINVAL; + + axi_clkgen_read(axi_clkgen, reg, val); + + return 0; +} + +static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen, + bool enable) +{ + axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable); +} + +static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = { + .write = axi_clkgen_v1_mmcm_write, + .read = axi_clkgen_v1_mmcm_read, + .enable = axi_clkgen_v1_mmcm_enable, +}; + +static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) +{ + unsigned int timeout = 10000; + unsigned int val; + + do { + axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val); + } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout); + + if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) + return -EIO; + + return val & 0xffff; +} + +static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int *val) +{ + unsigned int reg_val; + int ret; + + ret = axi_clkgen_wait_non_busy(axi_clkgen); + if (ret < 0) + return ret; + + reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ; + reg_val |= (reg << 16); + + axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); + + ret = axi_clkgen_wait_non_busy(axi_clkgen); + if (ret < 0) + return ret; + + *val = ret; + + return 0; +} + +static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, + unsigned int reg, unsigned int val, unsigned int mask) +{ + unsigned int reg_val = 0; + int ret; + + ret = axi_clkgen_wait_non_busy(axi_clkgen); + if (ret < 0) + return ret; + + if (mask != 0xffff) { + axi_clkgen_v2_mmcm_read(axi_clkgen, reg, ®_val); + reg_val &= ~mask; + } + + reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask); + + axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); + + return 0; +} + +static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, + bool enable) +{ + unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; + + if (enable) + val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE; + + axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val); +} + +static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = { + .write = axi_clkgen_v2_mmcm_write, + .read = axi_clkgen_v2_mmcm_read, + .enable = axi_clkgen_v2_mmcm_enable, +}; + static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) { return container_of(clk_hw, struct axi_clkgen, clk_hw); @@ -184,33 +378,29 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, filter = axi_clkgen_lookup_filter(m - 1); lock = axi_clkgen_lookup_lock(m - 1); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); - axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, - (high << 6) | low); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, - (edge << 7) | (nocount << 6)); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1, + (high << 6) | low, 0xefff); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2, + (edge << 7) | (nocount << 6), 0x03ff); axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, - (edge << 13) | (nocount << 12) | (high << 6) | low); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, + (edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff); axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, - (high << 6) | low); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, - (edge << 7) | (nocount << 6)); - - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, - (((lock >> 16) & 0x1f) << 10) | 0x1); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, - (((lock >> 24) & 0x1f) << 10) | 0x3e9); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); - - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1, + (high << 6) | low, 0xefff); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2, + (edge << 7) | (nocount << 6), 0x03ff); + + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, + (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3, + (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900); + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900); return 0; } @@ -236,11 +426,11 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, unsigned int reg; unsigned long long tmp; - axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); + axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®); dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); - axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); + axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®); d = (reg & 0x3f) + ((reg >> 6) & 0x3f); - axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); + axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®); m = (reg & 0x3f) + ((reg >> 6) & 0x3f); if (d == 0 || dout == 0) @@ -255,14 +445,45 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, return tmp; } +static int axi_clkgen_enable(struct clk_hw *clk_hw) +{ + struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); + + axi_clkgen_mmcm_enable(axi_clkgen, true); + + return 0; +} + +static void axi_clkgen_disable(struct clk_hw *clk_hw) +{ + struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); + + axi_clkgen_mmcm_enable(axi_clkgen, false); +} + static const struct clk_ops axi_clkgen_ops = { .recalc_rate = axi_clkgen_recalc_rate, .round_rate = axi_clkgen_round_rate, .set_rate = axi_clkgen_set_rate, + .enable = axi_clkgen_enable, + .disable = axi_clkgen_disable, }; +static const struct of_device_id axi_clkgen_ids[] = { + { + .compatible = "adi,axi-clkgen-1.00.a", + .data = &axi_clkgen_v1_mmcm_ops + }, { + .compatible = "adi,axi-clkgen-2.00.a", + .data = &axi_clkgen_v2_mmcm_ops, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, axi_clkgen_ids); + static int axi_clkgen_probe(struct platform_device *pdev) { + const struct of_device_id *id; struct axi_clkgen *axi_clkgen; struct clk_init_data init; const char *parent_name; @@ -270,10 +491,19 @@ static int axi_clkgen_probe(struct platform_device *pdev) struct resource *mem; struct clk *clk; + if (!pdev->dev.of_node) + return -ENODEV; + + id = of_match_node(axi_clkgen_ids, pdev->dev.of_node); + if (!id) + return -ENODEV; + axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); if (!axi_clkgen) return -ENOMEM; + axi_clkgen->mmcm_ops = id->data; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(axi_clkgen->base)) @@ -289,10 +519,12 @@ static int axi_clkgen_probe(struct platform_device *pdev) init.name = clk_name; init.ops = &axi_clkgen_ops; - init.flags = 0; + init.flags = CLK_SET_RATE_GATE; init.parent_names = &parent_name; init.num_parents = 1; + axi_clkgen_mmcm_enable(axi_clkgen, false); + axi_clkgen->clk_hw.init = &init; clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); if (IS_ERR(clk)) @@ -309,12 +541,6 @@ static int axi_clkgen_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id axi_clkgen_ids[] = { - { .compatible = "adi,axi-clkgen-1.00.a" }, - { }, -}; -MODULE_DEVICE_TABLE(of, axi_clkgen_ids); - static struct platform_driver axi_clkgen_driver = { .driver = { .name = "adi-axi-clkgen", -- cgit v1.2.3-58-ga151 From e69a8543ec7730c46225c886f74f0ea57e4656c5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 13 Mar 2014 17:24:33 -0300 Subject: clk: mvebu: Update binding documentation for the core divider clock The Core Divider clock support two new compatible strings for Armada 375 and Armada 380 SoCs. Add the compatible strings to the documentation. Signed-off-by: Ezequiel Garcia Link: https://lkml.kernel.org/r/1394742273-5113-7-git-send-email-ezequiel.garcia@free-electrons.com Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt index c62391fc0e39..520562a7dc2a 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt @@ -4,7 +4,10 @@ The following is a list of provided IDs and clock names on Armada 370/XP: 0 = nand (NAND clock) Required properties: -- compatible : must be "marvell,armada-370-corediv-clock" +- compatible : must be "marvell,armada-370-corediv-clock", + "marvell,armada-375-corediv-clock", + "marvell,armada-380-corediv-clock", + - reg : must be the register address of Core Divider control register - #clock-cells : from common clock binding; shall be set to 1 - clocks : must be set to the parent's phandle -- cgit v1.2.3-58-ga151 From c7bb4fc16ead2883a9e4eece2781fa78a0837735 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 28 Jan 2014 12:09:11 +0100 Subject: clk: add MOXA ART SoCs clock driver MOXA ART SoCs allow to determine PLL output and APB frequencies by reading registers holding multiplier and divisor information. Add a clock driver for this SoC. Signed-off-by: Jonas Jensen Signed-off-by: Mike Turquette --- .../bindings/clock/moxa,moxart-clock.txt | 48 +++++++++++ drivers/clk/Makefile | 1 + drivers/clk/clk-moxart.c | 97 ++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt create mode 100644 drivers/clk/clk-moxart.c (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt new file mode 100644 index 000000000000..fedea84314a1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt @@ -0,0 +1,48 @@ +Device Tree Clock bindings for arch-moxart + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +MOXA ART SoCs allow to determine PLL output and APB frequencies +by reading registers holding multiplier and divisor information. + + +PLL: + +Required properties: +- compatible : Must be "moxa,moxart-pll-clock" +- #clock-cells : Should be 0 +- reg : Should contain registers location and length +- clocks : Should contain phandle + clock-specifier for the parent clock + +Optional properties: +- clock-output-names : Should contain clock name + + +APB: + +Required properties: +- compatible : Must be "moxa,moxart-apb-clock" +- #clock-cells : Should be 0 +- reg : Should contain registers location and length +- clocks : Should contain phandle + clock-specifier for the parent clock + +Optional properties: +- clock-output-names : Should contain clock name + + +For example: + + clk_pll: clk_pll@98100000 { + compatible = "moxa,moxart-pll-clock"; + #clock-cells = <0>; + reg = <0x98100000 0x34>; + }; + + clk_apb: clk_apb@98100000 { + compatible = "moxa,moxart-apb-clock"; + #clock-cells = <0>; + reg = <0x98100000 0x34>; + clocks = <&clk_pll>; + }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a367a9831717..48a7ef3d05f6 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o +obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c new file mode 100644 index 000000000000..30a3b6999e10 --- /dev/null +++ b/drivers/clk/clk-moxart.c @@ -0,0 +1,97 @@ +/* + * MOXA ART SoCs clock driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * 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 + +void __init moxart_of_pll_clk_init(struct device_node *node) +{ + static void __iomem *base; + struct clk *clk, *ref_clk; + unsigned int mul; + const char *name = node->name; + const char *parent_name; + + of_property_read_string(node, "clock-output-names", &name); + parent_name = of_clk_get_parent_name(node, 0); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s: of_iomap failed\n", node->full_name); + return; + } + + mul = readl(base + 0x30) >> 3 & 0x3f; + iounmap(base); + + ref_clk = of_clk_get(node, 0); + if (IS_ERR(ref_clk)) { + pr_err("%s: of_clk_get failed\n", node->full_name); + return; + } + + clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock\n", node->full_name); + return; + } + + clk_register_clkdev(clk, NULL, name); + of_clk_add_provider(node, of_clk_src_simple_get, clk); +} +CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", + moxart_of_pll_clk_init); + +void __init moxart_of_apb_clk_init(struct device_node *node) +{ + static void __iomem *base; + struct clk *clk, *pll_clk; + unsigned int div, val; + unsigned int div_idx[] = { 2, 3, 4, 6, 8}; + const char *name = node->name; + const char *parent_name; + + of_property_read_string(node, "clock-output-names", &name); + parent_name = of_clk_get_parent_name(node, 0); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s: of_iomap failed\n", node->full_name); + return; + } + + val = readl(base + 0xc) >> 4 & 0x7; + iounmap(base); + + if (val > 4) + val = 0; + div = div_idx[val] * 2; + + pll_clk = of_clk_get(node, 0); + if (IS_ERR(pll_clk)) { + pr_err("%s: of_clk_get failed\n", node->full_name); + return; + } + + clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock\n", node->full_name); + return; + } + + clk_register_clkdev(clk, NULL, name); + of_clk_add_provider(node, of_clk_src_simple_get, clk); +} +CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", + moxart_of_apb_clk_init); -- cgit v1.2.3-58-ga151 From 843bad8361bb0d7e5ed6254c84abd8d2ec61b6a4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 28 Feb 2014 13:40:56 +0100 Subject: Documentation: clk: Add locking documentation Briefly document the common clock framework locking scheme from a clock driver point of view. Signed-off-by: Laurent Pinchart Signed-off-by: Mike Turquette --- Documentation/clk.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'Documentation') diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 699ef2a323b1..c9c399af7c08 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -255,3 +255,37 @@ are sorted out. To bypass this disabling, include "clk_ignore_unused" in the bootargs to the kernel. + + Part 7 - Locking + +The common clock framework uses two global locks, the prepare lock and the +enable lock. + +The enable lock is a spinlock and is held across calls to the .enable, +.disable and .is_enabled operations. Those operations are thus not allowed to +sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API +functions are allowed in atomic context. + +The prepare lock is a mutex and is held across calls to all other operations. +All those operations are allowed to sleep, and calls to the corresponding API +functions are not allowed in atomic context. + +This effectively divides operations in two groups from a locking perspective. + +Drivers don't need to manually protect resources shared between the operations +of one group, regardless of whether those resources are shared by multiple +clocks or not. However, access to resources that are shared between operations +of the two groups needs to be protected by the drivers. An example of such a +resource would be a register that controls both the clock rate and the clock +enable/disable state. + +The clock framework is reentrant, in that a driver is allowed to call clock +framework functions from within its implementation of clock operations. This +can for instance cause a .set_rate operation of one clock being called from +within the .set_rate operation of another clock. This case must be considered +in the driver implementations, but the code flow is usually controlled by the +driver in that case. + +Note that locking must also be considered when code outside of the common +clock framework needs to access resources used by the clock operations. This +is considered out of scope of this document. -- cgit v1.2.3-58-ga151 From a665962e8f4484647e7a19b4d6329d42ed8bc804 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 7 Mar 2014 17:00:37 +0100 Subject: clk: shmobile: add CPG driver for rz-platforms Signed-off-by: Wolfram Sang Signed-off-by: Mike Turquette --- .../bindings/clock/renesas,rz-cpg-clocks.txt | 29 ++++++ drivers/clk/shmobile/Makefile | 1 + drivers/clk/shmobile/clk-rz.c | 103 +++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt create mode 100644 drivers/clk/shmobile/clk-rz.c (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt new file mode 100644 index 000000000000..98a257492522 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt @@ -0,0 +1,29 @@ +* Renesas RZ Clock Pulse Generator (CPG) + +The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable +CPU and GPU clocks, and several fixed ratio dividers. + +Required Properties: + + - compatible: Must be one of + - "renesas,r7s72100-cpg-clocks" for the r7s72100 CPG + - "renesas,rz-cpg-clocks" for the generic RZ CPG + - reg: Base address and length of the memory resource used by the CPG + - clocks: References to possible parent clocks. Order must match clock modes + in the datasheet. For the r7s72100, this is extal, usb_x1. + - #clock-cells: Must be 1 + - clock-output-names: The names of the clocks. Supported clocks are "pll", + "i", and "g" + + +Example +------- + + cpg_clocks: cpg_clocks@fcfe0000 { + #clock-cells = <1>; + compatible = "renesas,r7s72100-cpg-clocks", + "renesas,rz-cpg-clocks"; + reg = <0xfcfe0000 0x18>; + clocks = <&extal_clk>, <&usb_x1_clk>; + clock-output-names = "pll", "i", "g"; + }; diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 9ecef140dba7..5404cb931ebf 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o +obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o diff --git a/drivers/clk/shmobile/clk-rz.c b/drivers/clk/shmobile/clk-rz.c new file mode 100644 index 000000000000..7e68e8630962 --- /dev/null +++ b/drivers/clk/shmobile/clk-rz.c @@ -0,0 +1,103 @@ +/* + * rz Core CPG Clocks + * + * Copyright (C) 2013 Ideas On Board SPRL + * Copyright (C) 2014 Wolfram Sang, Sang Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include + +struct rz_cpg { + struct clk_onecell_data data; + void __iomem *reg; +}; + +#define CPG_FRQCR 0x10 +#define CPG_FRQCR2 0x14 + +/* ----------------------------------------------------------------------------- + * Initialization + */ + +static struct clk * __init +rz_cpg_register_clock(struct device_node *np, struct rz_cpg *cpg, const char *name) +{ + u32 val; + unsigned mult; + static const unsigned frqcr_tab[4] = { 3, 2, 0, 1 }; + + if (strcmp(name, "pll") == 0) { + /* FIXME: cpg_mode should be read from GPIO. But no GPIO support yet */ + unsigned cpg_mode = 0; /* hardcoded to EXTAL for now */ + const char *parent_name = of_clk_get_parent_name(np, cpg_mode); + + mult = cpg_mode ? (32 / 4) : 30; + + return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, 1); + } + + /* If mapping regs failed, skip non-pll clocks. System will boot anyhow */ + if (!cpg->reg) + return ERR_PTR(-ENXIO); + + /* FIXME:"i" and "g" are variable clocks with non-integer dividers (e.g. 2/3) + * and the constraint that always g <= i. To get the rz platform started, + * let them run at fixed current speed and implement the details later. + */ + if (strcmp(name, "i") == 0) + val = (clk_readl(cpg->reg + CPG_FRQCR) >> 8) & 3; + else if (strcmp(name, "g") == 0) + val = clk_readl(cpg->reg + CPG_FRQCR2) & 3; + else + return ERR_PTR(-EINVAL); + + mult = frqcr_tab[val]; + return clk_register_fixed_factor(NULL, name, "pll", 0, mult, 3); +} + +static void __init rz_cpg_clocks_init(struct device_node *np) +{ + struct rz_cpg *cpg; + struct clk **clks; + unsigned i; + int num_clks; + + num_clks = of_property_count_strings(np, "clock-output-names"); + if (WARN(num_clks <= 0, "can't count CPG clocks\n")) + return; + + cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); + clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + BUG_ON(!cpg || !clks); + + cpg->data.clks = clks; + cpg->data.clk_num = num_clks; + + cpg->reg = of_iomap(np, 0); + + for (i = 0; i < num_clks; ++i) { + const char *name; + struct clk *clk; + + of_property_read_string_index(np, "clock-output-names", i, &name); + + clk = rz_cpg_register_clock(np, cpg, name); + if (IS_ERR(clk)) + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clk)); + else + cpg->data.clks[i] = clk; + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); +} +CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init); -- cgit v1.2.3-58-ga151 From be10afcd2274d263fed8f74c6fc59ef71265e7d5 Mon Sep 17 00:00:00 2001 From: Gabriel FERNANDEZ Date: Thu, 27 Feb 2014 16:24:20 +0100 Subject: clk: st: Adds divmux and prediv clock binding Signed-off-by: Gabriel Fernandez Signed-off-by: Mike Turquette --- .../bindings/clock/st/st,clkgen-divmux.txt | 49 +++++++++++++ .../bindings/clock/st/st,clkgen-prediv.txt | 36 ++++++++++ .../devicetree/bindings/clock/st/st,clkgen.txt | 83 ++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt new file mode 100644 index 000000000000..ae56315fcec5 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt @@ -0,0 +1,49 @@ +Binding for a ST divider and multiplexer clock driver. + +This binding uses the common clock binding[1]. +Base address is located to the parent node. See clock binding[2] + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt + +Required properties: + +- compatible : shall be: + "st,clkgena-divmux-c65-hs", "st,clkgena-divmux" + "st,clkgena-divmux-c65-ls", "st,clkgena-divmux" + "st,clkgena-divmux-c32-odf0", "st,clkgena-divmux" + "st,clkgena-divmux-c32-odf1", "st,clkgena-divmux" + "st,clkgena-divmux-c32-odf2", "st,clkgena-divmux" + "st,clkgena-divmux-c32-odf3", "st,clkgena-divmux" + +- #clock-cells : From common clock binding; shall be set to 1. + +- clocks : From common clock binding + +- clock-output-names : From common clock binding. + +Example: + + clockgenA@fd345000 { + reg = <0xfd345000 0xb50>; + + CLK_M_A1_DIV1: CLK_M_A1_DIV1 { + #clock-cells = <1>; + compatible = "st,clkgena-divmux-c32-odf1", + "st,clkgena-divmux"; + + clocks = <&CLK_M_A1_OSC_PREDIV>, + <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */ + <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */ + + clock-output-names = "CLK_M_RX_ICN_TS", + "CLK_M_RX_ICN_VDP_0", + "", /* Unused */ + "CLK_M_PRV_T1_BUS", + "CLK_M_ICN_REG_12", + "CLK_M_ICN_REG_10", + "", /* Unused */ + "CLK_M_ICN_ST231"; + }; + }; + diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt new file mode 100644 index 000000000000..566c9d79ed32 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt @@ -0,0 +1,36 @@ +Binding for a ST pre-divider clock driver. + +This binding uses the common clock binding[1]. +Base address is located to the parent node. See clock binding[2] + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt + +Required properties: + +- compatible : shall be: + "st,clkgena-prediv-c65", "st,clkgena-prediv" + "st,clkgena-prediv-c32", "st,clkgena-prediv" + +- #clock-cells : From common clock binding; shall be set to 0. + +- clocks : From common clock binding + +- clock-output-names : From common clock binding. + +Example: + + clockgenA@fd345000 { + reg = <0xfd345000 0xb50>; + + CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV { + #clock-cells = <0>; + compatible = "st,clkgena-prediv-c32", + "st,clkgena-prediv"; + + clocks = <&CLK_SYSIN>; + + clock-output-names = "CLK_M_A2_OSC_PREDIV"; + }; + }; + diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt new file mode 100644 index 000000000000..49ec5ae18b5b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt @@ -0,0 +1,83 @@ +Binding for a Clockgen hardware block found on +certain STMicroelectronics consumer electronics SoC devices. + +A Clockgen node can contain pll, diviser or multiplexer nodes. + +We will find only the base address of the Clockgen, this base +address is common of all subnode. + + clockgen_node { + reg = <>; + + pll_node { + ... + }; + + prediv_node { + ... + }; + + divmux_node { + ... + }; + + quadfs_node { + ... + }; + ... + }; + +This binding uses the common clock binding[1]. +Each subnode should use the binding discribe in [2]..[4] + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/st,quadfs.txt +[3] Documentation/devicetree/bindings/clock/st,quadfs.txt +[4] Documentation/devicetree/bindings/clock/st,quadfs.txt + +Required properties: +- reg : A Base address and length of the register set. + +Example: + + clockgenA@fee62000 { + + reg = <0xfee62000 0xb48>; + + CLK_S_A0_PLL: CLK_S_A0_PLL { + #clock-cells = <1>; + compatible = "st,clkgena-plls-c65"; + + clocks = <&CLK_SYSIN>; + + clock-output-names = "CLK_S_A0_PLL0_HS", + "CLK_S_A0_PLL0_LS", + "CLK_S_A0_PLL1"; + }; + + CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV { + #clock-cells = <0>; + compatible = "st,clkgena-prediv-c65", + "st,clkgena-prediv"; + + clocks = <&CLK_SYSIN>; + + clock-output-names = "CLK_S_A0_OSC_PREDIV"; + }; + + CLK_S_A0_HS: CLK_S_A0_HS { + #clock-cells = <1>; + compatible = "st,clkgena-divmux-c65-hs", + "st,clkgena-divmux"; + + clocks = <&CLK_S_A0_OSC_PREDIV>, + <&CLK_S_A0_PLL 0>, /* PLL0 HS */ + <&CLK_S_A0_PLL 2>; /* PLL1 */ + + clock-output-names = "CLK_S_FDMA_0", + "CLK_S_FDMA_1", + ""; /* CLK_S_JIT_SENSE */ + /* Fourth output unused */ + }; + }; + -- cgit v1.2.3-58-ga151 From 8b221488b75ef6db6724b13340d6ffe45a33b2cc Mon Sep 17 00:00:00 2001 From: Gabriel FERNANDEZ Date: Thu, 27 Feb 2014 16:24:21 +0100 Subject: clk: st: Adds clockgen clock binding Signed-off-by: Gabriel Fernandez Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/st/st,clkgen-pll.txt | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt new file mode 100644 index 000000000000..81eb3855ab92 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt @@ -0,0 +1,48 @@ +Binding for a ST pll clock driver. + +This binding uses the common clock binding[1]. +Base address is located to the parent node. See clock binding[2] + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt + +Required properties: + +- compatible : shall be: + "st,clkgena-prediv-c65", "st,clkgena-prediv" + "st,clkgena-prediv-c32", "st,clkgena-prediv" + + "st,clkgena-plls-c65" + "st,plls-c32-a1x-0", "st,clkgen-plls-c32" + "st,plls-c32-a1x-1", "st,clkgen-plls-c32" + "st,stih415-plls-c32-a9", "st,clkgen-plls-c32" + "st,stih415-plls-c32-ddr", "st,clkgen-plls-c32" + "st,stih416-plls-c32-a9", "st,clkgen-plls-c32" + "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32" + + "st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32" + "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32" + + +- #clock-cells : From common clock binding; shall be set to 1. + +- clocks : From common clock binding + +- clock-output-names : From common clock binding. + +Example: + + clockgenA@fee62000 { + reg = <0xfee62000 0xb48>; + + CLK_S_A0_PLL: CLK_S_A0_PLL { + #clock-cells = <1>; + compatible = "st,clkgena-plls-c65"; + + clocks = <&CLK_SYSIN>; + + clock-output-names = "CLK_S_A0_PLL0_HS", + "CLK_S_A0_PLL0_LS", + "CLK_S_A0_PLL1"; + }; + }; -- cgit v1.2.3-58-ga151 From e83c4e4d19736a77e28ce3c87e5c9e6d6bd88773 Mon Sep 17 00:00:00 2001 From: Gabriel FERNANDEZ Date: Thu, 27 Feb 2014 16:24:22 +0100 Subject: clk: st: Adds clockgen-vcc and clockgen-mux clock binding Signed-off-by: Gabriel Fernandez Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/st/st,clkgen-mux.txt | 36 +++++++++++++++ .../devicetree/bindings/clock/st/st,clkgen-vcc.txt | 53 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt new file mode 100644 index 000000000000..943e0808e212 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt @@ -0,0 +1,36 @@ +Binding for a ST multiplexed clock driver. + +This binding supports only simple indexed multiplexers, it does not +support table based parent index to hardware value translations. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: + +- compatible : shall be: + "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux" + "st,stih416-clkgenf-vcc-fvdp", "st,clkgen-mux" + "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux" + "st,stih416-clkgenf-vcc-hd", "st,clkgen-mux" + "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux" + "st,stih415-clkgen-a9-mux", "st,clkgen-mux" + "st,stih416-clkgen-a9-mux", "st,clkgen-mux" + + +- #clock-cells : from common clock binding; shall be set to 0. + +- reg : A Base address and length of the register set. + +- clocks : from common clock binding + +Example: + + CLK_M_HVA: CLK_M_HVA { + #clock-cells = <0>; + compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux"; + reg = <0xfd690868 4>; + + clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>; + }; diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt new file mode 100644 index 000000000000..4e3ff28b04c3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt @@ -0,0 +1,53 @@ +Binding for a type of STMicroelectronics clock crossbar (VCC). + +The crossbar can take up to 4 input clocks and control up to 16 +output clocks. Not all inputs or outputs have to be in use in a +particular instantiation. Each output can be individually enabled, +select any of the input clocks and apply a divide (by 1,2,4 or 8) to +that selected clock. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: + +- compatible : shall be: + "st,stih416-clkgenc", "st,vcc" + "st,stih416-clkgenf", "st,vcc" + +- #clock-cells : from common clock binding; shall be set to 1. + +- reg : A Base address and length of the register set. + +- clocks : from common clock binding + +- clock-output-names : From common clock binding. The block has 16 + clock outputs but not all of them in a specific instance + have to be used in the SoC. If a clock name is left as + an empty string then no clock will be created for the + output associated with that string index. If fewer than + 16 strings are provided then no clocks will be created + for the remaining outputs. + +Example: + + CLOCKGEN_C_VCC: CLOCKGEN_C_VCC { + #clock-cells = <1>; + compatible = "st,stih416-clkgenc", "st,clkgen-vcc"; + reg = <0xfe8308ac 12>; + + clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>, + <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>; + + clock-output-names = + "CLK_S_PIX_HDMI", "CLK_S_PIX_DVO", + "CLK_S_OUT_DVO", "CLK_S_PIX_HD", + "CLK_S_HDDAC", "CLK_S_DENC", + "CLK_S_SDDAC", "CLK_S_PIX_MAIN", + "CLK_S_PIX_AUX", "CLK_S_STFE_FRC_0", + "CLK_S_REF_MCRU", "CLK_S_SLAVE_MCRU", + "CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL", + "CLK_S_THSENS"; + }; + -- cgit v1.2.3-58-ga151 From 43080568f7d5dc4e31d90246b9e80e9b4112975c Mon Sep 17 00:00:00 2001 From: Gabriel FERNANDEZ Date: Thu, 27 Feb 2014 16:24:23 +0100 Subject: clk: st: Adds quadfs clock binding Signed-off-by: Gabriel Fernandez Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/st/st,quadfs.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt new file mode 100644 index 000000000000..ec86d62ca283 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt @@ -0,0 +1,45 @@ +Binding for a type of quad channel digital frequency synthesizer found on +certain STMicroelectronics consumer electronics SoC devices. + +This version contains a programmable PLL which can generate up to 216, 432 +or 660MHz (from a 30MHz oscillator input) as the input to the digital +synthesizers. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be: + "st,stih416-quadfs216", "st,quadfs" + "st,stih416-quadfs432", "st,quadfs" + "st,stih416-quadfs660-E", "st,quadfs" + "st,stih416-quadfs660-F", "st,quadfs" + +- #clock-cells : from common clock binding; shall be set to 1. + +- reg : A Base address and length of the register set. + +- clocks : from common clock binding + +- clock-output-names : From common clock binding. The block has 4 + clock outputs but not all of them in a specific instance + have to be used in the SoC. If a clock name is left as + an empty string then no clock will be created for the + output associated with that string index. If fewer than + 4 strings are provided then no clocks will be created + for the remaining outputs. + +Example: + + CLOCKGEN_E: CLOCKGEN_E { + #clock-cells = <1>; + compatible = "st,stih416-quadfs660-E", "st,quadfs"; + reg = <0xfd3208bc 0xB0>; + + clocks = <&CLK_SYSIN>; + clock-output-names = "CLK_M_PIX_MDTP_0", + "CLK_M_PIX_MDTP_1", + "CLK_M_PIX_MDTP_2", + "CLK_M_MPELPC"; + }; -- cgit v1.2.3-58-ga151