at master 4.2 kB view raw
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");