Skip to content

Commit d11f932

Browse files
Asmaa MnebhiLinus Walleij
authored andcommitted
pinctrl: mlxbf3: Add pinctrl driver support
NVIDIA BlueField-3 SoC has a few pins that can be used as GPIOs or take the default hardware functionality. Add a driver for the pin muxing. Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Link: https://lore.kernel.org/r/20230315215027.30685-3-asmaa@nvidia.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent cae630b commit d11f932

File tree

3 files changed

+334
-0
lines changed

3 files changed

+334
-0
lines changed

drivers/pinctrl/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,19 @@ config PINCTRL_ZYNQMP
523523
This driver can also be built as a module. If so, the module
524524
will be called pinctrl-zynqmp.
525525

526+
config PINCTRL_MLXBF3
527+
tristate "NVIDIA BlueField-3 SoC Pinctrl driver"
528+
depends on (MELLANOX_PLATFORM && ARM64) || COMPILE_TEST
529+
select PINMUX
530+
select GPIOLIB
531+
select GPIOLIB_IRQCHIP
532+
select GPIO_MLXBF3
533+
help
534+
Say Y to select the pinctrl driver for BlueField-3 SoCs.
535+
This pin controller allows selecting the mux function for
536+
each pin. This driver can also be built as a module called
537+
pinctrl-mlxbf3.
538+
526539
source "drivers/pinctrl/actions/Kconfig"
527540
source "drivers/pinctrl/aspeed/Kconfig"
528541
source "drivers/pinctrl/bcm/Kconfig"

drivers/pinctrl/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ obj-$(CONFIG_PINCTRL_MCP23S08_I2C) += pinctrl-mcp23s08_i2c.o
3636
obj-$(CONFIG_PINCTRL_MCP23S08_SPI) += pinctrl-mcp23s08_spi.o
3737
obj-$(CONFIG_PINCTRL_MCP23S08) += pinctrl-mcp23s08.o
3838
obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO) += pinctrl-microchip-sgpio.o
39+
obj-$(CONFIG_PINCTRL_MLXBF3) += pinctrl-mlxbf3.o
3940
obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
4041
obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.o
4142
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o

