Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
 1// SPDX-License-Identifier: GPL-2.0
 2//
 3// Spreadtrum divider clock driver
 4//
 5// Copyright (C) 2017 Spreadtrum, Inc.
 6// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
 7
 8#include <linux/clk-provider.h>
 9
10#include "div.h"
11
12long sprd_div_helper_round_rate(struct sprd_clk_common *common,
13				const struct sprd_div_internal *div,
14				unsigned long rate,
15				unsigned long *parent_rate)
16{
17	return divider_round_rate(&common->hw, rate, parent_rate,
18				  NULL, div->width, 0);
19}
20EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
21
22static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
23				unsigned long *parent_rate)
24{
25	struct sprd_div *cd = hw_to_sprd_div(hw);
26
27	return sprd_div_helper_round_rate(&cd->common, &cd->div,
28					  rate, parent_rate);
29}
30
31unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
32					  const struct sprd_div_internal *div,
33					  unsigned long parent_rate)
34{
35	unsigned long val;
36	unsigned int reg;
37
38	regmap_read(common->regmap, common->reg, &reg);
39	val = reg >> div->shift;
40	val &= (1 << div->width) - 1;
41
42	return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0,
43				   div->width);
44}
45EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
46
47static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
48					  unsigned long parent_rate)
49{
50	struct sprd_div *cd = hw_to_sprd_div(hw);
51
52	return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
53}
54
55int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
56			     const struct sprd_div_internal *div,
57			     unsigned long rate,
58			     unsigned long parent_rate)
59{
60	unsigned long val;
61	unsigned int reg;
62
63	val = divider_get_val(rate, parent_rate, NULL,
64			      div->width, 0);
65
66	regmap_read(common->regmap, common->reg, &reg);
67	reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
68
69	regmap_write(common->regmap, common->reg,
70			  reg | (val << div->shift));
71
72	return 0;
73
74}
75EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
76
77static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
78			     unsigned long parent_rate)
79{
80	struct sprd_div *cd = hw_to_sprd_div(hw);
81
82	return sprd_div_helper_set_rate(&cd->common, &cd->div,
83					rate, parent_rate);
84}
85
86const struct clk_ops sprd_div_ops = {
87	.recalc_rate = sprd_div_recalc_rate,
88	.round_rate = sprd_div_round_rate,
89	.set_rate = sprd_div_set_rate,
90};
91EXPORT_SYMBOL_GPL(sprd_div_ops);