1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix |
4 | */ |
5 | |
6 | #include <linux/clkdev.h> |
7 | #include <linux/clk-provider.h> |
8 | #include <linux/err.h> |
9 | #include <linux/init.h> |
10 | #include <linux/of.h> |
11 | #include <linux/of_address.h> |
12 | #include <dt-bindings/clock/imx1-clock.h> |
13 | #include <asm/irq.h> |
14 | |
15 | #include "clk.h" |
16 | |
17 | #define MX1_CCM_BASE_ADDR 0x0021b000 |
18 | #define MX1_TIM1_BASE_ADDR 0x00220000 |
19 | #define MX1_TIM1_INT (NR_IRQS_LEGACY + 59) |
20 | |
21 | static const char *prem_sel_clks[] = { "clk32_premult" , "clk16m" , }; |
22 | static const char *clko_sel_clks[] = { "per1" , "hclk" , "clk48m" , "clk16m" , |
23 | "prem" , "fclk" , }; |
24 | |
25 | static struct clk *clk[IMX1_CLK_MAX]; |
26 | static struct clk_onecell_data clk_data; |
27 | |
28 | static void __iomem *ccm __initdata; |
29 | #define CCM_CSCR (ccm + 0x0000) |
30 | #define CCM_MPCTL0 (ccm + 0x0004) |
31 | #define CCM_SPCTL0 (ccm + 0x000c) |
32 | #define CCM_PCDR (ccm + 0x0020) |
33 | #define SCM_GCCR (ccm + 0x0810) |
34 | |
35 | static void __init mx1_clocks_init_dt(struct device_node *np) |
36 | { |
37 | ccm = of_iomap(node: np, index: 0); |
38 | BUG_ON(!ccm); |
39 | |
40 | clk[IMX1_CLK_DUMMY] = imx_clk_fixed("dummy" , 0); |
41 | clk[IMX1_CLK_CLK32] = imx_obtain_fixed_clock(name: "clk32" , rate: 32768); |
42 | clk[IMX1_CLK_CLK16M_EXT] = imx_clk_fixed("clk16m_ext" , 16000000); |
43 | clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m" , "clk16m_ext" , CCM_CSCR, 17); |
44 | clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult" , "clk32" , 512, 1); |
45 | clk[IMX1_CLK_PREM] = imx_clk_mux("prem" , CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks)); |
46 | clk[IMX1_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "mpll" , "clk32_premult" , CCM_MPCTL0); |
47 | clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate" , "mpll" , CCM_CSCR, 0); |
48 | clk[IMX1_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "spll" , "prem" , CCM_SPCTL0); |
49 | clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate" , "spll" , CCM_CSCR, 1); |
50 | clk[IMX1_CLK_MCU] = imx_clk_divider("mcu" , "clk32_premult" , CCM_CSCR, 15, 1); |
51 | clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk" , "mpll_gate" , CCM_CSCR, 15, 1); |
52 | clk[IMX1_CLK_HCLK] = imx_clk_divider("hclk" , "spll_gate" , CCM_CSCR, 10, 4); |
53 | clk[IMX1_CLK_CLK48M] = imx_clk_divider("clk48m" , "spll_gate" , CCM_CSCR, 26, 3); |
54 | clk[IMX1_CLK_PER1] = imx_clk_divider("per1" , "spll_gate" , CCM_PCDR, 0, 4); |
55 | clk[IMX1_CLK_PER2] = imx_clk_divider("per2" , "spll_gate" , CCM_PCDR, 4, 4); |
56 | clk[IMX1_CLK_PER3] = imx_clk_divider("per3" , "spll_gate" , CCM_PCDR, 16, 7); |
57 | clk[IMX1_CLK_CLKO] = imx_clk_mux("clko" , CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); |
58 | clk[IMX1_CLK_UART3_GATE] = imx_clk_gate("uart3_gate" , "hclk" , SCM_GCCR, 6); |
59 | clk[IMX1_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate" , "hclk" , SCM_GCCR, 5); |
60 | clk[IMX1_CLK_BROM_GATE] = imx_clk_gate("brom_gate" , "hclk" , SCM_GCCR, 4); |
61 | clk[IMX1_CLK_DMA_GATE] = imx_clk_gate("dma_gate" , "hclk" , SCM_GCCR, 3); |
62 | clk[IMX1_CLK_CSI_GATE] = imx_clk_gate("csi_gate" , "hclk" , SCM_GCCR, 2); |
63 | clk[IMX1_CLK_MMA_GATE] = imx_clk_gate("mma_gate" , "hclk" , SCM_GCCR, 1); |
64 | clk[IMX1_CLK_USBD_GATE] = imx_clk_gate("usbd_gate" , "clk48m" , SCM_GCCR, 0); |
65 | |
66 | imx_check_clocks(clks: clk, ARRAY_SIZE(clk)); |
67 | |
68 | clk_data.clks = clk; |
69 | clk_data.clk_num = ARRAY_SIZE(clk); |
70 | of_clk_add_provider(np, clk_src_get: of_clk_src_onecell_get, data: &clk_data); |
71 | } |
72 | CLK_OF_DECLARE(imx1_ccm, "fsl,imx1-ccm" , mx1_clocks_init_dt); |
73 | |