xref: /linux/drivers/clk/meson/meson8-ddr.c (revision 522ba450b56fff29f868b1552bdc2965f55de7ed)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Amlogic Meson8 DDR clock controller
4  *
5  * Copyright (C) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
6  */
7 
8 #include <dt-bindings/clock/meson8-ddr-clkc.h>
9 
10 #include <linux/clk-provider.h>
11 #include <linux/platform_device.h>
12 
13 #include "clk-regmap.h"
14 #include "clk-pll.h"
15 #include "meson-clkc-utils.h"
16 
17 #define AM_DDR_PLL_CNTL			0x00
18 #define AM_DDR_PLL_CNTL1		0x04
19 #define AM_DDR_PLL_CNTL2		0x08
20 #define AM_DDR_PLL_CNTL3		0x0c
21 #define AM_DDR_PLL_CNTL4		0x10
22 #define AM_DDR_PLL_STS			0x14
23 #define DDR_CLK_CNTL			0x18
24 #define DDR_CLK_STS			0x1c
25 
26 static struct clk_regmap meson8_ddr_pll_dco = {
27 	.data = &(struct meson_clk_pll_data){
28 		.en = {
29 			.reg_off = AM_DDR_PLL_CNTL,
30 			.shift   = 30,
31 			.width   = 1,
32 		},
33 		.m = {
34 			.reg_off = AM_DDR_PLL_CNTL,
35 			.shift   = 0,
36 			.width   = 9,
37 		},
38 		.n = {
39 			.reg_off = AM_DDR_PLL_CNTL,
40 			.shift   = 9,
41 			.width   = 5,
42 		},
43 		.l = {
44 			.reg_off = AM_DDR_PLL_CNTL,
45 			.shift   = 31,
46 			.width   = 1,
47 		},
48 		.rst = {
49 			.reg_off = AM_DDR_PLL_CNTL,
50 			.shift   = 29,
51 			.width   = 1,
52 		},
53 	},
54 	.hw.init = &(struct clk_init_data){
55 		.name = "ddr_pll_dco",
56 		.ops = &meson_clk_pll_ro_ops,
57 		.parent_data = &(const struct clk_parent_data) {
58 			.fw_name = "xtal",
59 		},
60 		.num_parents = 1,
61 	},
62 };
63 
64 static struct clk_regmap meson8_ddr_pll = {
65 	.data = &(struct clk_regmap_div_data){
66 		.offset = AM_DDR_PLL_CNTL,
67 		.shift = 16,
68 		.width = 2,
69 		.flags = CLK_DIVIDER_POWER_OF_TWO,
70 	},
71 	.hw.init = &(struct clk_init_data){
72 		.name = "ddr_pll",
73 		.ops = &clk_regmap_divider_ro_ops,
74 		.parent_hws = (const struct clk_hw *[]) {
75 			&meson8_ddr_pll_dco.hw
76 		},
77 		.num_parents = 1,
78 	},
79 };
80 
81 static struct clk_hw *meson8_ddr_hw_clks[] = {
82 	[DDR_CLKID_DDR_PLL_DCO]		= &meson8_ddr_pll_dco.hw,
83 	[DDR_CLKID_DDR_PLL]		= &meson8_ddr_pll.hw,
84 };
85 
86 static const struct meson_clkc_data meson8_ddr_clkc_data = {
87 	.hw_clks = {
88 		.hws = meson8_ddr_hw_clks,
89 		.num = ARRAY_SIZE(meson8_ddr_hw_clks),
90 	},
91 };
92 
93 static const struct of_device_id meson8_ddr_clkc_match_table[] = {
94 	{
95 		.compatible = "amlogic,meson8-ddr-clkc",
96 		.data = &meson8_ddr_clkc_data,
97 	}, {
98 		.compatible = "amlogic,meson8b-ddr-clkc",
99 		.data = &meson8_ddr_clkc_data,
100 	},
101 	{ /* sentinel */ }
102 };
103 
104 static struct platform_driver meson8_ddr_clkc_driver = {
105 	.probe		= meson_clkc_mmio_probe,
106 	.driver		= {
107 		.name	= "meson8-ddr-clkc",
108 		.of_match_table = meson8_ddr_clkc_match_table,
109 	},
110 };
111 
112 builtin_platform_driver(meson8_ddr_clkc_driver);
113