summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-mlxbf3.c
blob: ffb5dda364dc81808cfd5a168ce3f1e9f119357d (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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/types.h>

#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>

#define MLXBF3_NGPIOS_GPIO0    32
#define MLXBF3_MAX_GPIO_PINS   56

enum {
	MLXBF3_GPIO_HW_MODE,
	MLXBF3_GPIO_SW_MODE,
};

struct mlxbf3_pinctrl {
	void __iomem *fw_ctrl_set0;
	void __iomem *fw_ctrl_clr0;
	void __iomem *fw_ctrl_set1;
	void __iomem *fw_ctrl_clr1;
	struct device *dev;
	struct pinctrl_dev *pctl;
	struct pinctrl_gpio_range gpio_range;
};

#define MLXBF3_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins)	\
	{							\
		.name = "mlxbf3_gpio_range",			\
		.id = _id,					\
		.base = _gpiobase,				\
		.pin_base = _pinbase,				\
		.npins = _npins,				\
	}

static struct pinctrl_gpio_range mlxbf3_pinctrl_gpio_ranges[] = {
	MLXBF3_GPIO_RANGE(0, 0,  480, 32),
	MLXBF3_GPIO_RANGE(1,  32, 456, 24),
};

static const struct pinctrl_pin_desc mlxbf3_pins[] = {
	PINCTRL_PIN(0, "gpio0"),
	PINCTRL_PIN(1, "gpio1"),
	PINCTRL_PIN(2, "gpio2"),
	PINCTRL_PIN(3, "gpio3"),
	PINCTRL_PIN(4, "gpio4"),
	PINCTRL_PIN(5, "gpio5"),
	PINCTRL_PIN(6, "gpio6"),
	PINCTRL_PIN(7, "gpio7"),
	PINCTRL_PIN(8, "gpio8"),
	PINCTRL_PIN(9, "gpio9"),
	PINCTRL_PIN(10, "gpio10"),
	PINCTRL_PIN(11, "gpio11"),
	PINCTRL_PIN(12, "gpio12"),
	PINCTRL_PIN(13, "gpio13"),
	PINCTRL_PIN(14, "gpio14"),
	PINCTRL_PIN(15, "gpio15"),
	PINCTRL_PIN(16, "gpio16"),
	PINCTRL_PIN(17, "gpio17"),
	PINCTRL_PIN(18, "gpio18"),
	PINCTRL_PIN(19, "gpio19"),
	PINCTRL_PIN(20, "gpio20"),
	PINCTRL_PIN(21, "gpio21"),
	PINCTRL_PIN(22, "gpio22"),
	PINCTRL_PIN(23, "gpio23"),
	PINCTRL_PIN(24, "gpio24"),
	PINCTRL_PIN(25, "gpio25"),
	PINCTRL_PIN(26, "gpio26"),
	PINCTRL_PIN(27, "gpio27"),
	PINCTRL_PIN(28, "gpio28"),
	PINCTRL_PIN(29, "gpio29"),
	PINCTRL_PIN(30, "gpio30"),
	PINCTRL_PIN(31, "gpio31"),
	PINCTRL_PIN(32, "gpio32"),
	PINCTRL_PIN(33, "gpio33"),
	PINCTRL_PIN(34, "gpio34"),
	PINCTRL_PIN(35, "gpio35"),
	PINCTRL_PIN(36, "gpio36"),
	PINCTRL_PIN(37, "gpio37"),
	PINCTRL_PIN(38, "gpio38"),
	PINCTRL_PIN(39, "gpio39"),
	PINCTRL_PIN(40, "gpio40"),
	PINCTRL_PIN(41, "gpio41"),
	PINCTRL_PIN(42, "gpio42"),
	PINCTRL_PIN(43, "gpio43"),
	PINCTRL_PIN(44, "gpio44"),
	PINCTRL_PIN(45, "gpio45"),
	PINCTRL_PIN(46, "gpio46"),
	PINCTRL_PIN(47, "gpio47"),
	PINCTRL_PIN(48, "gpio48"),
	PINCTRL_PIN(49, "gpio49"),
	PINCTRL_PIN(50, "gpio50"),
	PINCTRL_PIN(51, "gpio51"),
	PINCTRL_PIN(52, "gpio52"),
	PINCTRL_PIN(53, "gpio53"),
	PINCTRL_PIN(54, "gpio54"),
	PINCTRL_PIN(55, "gpio55"),
};

/*
 * All single-pin functions can be mapped to any GPIO, however pinmux applies
 * functions to pin groups and only those groups declared as supporting that
 * function. To make this work we must put each pin in its own dummy group so
 * that the functions can be described as applying to all pins.
 * We use the same name as in the datasheet.
 */
static const char * const mlxbf3_pinctrl_single_group_names[] = {
	"gpio0", "gpio1",  "gpio2",  "gpio3",  "gpio4",  "gpio5",  "gpio6", "gpio7",
	"gpio8",  "gpio9",  "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
	"gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
	"gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31",
	"gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39",
	"gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
	"gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
};

static int mlxbf3_get_groups_count(struct pinctrl_dev *pctldev)
{
	/* Number single-pin groups */
	return MLXBF3_MAX_GPIO_PINS;
}

static const char *mlxbf3_get_group_name(struct pinctrl_dev *pctldev,
					 unsigned int selector)
{
	return mlxbf3_pinctrl_single_group_names[selector];
}

static int mlxbf3_get_group_pins(struct pinctrl_dev *pctldev,
				 unsigned int selector,
				 const unsigned int **pins,
				 unsigned int *num_pins)
{
	/* return the dummy group for a single pin */
	*pins = &selector;
	*num_pins = 1;

	return 0;
}

static const struct pinctrl_ops mlxbf3_pinctrl_group_ops = {
	.get_groups_count = mlxbf3_get_groups_count,
	.get_group_name = mlxbf3_get_group_name,
	.get_group_pins = mlxbf3_get_group_pins,
};

/*
 * Only 2 functions are supported and they apply to all pins:
 * 1) Default hardware functionality
 * 2) Software controlled GPIO
 */
static const char * const mlxbf3_gpiofunc_group_names[] = { "swctrl" };
static const char * const mlxbf3_hwfunc_group_names[]   = { "hwctrl" };

static struct pinfunction mlxbf3_pmx_funcs[] = {
	PINCTRL_PINFUNCTION("hwfunc", mlxbf3_hwfunc_group_names, 1),
	PINCTRL_PINFUNCTION("gpiofunc", mlxbf3_gpiofunc_group_names, 1),
};

static int mlxbf3_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
	return ARRAY_SIZE(mlxbf3_pmx_funcs);
}

