0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk-provider.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/reset-controller.h>
0014 #include <linux/mfd/syscon.h>
0015 #include <linux/module.h>
0016 #include "meson-aoclk.h"
0017 #include "axg-aoclk.h"
0018
0019 #include "clk-regmap.h"
0020 #include "clk-dualdiv.h"
0021
0022
0023
0024
0025
0026 #define AO_RTI_PWR_CNTL_REG1 0x0C
0027 #define AO_RTI_PWR_CNTL_REG0 0x10
0028 #define AO_RTI_GEN_CNTL_REG0 0x40
0029 #define AO_OSCIN_CNTL 0x58
0030 #define AO_CRT_CLK_CNTL1 0x68
0031 #define AO_SAR_CLK 0x90
0032 #define AO_RTC_ALT_CLK_CNTL0 0x94
0033 #define AO_RTC_ALT_CLK_CNTL1 0x98
0034
0035 #define AXG_AO_GATE(_name, _bit) \
0036 static struct clk_regmap axg_aoclk_##_name = { \
0037 .data = &(struct clk_regmap_gate_data) { \
0038 .offset = (AO_RTI_GEN_CNTL_REG0), \
0039 .bit_idx = (_bit), \
0040 }, \
0041 .hw.init = &(struct clk_init_data) { \
0042 .name = "axg_ao_" #_name, \
0043 .ops = &clk_regmap_gate_ops, \
0044 .parent_data = &(const struct clk_parent_data) { \
0045 .fw_name = "mpeg-clk", \
0046 }, \
0047 .num_parents = 1, \
0048 .flags = CLK_IGNORE_UNUSED, \
0049 }, \
0050 }
0051
0052 AXG_AO_GATE(remote, 0);
0053 AXG_AO_GATE(i2c_master, 1);
0054 AXG_AO_GATE(i2c_slave, 2);
0055 AXG_AO_GATE(uart1, 3);
0056 AXG_AO_GATE(uart2, 5);
0057 AXG_AO_GATE(ir_blaster, 6);
0058 AXG_AO_GATE(saradc, 7);
0059
0060 static struct clk_regmap axg_aoclk_cts_oscin = {
0061 .data = &(struct clk_regmap_gate_data){
0062 .offset = AO_RTI_PWR_CNTL_REG0,
0063 .bit_idx = 14,
0064 },
0065 .hw.init = &(struct clk_init_data){
0066 .name = "cts_oscin",
0067 .ops = &clk_regmap_gate_ro_ops,
0068 .parent_data = &(const struct clk_parent_data) {
0069 .fw_name = "xtal",
0070 },
0071 .num_parents = 1,
0072 },
0073 };
0074
0075 static struct clk_regmap axg_aoclk_32k_pre = {
0076 .data = &(struct clk_regmap_gate_data){
0077 .offset = AO_RTC_ALT_CLK_CNTL0,
0078 .bit_idx = 31,
0079 },
0080 .hw.init = &(struct clk_init_data){
0081 .name = "axg_ao_32k_pre",
0082 .ops = &clk_regmap_gate_ops,
0083 .parent_hws = (const struct clk_hw *[]) {
0084 &axg_aoclk_cts_oscin.hw
0085 },
0086 .num_parents = 1,
0087 },
0088 };
0089
0090 static const struct meson_clk_dualdiv_param axg_32k_div_table[] = {
0091 {
0092 .dual = 1,
0093 .n1 = 733,
0094 .m1 = 8,
0095 .n2 = 732,
0096 .m2 = 11,
0097 }, {}
0098 };
0099
0100 static struct clk_regmap axg_aoclk_32k_div = {
0101 .data = &(struct meson_clk_dualdiv_data){
0102 .n1 = {
0103 .reg_off = AO_RTC_ALT_CLK_CNTL0,
0104 .shift = 0,
0105 .width = 12,
0106 },
0107 .n2 = {
0108 .reg_off = AO_RTC_ALT_CLK_CNTL0,
0109 .shift = 12,
0110 .width = 12,
0111 },
0112 .m1 = {
0113 .reg_off = AO_RTC_ALT_CLK_CNTL1,
0114 .shift = 0,
0115 .width = 12,
0116 },
0117 .m2 = {
0118 .reg_off = AO_RTC_ALT_CLK_CNTL1,
0119 .shift = 12,
0120 .width = 12,
0121 },
0122 .dual = {
0123 .reg_off = AO_RTC_ALT_CLK_CNTL0,
0124 .shift = 28,
0125 .width = 1,
0126 },
0127 .table = axg_32k_div_table,
0128 },
0129 .hw.init = &(struct clk_init_data){
0130 .name = "axg_ao_32k_div",
0131 .ops = &meson_clk_dualdiv_ops,
0132 .parent_hws = (const struct clk_hw *[]) {
0133 &axg_aoclk_32k_pre.hw
0134 },
0135 .num_parents = 1,
0136 },
0137 };
0138
0139 static struct clk_regmap axg_aoclk_32k_sel = {
0140 .data = &(struct clk_regmap_mux_data) {
0141 .offset = AO_RTC_ALT_CLK_CNTL1,
0142 .mask = 0x1,
0143 .shift = 24,
0144 .flags = CLK_MUX_ROUND_CLOSEST,
0145 },
0146 .hw.init = &(struct clk_init_data){
0147 .name = "axg_ao_32k_sel",
0148 .ops = &clk_regmap_mux_ops,
0149 .parent_hws = (const struct clk_hw *[]) {
0150 &axg_aoclk_32k_div.hw,
0151 &axg_aoclk_32k_pre.hw,
0152 },
0153 .num_parents = 2,
0154 .flags = CLK_SET_RATE_PARENT,
0155 },
0156 };
0157
0158 static struct clk_regmap axg_aoclk_32k = {
0159 .data = &(struct clk_regmap_gate_data){
0160 .offset = AO_RTC_ALT_CLK_CNTL0,
0161 .bit_idx = 30,
0162 },
0163 .hw.init = &(struct clk_init_data){
0164 .name = "axg_ao_32k",
0165 .ops = &clk_regmap_gate_ops,
0166 .parent_hws = (const struct clk_hw *[]) {
0167 &axg_aoclk_32k_sel.hw
0168 },
0169 .num_parents = 1,
0170 .flags = CLK_SET_RATE_PARENT,
0171 },
0172 };
0173
0174 static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
0175 .data = &(struct clk_regmap_mux_data) {
0176 .offset = AO_RTI_PWR_CNTL_REG0,
0177 .mask = 0x1,
0178 .shift = 10,
0179 .flags = CLK_MUX_ROUND_CLOSEST,
0180 },
0181 .hw.init = &(struct clk_init_data){
0182 .name = "axg_ao_cts_rtc_oscin",
0183 .ops = &clk_regmap_mux_ops,
0184 .parent_data = (const struct clk_parent_data []) {
0185 { .hw = &axg_aoclk_32k.hw },
0186 { .fw_name = "ext_32k-0", },
0187 },
0188 .num_parents = 2,
0189 .flags = CLK_SET_RATE_PARENT,
0190 },
0191 };
0192
0193 static struct clk_regmap axg_aoclk_clk81 = {
0194 .data = &(struct clk_regmap_mux_data) {
0195 .offset = AO_RTI_PWR_CNTL_REG0,
0196 .mask = 0x1,
0197 .shift = 8,
0198 .flags = CLK_MUX_ROUND_CLOSEST,
0199 },
0200 .hw.init = &(struct clk_init_data){
0201 .name = "axg_ao_clk81",
0202 .ops = &clk_regmap_mux_ro_ops,
0203 .parent_data = (const struct clk_parent_data []) {
0204 { .fw_name = "mpeg-clk", },
0205 { .hw = &axg_aoclk_cts_rtc_oscin.hw },
0206 },
0207 .num_parents = 2,
0208 .flags = CLK_SET_RATE_PARENT,
0209 },
0210 };
0211
0212 static struct clk_regmap axg_aoclk_saradc_mux = {
0213 .data = &(struct clk_regmap_mux_data) {
0214 .offset = AO_SAR_CLK,
0215 .mask = 0x3,
0216 .shift = 9,
0217 },
0218 .hw.init = &(struct clk_init_data){
0219 .name = "axg_ao_saradc_mux",
0220 .ops = &clk_regmap_mux_ops,
0221 .parent_data = (const struct clk_parent_data []) {
0222 { .fw_name = "xtal", },
0223 { .hw = &axg_aoclk_clk81.hw },
0224 },
0225 .num_parents = 2,
0226 },
0227 };
0228
0229 static struct clk_regmap axg_aoclk_saradc_div = {
0230 .data = &(struct clk_regmap_div_data) {
0231 .offset = AO_SAR_CLK,
0232 .shift = 0,
0233 .width = 8,
0234 },
0235 .hw.init = &(struct clk_init_data){
0236 .name = "axg_ao_saradc_div",
0237 .ops = &clk_regmap_divider_ops,
0238 .parent_hws = (const struct clk_hw *[]) {
0239 &axg_aoclk_saradc_mux.hw
0240 },
0241 .num_parents = 1,
0242 .flags = CLK_SET_RATE_PARENT,
0243 },
0244 };
0245
0246 static struct clk_regmap axg_aoclk_saradc_gate = {
0247 .data = &(struct clk_regmap_gate_data) {
0248 .offset = AO_SAR_CLK,
0249 .bit_idx = 8,
0250 },
0251 .hw.init = &(struct clk_init_data){
0252 .name = "axg_ao_saradc_gate",
0253 .ops = &clk_regmap_gate_ops,
0254 .parent_hws = (const struct clk_hw *[]) {
0255 &axg_aoclk_saradc_div.hw
0256 },
0257 .num_parents = 1,
0258 .flags = CLK_SET_RATE_PARENT,
0259 },
0260 };
0261
0262 static const unsigned int axg_aoclk_reset[] = {
0263 [RESET_AO_REMOTE] = 16,
0264 [RESET_AO_I2C_MASTER] = 18,
0265 [RESET_AO_I2C_SLAVE] = 19,
0266 [RESET_AO_UART1] = 17,
0267 [RESET_AO_UART2] = 22,
0268 [RESET_AO_IR_BLASTER] = 23,
0269 };
0270
0271 static struct clk_regmap *axg_aoclk_regmap[] = {
0272 &axg_aoclk_remote,
0273 &axg_aoclk_i2c_master,
0274 &axg_aoclk_i2c_slave,
0275 &axg_aoclk_uart1,
0276 &axg_aoclk_uart2,
0277 &axg_aoclk_ir_blaster,
0278 &axg_aoclk_saradc,
0279 &axg_aoclk_cts_oscin,
0280 &axg_aoclk_32k_pre,
0281 &axg_aoclk_32k_div,
0282 &axg_aoclk_32k_sel,
0283 &axg_aoclk_32k,
0284 &axg_aoclk_cts_rtc_oscin,
0285 &axg_aoclk_clk81,
0286 &axg_aoclk_saradc_mux,
0287 &axg_aoclk_saradc_div,
0288 &axg_aoclk_saradc_gate,
0289 };
0290
0291 static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
0292 .hws = {
0293 [CLKID_AO_REMOTE] = &axg_aoclk_remote.hw,
0294 [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master.hw,
0295 [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave.hw,
0296 [CLKID_AO_UART1] = &axg_aoclk_uart1.hw,
0297 [CLKID_AO_UART2] = &axg_aoclk_uart2.hw,
0298 [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster.hw,
0299 [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc.hw,
0300 [CLKID_AO_CLK81] = &axg_aoclk_clk81.hw,
0301 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux.hw,
0302 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div.hw,
0303 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate.hw,
0304 [CLKID_AO_CTS_OSCIN] = &axg_aoclk_cts_oscin.hw,
0305 [CLKID_AO_32K_PRE] = &axg_aoclk_32k_pre.hw,
0306 [CLKID_AO_32K_DIV] = &axg_aoclk_32k_div.hw,
0307 [CLKID_AO_32K_SEL] = &axg_aoclk_32k_sel.hw,
0308 [CLKID_AO_32K] = &axg_aoclk_32k.hw,
0309 [CLKID_AO_CTS_RTC_OSCIN] = &axg_aoclk_cts_rtc_oscin.hw,
0310 },
0311 .num = NR_CLKS,
0312 };
0313
0314 static const struct meson_aoclk_data axg_aoclkc_data = {
0315 .reset_reg = AO_RTI_GEN_CNTL_REG0,
0316 .num_reset = ARRAY_SIZE(axg_aoclk_reset),
0317 .reset = axg_aoclk_reset,
0318 .num_clks = ARRAY_SIZE(axg_aoclk_regmap),
0319 .clks = axg_aoclk_regmap,
0320 .hw_data = &axg_aoclk_onecell_data,
0321 };
0322
0323 static const struct of_device_id axg_aoclkc_match_table[] = {
0324 {
0325 .compatible = "amlogic,meson-axg-aoclkc",
0326 .data = &axg_aoclkc_data,
0327 },
0328 { }
0329 };
0330 MODULE_DEVICE_TABLE(of, axg_aoclkc_match_table);
0331
0332 static struct platform_driver axg_aoclkc_driver = {
0333 .probe = meson_aoclkc_probe,
0334 .driver = {
0335 .name = "axg-aoclkc",
0336 .of_match_table = axg_aoclkc_match_table,
0337 },
0338 };
0339
0340 module_platform_driver(axg_aoclkc_driver);
0341 MODULE_LICENSE("GPL v2");