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 30 struct 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. */ 39 struct 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 50 static 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 91 static 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 110 static 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 130 static const struct acpi_device_id mlxbf_gpio_acpi_match[] = { 131 { "MLNXBF02", 0 }, 132 {} 133 }; 134 MODULE_DEVICE_TABLE(acpi, mlxbf_gpio_acpi_match); 135 136 static 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 148 module_platform_driver(mlxbf_gpio_driver); 149 150 MODULE_DESCRIPTION("Mellanox BlueField GPIO Driver"); 151 MODULE_AUTHOR("Mellanox Technologies"); 152 MODULE_LICENSE("GPL"); 153