summaryrefslogtreecommitdiff
path: root/drivers/clk/meson/meson-clkc-utils.h
blob: ddadf14b4923781d8807546f35a1ba2e6a8a894a (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
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
 * Copyright (c) 2023 Neil Armstrong <neil.armstrong@linaro.org>
 */

#ifndef __MESON_CLKC_UTILS_H__
#define __MESON_CLKC_UTILS_H__

#include <linux/of_device.h>
#include <linux/clk-provider.h>

struct platform_device;

struct meson_clk_hw_data {
	struct clk_hw	**hws;
	unsigned int	num;
};

struct clk_hw *meson_clk_hw_get(struct of_phandle_args *clkspec, void *clk_hw_data);

struct meson_clkc_data {
	const struct reg_sequence	*init_regs;
	unsigned int			init_count;
	struct meson_clk_hw_data	hw_clks;
};

int meson_clkc_syscon_probe(struct platform_device *pdev);
int meson_clkc_mmio_probe(struct platform_device *pdev);

#define __MESON_PCLK(_name, _reg, _bit, _ops, _pdata, _flags)		\
struct clk_regmap _name = {						\
	.data = &(struct clk_regmap_gate_data) {			\
		.offset = (_reg),					\
		.bit_idx = (_bit),					\
	},								\
	.hw.init = &(struct clk_init_data) {				\
		.name = #_name,						\
		.ops = _ops,						\
		.parent_data = (_pdata),				\
		.num_parents = 1,					\
		.flags = (_flags),					\
	},								\
}

#define MESON_PCLK(_name, _reg, _bit, _pdata, _flags)			\
	__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pdata, _flags)

#define MESON_PCLK_RO(_name, _reg, _bit, _pdata, _flags)		\
	__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pdata, _flags)

/* Helpers for the usual sel/div/gate composite clocks */
#define MESON_COMP_SEL(_prefix, _name, _reg, _shift, _mask, _pdata,	\
		       _table, _dflags, _iflags)			\
struct clk_regmap _prefix##_name##_sel = {				\
	.data = &(struct clk_regmap_mux_data) {				\
		.offset = (_reg),					\
		.mask = (_mask),					\
		.shift = (_shift),					\
		.flags = (_dflags),					\
		.table = (_table),					\
	},								\
	.hw.init = &(struct clk_init_data){				\
		.name = #_name "_sel",					\
		.ops = &clk_regmap_mux_ops,				\
		.parent_data = _pdata,					\
		.num_parents = ARRAY_SIZE(_pdata),			\
		.flags = (_iflags),					\
	},								\
}

#define MESON_COMP_DIV(_prefix, _name, _reg, _shift, _width,		\
		       _dflags, _iflags)				\
struct clk_regmap _prefix##_name##_div = {				\
	.data = &(struct clk_regmap_div_data) {				\
		.offset = (_reg),					\
		.shift = (_shift),					\
		.width = (_width),					\
		.flags = (_dflags),					\
	},								\
	.hw.init = &(struct clk_init_data) {				\
		.name = #_name "_div",					\
		.ops = &clk_regmap_divider_ops,				\
		.parent_hws = (const struct clk_hw *[]) {		\
			&_prefix##_name##_sel.hw			\
		},							\
		.num_parents = 1,					\
		.flags = (_iflags),					\
	},								\
}

#define MESON_COMP_GATE(_prefix, _name, _reg, _bit, _iflags)		\
struct clk_regmap _prefix##_name = {					\
	.data = &(struct clk_regmap_gate_data) {			\
		.offset = (_reg),					\
		.bit_idx = (_bit),					\
	},								\
	.hw.init = &(struct clk_init_data) {				\
		.name = #_name,						\
		.ops = &clk_regmap_gate_ops,				\
		.parent_hws = (const struct clk_hw *[]) {		\
			&_prefix##_name##_div.hw			\
		},							\
		.num_parents = 1,					\
		.flags = (_iflags),					\
	},								\
}

#endif