summaryrefslogtreecommitdiff
path: root/include/linux/clk-provider.h
blob: 02ff1a311aca58a0988ecb1af449ed5e5b12261b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2019 DENX Software Engineering
 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
 *
 * Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
 * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
 */
#ifndef __LINUX_CLK_PROVIDER_H
#define __LINUX_CLK_PROVIDER_H
#include <clk-uclass.h>

static inline void clk_dm(ulong id, struct clk *clk)
{
	if (!IS_ERR(clk))
		clk->id = id;
}

/*
 * flags used across common struct clk.  these flags should only affect the
 * top-level framework.  custom flags for dealing with hardware specifics
 * belong in struct clk_foo
 *
 * Please update clk_flags[] in drivers/clk/clk.c when making changes here!
 */
#define CLK_SET_RATE_GATE	BIT(0) /* must be gated across rate change */
#define CLK_SET_PARENT_GATE	BIT(1) /* must be gated across re-parent */
#define CLK_SET_RATE_PARENT	BIT(2) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED	BIT(3) /* do not gate even if unused */
				/* unused */
#define CLK_IS_BASIC		BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE	BIT(6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
#define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after notifications */
#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run to set rate */
#define CLK_IS_CRITICAL		BIT(11) /* do not gate, ever */
/* parents need enable during gate/ungate, set rate and re-parent */
#define CLK_OPS_PARENT_ENABLE	BIT(12)
/* duty cycle call may be forwarded to the parent clock */
#define CLK_DUTY_CYCLE_PARENT	BIT(13)

#define CLK_MUX_INDEX_ONE		BIT(0)
#define CLK_MUX_INDEX_BIT		BIT(1)
#define CLK_MUX_HIWORD_MASK		BIT(2)
#define CLK_MUX_READ_ONLY		BIT(3) /* mux can't be changed */
#define CLK_MUX_ROUND_CLOSEST		BIT(4)

struct clk_mux {
	struct clk	clk;
	void __iomem	*reg;
	u32		*table;
	u32		mask;
	u8		shift;
	u8		flags;

	/*
	 * Fields from struct clk_init_data - this struct has been
	 * omitted to avoid too deep level of CCF for bootloader
	 */
	const char	* const *parent_names;
	u8		num_parents;
#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
	u32             io_mux_val;
#endif

};

#define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk)
extern const struct clk_ops clk_mux_ops;
u8 clk_mux_get_parent(struct clk *clk);

struct clk_gate {
	struct clk	clk;
	void __iomem	*reg;
	u8		bit_idx;
	u8		flags;
#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
	u32		io_gate_val;
#endif
};

#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk)

#define CLK_GATE_SET_TO_DISABLE		BIT(0)
#define CLK_GATE_HIWORD_MASK		BIT(1)

extern const struct clk_ops clk_gate_ops;
struct clk *clk_register_gate(struct device *dev, const char *name,
			      const char *parent_name, unsigned long flags,
			      void __iomem *reg, u8 bit_idx,
			      u8 clk_gate_flags, spinlock_t *lock);

struct clk_div_table {
	unsigned int	val;
	unsigned int	div;
};

struct clk_divider {
	struct clk	clk;
	void __iomem	*reg;
	u8		shift;
	u8		width;
	u8		flags;
	const struct clk_div_table	*table;
#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
	u32             io_divider_val;
#endif
};

#define clk_div_mask(width)	((1 << (width)) - 1)
#define to_clk_divider(_clk) container_of(_clk, struct clk_divider, clk)

#define CLK_DIVIDER_ONE_BASED		BIT(0)
#define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
#define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
#define CLK_DIVIDER_HIWORD_MASK		BIT(3)
#define CLK_DIVIDER_ROUND_CLOSEST	BIT(4)
#define CLK_DIVIDER_READ_ONLY		BIT(5)
#define CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
extern const struct clk_ops clk_divider_ops;
unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate,
				  unsigned int val,
				  const struct clk_div_table *table,
				  unsigned long flags, unsigned long width);

struct clk_fixed_factor {
	struct clk	clk;
	unsigned int	mult;
	unsigned int	div;
};

#define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\
					       clk)

struct clk_fixed_rate {
	struct clk clk;
	unsigned long fixed_rate;
};

#define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_platdata(dev))

struct clk_composite {
	struct clk	clk;
	struct clk_ops	ops;

	struct clk	*mux;
	struct clk	*rate;
	struct clk	*gate;

	const struct clk_ops	*mux_ops;
	const struct clk_ops	*rate_ops;
	const struct clk_ops	*gate_ops;
};

#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk)

struct clk *clk_register_composite(struct device *dev, const char *name,
		const char * const *parent_names, int num_parents,
		struct clk *mux_clk, const struct clk_ops *mux_ops,
		struct clk *rate_clk, const struct clk_ops *rate_ops,
		struct clk *gate_clk, const struct clk_ops *gate_ops,
		unsigned long flags);

int clk_register(struct clk *clk, const char *drv_name, const char *name,
		 const char *parent_name);

struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		unsigned int mult, unsigned int div);

struct clk *clk_register_divider(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width,
		u8 clk_divider_flags);

struct clk *clk_register_mux(struct device *dev, const char *name,
		const char * const *parent_names, u8 num_parents,
		unsigned long flags,
		void __iomem *reg, u8 shift, u8 width,
		u8 clk_mux_flags);

const char *clk_hw_get_name(const struct clk *hw);
ulong clk_generic_get_rate(struct clk *clk);

static inline struct clk *dev_get_clk_ptr(struct udevice *dev)
{
	return (struct clk *)dev_get_uclass_priv(dev);
}
#endif /* __LINUX_CLK_PROVIDER_H */