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

ARM: i.MX1 clk: Add devicetree support

This patch adds devicetree support CCM module for i.MX1 (MC9328MX1) CPUs.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>

authored by

Alexander Shiyan and committed by
Shawn Guo
ac36187b cd973e1c

+147 -70
+26
Documentation/devicetree/bindings/clock/imx1-clock.txt
··· 1 + * Clock bindings for Freescale i.MX1 CPUs 2 + 3 + Required properties: 4 + - compatible: Should be "fsl,imx1-ccm". 5 + - reg: Address and length of the register set. 6 + - #clock-cells: Should be <1>. 7 + 8 + The clock consumer should specify the desired clock by having the clock 9 + ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx1-clock.h 10 + for the full list of i.MX1 clock IDs. 11 + 12 + Examples: 13 + clks: ccm@0021b000 { 14 + #clock-cells = <1>; 15 + compatible = "fsl,imx1-ccm"; 16 + reg = <0x0021b000 0x1000>; 17 + }; 18 + 19 + pwm: pwm@00208000 { 20 + #pwm-cells = <2>; 21 + compatible = "fsl,imx1-pwm"; 22 + reg = <0x00208000 0x1000>; 23 + interrupts = <34>; 24 + clocks = <&clks IMX1_CLK_DUMMY>, <&clks IMX1_CLK_PER1>; 25 + clock-names = "ipg", "per"; 26 + };
+81 -70
arch/arm/mach-imx/clk-imx1.c
··· 15 15 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 16 16 */ 17 17 18 - #include <linux/kernel.h> 19 - #include <linux/init.h> 20 18 #include <linux/clk.h> 21 - #include <linux/io.h> 22 19 #include <linux/clkdev.h> 20 + #include <linux/clk-provider.h> 23 21 #include <linux/err.h> 22 + #include <linux/init.h> 23 + #include <linux/of.h> 24 + #include <linux/of_address.h> 25 + #include <dt-bindings/clock/imx1-clock.h> 24 26 25 27 #include "clk.h" 26 28 #include "common.h" 27 29 #include "hardware.h" 28 30 29 - /* CCM register addresses */ 30 - #define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off))) 31 - 32 - #define CCM_CSCR IO_ADDR_CCM(0x0) 33 - #define CCM_MPCTL0 IO_ADDR_CCM(0x4) 34 - #define CCM_SPCTL0 IO_ADDR_CCM(0xc) 35 - #define CCM_PCDR IO_ADDR_CCM(0x20) 36 - 37 - /* SCM register addresses */ 38 - #define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off))) 39 - 40 - #define SCM_GCCR IO_ADDR_SCM(0xc) 41 - 42 31 static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", }; 43 32 static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", 44 33 "prem", "fclk", }; 45 34 46 - enum imx1_clks { 47 - dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, mpll_gate, 48 - spll, spll_gate, mcu, fclk, hclk, clk48m, per1, per2, per3, clko, 49 - uart3_gate, ssi2_gate, brom_gate, dma_gate, csi_gate, mma_gate, 50 - usbd_gate, clk_max 51 - }; 35 + static struct clk *clk[IMX1_CLK_MAX]; 36 + static struct clk_onecell_data clk_data; 52 37 53 - static struct clk *clk[clk_max]; 38 + static void __iomem *ccm __initdata; 39 + #define CCM_CSCR (ccm + 0x0000) 40 + #define CCM_MPCTL0 (ccm + 0x0004) 41 + #define CCM_SPCTL0 (ccm + 0x000c) 42 + #define CCM_PCDR (ccm + 0x0020) 43 + #define SCM_GCCR (ccm + 0x0810) 54 44 55 - int __init mx1_clocks_init(unsigned long fref) 45 + static void __init _mx1_clocks_init(unsigned long fref) 56 46 { 57 - int i; 47 + unsigned i; 58 48 59 - clk[dummy] = imx_clk_fixed("dummy", 0); 60 - clk[clk32] = imx_clk_fixed("clk32", fref); 61 - clk[clk16m_ext] = imx_clk_fixed("clk16m_ext", 16000000); 62 - clk[clk16m] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17); 63 - clk[clk32_premult] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1); 64 - clk[prem] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, 65 - ARRAY_SIZE(prem_sel_clks)); 66 - clk[mpll] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0); 67 - clk[mpll_gate] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); 68 - clk[spll] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0); 69 - clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); 70 - clk[mcu] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1); 71 - clk[fclk] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1); 72 - clk[hclk] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4); 73 - clk[clk48m] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3); 74 - clk[per1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4); 75 - clk[per2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4); 76 - clk[per3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7); 77 - clk[clko] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, 78 - ARRAY_SIZE(clko_sel_clks)); 79 - clk[uart3_gate] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6); 80 - clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5); 81 - clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4); 82 - clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3); 83 - clk[csi_gate] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2); 84 - clk[mma_gate] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1); 85 - clk[usbd_gate] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0); 49 + clk[IMX1_CLK_DUMMY] = imx_clk_fixed("dummy", 0); 50 + clk[IMX1_CLK_CLK32] = imx_obtain_fixed_clock("clk32", fref); 51 + clk[IMX1_CLK_CLK16M_EXT] = imx_clk_fixed("clk16m_ext", 16000000); 52 + clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17); 53 + clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1); 54 + clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks)); 55 + clk[IMX1_CLK_MPLL] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0); 56 + clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); 57 + clk[IMX1_CLK_SPLL] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0); 58 + clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); 59 + clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1); 60 + clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1); 61 + clk[IMX1_CLK_HCLK] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4); 62 + clk[IMX1_CLK_CLK48M] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3); 63 + clk[IMX1_CLK_PER1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4); 64 + clk[IMX1_CLK_PER2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4); 65 + clk[IMX1_CLK_PER3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7); 66 + clk[IMX1_CLK_CLKO] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); 67 + clk[IMX1_CLK_UART3_GATE] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6); 68 + clk[IMX1_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5); 69 + clk[IMX1_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4); 70 + clk[IMX1_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3); 71 + clk[IMX1_CLK_CSI_GATE] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2); 72 + clk[IMX1_CLK_MMA_GATE] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1); 73 + clk[IMX1_CLK_USBD_GATE] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0); 86 74 87 75 for (i = 0; i < ARRAY_SIZE(clk); i++) 88 76 if (IS_ERR(clk[i])) 89 77 pr_err("imx1 clk %d: register failed with %ld\n", 90 78 i, PTR_ERR(clk[i])); 91 79 92 - clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma"); 93 - clk_register_clkdev(clk[hclk], "ipg", "imx1-dma"); 94 - clk_register_clkdev(clk[per1], "per", "imx-gpt.0"); 95 - clk_register_clkdev(clk[hclk], "ipg", "imx-gpt.0"); 96 - clk_register_clkdev(clk[per1], "per", "imx1-uart.0"); 97 - clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.0"); 98 - clk_register_clkdev(clk[per1], "per", "imx1-uart.1"); 99 - clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1"); 100 - clk_register_clkdev(clk[per1], "per", "imx1-uart.2"); 101 - clk_register_clkdev(clk[uart3_gate], "ipg", "imx1-uart.2"); 102 - clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0"); 103 - clk_register_clkdev(clk[per2], "per", "imx1-cspi.0"); 104 - clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0"); 105 - clk_register_clkdev(clk[per2], "per", "imx1-cspi.1"); 106 - clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1"); 107 - clk_register_clkdev(clk[per2], "per", "imx1-fb.0"); 108 - clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0"); 109 - clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0"); 80 + clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx-gpt.0"); 81 + clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx-gpt.0"); 82 + } 83 + 84 + int __init mx1_clocks_init(unsigned long fref) 85 + { 86 + ccm = MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR); 87 + 88 + _mx1_clocks_init(fref); 89 + 90 + clk_register_clkdev(clk[IMX1_CLK_DMA_GATE], "ahb", "imx1-dma"); 91 + clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-dma"); 92 + clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.0"); 93 + clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.0"); 94 + clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.1"); 95 + clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.1"); 96 + clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.2"); 97 + clk_register_clkdev(clk[IMX1_CLK_UART3_GATE], "ipg", "imx1-uart.2"); 98 + clk_register_clkdev(clk[IMX1_CLK_HCLK], NULL, "imx1-i2c.0"); 99 + clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.0"); 100 + clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.0"); 101 + clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.1"); 102 + clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.1"); 103 + clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-fb.0"); 104 + clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0"); 105 + clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0"); 110 106 111 107 mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT); 112 108 113 109 return 0; 114 110 } 111 + 112 + static void __init mx1_clocks_init_dt(struct device_node *np) 113 + { 114 + ccm = of_iomap(np, 0); 115 + BUG_ON(!ccm); 116 + 117 + _mx1_clocks_init(32768); 118 + 119 + clk_data.clks = clk; 120 + clk_data.clk_num = ARRAY_SIZE(clk); 121 + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 122 + 123 + mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx1-gpt")); 124 + } 125 + CLK_OF_DECLARE(imx1_ccm, "fsl,imx1-ccm", mx1_clocks_init_dt);
+40
include/dt-bindings/clock/imx1-clock.h
··· 1 + /* 2 + * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + */ 9 + 10 + #ifndef __DT_BINDINGS_CLOCK_IMX1_H 11 + #define __DT_BINDINGS_CLOCK_IMX1_H 12 + 13 + #define IMX1_CLK_DUMMY 0 14 + #define IMX1_CLK_CLK32 1 15 + #define IMX1_CLK_CLK16M_EXT 2 16 + #define IMX1_CLK_CLK16M 3 17 + #define IMX1_CLK_CLK32_PREMULT 4 18 + #define IMX1_CLK_PREM 5 19 + #define IMX1_CLK_MPLL 6 20 + #define IMX1_CLK_MPLL_GATE 7 21 + #define IMX1_CLK_SPLL 8 22 + #define IMX1_CLK_SPLL_GATE 9 23 + #define IMX1_CLK_MCU 10 24 + #define IMX1_CLK_FCLK 11 25 + #define IMX1_CLK_HCLK 12 26 + #define IMX1_CLK_CLK48M 13 27 + #define IMX1_CLK_PER1 14 28 + #define IMX1_CLK_PER2 15 29 + #define IMX1_CLK_PER3 16 30 + #define IMX1_CLK_CLKO 17 31 + #define IMX1_CLK_UART3_GATE 18 32 + #define IMX1_CLK_SSI2_GATE 19 33 + #define IMX1_CLK_BROM_GATE 20 34 + #define IMX1_CLK_DMA_GATE 21 35 + #define IMX1_CLK_CSI_GATE 22 36 + #define IMX1_CLK_MMA_GATE 23 37 + #define IMX1_CLK_USBD_GATE 24 38 + #define IMX1_CLK_MAX 25 39 + 40 + #endif