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");