1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com>
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/of_address.h>
9 #include <linux/platform_device.h>
11 #include "ccu_common.h"
12 #include "ccu_reset.h"
19 #include "ccu-sun50i-a100-r.h"
21 static const char * const cpus_r_apb2_parents
[] = { "dcxo24M", "osc32k",
22 "iosc", "pll-periph0" };
23 static const struct ccu_mux_var_prediv cpus_r_apb2_predivs
[] = {
24 { .index
= 3, .shift
= 0, .width
= 5 },
27 static struct ccu_div r_cpus_clk
= {
28 .div
= _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO
),
34 .var_predivs
= cpus_r_apb2_predivs
,
35 .n_var_predivs
= ARRAY_SIZE(cpus_r_apb2_predivs
),
40 .features
= CCU_FEATURE_VARIABLE_PREDIV
,
41 .hw
.init
= CLK_HW_INIT_PARENTS("cpus",
48 static CLK_FIXED_FACTOR_HW(r_ahb_clk
, "r-ahb", &r_cpus_clk
.common
.hw
, 1, 1, 0);
50 static struct ccu_div r_apb1_clk
= {
51 .div
= _SUNXI_CCU_DIV(0, 2),
55 .hw
.init
= CLK_HW_INIT("r-apb1",
62 static struct ccu_div r_apb2_clk
= {
63 .div
= _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO
),
69 .var_predivs
= cpus_r_apb2_predivs
,
70 .n_var_predivs
= ARRAY_SIZE(cpus_r_apb2_predivs
),
75 .features
= CCU_FEATURE_VARIABLE_PREDIV
,
76 .hw
.init
= CLK_HW_INIT_PARENTS("r-apb2",
83 static const struct clk_parent_data clk_parent_r_apb1
[] = {
84 { .hw
= &r_apb1_clk
.common
.hw
},
87 static const struct clk_parent_data clk_parent_r_apb2
[] = {
88 { .hw
= &r_apb2_clk
.common
.hw
},
91 static SUNXI_CCU_GATE_DATA(r_apb1_timer_clk
, "r-apb1-timer", clk_parent_r_apb1
,
94 static SUNXI_CCU_GATE_DATA(r_apb1_twd_clk
, "r-apb1-twd", clk_parent_r_apb1
,
97 static const char * const r_apb1_pwm_clk_parents
[] = { "dcxo24M", "osc32k",
99 static SUNXI_CCU_MUX(r_apb1_pwm_clk
, "r-apb1-pwm", r_apb1_pwm_clk_parents
,
102 static SUNXI_CCU_GATE_DATA(r_apb1_bus_pwm_clk
, "r-apb1-bus-pwm",
103 clk_parent_r_apb1
, 0x13c, BIT(0), 0);
105 static SUNXI_CCU_GATE_DATA(r_apb1_ppu_clk
, "r-apb1-ppu", clk_parent_r_apb1
,
108 static SUNXI_CCU_GATE_DATA(r_apb2_uart_clk
, "r-apb2-uart", clk_parent_r_apb2
,
111 static SUNXI_CCU_GATE_DATA(r_apb2_i2c0_clk
, "r-apb2-i2c0", clk_parent_r_apb2
,
114 static SUNXI_CCU_GATE_DATA(r_apb2_i2c1_clk
, "r-apb2-i2c1", clk_parent_r_apb2
,
117 static const char * const r_apb1_ir_rx_parents
[] = { "osc32k", "dcxo24M" };
118 static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb1_ir_rx_clk
, "r-apb1-ir-rx",
119 r_apb1_ir_rx_parents
, 0x1c0,
126 static SUNXI_CCU_GATE_DATA(r_apb1_bus_ir_rx_clk
, "r-apb1-bus-ir-rx",
127 clk_parent_r_apb1
, 0x1cc, BIT(0), 0);
129 static SUNXI_CCU_GATE(r_ahb_bus_rtc_clk
, "r-ahb-rtc", "r-ahb",
132 static struct ccu_common
*sun50i_a100_r_ccu_clks
[] = {
136 &r_apb1_timer_clk
.common
,
137 &r_apb1_twd_clk
.common
,
138 &r_apb1_pwm_clk
.common
,
139 &r_apb1_bus_pwm_clk
.common
,
140 &r_apb1_ppu_clk
.common
,
141 &r_apb2_uart_clk
.common
,
142 &r_apb2_i2c0_clk
.common
,
143 &r_apb2_i2c1_clk
.common
,
144 &r_apb1_ir_rx_clk
.common
,
145 &r_apb1_bus_ir_rx_clk
.common
,
146 &r_ahb_bus_rtc_clk
.common
,
149 static struct clk_hw_onecell_data sun50i_a100_r_hw_clks
= {
151 [CLK_R_CPUS
] = &r_cpus_clk
.common
.hw
,
152 [CLK_R_AHB
] = &r_ahb_clk
.hw
,
153 [CLK_R_APB1
] = &r_apb1_clk
.common
.hw
,
154 [CLK_R_APB2
] = &r_apb2_clk
.common
.hw
,
155 [CLK_R_APB1_TIMER
] = &r_apb1_timer_clk
.common
.hw
,
156 [CLK_R_APB1_TWD
] = &r_apb1_twd_clk
.common
.hw
,
157 [CLK_R_APB1_PWM
] = &r_apb1_pwm_clk
.common
.hw
,
158 [CLK_R_APB1_BUS_PWM
] = &r_apb1_bus_pwm_clk
.common
.hw
,
159 [CLK_R_APB1_PPU
] = &r_apb1_ppu_clk
.common
.hw
,
160 [CLK_R_APB2_UART
] = &r_apb2_uart_clk
.common
.hw
,
161 [CLK_R_APB2_I2C0
] = &r_apb2_i2c0_clk
.common
.hw
,
162 [CLK_R_APB2_I2C1
] = &r_apb2_i2c1_clk
.common
.hw
,
163 [CLK_R_APB1_IR
] = &r_apb1_ir_rx_clk
.common
.hw
,
164 [CLK_R_APB1_BUS_IR
] = &r_apb1_bus_ir_rx_clk
.common
.hw
,
165 [CLK_R_AHB_BUS_RTC
] = &r_ahb_bus_rtc_clk
.common
.hw
,
170 static struct ccu_reset_map sun50i_a100_r_ccu_resets
[] = {
171 [RST_R_APB1_TIMER
] = { 0x11c, BIT(16) },
172 [RST_R_APB1_BUS_PWM
] = { 0x13c, BIT(16) },
173 [RST_R_APB1_PPU
] = { 0x17c, BIT(16) },
174 [RST_R_APB2_UART
] = { 0x18c, BIT(16) },
175 [RST_R_APB2_I2C0
] = { 0x19c, BIT(16) },
176 [RST_R_APB2_I2C1
] = { 0x19c, BIT(17) },
177 [RST_R_APB1_BUS_IR
] = { 0x1cc, BIT(16) },
178 [RST_R_AHB_BUS_RTC
] = { 0x20c, BIT(16) },
181 static const struct sunxi_ccu_desc sun50i_a100_r_ccu_desc
= {
182 .ccu_clks
= sun50i_a100_r_ccu_clks
,
183 .num_ccu_clks
= ARRAY_SIZE(sun50i_a100_r_ccu_clks
),
185 .hw_clks
= &sun50i_a100_r_hw_clks
,
187 .resets
= sun50i_a100_r_ccu_resets
,
188 .num_resets
= ARRAY_SIZE(sun50i_a100_r_ccu_resets
),
191 static int sun50i_a100_r_ccu_probe(struct platform_device
*pdev
)
195 reg
= devm_platform_ioremap_resource(pdev
, 0);
199 return sunxi_ccu_probe(pdev
->dev
.of_node
, reg
, &sun50i_a100_r_ccu_desc
);
202 static const struct of_device_id sun50i_a100_r_ccu_ids
[] = {
203 { .compatible
= "allwinner,sun50i-a100-r-ccu" },
207 static struct platform_driver sun50i_a100_r_ccu_driver
= {
208 .probe
= sun50i_a100_r_ccu_probe
,
210 .name
= "sun50i-a100-r-ccu",
211 .of_match_table
= sun50i_a100_r_ccu_ids
,
214 module_platform_driver(sun50i_a100_r_ccu_driver
);