xref: /openbmc/linux/drivers/clk/at91/clk-slow.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
280eded6cSBoris BREZILLON /*
380eded6cSBoris BREZILLON  * drivers/clk/at91/clk-slow.c
480eded6cSBoris BREZILLON  *
580eded6cSBoris BREZILLON  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
680eded6cSBoris BREZILLON  */
780eded6cSBoris BREZILLON 
880eded6cSBoris BREZILLON #include <linux/clk-provider.h>
980eded6cSBoris BREZILLON #include <linux/clkdev.h>
1080eded6cSBoris BREZILLON #include <linux/clk/at91_pmc.h>
1180eded6cSBoris BREZILLON #include <linux/of.h>
121bdf0232SBoris Brezillon #include <linux/mfd/syscon.h>
131bdf0232SBoris Brezillon #include <linux/regmap.h>
1480eded6cSBoris BREZILLON 
1580eded6cSBoris BREZILLON #include "pmc.h"
1680eded6cSBoris BREZILLON 
1780eded6cSBoris BREZILLON struct clk_sam9260_slow {
1880eded6cSBoris BREZILLON 	struct clk_hw hw;
191bdf0232SBoris Brezillon 	struct regmap *regmap;
2080eded6cSBoris BREZILLON };
2180eded6cSBoris BREZILLON 
2280eded6cSBoris BREZILLON #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
2380eded6cSBoris BREZILLON 
clk_sam9260_slow_get_parent(struct clk_hw * hw)2480eded6cSBoris BREZILLON static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
2580eded6cSBoris BREZILLON {
2680eded6cSBoris BREZILLON 	struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
271bdf0232SBoris Brezillon 	unsigned int status;
2880eded6cSBoris BREZILLON 
291bdf0232SBoris Brezillon 	regmap_read(slowck->regmap, AT91_PMC_SR, &status);
301bdf0232SBoris Brezillon 
311bdf0232SBoris Brezillon 	return status & AT91_PMC_OSCSEL ? 1 : 0;
3280eded6cSBoris BREZILLON }
3380eded6cSBoris BREZILLON 
3480eded6cSBoris BREZILLON static const struct clk_ops sam9260_slow_ops = {
3580eded6cSBoris BREZILLON 	.get_parent = clk_sam9260_slow_get_parent,
3680eded6cSBoris BREZILLON };
3780eded6cSBoris BREZILLON 
38b2e39dc0SAlexandre Belloni struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap * regmap,const char * name,const char ** parent_names,int num_parents)391bdf0232SBoris Brezillon at91_clk_register_sam9260_slow(struct regmap *regmap,
4080eded6cSBoris BREZILLON 			       const char *name,
4180eded6cSBoris BREZILLON 			       const char **parent_names,
4280eded6cSBoris BREZILLON 			       int num_parents)
4380eded6cSBoris BREZILLON {
4480eded6cSBoris BREZILLON 	struct clk_sam9260_slow *slowck;
45f5644f10SStephen Boyd 	struct clk_hw *hw;
4680eded6cSBoris BREZILLON 	struct clk_init_data init;
47f5644f10SStephen Boyd 	int ret;
4880eded6cSBoris BREZILLON 
491bdf0232SBoris Brezillon 	if (!name)
5080eded6cSBoris BREZILLON 		return ERR_PTR(-EINVAL);
5180eded6cSBoris BREZILLON 
5280eded6cSBoris BREZILLON 	if (!parent_names || !num_parents)
5380eded6cSBoris BREZILLON 		return ERR_PTR(-EINVAL);
5480eded6cSBoris BREZILLON 
5580eded6cSBoris BREZILLON 	slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
5680eded6cSBoris BREZILLON 	if (!slowck)
5780eded6cSBoris BREZILLON 		return ERR_PTR(-ENOMEM);
5880eded6cSBoris BREZILLON 
5980eded6cSBoris BREZILLON 	init.name = name;
6080eded6cSBoris BREZILLON 	init.ops = &sam9260_slow_ops;
6180eded6cSBoris BREZILLON 	init.parent_names = parent_names;
6280eded6cSBoris BREZILLON 	init.num_parents = num_parents;
6380eded6cSBoris BREZILLON 	init.flags = 0;
6480eded6cSBoris BREZILLON 
6580eded6cSBoris BREZILLON 	slowck->hw.init = &init;
661bdf0232SBoris Brezillon 	slowck->regmap = regmap;
6780eded6cSBoris BREZILLON 
68f5644f10SStephen Boyd 	hw = &slowck->hw;
69f5644f10SStephen Boyd 	ret = clk_hw_register(NULL, &slowck->hw);
70f5644f10SStephen Boyd 	if (ret) {
7180eded6cSBoris BREZILLON 		kfree(slowck);
72f5644f10SStephen Boyd 		hw = ERR_PTR(ret);
73f5644f10SStephen Boyd 	}
7480eded6cSBoris BREZILLON 
75f5644f10SStephen Boyd 	return hw;
7680eded6cSBoris BREZILLON }
77