summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/mvebu/common.h
blob: 079a47679e0f188e1914b639b7366df83d2f8065 (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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Marvell MVEBU pinctrl driver
 *
 * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 *          Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
 */

#ifndef __PINCTRL_MVEBU_H__
#define __PINCTRL_MVEBU_H__

#include <io.h>

/**
 * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting
 * @val: ctrl setting value
 * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode
 * @subname: (optional) additional ctrl setting name, e.g. rts, cts
 * @variant: (optional) variant identifier mask
 * @flags: (private) flags to store gpi/gpo/gpio capabilities
 *
 * A ctrl_setting describes a specific internal mux function that a mpp pin
 * can be switched to. The value (val) will be written in the corresponding
 * register for common mpp pin configuration registers on MVEBU. SoC specific
 * mpp_get/_set function may use val to distinguish between different settings.
 *
 * The name will be used to switch to this setting in DT description, e.g.
 * marvell,function = "uart2". subname is only for debugging purposes.
 *
 * If name is one of "gpi", "gpo", "gpio" gpio capabilities are
 * parsed during initialization and stored in flags.
 *
 * The variant can be used to combine different revisions of one SoC to a
 * common pinctrl driver. It is matched (AND) with variant of soc_info to
 * determine if a setting is available on the current SoC revision.
 */
struct mvebu_mpp_ctrl_setting {
	u8 val;
	const char *name;
	const char *subname;
	u8 variant;
	u8 flags;
#define  MVEBU_SETTING_GPO	(1 << 0)
#define  MVEBU_SETTING_GPI	(1 << 1)
};

/**
 * struct mvebu_mpp_mode - link ctrl and settings
 * @pid: first pin id handled by this mode
 * @name: name of the mpp group
 * @mpp_get: function to get mpp setting
 * @mpp_set: function to set mpp setting
 * @settings: list of settings available for this mode
 *
 * A mode connects all available settings with the corresponding mpp_ctrl
 * given by pid.
 */
struct mvebu_mpp_mode {
	u8 pid;
	const char *name;
	int (*mpp_get)(unsigned pid, unsigned long *config);
	int (*mpp_set)(unsigned pid, unsigned long config);
	struct mvebu_mpp_ctrl_setting *settings;
};

/**
 * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
 * @variant: variant mask of soc_info
 * @controls: list of available mvebu_mpp_ctrls
 * @ncontrols: number of available mvebu_mpp_ctrls
 * @modes: list of available mvebu_mpp_modes
 * @nmodes: number of available mvebu_mpp_modes
 * @gpioranges: list of pinctrl_gpio_ranges
 * @ngpioranges: number of available pinctrl_gpio_ranges
 *
 * This struct describes all pinctrl related information for a specific SoC.
 * If variant is unequal 0 it will be matched (AND) with variant of each
 * setting and allows to distinguish between different revisions of one SoC.
 */
struct mvebu_pinctrl_soc_info {
	u8 variant;
	struct mvebu_mpp_mode *modes;
	int nmodes;
};

#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
	{							\
		.val = _val,					\
		.name = _name,					\
		.subname = _subname,				\
		.variant = _mask,				\
		.flags = 0,					\
	}

#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
	_MPP_VAR_FUNCTION(_val, _name, _subname, _mask)

#define MPP_FUNCTION(_val, _name, _subname)			\
	MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1)

#define MPP_MODE(_id, _name, _func, ...)			\
	{							\
		.pid = _id,					\
		.name = _name,					\
		.mpp_get = _func ## _get,			\
		.mpp_set = _func ## _set,			\
		.settings = (struct mvebu_mpp_ctrl_setting[]){	\
			__VA_ARGS__, { } },			\
	}

#define MVEBU_MPPS_PER_REG	8
#define MVEBU_MPP_BITS		4
#define MVEBU_MPP_MASK		0xf

static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
				       unsigned long *config)
{
	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;

	*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;

	return 0;
}

static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
				       unsigned long config)
{
	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
	unsigned long reg;

	reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
	writel(reg | (config << shift), base + off);

	return 0;
}

int mvebu_pinctrl_probe(struct device_d *dev,
			struct mvebu_pinctrl_soc_info *soc);

#endif