1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Amlogic Meson-AXG Clock Controller Driver 4 * 5 * Copyright (c) 2016 Baylibre SAS. 6 * Author: Michael Turquette <mturquette@baylibre.com> 7 * 8 * Copyright (c) 2018 Amlogic, inc. 9 * Author: Qiufang Dai <qiufang.dai@amlogic.com> 10 */ 11 #include <linux/clk-provider.h> 12 #include <linux/platform_device.h> 13 #include <linux/reset-controller.h> 14 #include <linux/mfd/syscon.h> 15 #include "clk-regmap.h" 16 #include "meson-aoclk.h" 17 #include "axg-aoclk.h" 18 19 #define AXG_AO_GATE(_name, _bit) \ 20 static struct clk_regmap axg_aoclk_##_name = { \ 21 .data = &(struct clk_regmap_gate_data) { \ 22 .offset = (AO_RTI_GEN_CNTL_REG0), \ 23 .bit_idx = (_bit), \ 24 }, \ 25 .hw.init = &(struct clk_init_data) { \ 26 .name = "axg_ao_" #_name, \ 27 .ops = &clk_regmap_gate_ops, \ 28 .parent_names = (const char *[]){ "clk81" }, \ 29 .num_parents = 1, \ 30 .flags = CLK_IGNORE_UNUSED, \ 31 }, \ 32 } 33 34 AXG_AO_GATE(remote, 0); 35 AXG_AO_GATE(i2c_master, 1); 36 AXG_AO_GATE(i2c_slave, 2); 37 AXG_AO_GATE(uart1, 3); 38 AXG_AO_GATE(uart2, 5); 39 AXG_AO_GATE(ir_blaster, 6); 40 AXG_AO_GATE(saradc, 7); 41 42 static struct clk_regmap axg_aoclk_clk81 = { 43 .data = &(struct clk_regmap_mux_data) { 44 .offset = AO_RTI_PWR_CNTL_REG0, 45 .mask = 0x1, 46 .shift = 8, 47 }, 48 .hw.init = &(struct clk_init_data){ 49 .name = "axg_ao_clk81", 50 .ops = &clk_regmap_mux_ro_ops, 51 .parent_names = (const char *[]){ "clk81", "ao_alt_xtal"}, 52 .num_parents = 2, 53 }, 54 }; 55 56 static struct clk_regmap axg_aoclk_saradc_mux = { 57 .data = &(struct clk_regmap_mux_data) { 58 .offset = AO_SAR_CLK, 59 .mask = 0x3, 60 .shift = 9, 61 }, 62 .hw.init = &(struct clk_init_data){ 63 .name = "axg_ao_saradc_mux", 64 .ops = &clk_regmap_mux_ops, 65 .parent_names = (const char *[]){ "xtal", "axg_ao_clk81" }, 66 .num_parents = 2, 67 }, 68 }; 69 70 static struct clk_regmap axg_aoclk_saradc_div = { 71 .data = &(struct clk_regmap_div_data) { 72 .offset = AO_SAR_CLK, 73 .shift = 0, 74 .width = 8, 75 }, 76 .hw.init = &(struct clk_init_data){ 77 .name = "axg_ao_saradc_div", 78 .ops = &clk_regmap_divider_ops, 79 .parent_names = (const char *[]){ "axg_ao_saradc_mux" }, 80 .num_parents = 1, 81 .flags = CLK_SET_RATE_PARENT, 82 }, 83 }; 84 85 static struct clk_regmap axg_aoclk_saradc_gate = { 86 .data = &(struct clk_regmap_gate_data) { 87 .offset = AO_SAR_CLK, 88 .bit_idx = 8, 89 }, 90 .hw.init = &(struct clk_init_data){ 91 .name = "axg_ao_saradc_gate", 92 .ops = &clk_regmap_gate_ops, 93 .parent_names = (const char *[]){ "axg_ao_saradc_div" }, 94 .num_parents = 1, 95 .flags = CLK_SET_RATE_PARENT, 96 }, 97 }; 98 99 static const unsigned int axg_aoclk_reset[] = { 100 [RESET_AO_REMOTE] = 16, 101 [RESET_AO_I2C_MASTER] = 18, 102 [RESET_AO_I2C_SLAVE] = 19, 103 [RESET_AO_UART1] = 17, 104 [RESET_AO_UART2] = 22, 105 [RESET_AO_IR_BLASTER] = 23, 106 }; 107 108 static struct clk_regmap *axg_aoclk_regmap[] = { 109 [CLKID_AO_REMOTE] = &axg_aoclk_remote, 110 [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master, 111 [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave, 112 [CLKID_AO_UART1] = &axg_aoclk_uart1, 113 [CLKID_AO_UART2] = &axg_aoclk_uart2, 114 [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster, 115 [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc, 116 [CLKID_AO_CLK81] = &axg_aoclk_clk81, 117 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux, 118 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div, 119 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate, 120 }; 121 122 static const struct clk_hw_onecell_data axg_aoclk_onecell_data = { 123 .hws = { 124 [CLKID_AO_REMOTE] = &axg_aoclk_remote.hw, 125 [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master.hw, 126 [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave.hw, 127 [CLKID_AO_UART1] = &axg_aoclk_uart1.hw, 128 [CLKID_AO_UART2] = &axg_aoclk_uart2.hw, 129 [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster.hw, 130 [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc.hw, 131 [CLKID_AO_CLK81] = &axg_aoclk_clk81.hw, 132 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux.hw, 133 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div.hw, 134 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate.hw, 135 }, 136 .num = NR_CLKS, 137 }; 138 139 static const struct meson_aoclk_data axg_aoclkc_data = { 140 .reset_reg = AO_RTI_GEN_CNTL_REG0, 141 .num_reset = ARRAY_SIZE(axg_aoclk_reset), 142 .reset = axg_aoclk_reset, 143 .num_clks = ARRAY_SIZE(axg_aoclk_regmap), 144 .clks = axg_aoclk_regmap, 145 .hw_data = &axg_aoclk_onecell_data, 146 }; 147 148 static const struct of_device_id axg_aoclkc_match_table[] = { 149 { 150 .compatible = "amlogic,meson-axg-aoclkc", 151 .data = &axg_aoclkc_data, 152 }, 153 { } 154 }; 155 156 static struct platform_driver axg_aoclkc_driver = { 157 .probe = meson_aoclkc_probe, 158 .driver = { 159 .name = "axg-aoclkc", 160 .of_match_table = axg_aoclkc_match_table, 161 }, 162 }; 163 164 builtin_platform_driver(axg_aoclkc_driver); 165