cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-mlxbf.c (4042B)


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