Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: emev2: Add support for emev2 SMU clocks with DT

Device tree clock binding document for EMMA Mobile EV2 SMU,
And Common clock framework based implementation of it.
Following nodes are defined to describe clock tree.
- renesas,emev2-smu
- renesas,emev2-smu-clkdiv
- renesas,emev2-smu-gclk

These bindings are designed manually based on
19UH0037EJ1000_SMU : System Management Unit User's Manual

So far, reparent is not implemented, and is fixed to index #0.
Clock tree description is not included, and should be provided
by device-tree.

Signed-off-by: Takashi Yoshii <takasi-y@ops.dti.ne.jp>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

authored by

Takashi Yoshii and committed by
Simon Horman
92ca6a8c f94859c2

+203 -1
+98
Documentation/devicetree/bindings/clock/emev2-clock.txt
··· 1 + Device tree Clock bindings for Renesas EMMA Mobile EV2 2 + 3 + This binding uses the common clock binding. 4 + 5 + * SMU 6 + System Management Unit described in user's manual R19UH0037EJ1000_SMU. 7 + This is not a clock provider, but clocks under SMU depend on it. 8 + 9 + Required properties: 10 + - compatible: Should be "renesas,emev2-smu" 11 + - reg: Address and Size of SMU registers 12 + 13 + * SMU_CLKDIV 14 + Function block with an input mux and a divider, which corresponds to 15 + "Serial clock generator" in fig."Clock System Overview" of the manual, 16 + and "xxx frequency division setting register" (XXXCLKDIV) registers. 17 + This makes internal (neither input nor output) clock that is provided 18 + to input of xxxGCLK block. 19 + 20 + Required properties: 21 + - compatible: Should be "renesas,emev2-smu-clkdiv" 22 + - reg: Byte offset from SMU base and Bit position in the register 23 + - clocks: Parent clocks. Input clocks as described in clock-bindings.txt 24 + - #clock-cells: Should be <0> 25 + 26 + * SMU_GCLK 27 + Clock gating node shown as "Clock stop processing block" in the 28 + fig."Clock System Overview" of the manual. 29 + Registers are "xxx clock gate control register" (XXXGCLKCTRL). 30 + 31 + Required properties: 32 + - compatible: Should be "renesas,emev2-smu-gclk" 33 + - reg: Byte offset from SMU base and Bit position in the register 34 + - clocks: Input clock as described in clock-bindings.txt 35 + - #clock-cells: Should be <0> 36 + 37 + Example of provider: 38 + 39 + usia_u0_sclkdiv: usia_u0_sclkdiv { 40 + compatible = "renesas,emev2-smu-clkdiv"; 41 + reg = <0x610 0>; 42 + clocks = <&pll3_fo>, <&pll4_fo>, <&pll1_fo>, <&osc1_fo>; 43 + #clock-cells = <0>; 44 + }; 45 + 46 + usia_u0_sclk: usia_u0_sclk { 47 + compatible = "renesas,emev2-smu-gclk"; 48 + reg = <0x4a0 1>; 49 + clocks = <&usia_u0_sclkdiv>; 50 + #clock-cells = <0>; 51 + }; 52 + 53 + Example of consumer: 54 + 55 + uart@e1020000 { 56 + compatible = "renesas,em-uart"; 57 + reg = <0xe1020000 0x38>; 58 + interrupts = <0 8 0>; 59 + clocks = <&usia_u0_sclk>; 60 + clock-names = "sclk"; 61 + }; 62 + 63 + Example of clock-tree description: 64 + 65 + This describes a clock path in the clock tree 66 + c32ki -> pll3_fo -> usia_u0_sclkdiv -> usia_u0_sclk 67 + 68 + smu@e0110000 { 69 + compatible = "renesas,emev2-smu"; 70 + reg = <0xe0110000 0x10000>; 71 + #address-cells = <2>; 72 + #size-cells = <0>; 73 + 74 + c32ki: c32ki { 75 + compatible = "fixed-clock"; 76 + clock-frequency = <32768>; 77 + #clock-cells = <0>; 78 + }; 79 + pll3_fo: pll3_fo { 80 + compatible = "fixed-factor-clock"; 81 + clocks = <&c32ki>; 82 + clock-div = <1>; 83 + clock-mult = <7000>; 84 + #clock-cells = <0>; 85 + }; 86 + usia_u0_sclkdiv: usia_u0_sclkdiv { 87 + compatible = "renesas,emev2-smu-clkdiv"; 88 + reg = <0x610 0>; 89 + clocks = <&pll3_fo>; 90 + #clock-cells = <0>; 91 + }; 92 + usia_u0_sclk: usia_u0_sclk { 93 + compatible = "renesas,emev2-smu-gclk"; 94 + reg = <0x4a0 1>; 95 + clocks = <&usia_u0_sclkdiv>; 96 + #clock-cells = <0>; 97 + }; 98 + };
+1 -1
drivers/clk/shmobile/Makefile
··· 1 + obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o 1 2 obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o 2 3 obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o 3 4 obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o 4 5 obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o 5 - 6 6 # for emply built-in.o 7 7 obj-n := dummy
+104
drivers/clk/shmobile/clk-emev2.c
··· 1 + /* 2 + * EMMA Mobile EV2 common clock framework support 3 + * 4 + * Copyright (C) 2013 Takashi Yoshii <takashi.yoshii.ze@renesas.com> 5 + * Copyright (C) 2012 Magnus Damm 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; version 2 of the License. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 + */ 20 + #include <linux/clk-provider.h> 21 + #include <linux/clkdev.h> 22 + #include <linux/io.h> 23 + #include <linux/of.h> 24 + #include <linux/of_address.h> 25 + 26 + /* EMEV2 SMU registers */ 27 + #define USIAU0_RSTCTRL 0x094 28 + #define USIBU1_RSTCTRL 0x0ac 29 + #define USIBU2_RSTCTRL 0x0b0 30 + #define USIBU3_RSTCTRL 0x0b4 31 + #define STI_RSTCTRL 0x124 32 + #define STI_CLKSEL 0x688 33 + 34 + static DEFINE_SPINLOCK(lock); 35 + 36 + /* not pretty, but hey */ 37 + void __iomem *smu_base; 38 + 39 + static void __init emev2_smu_write(unsigned long value, int offs) 40 + { 41 + BUG_ON(!smu_base || (offs >= PAGE_SIZE)); 42 + writel_relaxed(value, smu_base + offs); 43 + } 44 + 45 + static const struct of_device_id smu_id[] __initconst = { 46 + { .compatible = "renesas,emev2-smu", }, 47 + {}, 48 + }; 49 + 50 + static void __init emev2_smu_init(void) 51 + { 52 + struct device_node *np; 53 + 54 + np = of_find_matching_node(NULL, smu_id); 55 + BUG_ON(!np); 56 + smu_base = of_iomap(np, 0); 57 + BUG_ON(!smu_base); 58 + of_node_put(np); 59 + 60 + /* setup STI timer to run on 32.768 kHz and deassert reset */ 61 + emev2_smu_write(0, STI_CLKSEL); 62 + emev2_smu_write(1, STI_RSTCTRL); 63 + 64 + /* deassert reset for UART0->UART3 */ 65 + emev2_smu_write(2, USIAU0_RSTCTRL); 66 + emev2_smu_write(2, USIBU1_RSTCTRL); 67 + emev2_smu_write(2, USIBU2_RSTCTRL); 68 + emev2_smu_write(2, USIBU3_RSTCTRL); 69 + } 70 + 71 + static void __init emev2_smu_clkdiv_init(struct device_node *np) 72 + { 73 + u32 reg[2]; 74 + struct clk *clk; 75 + const char *parent_name = of_clk_get_parent_name(np, 0); 76 + if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) 77 + return; 78 + if (!smu_base) 79 + emev2_smu_init(); 80 + clk = clk_register_divider(NULL, np->name, parent_name, 0, 81 + smu_base + reg[0], reg[1], 8, 0, &lock); 82 + of_clk_add_provider(np, of_clk_src_simple_get, clk); 83 + clk_register_clkdev(clk, np->name, NULL); 84 + pr_debug("## %s %s %p\n", __func__, np->name, clk); 85 + } 86 + CLK_OF_DECLARE(emev2_smu_clkdiv, "renesas,emev2-smu-clkdiv", 87 + emev2_smu_clkdiv_init); 88 + 89 + static void __init emev2_smu_gclk_init(struct device_node *np) 90 + { 91 + u32 reg[2]; 92 + struct clk *clk; 93 + const char *parent_name = of_clk_get_parent_name(np, 0); 94 + if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) 95 + return; 96 + if (!smu_base) 97 + emev2_smu_init(); 98 + clk = clk_register_gate(NULL, np->name, parent_name, 0, 99 + smu_base + reg[0], reg[1], 0, &lock); 100 + of_clk_add_provider(np, of_clk_src_simple_get, clk); 101 + clk_register_clkdev(clk, np->name, NULL); 102 + pr_debug("## %s %s %p\n", __func__, np->name, clk); 103 + } 104 + CLK_OF_DECLARE(emev2_smu_gclk, "renesas,emev2-smu-gclk", emev2_smu_gclk_init);