Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0+
2//
3// OWL divider clock driver
4//
5// Copyright (c) 2014 Actions Semi Inc.
6// Author: David Liu <liuwei@actions-semi.com>
7//
8// Copyright (c) 2018 Linaro Ltd.
9// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
10
11#include <linux/clk-provider.h>
12#include <linux/regmap.h>
13
14#include "owl-divider.h"
15
16static int owl_divider_determine_rate(struct clk_hw *hw,
17 struct clk_rate_request *req)
18{
19 struct owl_divider *div = hw_to_owl_divider(hw);
20
21 return divider_determine_rate(hw, req, div->div_hw.table,
22 div->div_hw.width, div->div_hw.div_flags);
23}
24
25unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
26 const struct owl_divider_hw *div_hw,
27 unsigned long parent_rate)
28{
29 unsigned long val;
30 unsigned int reg;
31
32 regmap_read(common->regmap, div_hw->reg, ®);
33 val = reg >> div_hw->shift;
34 val &= (1 << div_hw->width) - 1;
35
36 return divider_recalc_rate(&common->hw, parent_rate,
37 val, div_hw->table,
38 div_hw->div_flags,
39 div_hw->width);
40}
41
42static unsigned long owl_divider_recalc_rate(struct clk_hw *hw,
43 unsigned long parent_rate)
44{
45 struct owl_divider *div = hw_to_owl_divider(hw);
46
47 return owl_divider_helper_recalc_rate(&div->common,
48 &div->div_hw, parent_rate);
49}
50
51int owl_divider_helper_set_rate(const struct owl_clk_common *common,
52 const struct owl_divider_hw *div_hw,
53 unsigned long rate,
54 unsigned long parent_rate)
55{
56 unsigned long val;
57 unsigned int reg;
58
59 val = divider_get_val(rate, parent_rate, div_hw->table,
60 div_hw->width, 0);
61
62 regmap_read(common->regmap, div_hw->reg, ®);
63 reg &= ~GENMASK(div_hw->width + div_hw->shift - 1, div_hw->shift);
64
65 regmap_write(common->regmap, div_hw->reg,
66 reg | (val << div_hw->shift));
67
68 return 0;
69}
70
71static int owl_divider_set_rate(struct clk_hw *hw, unsigned long rate,
72 unsigned long parent_rate)
73{
74 struct owl_divider *div = hw_to_owl_divider(hw);
75
76 return owl_divider_helper_set_rate(&div->common, &div->div_hw,
77 rate, parent_rate);
78}
79
80const struct clk_ops owl_divider_ops = {
81 .recalc_rate = owl_divider_recalc_rate,
82 .determine_rate = owl_divider_determine_rate,
83 .set_rate = owl_divider_set_rate,
84};