drivers/gpio/gpio-mlxbf.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-mlxbf.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-mlxbf.c
Extension
.c
Size
4226 bytes
Lines
158
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlxbf_gpio_context_save_regs {
	u64 scratchpad;
	u64 pad_control[MLXBF_GPIO_NR];
	u64 pin_dir_i;
	u64 pin_dir_o;
};
#endif

/* Device state structure. */
struct mlxbf_gpio_state {
	struct gpio_generic_chip chip;

	/* Memory Address */
	void __iomem *base;

#ifdef CONFIG_PM
	struct mlxbf_gpio_context_save_regs csave_regs;
#endif
};

static int mlxbf_gpio_probe(struct platform_device *pdev)
{
	struct gpio_generic_chip_config config;
	struct mlxbf_gpio_state *gs;
	struct device *dev = &pdev->dev;
	struct gpio_chip *gc;
	int ret;

	gs = devm_kzalloc(&pdev->dev, sizeof(*gs), GFP_KERNEL);
	if (!gs)
		return -ENOMEM;

	gs->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(gs->base))
		return PTR_ERR(gs->base);

	gc = &gs->chip.gc;

	config = (struct gpio_generic_chip_config) {
		.dev = dev,
		.sz = 8,
		.dat = gs->base + MLXBF_GPIO_PIN_STATE,
		.dirout = gs->base + MLXBF_GPIO_PIN_DIR_O,
		.dirin =  gs->base + MLXBF_GPIO_PIN_DIR_I,
	};

	ret = gpio_generic_chip_init(&gs->chip, &config);
	if (ret)
		return -ENODEV;

	gc->owner = THIS_MODULE;
	gc->ngpio = MLXBF_GPIO_NR;

	ret = devm_gpiochip_add_data(dev, &gs->chip.gc, gs);
	if (ret) {
		dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
		return ret;
	}

	platform_set_drvdata(pdev, gs);
	dev_info(&pdev->dev, "registered Mellanox BlueField GPIO");
	return 0;
}

#ifdef CONFIG_PM
static int mlxbf_gpio_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);

	gs->csave_regs.scratchpad = readq(gs->base + MLXBF_GPIO_SCRATCHPAD);
	gs->csave_regs.pad_control[0] =
		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD);
	gs->csave_regs.pad_control[1] =
		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD);
	gs->csave_regs.pad_control[2] =
		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD);
	gs->csave_regs.pad_control[3] =
		readq(gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD);
	gs->csave_regs.pin_dir_i = readq(gs->base + MLXBF_GPIO_PIN_DIR_I);
	gs->csave_regs.pin_dir_o = readq(gs->base + MLXBF_GPIO_PIN_DIR_O);

	return 0;
}

static int mlxbf_gpio_resume(struct platform_device *pdev)
{
	struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);

	writeq(gs->csave_regs.scratchpad, gs->base + MLXBF_GPIO_SCRATCHPAD);
	writeq(gs->csave_regs.pad_control[0],

Annotation

Implementation Notes