File Index
Files and directories
Sign in
FILE

gpio-mlxbf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-mlxbf.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/acpi.h>
  4#include <linux/bitops.h>
  5#include <linux/device.h>
  6#include <linux/gpio/driver.h>
  7#include <linux/gpio/generic.h>
  8#include <linux/io.h>
  9#include <linux/kernel.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <linux/pm.h>
 13#include <linux/resource.h>
 14#include <linux/types.h>
 15
 16/* Number of pins on BlueField */
 17#define MLXBF_GPIO_NR 54
 18
 19/* Pad Electrical Controls. */
 20#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
 21#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
 22#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
 23#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
 24
 25#define MLXBF_GPIO_PIN_DIR_I 0x1040
 26#define MLXBF_GPIO_PIN_DIR_O 0x1048
 27#define MLXBF_GPIO_PIN_STATE 0x1000
 28#define MLXBF_GPIO_SCRATCHPAD 0x20
 29
 30#ifdef CONFIG_PM
 31struct mlxbf_gpio_context_save_regs {
 32	u64 scratchpad;
 33	u64 pad_control[MLXBF_GPIO_NR];
 34	u64 pin_dir_i;
 35	u64 pin_dir_o;
 36};
 37#endif
 38
 39/* Device state structure. */
 40struct mlxbf_gpio_state {
 41	struct gpio_generic_chip chip;
 42
 43	/* Memory Address */
 44	void __iomem *base;
 45
 46#ifdef CONFIG_PM
 47	struct mlxbf_gpio_context_save_regs csave_regs;
 48#endif
 49};
 50
 51static int mlxbf_gpio_probe(struct platform_device *pdev)
 52{
 53	struct gpio_generic_chip_config config;
 54	struct mlxbf_gpio_state *gs;
 55	struct device *dev = &pdev->dev;
 56	struct gpio_chip *gc;
 57	int ret;
 58
 59	gs = devm_kzalloc(&pdev->dev, sizeof(*gs), GFP_KERNEL);
 60	if (!gs)
 61		return -ENOMEM;
 62
 63	gs->base = devm_platform_ioremap_resource(pdev, 0);
 64	if (IS_ERR(gs->base))
 65		return PTR_ERR(gs->base);
 66
 67	gc = &gs->chip.gc;
 68
 69	config = (struct gpio_generic_chip_config) {
 70		.dev = dev,
 71		.sz = 8,
 72		.dat = gs->base + MLXBF_GPIO_PIN_STATE,
 73		.dirout = gs->base + MLXBF_GPIO_PIN_DIR_O,
 74		.dirin =  gs->base + MLXBF_GPIO_PIN_DIR_I,
 75	};
 76
 77	ret = gpio_generic_chip_init(&gs->chip, &config);
 78	if (ret)
 79		return -ENODEV;
 80
 81	gc->owner = THIS_MODULE;
 82	gc->ngpio = MLXBF_GPIO_NR;
 83
 84	ret = devm_gpiochip_add_data(dev, &gs->chip.gc, gs);
 85	if (ret) {
 86		dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
 87		return ret;
 88	}
 89
 90	platform_set_drvdata(pdev, gs);
 91	dev_info(&pdev->dev, "registered Mellanox BlueField GPIO");
 92	return 0;
 93}
 94
 95#ifdef CONFIG_PM
 96static int mlxbf_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 97{
 98	struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);
 99
100	gs->csave_regs.scratchpad = readq(gs->base + MLXBF_GPIO_SCRATCHPAD);
101	gs->csave_regs.pad_control[0] =
102		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD);
103	gs->csave_regs.pad_control[1] =
104		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD);
105	gs->csave_regs.pad_control[2] =
106		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD);
107	gs->csave_regs.pad_control[3] =
108		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD);
109	gs->csave_regs.pin_dir_i = readq(gs->base + MLXBF_GPIO_PIN_DIR_I);
110	gs->csave_regs.pin_dir_o = readq(gs->base + MLXBF_GPIO_PIN_DIR_O);
111
112	return 0;
113}
114
115static int mlxbf_gpio_resume(struct platform_device *pdev)
116{
117	struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);
118
119	writeq(gs->csave_regs.scratchpad, gs->base + MLXBF_GPIO_SCRATCHPAD);
120	writeq(gs->csave_regs.pad_control[0],
121	       gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD);
122	writeq(gs->csave_regs.pad_control[1],
123	       gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD);
124	writeq(gs->csave_regs.pad_control[2],
125	       gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD);
126	writeq(gs->csave_regs.pad_control[3],
127	       gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD);
128	writeq(gs->csave_regs.pin_dir_i, gs->base + MLXBF_GPIO_PIN_DIR_I);
129	writeq(gs->csave_regs.pin_dir_o, gs->base + MLXBF_GPIO_PIN_DIR_O);
130
131	return 0;
132}
133#endif
134
135static const struct acpi_device_id __maybe_unused mlxbf_gpio_acpi_match[] = {
136	{ "MLNXBF02", 0 },
137	{}
138};
139MODULE_DEVICE_TABLE(acpi, mlxbf_gpio_acpi_match);
140
141static struct platform_driver mlxbf_gpio_driver = {
142	.driver = {
143		.name = "mlxbf_gpio",
144		.acpi_match_table = ACPI_PTR(mlxbf_gpio_acpi_match),
145	},
146	.probe    = mlxbf_gpio_probe,
147#ifdef CONFIG_PM
148	.suspend  = mlxbf_gpio_suspend,
149	.resume   = mlxbf_gpio_resume,
150#endif
151};
152
153module_platform_driver(mlxbf_gpio_driver);
154
155MODULE_DESCRIPTION("Mellanox BlueField GPIO Driver");
156MODULE_AUTHOR("Mellanox Technologies");
157MODULE_LICENSE("GPL");
~/ Read-only file preview.