xref: /openbmc/linux/drivers/clk/mmp/clk.c (revision 742b50f9)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
24661fda1SChao Xie #include <linux/io.h>
34661fda1SChao Xie #include <linux/clk-provider.h>
4528b7697SStephen Boyd #include <linux/slab.h>
54661fda1SChao Xie #include <linux/of.h>
64661fda1SChao Xie #include <linux/of_address.h>
74661fda1SChao Xie 
84661fda1SChao Xie #include "clk.h"
94661fda1SChao Xie 
mmp_clk_init(struct device_node * np,struct mmp_clk_unit * unit,int nr_clks)104661fda1SChao Xie void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
114661fda1SChao Xie 		int nr_clks)
124661fda1SChao Xie {
134aafe9c6SJulia Lawall 	struct clk **clk_table;
144661fda1SChao Xie 
154661fda1SChao Xie 	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
164661fda1SChao Xie 	if (!clk_table)
174661fda1SChao Xie 		return;
184661fda1SChao Xie 
194661fda1SChao Xie 	unit->clk_table = clk_table;
204661fda1SChao Xie 	unit->nr_clks = nr_clks;
214661fda1SChao Xie 	unit->clk_data.clks = clk_table;
224661fda1SChao Xie 	unit->clk_data.clk_num = nr_clks;
234661fda1SChao Xie 	of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
244661fda1SChao Xie }
254661fda1SChao Xie 
mmp_register_fixed_rate_clks(struct mmp_clk_unit * unit,struct mmp_param_fixed_rate_clk * clks,int size)264661fda1SChao Xie void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
274661fda1SChao Xie 				struct mmp_param_fixed_rate_clk *clks,
284661fda1SChao Xie 				int size)
294661fda1SChao Xie {
304661fda1SChao Xie 	int i;
314661fda1SChao Xie 	struct clk *clk;
324661fda1SChao Xie 
334661fda1SChao Xie 	for (i = 0; i < size; i++) {
344661fda1SChao Xie 		clk = clk_register_fixed_rate(NULL, clks[i].name,
354661fda1SChao Xie 					clks[i].parent_name,
364661fda1SChao Xie 					clks[i].flags,
374661fda1SChao Xie 					clks[i].fixed_rate);
384661fda1SChao Xie 		if (IS_ERR(clk)) {
394661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
404661fda1SChao Xie 			       __func__, clks[i].name);
414661fda1SChao Xie 			continue;
424661fda1SChao Xie 		}
434661fda1SChao Xie 		if (clks[i].id)
444661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
454661fda1SChao Xie 	}
464661fda1SChao Xie }
474661fda1SChao Xie 
mmp_register_fixed_factor_clks(struct mmp_clk_unit * unit,struct mmp_param_fixed_factor_clk * clks,int size)484661fda1SChao Xie void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
494661fda1SChao Xie 				struct mmp_param_fixed_factor_clk *clks,
504661fda1SChao Xie 				int size)
514661fda1SChao Xie {
524661fda1SChao Xie 	struct clk *clk;
534661fda1SChao Xie 	int i;
544661fda1SChao Xie 
554661fda1SChao Xie 	for (i = 0; i < size; i++) {
564661fda1SChao Xie 		clk = clk_register_fixed_factor(NULL, clks[i].name,
574661fda1SChao Xie 						clks[i].parent_name,
584661fda1SChao Xie 						clks[i].flags, clks[i].mult,
594661fda1SChao Xie 						clks[i].div);
604661fda1SChao Xie 		if (IS_ERR(clk)) {
614661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
624661fda1SChao Xie 			       __func__, clks[i].name);
634661fda1SChao Xie 			continue;
644661fda1SChao Xie 		}
654661fda1SChao Xie 		if (clks[i].id)
664661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
674661fda1SChao Xie 	}
684661fda1SChao Xie }
694661fda1SChao Xie 
mmp_register_general_gate_clks(struct mmp_clk_unit * unit,struct mmp_param_general_gate_clk * clks,void __iomem * base,int size)704661fda1SChao Xie void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
714661fda1SChao Xie 				struct mmp_param_general_gate_clk *clks,
724661fda1SChao Xie 				void __iomem *base, int size)
734661fda1SChao Xie {
744661fda1SChao Xie 	struct clk *clk;
754661fda1SChao Xie 	int i;
764661fda1SChao Xie 
774661fda1SChao Xie 	for (i = 0; i < size; i++) {
784661fda1SChao Xie 		clk = clk_register_gate(NULL, clks[i].name,
794661fda1SChao Xie 					clks[i].parent_name,
804661fda1SChao Xie 					clks[i].flags,
814661fda1SChao Xie 					base + clks[i].offset,
824661fda1SChao Xie 					clks[i].bit_idx,
834661fda1SChao Xie 					clks[i].gate_flags,
844661fda1SChao Xie 					clks[i].lock);
854661fda1SChao Xie 
864661fda1SChao Xie 		if (IS_ERR(clk)) {
874661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
884661fda1SChao Xie 			       __func__, clks[i].name);
894661fda1SChao Xie 			continue;
904661fda1SChao Xie 		}
914661fda1SChao Xie 		if (clks[i].id)
924661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
934661fda1SChao Xie 	}
944661fda1SChao Xie }
954661fda1SChao Xie 
mmp_register_gate_clks(struct mmp_clk_unit * unit,struct mmp_param_gate_clk * clks,void __iomem * base,int size)964661fda1SChao Xie void mmp_register_gate_clks(struct mmp_clk_unit *unit,
974661fda1SChao Xie 			struct mmp_param_gate_clk *clks,
984661fda1SChao Xie 			void __iomem *base, int size)
994661fda1SChao Xie {
1004661fda1SChao Xie 	struct clk *clk;
1014661fda1SChao Xie 	int i;
1024661fda1SChao Xie 
1034661fda1SChao Xie 	for (i = 0; i < size; i++) {
1044661fda1SChao Xie 		clk = mmp_clk_register_gate(NULL, clks[i].name,
1054661fda1SChao Xie 					clks[i].parent_name,
1064661fda1SChao Xie 					clks[i].flags,
1074661fda1SChao Xie 					base + clks[i].offset,
1084661fda1SChao Xie 					clks[i].mask,
1094661fda1SChao Xie 					clks[i].val_enable,
1104661fda1SChao Xie 					clks[i].val_disable,
1114661fda1SChao Xie 					clks[i].gate_flags,
1124661fda1SChao Xie 					clks[i].lock);
1134661fda1SChao Xie 
1144661fda1SChao Xie 		if (IS_ERR(clk)) {
1154661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
1164661fda1SChao Xie 			       __func__, clks[i].name);
1174661fda1SChao Xie 			continue;
1184661fda1SChao Xie 		}
1194661fda1SChao Xie 		if (clks[i].id)
1204661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
1214661fda1SChao Xie 	}
1224661fda1SChao Xie }
1234661fda1SChao Xie 
mmp_register_mux_clks(struct mmp_clk_unit * unit,struct mmp_param_mux_clk * clks,void __iomem * base,int size)1244661fda1SChao Xie void mmp_register_mux_clks(struct mmp_clk_unit *unit,
1254661fda1SChao Xie 			struct mmp_param_mux_clk *clks,
1264661fda1SChao Xie 			void __iomem *base, int size)
1274661fda1SChao Xie {
1284661fda1SChao Xie 	struct clk *clk;
1294661fda1SChao Xie 	int i;
1304661fda1SChao Xie 
1314661fda1SChao Xie 	for (i = 0; i < size; i++) {
1324661fda1SChao Xie 		clk = clk_register_mux(NULL, clks[i].name,
1334661fda1SChao Xie 					clks[i].parent_name,
1344661fda1SChao Xie 					clks[i].num_parents,
1354661fda1SChao Xie 					clks[i].flags,
1364661fda1SChao Xie 					base + clks[i].offset,
1374661fda1SChao Xie 					clks[i].shift,
1384661fda1SChao Xie 					clks[i].width,
1394661fda1SChao Xie 					clks[i].mux_flags,
1404661fda1SChao Xie 					clks[i].lock);
1414661fda1SChao Xie 
1424661fda1SChao Xie 		if (IS_ERR(clk)) {
1434661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
1444661fda1SChao Xie 			       __func__, clks[i].name);
1454661fda1SChao Xie 			continue;
1464661fda1SChao Xie 		}
1474661fda1SChao Xie 		if (clks[i].id)
1484661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
1494661fda1SChao Xie 	}
1504661fda1SChao Xie }
1514661fda1SChao Xie 
mmp_register_div_clks(struct mmp_clk_unit * unit,struct mmp_param_div_clk * clks,void __iomem * base,int size)1524661fda1SChao Xie void mmp_register_div_clks(struct mmp_clk_unit *unit,
1534661fda1SChao Xie 			struct mmp_param_div_clk *clks,
1544661fda1SChao Xie 			void __iomem *base, int size)
1554661fda1SChao Xie {
1564661fda1SChao Xie 	struct clk *clk;
1574661fda1SChao Xie 	int i;
1584661fda1SChao Xie 
1594661fda1SChao Xie 	for (i = 0; i < size; i++) {
1604661fda1SChao Xie 		clk = clk_register_divider(NULL, clks[i].name,
1614661fda1SChao Xie 					clks[i].parent_name,
1624661fda1SChao Xie 					clks[i].flags,
1634661fda1SChao Xie 					base + clks[i].offset,
1644661fda1SChao Xie 					clks[i].shift,
1654661fda1SChao Xie 					clks[i].width,
1664661fda1SChao Xie 					clks[i].div_flags,
1674661fda1SChao Xie 					clks[i].lock);
1684661fda1SChao Xie 
1694661fda1SChao Xie 		if (IS_ERR(clk)) {
1704661fda1SChao Xie 			pr_err("%s: failed to register clock %s\n",
1714661fda1SChao Xie 			       __func__, clks[i].name);
1724661fda1SChao Xie 			continue;
1734661fda1SChao Xie 		}
1744661fda1SChao Xie 		if (clks[i].id)
1754661fda1SChao Xie 			unit->clk_table[clks[i].id] = clk;
1764661fda1SChao Xie 	}
1774661fda1SChao Xie }
1784661fda1SChao Xie 
mmp_clk_add(struct mmp_clk_unit * unit,unsigned int id,struct clk * clk)1794661fda1SChao Xie void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
1804661fda1SChao Xie 			struct clk *clk)
1814661fda1SChao Xie {
1824661fda1SChao Xie 	if (IS_ERR_OR_NULL(clk)) {
1834661fda1SChao Xie 		pr_err("CLK %d has invalid pointer %p\n", id, clk);
1844661fda1SChao Xie 		return;
1854661fda1SChao Xie 	}
1862e85c574SDan Carpenter 	if (id >= unit->nr_clks) {
1874661fda1SChao Xie 		pr_err("CLK %d is invalid\n", id);
1884661fda1SChao Xie 		return;
1894661fda1SChao Xie 	}
1904661fda1SChao Xie 
1914661fda1SChao Xie 	unit->clk_table[id] = clk;
1924661fda1SChao Xie }
193