drivers/pinctrl/pinctrl-mlxbf3.c

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
2+
/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */
3+
4+
#include <linux/bitfield.h>
5+
#include <linux/bitops.h>
6+
#include <linux/err.h>
7+
#include <linux/io.h>
8+
#include <linux/module.h>
9+
#include <linux/mod_devicetable.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/types.h>
12+
13+
#include <linux/pinctrl/pinctrl.h>
14+
#include <linux/pinctrl/pinmux.h>
15+
16+
#define MLXBF3_NGPIOS_GPIO0 32
17+
#define MLXBF3_MAX_GPIO_PINS 56
18+
19+
enum {
20+
MLXBF3_GPIO_HW_MODE,
21+
MLXBF3_GPIO_SW_MODE,
22+
};
23+
24+
struct mlxbf3_pinctrl {
25+
void __iomem *fw_ctrl_set0;
26+
void __iomem *fw_ctrl_clr0;
27+
void __iomem *fw_ctrl_set1;
28+
void __iomem *fw_ctrl_clr1;
29+
struct device *dev;
30+
struct pinctrl_dev *pctl;
31+
struct pinctrl_gpio_range gpio_range;
32+
};
33+
34+
#define MLXBF3_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins) \
35+
{ \
36+
.name = "mlxbf3_gpio_range", \
37+
.id = _id, \
38+
.base = _gpiobase, \
39+
.pin_base = _pinbase, \
40+
.npins = _npins, \
41+
}
42+
43+
static struct pinctrl_gpio_range mlxbf3_pinctrl_gpio_ranges[] = {
44+
MLXBF3_GPIO_RANGE(0, 0, 480, 32),
45+
MLXBF3_GPIO_RANGE(1, 32, 456, 24),
46+
};
47+
48+
static const struct pinctrl_pin_desc mlxbf3_pins[] = {
49+
PINCTRL_PIN(0, "gpio0"),
50+
PINCTRL_PIN(1, "gpio1"),
51+
PINCTRL_PIN(2, "gpio2"),
52+
PINCTRL_PIN(3, "gpio3"),
53+
PINCTRL_PIN(4, "gpio4"),
54+
PINCTRL_PIN(5, "gpio5"),
55+
PINCTRL_PIN(6, "gpio6"),
56+
PINCTRL_PIN(7, "gpio7"),
57+
PINCTRL_PIN(8, "gpio8"),
58+
PINCTRL_PIN(9, "gpio9"),
59+
PINCTRL_PIN(10, "gpio10"),
60+
PINCTRL_PIN(11, "gpio11"),
61+
PINCTRL_PIN(12, "gpio12"),
62+
PINCTRL_PIN(13, "gpio13"),
63+
PINCTRL_PIN(14, "gpio14"),
64+
PINCTRL_PIN(15, "gpio15"),
65+
PINCTRL_PIN(16, "gpio16"),
66+
PINCTRL_PIN(17, "gpio17"),
67+
PINCTRL_PIN(18, "gpio18"),
68+
PINCTRL_PIN(19, "gpio19"),
69+
PINCTRL_PIN(20, "gpio20"),
70+
PINCTRL_PIN(21, "gpio21"),
71+
PINCTRL_PIN(22, "gpio22"),
72+
PINCTRL_PIN(23, "gpio23"),
73+
PINCTRL_PIN(24, "gpio24"),
74+
PINCTRL_PIN(25, "gpio25"),
75+
PINCTRL_PIN(26, "gpio26"),
76+
PINCTRL_PIN(27, "gpio27"),
77+
PINCTRL_PIN(28, "gpio28"),
78+
PINCTRL_PIN(29, "gpio29"),
79+
PINCTRL_PIN(30, "gpio30"),
80+
PINCTRL_PIN(31, "gpio31"),
81+
PINCTRL_PIN(32, "gpio32"),
82+
PINCTRL_PIN(33, "gpio33"),
83+
PINCTRL_PIN(34, "gpio34"),
84+
PINCTRL_PIN(35, "gpio35"),
85+
PINCTRL_PIN(36, "gpio36"),
86+
PINCTRL_PIN(37, "gpio37"),
87+
PINCTRL_PIN(38, "gpio38"),
88+
PINCTRL_PIN(39, "gpio39"),
89+
PINCTRL_PIN(40, "gpio40"),
90+
PINCTRL_PIN(41, "gpio41"),
91+
PINCTRL_PIN(42, "gpio42"),
92+
PINCTRL_PIN(43, "gpio43"),
93+
PINCTRL_PIN(44, "gpio44"),
94+
PINCTRL_PIN(45, "gpio45"),
95+
PINCTRL_PIN(46, "gpio46"),
96+
PINCTRL_PIN(47, "gpio47"),
97+
PINCTRL_PIN(48, "gpio48"),
98+
PINCTRL_PIN(49, "gpio49"),
99+
PINCTRL_PIN(50, "gpio50"),
100+
PINCTRL_PIN(51, "gpio51"),
101+
PINCTRL_PIN(52, "gpio52"),
102+
PINCTRL_PIN(53, "gpio53"),
103+
PINCTRL_PIN(54, "gpio54"),
104+
PINCTRL_PIN(55, "gpio55"),
105+
};
106+
107+
/*
108+
* All single-pin functions can be mapped to any GPIO, however pinmux applies
109+
* functions to pin groups and only those groups declared as supporting that
110+
* function. To make this work we must put each pin in its own dummy group so
111+
* that the functions can be described as applying to all pins.
112+
* We use the same name as in the datasheet.
113+
*/
114+
static const char * const mlxbf3_pinctrl_single_group_names[] = {
115+
"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
116+
"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
117+
"gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
118+
"gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31",
119+
"gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39",
120+
"gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
121+
"gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
122+
};
123+
124+
static int mlxbf3_get_groups_count(struct pinctrl_dev *pctldev)
125+
{
126+
/* Number single-pin groups */
127+
return MLXBF3_MAX_GPIO_PINS;
128+
}
129+
130+
static const char *mlxbf3_get_group_name(struct pinctrl_dev *pctldev,
131+
unsigned int selector)
132+
{
133+
return mlxbf3_pinctrl_single_group_names[selector];
134+
}
135+
136+
static int mlxbf3_get_group_pins(struct pinctrl_dev *pctldev,
137+
unsigned int selector,
138+
const unsigned int **pins,
139+
unsigned int *num_pins)
140+
{
141+
/* return the dummy group for a single pin */
142+
*pins = &selector;
143+
*num_pins = 1;
144+
145+
return 0;
146+
}
147+
148+
static const struct pinctrl_ops mlxbf3_pinctrl_group_ops = {
149+
.get_groups_count = mlxbf3_get_groups_count,
150+
.get_group_name = mlxbf3_get_group_name,
151+
.get_group_pins = mlxbf3_get_group_pins,
152+
};
153+
154+
/*
155+
* Only 2 functions are supported and they apply to all pins:
156+
* 1) Default hardware functionality
157+
* 2) Software controlled GPIO
158+
*/
159+
static const char * const mlxbf3_gpiofunc_group_names[] = { "swctrl" };
160+
static const char * const mlxbf3_hwfunc_group_names[] = { "hwctrl" };
161+
162+
struct pinfunction mlxbf3_pmx_funcs[] = {
163+
PINCTRL_PINFUNCTION("hwfunc", mlxbf3_hwfunc_group_names, 1),
164+
PINCTRL_PINFUNCTION("gpiofunc", mlxbf3_gpiofunc_group_names, 1),
165+
};
166+
167+
static int mlxbf3_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
168+
{
169+
return ARRAY_SIZE(mlxbf3_pmx_funcs);
170+
}
171+
172+
static const char *mlxbf3_pmx_get_func_name(struct pinctrl_dev *pctldev,
173+
unsigned int selector)
174+
{
175+
return mlxbf3_pmx_funcs[selector].name;
176+
}
177+
178+
static int mlxbf3_pmx_get_groups(struct pinctrl_dev *pctldev,
179+
unsigned int selector,
180+
const char * const **groups,
181+
unsigned int * const num_groups)
182+
{
183+
*groups = mlxbf3_pmx_funcs[selector].groups;
184+
*num_groups = MLXBF3_MAX_GPIO_PINS;
185+
186+
return 0;
187+
}
188+
189+
static int mlxbf3_pmx_set(struct pinctrl_dev *pctldev,
190+
unsigned int selector,
191+
unsigned int group)
192+
{
193+
struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);
194+
195+
if (selector == MLXBF3_GPIO_HW_MODE) {
196+
if (group < MLXBF3_NGPIOS_GPIO0)
197+
writel(BIT(group), priv->fw_ctrl_clr0);
198+
else
199+
writel(BIT(group % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_clr1);
200+
}
201+
202+
if (selector == MLXBF3_GPIO_SW_MODE) {
203+
if (group < MLXBF3_NGPIOS_GPIO0)
204+
writel(BIT(group), priv->fw_ctrl_set0);
205+
else
206+
writel(BIT(group % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_set1);
207+
}
208+
209+
return 0;
210+
}
211+
212+
static int mlxbf3_gpio_request_enable(struct pinctrl_dev *pctldev,
213+
struct pinctrl_gpio_range *range,
214+
unsigned int offset)
215+
{
216+
struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);
217+
218+
if (offset < MLXBF3_NGPIOS_GPIO0)
219+
writel(BIT(offset), priv->fw_ctrl_set0);
220+
else
221+
writel(BIT(offset % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_set1);
222+
223+
return 0;
224+
}
225+
226+
static void mlxbf3_gpio_disable_free(struct pinctrl_dev *pctldev,
227+
struct pinctrl_gpio_range *range,
228+
unsigned int offset)
229+
{
230+
struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);
231+
232+
/* disable GPIO functionality by giving control back to hardware */
233+
if (offset < MLXBF3_NGPIOS_GPIO0)
234+
writel(BIT(offset), priv->fw_ctrl_clr0);
235+
else
236+
writel(BIT(offset % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_clr1);
237+
}
238+
239+
static const struct pinmux_ops mlxbf3_pmx_ops = {
240+
.get_functions_count = mlxbf3_pmx_get_funcs_count,
241+
.get_function_name = mlxbf3_pmx_get_func_name,
242+
.get_function_groups = mlxbf3_pmx_get_groups,
243+
.set_mux = mlxbf3_pmx_set,
244+
.gpio_request_enable = mlxbf3_gpio_request_enable,
245+
.gpio_disable_free = mlxbf3_gpio_disable_free,
246+
};
247+
248+
static struct pinctrl_desc mlxbf3_pin_desc = {
249+
.name = "pinctrl-mlxbf3",
250+
.pins = mlxbf3_pins,
251+
.npins = ARRAY_SIZE(mlxbf3_pins),
252+
.pctlops = &mlxbf3_pinctrl_group_ops,
253+
.pmxops = &mlxbf3_pmx_ops,
254+
.owner = THIS_MODULE,
255+
};
256+
257+
static_assert(ARRAY_SIZE(mlxbf3_pinctrl_single_group_names) == MLXBF3_MAX_GPIO_PINS);
258+
259+
static int mlxbf3_pinctrl_probe(struct platform_device *pdev)
260+
{
261+
struct device *dev = &pdev->dev;
262+
struct mlxbf3_pinctrl *priv;
263+
int ret;
264+
265+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
266+
if (!priv)
267+
return -ENOMEM;
268+
269+
priv->dev = &pdev->dev;
270+
271+
priv->fw_ctrl_set0 = devm_platform_ioremap_resource(pdev, 0);
272+
if (IS_ERR(priv->fw_ctrl_set0))
273+
return PTR_ERR(priv->fw_ctrl_set0);
274+
275+
priv->fw_ctrl_clr0 = devm_platform_ioremap_resource(pdev, 1);
276+
if (IS_ERR(priv->fw_ctrl_set0))
277+
return PTR_ERR(priv->fw_ctrl_set0);
278+
279+
priv->fw_ctrl_set1 = devm_platform_ioremap_resource(pdev, 2);
280+
if (IS_ERR(priv->fw_ctrl_set0))
281+
return PTR_ERR(priv->fw_ctrl_set0);
282+
283+
priv->fw_ctrl_clr1 = devm_platform_ioremap_resource(pdev, 3);
284+
if (IS_ERR(priv->fw_ctrl_set0))
285+
return PTR_ERR(priv->fw_ctrl_set0);
286+
287+
ret = devm_pinctrl_register_and_init(dev,
288+
&mlxbf3_pin_desc,
289+
priv,
290+
&priv->pctl);
291+
if (ret)
292+
return dev_err_probe(dev, ret, "Failed to register pinctrl\n");
293+
294+
ret = pinctrl_enable(priv->pctl);
295+
if (ret)
296+
return dev_err_probe(dev, ret, "Failed to enable pinctrl\n");
297+
298+
pinctrl_add_gpio_ranges(priv->pctl, mlxbf3_pinctrl_gpio_ranges, 2);
299+
300+
return 0;
301+
}
302+
303+
static const struct acpi_device_id mlxbf3_pinctrl_acpi_ids[] = {
304+
{ "MLNXBF34", 0 },
305+
{}
306+
};
307+
MODULE_DEVICE_TABLE(acpi, mlxbf3_pinctrl_acpi_ids);
308+
309+
static struct platform_driver mlxbf3_pinctrl_driver = {
310+
.driver = {
311+
.name = "pinctrl-mlxbf3",
312+
.acpi_match_table = mlxbf3_pinctrl_acpi_ids,
313+
},
314+
.probe = mlxbf3_pinctrl_probe,
315+
};
316+
module_platform_driver(mlxbf3_pinctrl_driver);
317+
318+
MODULE_DESCRIPTION("NVIDIA pinctrl driver");
319+
MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
320+
MODULE_LICENSE("Dual BSD/GPL");

0 commit comments

Comments
 (0)