1*a1b4c3a6SJian Hu // SPDX-License-Identifier: (GPL-2.0-only OR MIT) 2*a1b4c3a6SJian Hu /* 3*a1b4c3a6SJian Hu * Copyright (C) 2026 Amlogic, Inc. All rights reserved 4*a1b4c3a6SJian Hu */ 5*a1b4c3a6SJian Hu 6*a1b4c3a6SJian Hu #include <dt-bindings/clock/amlogic,a9-aoclkc.h> 7*a1b4c3a6SJian Hu #include <linux/clk-provider.h> 8*a1b4c3a6SJian Hu #include <linux/module.h> 9*a1b4c3a6SJian Hu #include <linux/platform_device.h> 10*a1b4c3a6SJian Hu #include "clk-regmap.h" 11*a1b4c3a6SJian Hu #include "clk-dualdiv.h" 12*a1b4c3a6SJian Hu #include "meson-clkc-utils.h" 13*a1b4c3a6SJian Hu 14*a1b4c3a6SJian Hu #define AO_OSCIN_CTRL 0x00 15*a1b4c3a6SJian Hu #define AO_SYS_CLK0 0x04 16*a1b4c3a6SJian Hu #define AO_PWM_CLK_A_CTRL 0x1c 17*a1b4c3a6SJian Hu #define AO_PWM_CLK_B_CTRL 0x20 18*a1b4c3a6SJian Hu #define AO_PWM_CLK_C_CTRL 0x24 19*a1b4c3a6SJian Hu #define AO_PWM_CLK_D_CTRL 0x28 20*a1b4c3a6SJian Hu #define AO_PWM_CLK_E_CTRL 0x2c 21*a1b4c3a6SJian Hu #define AO_PWM_CLK_F_CTRL 0x30 22*a1b4c3a6SJian Hu #define AO_PWM_CLK_G_CTRL 0x34 23*a1b4c3a6SJian Hu #define AO_CEC_CTRL0 0x38 24*a1b4c3a6SJian Hu #define AO_CEC_CTRL1 0x3c 25*a1b4c3a6SJian Hu #define AO_RTC_BY_OSCIN_CTRL0 0x50 26*a1b4c3a6SJian Hu #define AO_RTC_BY_OSCIN_CTRL1 0x54 27*a1b4c3a6SJian Hu 28*a1b4c3a6SJian Hu #define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \ 29*a1b4c3a6SJian Hu MESON_COMP_SEL(a9_ao_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0) 30*a1b4c3a6SJian Hu 31*a1b4c3a6SJian Hu #define A9_COMP_DIV(_name, _reg, _shift, _width) \ 32*a1b4c3a6SJian Hu MESON_COMP_DIV(a9_ao_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) 33*a1b4c3a6SJian Hu 34*a1b4c3a6SJian Hu #define A9_COMP_GATE(_name, _reg, _bit) \ 35*a1b4c3a6SJian Hu MESON_COMP_GATE(a9_ao_, _name, _reg, _bit, CLK_SET_RATE_PARENT) 36*a1b4c3a6SJian Hu 37*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_xtal_in = { 38*a1b4c3a6SJian Hu .data = &(struct clk_regmap_gate_data){ 39*a1b4c3a6SJian Hu .offset = AO_OSCIN_CTRL, 40*a1b4c3a6SJian Hu .bit_idx = 3, 41*a1b4c3a6SJian Hu }, 42*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data) { 43*a1b4c3a6SJian Hu .name = "ao_xtal_in", 44*a1b4c3a6SJian Hu .ops = &clk_regmap_gate_ops, 45*a1b4c3a6SJian Hu .parent_data = &(const struct clk_parent_data) { 46*a1b4c3a6SJian Hu .fw_name = "xtal", 47*a1b4c3a6SJian Hu }, 48*a1b4c3a6SJian Hu .num_parents = 1, 49*a1b4c3a6SJian Hu }, 50*a1b4c3a6SJian Hu }; 51*a1b4c3a6SJian Hu 52*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_xtal = { 53*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 54*a1b4c3a6SJian Hu .offset = AO_OSCIN_CTRL, 55*a1b4c3a6SJian Hu .mask = 0x1, 56*a1b4c3a6SJian Hu .shift = 0, 57*a1b4c3a6SJian Hu }, 58*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 59*a1b4c3a6SJian Hu .name = "ao_xtal", 60*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 61*a1b4c3a6SJian Hu /* ext_32k is from external PAD, do not automatically reparent */ 62*a1b4c3a6SJian Hu .parent_data = (const struct clk_parent_data []) { 63*a1b4c3a6SJian Hu { .hw = &a9_ao_xtal_in.hw }, 64*a1b4c3a6SJian Hu { .fw_name = "ext_32k", }, 65*a1b4c3a6SJian Hu }, 66*a1b4c3a6SJian Hu .num_parents = 2, 67*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_NO_REPARENT, 68*a1b4c3a6SJian Hu }, 69*a1b4c3a6SJian Hu }; 70*a1b4c3a6SJian Hu 71*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_sys = { 72*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 73*a1b4c3a6SJian Hu .offset = AO_OSCIN_CTRL, 74*a1b4c3a6SJian Hu .mask = 0x1, 75*a1b4c3a6SJian Hu .shift = 1, 76*a1b4c3a6SJian Hu }, 77*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 78*a1b4c3a6SJian Hu .name = "ao_sys", 79*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 80*a1b4c3a6SJian Hu .parent_data = (const struct clk_parent_data []) { 81*a1b4c3a6SJian Hu { .hw = &a9_ao_xtal.hw }, 82*a1b4c3a6SJian Hu { .fw_name = "sys", }, 83*a1b4c3a6SJian Hu }, 84*a1b4c3a6SJian Hu .num_parents = 2, 85*a1b4c3a6SJian Hu }, 86*a1b4c3a6SJian Hu }; 87*a1b4c3a6SJian Hu 88*a1b4c3a6SJian Hu static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw }; 89*a1b4c3a6SJian Hu 90*a1b4c3a6SJian Hu #define A9_AO_PCLK(_name, _bit, _flags) \ 91*a1b4c3a6SJian Hu MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \ 92*a1b4c3a6SJian Hu &a9_ao_pclk_parents, _flags) 93*a1b4c3a6SJian Hu 94*a1b4c3a6SJian Hu /* 95*a1b4c3a6SJian Hu * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys 96*a1b4c3a6SJian Hu * clocks control the AOCPU modules. Mark the AOCPU-related clocks with 97*a1b4c3a6SJian Hu * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality. 98*a1b4c3a6SJian Hu * AOCPU-related clocks list: 99*a1b4c3a6SJian Hu * - clktree 100*a1b4c3a6SJian Hu * - rst_ctrl 101*a1b4c3a6SJian Hu * - pad 102*a1b4c3a6SJian Hu * - irq 103*a1b4c3a6SJian Hu * - pwrctrl 104*a1b4c3a6SJian Hu * - aocpu 105*a1b4c3a6SJian Hu * - sram 106*a1b4c3a6SJian Hu */ 107*a1b4c3a6SJian Hu static A9_AO_PCLK(i3c, 0, 0); 108*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_reg, 1, 0); 109*a1b4c3a6SJian Hu static A9_AO_PCLK(clktree, 2, CLK_IS_CRITICAL); 110*a1b4c3a6SJian Hu static A9_AO_PCLK(rst_ctrl, 3, CLK_IS_CRITICAL); 111*a1b4c3a6SJian Hu static A9_AO_PCLK(pad, 4, CLK_IS_CRITICAL); 112*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_dig, 5, 0); 113*a1b4c3a6SJian Hu static A9_AO_PCLK(irq, 6, CLK_IS_CRITICAL); 114*a1b4c3a6SJian Hu static A9_AO_PCLK(pwrctrl, 7, CLK_IS_CRITICAL); 115*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_a, 8, 0); 116*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_b, 9, 0); 117*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_c, 10, 0); 118*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_d, 11, 0); 119*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_e, 12, 0); 120*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_f, 13, 0); 121*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_g, 14, 0); 122*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_a, 15, 0); 123*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_b, 16, 0); 124*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_c, 17, 0); 125*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_d, 18, 0); 126*a1b4c3a6SJian Hu static A9_AO_PCLK(sed, 19, 0); 127*a1b4c3a6SJian Hu static A9_AO_PCLK(ir_ctrl, 20, 0); 128*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_b, 21, 0); 129*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_c, 22, 0); 130*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_d, 23, 0); 131*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_e, 24, 0); 132*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_0, 25, 0); 133*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_secure, 26, 0); 134*a1b4c3a6SJian Hu static A9_AO_PCLK(cec, 27, 0); 135*a1b4c3a6SJian Hu static A9_AO_PCLK(aocpu, 28, CLK_IS_CRITICAL); 136*a1b4c3a6SJian Hu static A9_AO_PCLK(sram, 29, CLK_IS_CRITICAL); 137*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_1, 30, 0); 138*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_2, 31, 0); 139*a1b4c3a6SJian Hu 140*a1b4c3a6SJian Hu static const struct clk_parent_data a9_ao_pwm_parents[] = { 141*a1b4c3a6SJian Hu { .hw = &a9_ao_xtal.hw }, 142*a1b4c3a6SJian Hu { .fw_name = "fdiv5", }, 143*a1b4c3a6SJian Hu { .fw_name = "fdiv4", }, 144*a1b4c3a6SJian Hu { .fw_name = "fdiv3", } 145*a1b4c3a6SJian Hu }; 146*a1b4c3a6SJian Hu 147*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents); 148*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_a, AO_PWM_CLK_A_CTRL, 0, 8); 149*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_a, AO_PWM_CLK_A_CTRL, 8); 150*a1b4c3a6SJian Hu 151*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents); 152*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_b, AO_PWM_CLK_B_CTRL, 0, 8); 153*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_b, AO_PWM_CLK_B_CTRL, 8); 154*a1b4c3a6SJian Hu 155*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents); 156*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_c, AO_PWM_CLK_C_CTRL, 0, 8); 157*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_c, AO_PWM_CLK_C_CTRL, 8); 158*a1b4c3a6SJian Hu 159*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents); 160*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_d, AO_PWM_CLK_D_CTRL, 0, 8); 161*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_d, AO_PWM_CLK_D_CTRL, 8); 162*a1b4c3a6SJian Hu 163*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents); 164*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_e, AO_PWM_CLK_E_CTRL, 0, 8); 165*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_e, AO_PWM_CLK_E_CTRL, 8); 166*a1b4c3a6SJian Hu 167*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents); 168*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_f, AO_PWM_CLK_F_CTRL, 0, 8); 169*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_f, AO_PWM_CLK_F_CTRL, 8); 170*a1b4c3a6SJian Hu 171*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents); 172*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_g, AO_PWM_CLK_G_CTRL, 0, 8); 173*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_g, AO_PWM_CLK_G_CTRL, 8); 174*a1b4c3a6SJian Hu 175*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_in = { 176*a1b4c3a6SJian Hu .data = &(struct clk_regmap_gate_data){ 177*a1b4c3a6SJian Hu .offset = AO_RTC_BY_OSCIN_CTRL0, 178*a1b4c3a6SJian Hu .bit_idx = 31, 179*a1b4c3a6SJian Hu }, 180*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data) { 181*a1b4c3a6SJian Hu .name = "ao_rtc_dualdiv_in", 182*a1b4c3a6SJian Hu .ops = &clk_regmap_gate_ops, 183*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 184*a1b4c3a6SJian Hu &a9_ao_xtal.hw 185*a1b4c3a6SJian Hu }, 186*a1b4c3a6SJian Hu .num_parents = 1, 187*a1b4c3a6SJian Hu }, 188*a1b4c3a6SJian Hu }; 189*a1b4c3a6SJian Hu 190*a1b4c3a6SJian Hu static const struct meson_clk_dualdiv_param a9_ao_dualdiv_table[] = { 191*a1b4c3a6SJian Hu { 733, 732, 8, 11, 1 }, 192*a1b4c3a6SJian Hu { /* sentinel */ } 193*a1b4c3a6SJian Hu }; 194*a1b4c3a6SJian Hu 195*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_div = { 196*a1b4c3a6SJian Hu .data = &(struct meson_clk_dualdiv_data){ 197*a1b4c3a6SJian Hu .n1 = { 198*a1b4c3a6SJian Hu .reg_off = AO_RTC_BY_OSCIN_CTRL0, 199*a1b4c3a6SJian Hu .shift = 0, 200*a1b4c3a6SJian Hu .width = 12, 201*a1b4c3a6SJian Hu }, 202*a1b4c3a6SJian Hu .n2 = { 203*a1b4c3a6SJian Hu .reg_off = AO_RTC_BY_OSCIN_CTRL0, 204*a1b4c3a6SJian Hu .shift = 12, 205*a1b4c3a6SJian Hu .width = 12, 206*a1b4c3a6SJian Hu }, 207*a1b4c3a6SJian Hu .m1 = { 208*a1b4c3a6SJian Hu .reg_off = AO_RTC_BY_OSCIN_CTRL1, 209*a1b4c3a6SJian Hu .shift = 0, 210*a1b4c3a6SJian Hu .width = 12, 211*a1b4c3a6SJian Hu }, 212*a1b4c3a6SJian Hu .m2 = { 213*a1b4c3a6SJian Hu .reg_off = AO_RTC_BY_OSCIN_CTRL1, 214*a1b4c3a6SJian Hu .shift = 12, 215*a1b4c3a6SJian Hu .width = 12, 216*a1b4c3a6SJian Hu }, 217*a1b4c3a6SJian Hu .dual = { 218*a1b4c3a6SJian Hu .reg_off = AO_RTC_BY_OSCIN_CTRL0, 219*a1b4c3a6SJian Hu .shift = 28, 220*a1b4c3a6SJian Hu .width = 1, 221*a1b4c3a6SJian Hu }, 222*a1b4c3a6SJian Hu .table = a9_ao_dualdiv_table, 223*a1b4c3a6SJian Hu }, 224*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 225*a1b4c3a6SJian Hu .name = "a9_ao_rtc_dualdiv_div", 226*a1b4c3a6SJian Hu .ops = &meson_clk_dualdiv_ops, 227*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 228*a1b4c3a6SJian Hu &a9_ao_rtc_dualdiv_in.hw 229*a1b4c3a6SJian Hu }, 230*a1b4c3a6SJian Hu .num_parents = 1, 231*a1b4c3a6SJian Hu }, 232*a1b4c3a6SJian Hu }; 233*a1b4c3a6SJian Hu 234*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_sel = { 235*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 236*a1b4c3a6SJian Hu .offset = AO_RTC_BY_OSCIN_CTRL1, 237*a1b4c3a6SJian Hu .mask = 0x1, 238*a1b4c3a6SJian Hu .shift = 24, 239*a1b4c3a6SJian Hu }, 240*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 241*a1b4c3a6SJian Hu .name = "ao_rtc_dualdiv_sel", 242*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 243*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 244*a1b4c3a6SJian Hu &a9_ao_rtc_dualdiv_div.hw, 245*a1b4c3a6SJian Hu &a9_ao_rtc_dualdiv_in.hw, 246*a1b4c3a6SJian Hu }, 247*a1b4c3a6SJian Hu .num_parents = 2, 248*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 249*a1b4c3a6SJian Hu }, 250*a1b4c3a6SJian Hu }; 251*a1b4c3a6SJian Hu 252*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv = { 253*a1b4c3a6SJian Hu .data = &(struct clk_regmap_gate_data){ 254*a1b4c3a6SJian Hu .offset = AO_RTC_BY_OSCIN_CTRL0, 255*a1b4c3a6SJian Hu .bit_idx = 30, 256*a1b4c3a6SJian Hu }, 257*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data) { 258*a1b4c3a6SJian Hu .name = "ao_rtc_dualdiv", 259*a1b4c3a6SJian Hu .ops = &clk_regmap_gate_ops, 260*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 261*a1b4c3a6SJian Hu &a9_ao_rtc_dualdiv_sel.hw 262*a1b4c3a6SJian Hu }, 263*a1b4c3a6SJian Hu .num_parents = 1, 264*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 265*a1b4c3a6SJian Hu }, 266*a1b4c3a6SJian Hu }; 267*a1b4c3a6SJian Hu 268*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc = { 269*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 270*a1b4c3a6SJian Hu .offset = AO_RTC_BY_OSCIN_CTRL1, 271*a1b4c3a6SJian Hu .mask = 0x1, 272*a1b4c3a6SJian Hu .shift = 30, 273*a1b4c3a6SJian Hu }, 274*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 275*a1b4c3a6SJian Hu .name = "ao_rtc", 276*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 277*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 278*a1b4c3a6SJian Hu &a9_ao_xtal.hw, 279*a1b4c3a6SJian Hu &a9_ao_rtc_dualdiv.hw, 280*a1b4c3a6SJian Hu }, 281*a1b4c3a6SJian Hu .num_parents = 2, 282*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 283*a1b4c3a6SJian Hu }, 284*a1b4c3a6SJian Hu }; 285*a1b4c3a6SJian Hu 286*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_in = { 287*a1b4c3a6SJian Hu .data = &(struct clk_regmap_gate_data){ 288*a1b4c3a6SJian Hu .offset = AO_CEC_CTRL0, 289*a1b4c3a6SJian Hu .bit_idx = 31, 290*a1b4c3a6SJian Hu }, 291*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data) { 292*a1b4c3a6SJian Hu .name = "ao_cec_dualdiv_in", 293*a1b4c3a6SJian Hu .ops = &clk_regmap_gate_ops, 294*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 295*a1b4c3a6SJian Hu &a9_ao_xtal.hw 296*a1b4c3a6SJian Hu }, 297*a1b4c3a6SJian Hu .num_parents = 1, 298*a1b4c3a6SJian Hu }, 299*a1b4c3a6SJian Hu }; 300*a1b4c3a6SJian Hu 301*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_div = { 302*a1b4c3a6SJian Hu .data = &(struct meson_clk_dualdiv_data){ 303*a1b4c3a6SJian Hu .n1 = { 304*a1b4c3a6SJian Hu .reg_off = AO_CEC_CTRL0, 305*a1b4c3a6SJian Hu .shift = 0, 306*a1b4c3a6SJian Hu .width = 12, 307*a1b4c3a6SJian Hu }, 308*a1b4c3a6SJian Hu .n2 = { 309*a1b4c3a6SJian Hu .reg_off = AO_CEC_CTRL0, 310*a1b4c3a6SJian Hu .shift = 12, 311*a1b4c3a6SJian Hu .width = 12, 312*a1b4c3a6SJian Hu }, 313*a1b4c3a6SJian Hu .m1 = { 314*a1b4c3a6SJian Hu .reg_off = AO_CEC_CTRL1, 315*a1b4c3a6SJian Hu .shift = 0, 316*a1b4c3a6SJian Hu .width = 12, 317*a1b4c3a6SJian Hu }, 318*a1b4c3a6SJian Hu .m2 = { 319*a1b4c3a6SJian Hu .reg_off = AO_CEC_CTRL1, 320*a1b4c3a6SJian Hu .shift = 12, 321*a1b4c3a6SJian Hu .width = 12, 322*a1b4c3a6SJian Hu }, 323*a1b4c3a6SJian Hu .dual = { 324*a1b4c3a6SJian Hu .reg_off = AO_CEC_CTRL0, 325*a1b4c3a6SJian Hu .shift = 28, 326*a1b4c3a6SJian Hu .width = 1, 327*a1b4c3a6SJian Hu }, 328*a1b4c3a6SJian Hu .table = a9_ao_dualdiv_table, 329*a1b4c3a6SJian Hu }, 330*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 331*a1b4c3a6SJian Hu .name = "ao_cec_dualdiv_div", 332*a1b4c3a6SJian Hu .ops = &meson_clk_dualdiv_ops, 333*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 334*a1b4c3a6SJian Hu &a9_ao_cec_dualdiv_in.hw 335*a1b4c3a6SJian Hu }, 336*a1b4c3a6SJian Hu .num_parents = 1, 337*a1b4c3a6SJian Hu }, 338*a1b4c3a6SJian Hu }; 339*a1b4c3a6SJian Hu 340*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_sel = { 341*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 342*a1b4c3a6SJian Hu .offset = AO_CEC_CTRL1, 343*a1b4c3a6SJian Hu .mask = 0x1, 344*a1b4c3a6SJian Hu .shift = 24, 345*a1b4c3a6SJian Hu }, 346*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 347*a1b4c3a6SJian Hu .name = "ao_cec_dualdiv_sel", 348*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 349*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 350*a1b4c3a6SJian Hu &a9_ao_cec_dualdiv_div.hw, 351*a1b4c3a6SJian Hu &a9_ao_cec_dualdiv_in.hw, 352*a1b4c3a6SJian Hu }, 353*a1b4c3a6SJian Hu .num_parents = 2, 354*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 355*a1b4c3a6SJian Hu }, 356*a1b4c3a6SJian Hu }; 357*a1b4c3a6SJian Hu 358*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv = { 359*a1b4c3a6SJian Hu .data = &(struct clk_regmap_gate_data){ 360*a1b4c3a6SJian Hu .offset = AO_CEC_CTRL0, 361*a1b4c3a6SJian Hu .bit_idx = 30, 362*a1b4c3a6SJian Hu }, 363*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 364*a1b4c3a6SJian Hu .name = "ao_cec_dualdiv", 365*a1b4c3a6SJian Hu .ops = &clk_regmap_gate_ops, 366*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 367*a1b4c3a6SJian Hu &a9_ao_cec_dualdiv_sel.hw 368*a1b4c3a6SJian Hu }, 369*a1b4c3a6SJian Hu .num_parents = 1, 370*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 371*a1b4c3a6SJian Hu }, 372*a1b4c3a6SJian Hu }; 373*a1b4c3a6SJian Hu 374*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec = { 375*a1b4c3a6SJian Hu .data = &(struct clk_regmap_mux_data) { 376*a1b4c3a6SJian Hu .offset = AO_CEC_CTRL1, 377*a1b4c3a6SJian Hu .mask = 0x1, 378*a1b4c3a6SJian Hu .shift = 30, 379*a1b4c3a6SJian Hu }, 380*a1b4c3a6SJian Hu .hw.init = &(struct clk_init_data){ 381*a1b4c3a6SJian Hu .name = "ao_cec", 382*a1b4c3a6SJian Hu .ops = &clk_regmap_mux_ops, 383*a1b4c3a6SJian Hu .parent_hws = (const struct clk_hw *[]) { 384*a1b4c3a6SJian Hu &a9_ao_cec_dualdiv.hw, 385*a1b4c3a6SJian Hu &a9_ao_rtc.hw, 386*a1b4c3a6SJian Hu }, 387*a1b4c3a6SJian Hu .num_parents = 2, 388*a1b4c3a6SJian Hu .flags = CLK_SET_RATE_PARENT, 389*a1b4c3a6SJian Hu }, 390*a1b4c3a6SJian Hu }; 391*a1b4c3a6SJian Hu 392*a1b4c3a6SJian Hu static struct clk_hw *a9_ao_hw_clks[] = { 393*a1b4c3a6SJian Hu [CLKID_AO_XTAL_IN] = &a9_ao_xtal_in.hw, 394*a1b4c3a6SJian Hu [CLKID_AO_XTAL] = &a9_ao_xtal.hw, 395*a1b4c3a6SJian Hu [CLKID_AO_SYS] = &a9_ao_sys.hw, 396*a1b4c3a6SJian Hu [CLKID_AO_SYS_I3C] = &a9_ao_sys_i3c.hw, 397*a1b4c3a6SJian Hu [CLKID_AO_SYS_RTC_REG] = &a9_ao_sys_rtc_reg.hw, 398*a1b4c3a6SJian Hu [CLKID_AO_SYS_CLKTREE] = &a9_ao_sys_clktree.hw, 399*a1b4c3a6SJian Hu [CLKID_AO_SYS_RST_CTRL] = &a9_ao_sys_rst_ctrl.hw, 400*a1b4c3a6SJian Hu [CLKID_AO_SYS_PAD] = &a9_ao_sys_pad.hw, 401*a1b4c3a6SJian Hu [CLKID_AO_SYS_RTC_DIG] = &a9_ao_sys_rtc_dig.hw, 402*a1b4c3a6SJian Hu [CLKID_AO_SYS_IRQ] = &a9_ao_sys_irq.hw, 403*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWRCTRL] = &a9_ao_sys_pwrctrl.hw, 404*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_A] = &a9_ao_sys_pwm_a.hw, 405*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_B] = &a9_ao_sys_pwm_b.hw, 406*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_C] = &a9_ao_sys_pwm_c.hw, 407*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_D] = &a9_ao_sys_pwm_d.hw, 408*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_E] = &a9_ao_sys_pwm_e.hw, 409*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_F] = &a9_ao_sys_pwm_f.hw, 410*a1b4c3a6SJian Hu [CLKID_AO_SYS_PWM_G] = &a9_ao_sys_pwm_g.hw, 411*a1b4c3a6SJian Hu [CLKID_AO_SYS_I2C_A] = &a9_ao_sys_i2c_a.hw, 412*a1b4c3a6SJian Hu [CLKID_AO_SYS_I2C_B] = &a9_ao_sys_i2c_b.hw, 413*a1b4c3a6SJian Hu [CLKID_AO_SYS_I2C_C] = &a9_ao_sys_i2c_c.hw, 414*a1b4c3a6SJian Hu [CLKID_AO_SYS_I2C_D] = &a9_ao_sys_i2c_d.hw, 415*a1b4c3a6SJian Hu [CLKID_AO_SYS_SED] = &a9_ao_sys_sed.hw, 416*a1b4c3a6SJian Hu [CLKID_AO_SYS_IR_CTRL] = &a9_ao_sys_ir_ctrl.hw, 417*a1b4c3a6SJian Hu [CLKID_AO_SYS_UART_B] = &a9_ao_sys_uart_b.hw, 418*a1b4c3a6SJian Hu [CLKID_AO_SYS_UART_C] = &a9_ao_sys_uart_c.hw, 419*a1b4c3a6SJian Hu [CLKID_AO_SYS_UART_D] = &a9_ao_sys_uart_d.hw, 420*a1b4c3a6SJian Hu [CLKID_AO_SYS_UART_E] = &a9_ao_sys_uart_e.hw, 421*a1b4c3a6SJian Hu [CLKID_AO_SYS_SPISG_0] = &a9_ao_sys_spisg_0.hw, 422*a1b4c3a6SJian Hu [CLKID_AO_SYS_RTC_SECURE] = &a9_ao_sys_rtc_secure.hw, 423*a1b4c3a6SJian Hu [CLKID_AO_SYS_CEC] = &a9_ao_sys_cec.hw, 424*a1b4c3a6SJian Hu [CLKID_AO_SYS_AOCPU] = &a9_ao_sys_aocpu.hw, 425*a1b4c3a6SJian Hu [CLKID_AO_SYS_SRAM] = &a9_ao_sys_sram.hw, 426*a1b4c3a6SJian Hu [CLKID_AO_SYS_SPISG_1] = &a9_ao_sys_spisg_1.hw, 427*a1b4c3a6SJian Hu [CLKID_AO_SYS_SPISG_2] = &a9_ao_sys_spisg_2.hw, 428*a1b4c3a6SJian Hu [CLKID_AO_PWM_A_SEL] = &a9_ao_pwm_a_sel.hw, 429*a1b4c3a6SJian Hu [CLKID_AO_PWM_A_DIV] = &a9_ao_pwm_a_div.hw, 430*a1b4c3a6SJian Hu [CLKID_AO_PWM_A] = &a9_ao_pwm_a.hw, 431*a1b4c3a6SJian Hu [CLKID_AO_PWM_B_SEL] = &a9_ao_pwm_b_sel.hw, 432*a1b4c3a6SJian Hu [CLKID_AO_PWM_B_DIV] = &a9_ao_pwm_b_div.hw, 433*a1b4c3a6SJian Hu [CLKID_AO_PWM_B] = &a9_ao_pwm_b.hw, 434*a1b4c3a6SJian Hu [CLKID_AO_PWM_C_SEL] = &a9_ao_pwm_c_sel.hw, 435*a1b4c3a6SJian Hu [CLKID_AO_PWM_C_DIV] = &a9_ao_pwm_c_div.hw, 436*a1b4c3a6SJian Hu [CLKID_AO_PWM_C] = &a9_ao_pwm_c.hw, 437*a1b4c3a6SJian Hu [CLKID_AO_PWM_D_SEL] = &a9_ao_pwm_d_sel.hw, 438*a1b4c3a6SJian Hu [CLKID_AO_PWM_D_DIV] = &a9_ao_pwm_d_div.hw, 439*a1b4c3a6SJian Hu [CLKID_AO_PWM_D] = &a9_ao_pwm_d.hw, 440*a1b4c3a6SJian Hu [CLKID_AO_PWM_E_SEL] = &a9_ao_pwm_e_sel.hw, 441*a1b4c3a6SJian Hu [CLKID_AO_PWM_E_DIV] = &a9_ao_pwm_e_div.hw, 442*a1b4c3a6SJian Hu [CLKID_AO_PWM_E] = &a9_ao_pwm_e.hw, 443*a1b4c3a6SJian Hu [CLKID_AO_PWM_F_SEL] = &a9_ao_pwm_f_sel.hw, 444*a1b4c3a6SJian Hu [CLKID_AO_PWM_F_DIV] = &a9_ao_pwm_f_div.hw, 445*a1b4c3a6SJian Hu [CLKID_AO_PWM_F] = &a9_ao_pwm_f.hw, 446*a1b4c3a6SJian Hu [CLKID_AO_PWM_G_SEL] = &a9_ao_pwm_g_sel.hw, 447*a1b4c3a6SJian Hu [CLKID_AO_PWM_G_DIV] = &a9_ao_pwm_g_div.hw, 448*a1b4c3a6SJian Hu [CLKID_AO_PWM_G] = &a9_ao_pwm_g.hw, 449*a1b4c3a6SJian Hu [CLKID_AO_RTC_DUALDIV_IN] = &a9_ao_rtc_dualdiv_in.hw, 450*a1b4c3a6SJian Hu [CLKID_AO_RTC_DUALDIV_DIV] = &a9_ao_rtc_dualdiv_div.hw, 451*a1b4c3a6SJian Hu [CLKID_AO_RTC_DUALDIV_SEL] = &a9_ao_rtc_dualdiv_sel.hw, 452*a1b4c3a6SJian Hu [CLKID_AO_RTC_DUALDIV] = &a9_ao_rtc_dualdiv.hw, 453*a1b4c3a6SJian Hu [CLKID_AO_RTC] = &a9_ao_rtc.hw, 454*a1b4c3a6SJian Hu [CLKID_AO_CEC_DUALDIV_IN] = &a9_ao_cec_dualdiv_in.hw, 455*a1b4c3a6SJian Hu [CLKID_AO_CEC_DUALDIV_DIV] = &a9_ao_cec_dualdiv_div.hw, 456*a1b4c3a6SJian Hu [CLKID_AO_CEC_DUALDIV_SEL] = &a9_ao_cec_dualdiv_sel.hw, 457*a1b4c3a6SJian Hu [CLKID_AO_CEC_DUALDIV] = &a9_ao_cec_dualdiv.hw, 458*a1b4c3a6SJian Hu [CLKID_AO_CEC] = &a9_ao_cec.hw, 459*a1b4c3a6SJian Hu }; 460*a1b4c3a6SJian Hu 461*a1b4c3a6SJian Hu static const struct meson_clkc_data a9_ao_clkc_data = { 462*a1b4c3a6SJian Hu .hw_clks = { 463*a1b4c3a6SJian Hu .hws = a9_ao_hw_clks, 464*a1b4c3a6SJian Hu .num = ARRAY_SIZE(a9_ao_hw_clks), 465*a1b4c3a6SJian Hu }, 466*a1b4c3a6SJian Hu }; 467*a1b4c3a6SJian Hu 468*a1b4c3a6SJian Hu static const struct of_device_id a9_ao_clkc_match_table[] = { 469*a1b4c3a6SJian Hu { 470*a1b4c3a6SJian Hu .compatible = "amlogic,a9-aoclkc", 471*a1b4c3a6SJian Hu .data = &a9_ao_clkc_data, 472*a1b4c3a6SJian Hu }, 473*a1b4c3a6SJian Hu { } 474*a1b4c3a6SJian Hu }; 475*a1b4c3a6SJian Hu MODULE_DEVICE_TABLE(of, a9_ao_clkc_match_table); 476*a1b4c3a6SJian Hu 477*a1b4c3a6SJian Hu static struct platform_driver a9_ao_clkc_driver = { 478*a1b4c3a6SJian Hu .probe = meson_clkc_mmio_probe, 479*a1b4c3a6SJian Hu .driver = { 480*a1b4c3a6SJian Hu .name = "a9-aoclkc", 481*a1b4c3a6SJian Hu .of_match_table = a9_ao_clkc_match_table, 482*a1b4c3a6SJian Hu }, 483*a1b4c3a6SJian Hu }; 484*a1b4c3a6SJian Hu module_platform_driver(a9_ao_clkc_driver); 485*a1b4c3a6SJian Hu 486*a1b4c3a6SJian Hu MODULE_DESCRIPTION("Amlogic A9 Always-ON Clock Controller driver"); 487*a1b4c3a6SJian Hu MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); 488*a1b4c3a6SJian Hu MODULE_LICENSE("GPL"); 489*a1b4c3a6SJian Hu MODULE_IMPORT_NS("CLK_MESON"); 490