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_clk_add(struct mmp_clk_unit *unit, unsigned int id, 180 struct clk *clk) 181 { 182 if (IS_ERR_OR_NULL(clk)) { 183 pr_err("CLK %d has invalid pointer %p\n", id, clk); 184 return; 185 } 186 if (id >= unit->nr_clks) { 187 pr_err("CLK %d is invalid\n", id); 188 return; 189 } 190 191 unit->clk_table[id] = clk; 192 } 193