1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/io.h> 3 #include <linux/clk-provider.h> 4 #include <linux/slab.h> 5 #include <linux/of.h> 6 #include <linux/of_address.h> 7 8 #include "clk.h" 9 10 void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, 11 int nr_clks) 12 { 13 struct clk **clk_table; 14 15 clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); 16 if (!clk_table) 17 return; 18 19 unit->clk_table = clk_table; 20 unit->nr_clks = nr_clks; 21 unit->clk_data.clks = clk_table; 22 unit->clk_data.clk_num = nr_clks; 23 of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data); 24 } 25 26 void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, 27 struct mmp_param_fixed_rate_clk *clks, 28 int size) 29 { 30 int i; 31 struct clk *clk; 32 33 for (i = 0; i < size; i++) { 34 clk = clk_register_fixed_rate(NULL, clks[i].name, 35 clks[i].parent_name, 36 clks[i].flags, 37 clks[i].fixed_rate); 38 if (IS_ERR(clk)) { 39 pr_err("%s: failed to register clock %s\n", 40 __func__, clks[i].name); 41 continue; 42 } 43 if (clks[i].id) 44 unit->clk_table[clks[i].id] = clk; 45 } 46 } 47 48 void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, 49 struct mmp_param_fixed_factor_clk *clks, 50 int size) 51 { 52 struct clk *clk; 53 int i; 54 55 for (i = 0; i < size; i++) { 56 clk = clk_register_fixed_factor(NULL, clks[i].name, 57 clks[i].parent_name, 58 clks[i].flags, clks[i].mult, 59 clks[i].div); 60 if (IS_ERR(clk)) { 61 pr_err("%s: failed to register clock %s\n", 62 __func__, clks[i].name); 63 continue; 64 } 65 if (clks[i].id) 66 unit->clk_table[clks[i].id] = clk; 67 } 68 } 69 70 void mmp_register_general_gate_clks(struct mmp_clk_unit *unit, 71 struct mmp_param_general_gate_clk *clks, 72 void __iomem *base, int size) 73 { 74 struct clk *clk; 75 int i; 76 77 for (i = 0; i < size; i++) { 78 clk = clk_register_gate(NULL, clks[i].name, 79 clks[i].parent_name, 80 clks[i].flags, 81 base + clks[i].offset, 82 clks[i].bit_idx, 83 clks[i].gate_flags, 84 clks[i].lock); 85 86 if (IS_ERR(clk)) { 87 pr_err("%s: failed to register clock %s\n", 88 __func__, clks[i].name); 89 continue; 90 } 91 if (clks[i].id) 92 unit->clk_table[clks[i].id] = clk; 93 } 94 } 95 96 void mmp_register_gate_clks(struct mmp_clk_unit *unit, 97 struct mmp_param_gate_clk *clks, 98 void __iomem *base, int size) 99 { 100 struct clk *clk; 101 int i; 102 103 for (i = 0; i < size; i++) { 104 clk = mmp_clk_register_gate(NULL, clks[i].name, 105 clks[i].parent_name, 106 clks[i].flags, 107 base + clks[i].offset, 108 clks[i].mask, 109 clks[i].val_enable, 110 clks[i].val_disable, 111 clks[i].gate_flags, 112 clks[i].lock); 113 114 if (IS_ERR(clk)) { 115 pr_err("%s: failed to register clock %s\n", 116 __func__, clks[i].name); 117 continue; 118 } 119 if (clks[i].id) 120 unit->clk_table[clks[i].id] = clk; 121 } 122 } 123 124 void mmp_register_mux_clks(struct mmp_clk_unit *unit, 125 struct mmp_param_mux_clk *clks, 126 void __iomem *base, int size) 127 { 128 struct clk *clk; 129 int i; 130 131 for (i = 0; i < size; i++) { 132 clk = clk_register_mux(NULL, clks[i].name, 133 clks[i].parent_name, 134 clks[i].num_parents, 135 clks[i].flags, 136 base + clks[i].offset, 137 clks[i].shift, 138 clks[i].width, 139 clks[i].mux_flags, 140 clks[i].lock); 141 142 if (IS_ERR(clk)) { 143 pr_err("%s: failed to register clock %s\n", 144 __func__, clks[i].name); 145 continue; 146 } 147 if (clks[i].id) 148 unit->clk_table[clks[i].id] = clk; 149 } 150 } 151 152 void mmp_register_div_clks(struct mmp_clk_unit *unit, 153 struct mmp_param_div_clk *clks, 154 void __iomem *base, int size) 155 { 156 struct clk *clk; 157 int i; 158 159 for (i = 0; i < size; i++) { 160 clk = clk_register_divider(NULL, clks[i].name, 161 clks[i].parent_name, 162 clks[i].flags, 163 base + clks[i].offset, 164 clks[i].shift, 165 clks[i].width, 166 clks[i].div_flags, 167 clks[i].lock); 168 169 if (IS_ERR(clk)) { 170 pr_err("%s: failed to register clock %s\n", 171 __func__, clks[i].name); 172 continue; 173 } 174 if (clks[i].id) 175 unit->clk_table[clks[i].id] = clk; 176 } 177 } 178 179 void mmp_register_pll_clks(struct mmp_clk_unit *unit, 180 struct mmp_param_pll_clk *clks, 181 void __iomem *base, int size) 182 { 183 struct clk *clk; 184 int i; 185 186 for (i = 0; i < size; i++) { 187 void __iomem *reg = NULL; 188 189 if (clks[i].offset) 190 reg = base + clks[i].offset; 191 192 clk = mmp_clk_register_pll(clks[i].name, 193 clks[i].default_rate, 194 base + clks[i].enable_offset, 195 clks[i].enable, 196 reg, clks[i].shift, 197 clks[i].input_rate, 198 base + clks[i].postdiv_offset, 199 clks[i].postdiv_shift); 200 if (IS_ERR(clk)) { 201 pr_err("%s: failed to register clock %s\n", 202 __func__, clks[i].name); 203 continue; 204 } 205 if (clks[i].id) 206 unit->clk_table[clks[i].id] = clk; 207 } 208 } 209 210 void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, 211 struct clk *clk) 212 { 213 if (IS_ERR_OR_NULL(clk)) { 214 pr_err("CLK %d has invalid pointer %p\n", id, clk); 215 return; 216 } 217 if (id >= unit->nr_clks) { 218 pr_err("CLK %d is invalid\n", id); 219 return; 220 } 221 222 unit->clk_table[id] = clk; 223 } 224