static const char *mlxbf3_pmx_get_func_name(struct pinctrl_dev *pctldev,
					   unsigned int selector)
{
	return mlxbf3_pmx_funcs[selector].name;
}

static int mlxbf3_pmx_get_groups(struct pinctrl_dev *pctldev,
				 unsigned int selector,
				 const char * const **groups,
				 unsigned int * const num_groups)
{
	*groups = mlxbf3_pmx_funcs[selector].groups;
	*num_groups = MLXBF3_MAX_GPIO_PINS;

	return 0;
}

static int mlxbf3_pmx_set(struct pinctrl_dev *pctldev,
			      unsigned int selector,
			      unsigned int group)
{
	struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);

	if (selector == MLXBF3_GPIO_HW_MODE) {
		if (group < MLXBF3_NGPIOS_GPIO0)
			writel(BIT(group), priv->fw_ctrl_clr0);
		else
			writel(BIT(group % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_clr1);
	}

	if (selector == MLXBF3_GPIO_SW_MODE) {
		if (group < MLXBF3_NGPIOS_GPIO0)
			writel(BIT(group), priv->fw_ctrl_set0);
		else
			writel(BIT(group % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_set1);
	}

	return 0;
}

static int mlxbf3_gpio_request_enable(struct pinctrl_dev *pctldev,
				     struct pinctrl_gpio_range *range,
				     unsigned int offset)
{
	struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);

	if (offset < MLXBF3_NGPIOS_GPIO0)
		writel(BIT(offset), priv->fw_ctrl_set0);
	else
		writel(BIT(offset % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_set1);

	return 0;
}

static const struct pinmux_ops mlxbf3_pmx_ops = {
	.get_functions_count = mlxbf3_pmx_get_funcs_count,
	.get_function_name = mlxbf3_pmx_get_func_name,
	.get_function_groups = mlxbf3_pmx_get_groups,
	.set_mux = mlxbf3_pmx_set,
	.gpio_request_enable = mlxbf3_gpio_request_enable,
};

static struct pinctrl_desc mlxbf3_pin_desc = {
	.name = "pinctrl-mlxbf3",
	.pins = mlxbf3_pins,
	.npins = ARRAY_SIZE(mlxbf3_pins),
	.pctlops = &mlxbf3_pinctrl_group_ops,
	.pmxops = &mlxbf3_pmx_ops,
	.owner = THIS_MODULE,
};

static_assert(ARRAY_SIZE(mlxbf3_pinctrl_single_group_names) == MLXBF3_MAX_GPIO_PINS);

static int mlxbf3_pinctrl_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct mlxbf3_pinctrl *priv;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->dev = &pdev->dev;

	priv->fw_ctrl_set0 = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(priv->fw_ctrl_set0))
		return PTR_ERR(priv->fw_ctrl_set0);

	priv->fw_ctrl_clr0 = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(priv->fw_ctrl_clr0))
		return PTR_ERR(priv->fw_ctrl_clr0);

	priv->fw_ctrl_set1 = devm_platform_ioremap_resource(pdev, 2);
	if (IS_ERR(priv->fw_ctrl_set1))
		return PTR_ERR(priv->fw_ctrl_set1);

	priv->fw_ctrl_clr1 = devm_platform_ioremap_resource(pdev, 3);
	if (IS_ERR(priv->fw_ctrl_clr1))
		return PTR_ERR(priv->fw_ctrl_clr1);

	ret = devm_pinctrl_register_and_init(dev,
					     &mlxbf3_pin_desc,
					     priv,
					     &priv->pctl);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to register pinctrl\n");

	ret = pinctrl_enable(priv->pctl);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to enable pinctrl\n");

	pinctrl_add_gpio_ranges(priv->pctl, mlxbf3_pinctrl_gpio_ranges, 2);

	return 0;
}

static const struct acpi_device_id mlxbf3_pinctrl_acpi_ids[] = {
	{ "MLNXBF34", 0 },
	{}
};
MODULE_DEVICE_TABLE(acpi, mlxbf3_pinctrl_acpi_ids);

static struct platform_driver mlxbf3_pinctrl_driver = {
	.driver = {
		.name = "pinctrl-mlxbf3",
		.acpi_match_table = mlxbf3_pinctrl_acpi_ids,
	},
	.probe = mlxbf3_pinctrl_probe,
};
module_platform_driver(mlxbf3_pinctrl_driver);

MODULE_DESCRIPTION("NVIDIA pinctrl driver");
MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
MODULE_LICENSE("Dual BSD/GPL");