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 31 struct 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. */ 40 struct 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 51 static 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 96 static 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 115 static 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 135 static const struct acpi_device_id __maybe_unused mlxbf_gpio_acpi_match[] = { 136 { "MLNXBF02", 0 }, 137 {} 138 }; 139 MODULE_DEVICE_TABLE(acpi, mlxbf_gpio_acpi_match); 140 141 static 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 153 module_platform_driver(mlxbf_gpio_driver); 154 155 MODULE_DESCRIPTION("Mellanox BlueField GPIO Driver"); 156 MODULE_AUTHOR("Mellanox Technologies"); 157 MODULE_LICENSE("GPL"); 158