1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 huangzhenwei@allwinnertech.com
4 */
5
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/of_address.h>
9 #include <linux/platform_device.h>
10
11 #include "ccu_common.h"
12 #include "ccu_reset.h"
13
14 #include "ccu_div.h"
15 #include "ccu_gate.h"
16 #include "ccu_mp.h"
17 #include "ccu_nm.h"
18
19 #include "ccu-sun8iw20-r.h"
20
21 static const char * const ahbs_apbs0_parents[] = { "dcxo24M", "osc32k",
22 "iosc", "pll-periph0-div3" };
23 static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb",
24 ahbs_apbs0_parents, 0x000,
25 0, 5,
26 8, 2,
27 24, 3,
28 0);
29
30 static SUNXI_CCU_MP_WITH_MUX(r_apb0_clk, "r-apb0",
31 ahbs_apbs0_parents, 0x00c,
32 0, 5,
33 8, 2,
34 24, 3,
35 0);
36
37 static SUNXI_CCU_GATE(r_apb0_timer_clk, "r-apb0-timer", "r-apb0",
38 0x11c, BIT(0), 0);
39
40 static SUNXI_CCU_GATE(r_apb0_twd_clk, "r-apb0-twd", "r-apb0",
41 0x12c, BIT(0), 0);
42
43 static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "r-apb0",
44 0x1ac, BIT(0), 0);
45
46 static const char * const r_apb0_ir_rx_parents[] = { "osc32k", "dcxo24M" };
47 static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb0_ir_rx_clk, "r-apb0-ir-rx",
48 r_apb0_ir_rx_parents, 0x1c0,
49 0, 5, /* M */
50 8, 2, /* P */
51 24, 2, /* mux */
52 BIT(31), /* gate */
53 0);
54
55 static SUNXI_CCU_GATE(r_apb0_bus_ir_rx_clk, "r-apb0-bus-ir-rx", "r-apb0",
56 0x1cc, BIT(0), 0);
57
58 static SUNXI_CCU_GATE(r_ahb_bus_rtc_clk, "r-ahb-rtc", "r-ahb",
59 0x20c, BIT(0), 0);
60
61 static SUNXI_CCU_GATE(r_apb0_cpucfg_clk, "r-apb0-cpucfg", "r-apb0",
62 0x22c, BIT(0), 0);
63
64 static struct ccu_common *sun8iw20_r_ccu_clks[] = {
65 &r_ahb_clk.common,
66 &r_apb0_clk.common,
67 &r_apb0_timer_clk.common,
68 &r_apb0_twd_clk.common,
69 &r_ppu_clk.common,
70 &r_apb0_ir_rx_clk.common,
71 &r_apb0_bus_ir_rx_clk.common,
72 &r_ahb_bus_rtc_clk.common,
73 &r_apb0_cpucfg_clk.common,
74 };
75
76 static struct clk_hw_onecell_data sun8iw20_r_hw_clks = {
77 .hws = {
78 [CLK_R_AHB] = &r_ahb_clk.common.hw,
79 [CLK_R_APB0] = &r_apb0_clk.common.hw,
80 [CLK_R_APB0_TIMER] = &r_apb0_timer_clk.common.hw,
81 [CLK_R_APB0_TWD] = &r_apb0_twd_clk.common.hw,
82 [CLK_R_PPU] = &r_ppu_clk.common.hw,
83 [CLK_R_APB0_IRRX] = &r_apb0_ir_rx_clk.common.hw,
84 [CLK_R_APB0_BUS_IRRX] = &r_apb0_bus_ir_rx_clk.common.hw,
85 [CLK_R_AHB_BUS_RTC] = &r_ahb_bus_rtc_clk.common.hw,
86 [CLK_R_APB0_CPUCFG] = &r_apb0_cpucfg_clk.common.hw,
87 },
88 .num = CLK_NUMBER,
89 };
90
91 static struct ccu_reset_map sun8iw20_r_ccu_resets[] = {
92 [RST_R_APB0_TIMER] = { 0x11c, BIT(16) },
93 [RST_R_APB0_TWD] = { 0x12c, BIT(16) },
94 [RST_R_PPU] = { 0x1ac, BIT(16) },
95 [RST_R_APB0_BUS_IRRX] = { 0x1cc, BIT(16) },
96 [RST_R_AHB_BUS_RTC] = { 0x20c, BIT(16) },
97 [RST_R_APB0_CPUCFG] = { 0x22c, BIT(16) },
98 };
99
100 static const struct sunxi_ccu_desc sun8iw20_r_ccu_desc = {
101 .ccu_clks = sun8iw20_r_ccu_clks,
102 .num_ccu_clks = ARRAY_SIZE(sun8iw20_r_ccu_clks),
103
104 .hw_clks = &sun8iw20_r_hw_clks,
105
106 .resets = sun8iw20_r_ccu_resets,
107 .num_resets = ARRAY_SIZE(sun8iw20_r_ccu_resets),
108 };
109
sun8iw20_r_ccu_probe(struct platform_device * pdev)110 static int sun8iw20_r_ccu_probe(struct platform_device *pdev)
111 {
112 void __iomem *reg;
113 int ret;
114
115 reg = devm_platform_ioremap_resource(pdev, 0);
116 if (IS_ERR(reg))
117 return PTR_ERR(reg);
118
119 ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8iw20_r_ccu_desc);
120 if (ret)
121 return ret;
122
123 sunxi_ccu_sleep_init(reg, sun8iw20_r_ccu_clks,
124 ARRAY_SIZE(sun8iw20_r_ccu_clks),
125 NULL, 0);
126
127 return 0;
128 }
129
130 static const struct of_device_id sun8iw20_r_ccu_ids[] = {
131 { .compatible = "allwinner,sun8iw20-r-ccu" },
132 { .compatible = "allwinner,sun20iw1-r-ccu" },
133 { }
134 };
135
136 static struct platform_driver sun8iw20_r_ccu_driver = {
137 .probe = sun8iw20_r_ccu_probe,
138 .driver = {
139 .name = "sun8iw20-r-ccu",
140 .of_match_table = sun8iw20_r_ccu_ids,
141 },
142 };
143
sunxi_r_ccu_sun8iw20_init(void)144 static int __init sunxi_r_ccu_sun8iw20_init(void)
145 {
146 int ret;
147
148 ret = platform_driver_register(&sun8iw20_r_ccu_driver);
149 if (ret)
150 pr_err("register ccu sun8iw20 failed\n");
151
152 return ret;
153 }
154 core_initcall(sunxi_r_ccu_sun8iw20_init);
155
sunxi_r_ccu_sun8iw20_exit(void)156 static void __exit sunxi_r_ccu_sun8iw20_exit(void)
157 {
158 return platform_driver_unregister(&sun8iw20_r_ccu_driver);
159 }
160 module_exit(sunxi_r_ccu_sun8iw20_exit);
161
162 MODULE_VERSION("0.5.0");
163