162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/io.h> 362306a36Sopenharmony_ci#include <linux/clk-provider.h> 462306a36Sopenharmony_ci#include <linux/slab.h> 562306a36Sopenharmony_ci#include <linux/of.h> 662306a36Sopenharmony_ci#include <linux/of_address.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "clk.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_civoid mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, 1162306a36Sopenharmony_ci int nr_clks) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci struct clk **clk_table; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); 1662306a36Sopenharmony_ci if (!clk_table) 1762306a36Sopenharmony_ci return; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci unit->clk_table = clk_table; 2062306a36Sopenharmony_ci unit->nr_clks = nr_clks; 2162306a36Sopenharmony_ci unit->clk_data.clks = clk_table; 2262306a36Sopenharmony_ci unit->clk_data.clk_num = nr_clks; 2362306a36Sopenharmony_ci of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_civoid mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, 2762306a36Sopenharmony_ci struct mmp_param_fixed_rate_clk *clks, 2862306a36Sopenharmony_ci int size) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci int i; 3162306a36Sopenharmony_ci struct clk *clk; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci for (i = 0; i < size; i++) { 3462306a36Sopenharmony_ci clk = clk_register_fixed_rate(NULL, clks[i].name, 3562306a36Sopenharmony_ci clks[i].parent_name, 3662306a36Sopenharmony_ci clks[i].flags, 3762306a36Sopenharmony_ci clks[i].fixed_rate); 3862306a36Sopenharmony_ci if (IS_ERR(clk)) { 3962306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 4062306a36Sopenharmony_ci __func__, clks[i].name); 4162306a36Sopenharmony_ci continue; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci if (clks[i].id) 4462306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_civoid mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, 4962306a36Sopenharmony_ci struct mmp_param_fixed_factor_clk *clks, 5062306a36Sopenharmony_ci int size) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct clk *clk; 5362306a36Sopenharmony_ci int i; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci for (i = 0; i < size; i++) { 5662306a36Sopenharmony_ci clk = clk_register_fixed_factor(NULL, clks[i].name, 5762306a36Sopenharmony_ci clks[i].parent_name, 5862306a36Sopenharmony_ci clks[i].flags, clks[i].mult, 5962306a36Sopenharmony_ci clks[i].div); 6062306a36Sopenharmony_ci if (IS_ERR(clk)) { 6162306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 6262306a36Sopenharmony_ci __func__, clks[i].name); 6362306a36Sopenharmony_ci continue; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci if (clks[i].id) 6662306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_civoid mmp_register_general_gate_clks(struct mmp_clk_unit *unit, 7162306a36Sopenharmony_ci struct mmp_param_general_gate_clk *clks, 7262306a36Sopenharmony_ci void __iomem *base, int size) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct clk *clk; 7562306a36Sopenharmony_ci int i; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i = 0; i < size; i++) { 7862306a36Sopenharmony_ci clk = clk_register_gate(NULL, clks[i].name, 7962306a36Sopenharmony_ci clks[i].parent_name, 8062306a36Sopenharmony_ci clks[i].flags, 8162306a36Sopenharmony_ci base + clks[i].offset, 8262306a36Sopenharmony_ci clks[i].bit_idx, 8362306a36Sopenharmony_ci clks[i].gate_flags, 8462306a36Sopenharmony_ci clks[i].lock); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (IS_ERR(clk)) { 8762306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 8862306a36Sopenharmony_ci __func__, clks[i].name); 8962306a36Sopenharmony_ci continue; 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci if (clks[i].id) 9262306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_civoid mmp_register_gate_clks(struct mmp_clk_unit *unit, 9762306a36Sopenharmony_ci struct mmp_param_gate_clk *clks, 9862306a36Sopenharmony_ci void __iomem *base, int size) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct clk *clk; 10162306a36Sopenharmony_ci int i; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci for (i = 0; i < size; i++) { 10462306a36Sopenharmony_ci clk = mmp_clk_register_gate(NULL, clks[i].name, 10562306a36Sopenharmony_ci clks[i].parent_name, 10662306a36Sopenharmony_ci clks[i].flags, 10762306a36Sopenharmony_ci base + clks[i].offset, 10862306a36Sopenharmony_ci clks[i].mask, 10962306a36Sopenharmony_ci clks[i].val_enable, 11062306a36Sopenharmony_ci clks[i].val_disable, 11162306a36Sopenharmony_ci clks[i].gate_flags, 11262306a36Sopenharmony_ci clks[i].lock); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (IS_ERR(clk)) { 11562306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 11662306a36Sopenharmony_ci __func__, clks[i].name); 11762306a36Sopenharmony_ci continue; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci if (clks[i].id) 12062306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_civoid mmp_register_mux_clks(struct mmp_clk_unit *unit, 12562306a36Sopenharmony_ci struct mmp_param_mux_clk *clks, 12662306a36Sopenharmony_ci void __iomem *base, int size) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci struct clk *clk; 12962306a36Sopenharmony_ci int i; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci for (i = 0; i < size; i++) { 13262306a36Sopenharmony_ci clk = clk_register_mux(NULL, clks[i].name, 13362306a36Sopenharmony_ci clks[i].parent_name, 13462306a36Sopenharmony_ci clks[i].num_parents, 13562306a36Sopenharmony_ci clks[i].flags, 13662306a36Sopenharmony_ci base + clks[i].offset, 13762306a36Sopenharmony_ci clks[i].shift, 13862306a36Sopenharmony_ci clks[i].width, 13962306a36Sopenharmony_ci clks[i].mux_flags, 14062306a36Sopenharmony_ci clks[i].lock); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (IS_ERR(clk)) { 14362306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 14462306a36Sopenharmony_ci __func__, clks[i].name); 14562306a36Sopenharmony_ci continue; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci if (clks[i].id) 14862306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_civoid mmp_register_div_clks(struct mmp_clk_unit *unit, 15362306a36Sopenharmony_ci struct mmp_param_div_clk *clks, 15462306a36Sopenharmony_ci void __iomem *base, int size) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct clk *clk; 15762306a36Sopenharmony_ci int i; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (i = 0; i < size; i++) { 16062306a36Sopenharmony_ci clk = clk_register_divider(NULL, clks[i].name, 16162306a36Sopenharmony_ci clks[i].parent_name, 16262306a36Sopenharmony_ci clks[i].flags, 16362306a36Sopenharmony_ci base + clks[i].offset, 16462306a36Sopenharmony_ci clks[i].shift, 16562306a36Sopenharmony_ci clks[i].width, 16662306a36Sopenharmony_ci clks[i].div_flags, 16762306a36Sopenharmony_ci clks[i].lock); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (IS_ERR(clk)) { 17062306a36Sopenharmony_ci pr_err("%s: failed to register clock %s\n", 17162306a36Sopenharmony_ci __func__, clks[i].name); 17262306a36Sopenharmony_ci continue; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci if (clks[i].id) 17562306a36Sopenharmony_ci unit->clk_table[clks[i].id] = clk; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_civoid mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, 18062306a36Sopenharmony_ci struct clk *clk) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci if (IS_ERR_OR_NULL(clk)) { 18362306a36Sopenharmony_ci pr_err("CLK %d has invalid pointer %p\n", id, clk); 18462306a36Sopenharmony_ci return; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci if (id >= unit->nr_clks) { 18762306a36Sopenharmony_ci pr_err("CLK %d is invalid\n", id); 18862306a36Sopenharmony_ci return; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci unit->clk_table[id] = clk; 19262306a36Sopenharmony_ci} 193