18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/acpi.h> 48c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 58c2ecf20Sopenharmony_ci#include <linux/bitops.h> 68c2ecf20Sopenharmony_ci#include <linux/device.h> 78c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 88c2ecf20Sopenharmony_ci#include <linux/io.h> 98c2ecf20Sopenharmony_ci#include <linux/ioport.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/pm.h> 148c2ecf20Sopenharmony_ci#include <linux/resource.h> 158c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 168c2ecf20Sopenharmony_ci#include <linux/types.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * There are 3 YU GPIO blocks: 208c2ecf20Sopenharmony_ci * gpio[0]: HOST_GPIO0->HOST_GPIO31 218c2ecf20Sopenharmony_ci * gpio[1]: HOST_GPIO32->HOST_GPIO63 228c2ecf20Sopenharmony_ci * gpio[2]: HOST_GPIO64->HOST_GPIO69 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci#define MLXBF2_GPIO_MAX_PINS_PER_BLOCK 32 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * arm_gpio_lock register: 288c2ecf20Sopenharmony_ci * bit[31] lock status: active if set 298c2ecf20Sopenharmony_ci * bit[15:0] set lock 308c2ecf20Sopenharmony_ci * The lock is enabled only if 0xd42f is written to this field 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#define YU_ARM_GPIO_LOCK_ADDR 0x2801088 338c2ecf20Sopenharmony_ci#define YU_ARM_GPIO_LOCK_SIZE 0x8 348c2ecf20Sopenharmony_ci#define YU_LOCK_ACTIVE_BIT(val) (val >> 31) 358c2ecf20Sopenharmony_ci#define YU_ARM_GPIO_LOCK_ACQUIRE 0xd42f 368c2ecf20Sopenharmony_ci#define YU_ARM_GPIO_LOCK_RELEASE 0x0 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * gpio[x] block registers and their offset 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci#define YU_GPIO_DATAIN 0x04 428c2ecf20Sopenharmony_ci#define YU_GPIO_MODE1 0x08 438c2ecf20Sopenharmony_ci#define YU_GPIO_MODE0 0x0c 448c2ecf20Sopenharmony_ci#define YU_GPIO_DATASET 0x14 458c2ecf20Sopenharmony_ci#define YU_GPIO_DATACLEAR 0x18 468c2ecf20Sopenharmony_ci#define YU_GPIO_MODE1_CLEAR 0x50 478c2ecf20Sopenharmony_ci#define YU_GPIO_MODE0_SET 0x54 488c2ecf20Sopenharmony_ci#define YU_GPIO_MODE0_CLEAR 0x58 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 518c2ecf20Sopenharmony_cistruct mlxbf2_gpio_context_save_regs { 528c2ecf20Sopenharmony_ci u32 gpio_mode0; 538c2ecf20Sopenharmony_ci u32 gpio_mode1; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci#endif 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* BlueField-2 gpio block context structure. */ 588c2ecf20Sopenharmony_cistruct mlxbf2_gpio_context { 598c2ecf20Sopenharmony_ci struct gpio_chip gc; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci /* YU GPIO blocks address */ 628c2ecf20Sopenharmony_ci void __iomem *gpio_io; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 658c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context_save_regs *csave_regs; 668c2ecf20Sopenharmony_ci#endif 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* BlueField-2 gpio shared structure. */ 708c2ecf20Sopenharmony_cistruct mlxbf2_gpio_param { 718c2ecf20Sopenharmony_ci void __iomem *io; 728c2ecf20Sopenharmony_ci struct resource *res; 738c2ecf20Sopenharmony_ci struct mutex *lock; 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic struct resource yu_arm_gpio_lock_res = { 778c2ecf20Sopenharmony_ci .start = YU_ARM_GPIO_LOCK_ADDR, 788c2ecf20Sopenharmony_ci .end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1, 798c2ecf20Sopenharmony_ci .name = "YU_ARM_GPIO_LOCK", 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(yu_arm_gpio_lock_mutex); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic struct mlxbf2_gpio_param yu_arm_gpio_lock_param = { 858c2ecf20Sopenharmony_ci .res = &yu_arm_gpio_lock_res, 868c2ecf20Sopenharmony_ci .lock = &yu_arm_gpio_lock_mutex, 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* Request memory region and map yu_arm_gpio_lock resource */ 908c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 938c2ecf20Sopenharmony_ci struct resource *res; 948c2ecf20Sopenharmony_ci resource_size_t size; 958c2ecf20Sopenharmony_ci int ret = 0; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci mutex_lock(yu_arm_gpio_lock_param.lock); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* Check if the memory map already exists */ 1008c2ecf20Sopenharmony_ci if (yu_arm_gpio_lock_param.io) 1018c2ecf20Sopenharmony_ci goto exit; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci res = yu_arm_gpio_lock_param.res; 1048c2ecf20Sopenharmony_ci size = resource_size(res); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (!devm_request_mem_region(dev, res->start, size, res->name)) { 1078c2ecf20Sopenharmony_ci ret = -EFAULT; 1088c2ecf20Sopenharmony_ci goto exit; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size); 1128c2ecf20Sopenharmony_ci if (!yu_arm_gpio_lock_param.io) 1138c2ecf20Sopenharmony_ci ret = -ENOMEM; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciexit: 1168c2ecf20Sopenharmony_ci mutex_unlock(yu_arm_gpio_lock_param.lock); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return ret; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* 1228c2ecf20Sopenharmony_ci * Acquire the YU arm_gpio_lock to be able to change the direction 1238c2ecf20Sopenharmony_ci * mode. If the lock_active bit is already set, return an error. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci u32 arm_gpio_lock_val; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci mutex_lock(yu_arm_gpio_lock_param.lock); 1308c2ecf20Sopenharmony_ci spin_lock(&gs->gc.bgpio_lock); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci arm_gpio_lock_val = readl(yu_arm_gpio_lock_param.io); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* 1358c2ecf20Sopenharmony_ci * When lock active bit[31] is set, ModeX is write enabled 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci if (YU_LOCK_ACTIVE_BIT(arm_gpio_lock_val)) { 1388c2ecf20Sopenharmony_ci spin_unlock(&gs->gc.bgpio_lock); 1398c2ecf20Sopenharmony_ci mutex_unlock(yu_arm_gpio_lock_param.lock); 1408c2ecf20Sopenharmony_ci return -EINVAL; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci writel(YU_ARM_GPIO_LOCK_ACQUIRE, yu_arm_gpio_lock_param.io); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci return 0; 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci/* 1498c2ecf20Sopenharmony_ci * Release the YU arm_gpio_lock after changing the direction mode. 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_cistatic void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs) 1528c2ecf20Sopenharmony_ci __releases(&gs->gc.bgpio_lock) 1538c2ecf20Sopenharmony_ci __releases(yu_arm_gpio_lock_param.lock) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io); 1568c2ecf20Sopenharmony_ci spin_unlock(&gs->gc.bgpio_lock); 1578c2ecf20Sopenharmony_ci mutex_unlock(yu_arm_gpio_lock_param.lock); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * mode0 and mode1 are both locked by the gpio_lock field. 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci * Together, mode0 and mode1 define the gpio Mode dependeing also 1648c2ecf20Sopenharmony_ci * on Reg_DataOut. 1658c2ecf20Sopenharmony_ci * 1668c2ecf20Sopenharmony_ci * {mode1,mode0}:{Reg_DataOut=0,Reg_DataOut=1}->{DataOut=0,DataOut=1} 1678c2ecf20Sopenharmony_ci * 1688c2ecf20Sopenharmony_ci * {0,0}:Reg_DataOut{0,1}->{Z,Z} Input PAD 1698c2ecf20Sopenharmony_ci * {0,1}:Reg_DataOut{0,1}->{0,1} Full drive Output PAD 1708c2ecf20Sopenharmony_ci * {1,0}:Reg_DataOut{0,1}->{0,Z} 0-set PAD to low, 1-float 1718c2ecf20Sopenharmony_ci * {1,1}:Reg_DataOut{0,1}->{Z,1} 0-float, 1-set PAD to high 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/* 1758c2ecf20Sopenharmony_ci * Set input direction: 1768c2ecf20Sopenharmony_ci * {mode1,mode0} = {0,0} 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_direction_input(struct gpio_chip *chip, 1798c2ecf20Sopenharmony_ci unsigned int offset) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); 1828c2ecf20Sopenharmony_ci int ret; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* 1858c2ecf20Sopenharmony_ci * Although the arm_gpio_lock was set in the probe function, check again 1868c2ecf20Sopenharmony_ci * if it is still enabled to be able to write to the ModeX registers. 1878c2ecf20Sopenharmony_ci */ 1888c2ecf20Sopenharmony_ci ret = mlxbf2_gpio_lock_acquire(gs); 1898c2ecf20Sopenharmony_ci if (ret < 0) 1908c2ecf20Sopenharmony_ci return ret; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_CLEAR); 1938c2ecf20Sopenharmony_ci writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci mlxbf2_gpio_lock_release(gs); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return ret; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/* 2018c2ecf20Sopenharmony_ci * Set output direction: 2028c2ecf20Sopenharmony_ci * {mode1,mode0} = {0,1} 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_direction_output(struct gpio_chip *chip, 2058c2ecf20Sopenharmony_ci unsigned int offset, 2068c2ecf20Sopenharmony_ci int value) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); 2098c2ecf20Sopenharmony_ci int ret = 0; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* 2128c2ecf20Sopenharmony_ci * Although the arm_gpio_lock was set in the probe function, 2138c2ecf20Sopenharmony_ci * check again it is still enabled to be able to write to the 2148c2ecf20Sopenharmony_ci * ModeX registers. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_ci ret = mlxbf2_gpio_lock_acquire(gs); 2178c2ecf20Sopenharmony_ci if (ret < 0) 2188c2ecf20Sopenharmony_ci return ret; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); 2218c2ecf20Sopenharmony_ci writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_SET); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci mlxbf2_gpio_lock_release(gs); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci return ret; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/* BlueField-2 GPIO driver initialization routine. */ 2298c2ecf20Sopenharmony_cistatic int 2308c2ecf20Sopenharmony_cimlxbf2_gpio_probe(struct platform_device *pdev) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context *gs; 2338c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2348c2ecf20Sopenharmony_ci struct gpio_chip *gc; 2358c2ecf20Sopenharmony_ci struct resource *res; 2368c2ecf20Sopenharmony_ci unsigned int npins; 2378c2ecf20Sopenharmony_ci int ret; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); 2408c2ecf20Sopenharmony_ci if (!gs) 2418c2ecf20Sopenharmony_ci return -ENOMEM; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* YU GPIO block address */ 2448c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2458c2ecf20Sopenharmony_ci if (!res) 2468c2ecf20Sopenharmony_ci return -ENODEV; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); 2498c2ecf20Sopenharmony_ci if (!gs->gpio_io) 2508c2ecf20Sopenharmony_ci return -ENOMEM; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ret = mlxbf2_gpio_get_lock_res(pdev); 2538c2ecf20Sopenharmony_ci if (ret) { 2548c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get yu_arm_gpio_lock resource\n"); 2558c2ecf20Sopenharmony_ci return ret; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (device_property_read_u32(dev, "npins", &npins)) 2598c2ecf20Sopenharmony_ci npins = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci gc = &gs->gc; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci ret = bgpio_init(gc, dev, 4, 2648c2ecf20Sopenharmony_ci gs->gpio_io + YU_GPIO_DATAIN, 2658c2ecf20Sopenharmony_ci gs->gpio_io + YU_GPIO_DATASET, 2668c2ecf20Sopenharmony_ci gs->gpio_io + YU_GPIO_DATACLEAR, 2678c2ecf20Sopenharmony_ci NULL, 2688c2ecf20Sopenharmony_ci NULL, 2698c2ecf20Sopenharmony_ci 0); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (ret) { 2728c2ecf20Sopenharmony_ci dev_err(dev, "bgpio_init failed\n"); 2738c2ecf20Sopenharmony_ci return ret; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci gc->direction_input = mlxbf2_gpio_direction_input; 2778c2ecf20Sopenharmony_ci gc->direction_output = mlxbf2_gpio_direction_output; 2788c2ecf20Sopenharmony_ci gc->ngpio = npins; 2798c2ecf20Sopenharmony_ci gc->owner = THIS_MODULE; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, gs); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci ret = devm_gpiochip_add_data(dev, &gs->gc, gs); 2848c2ecf20Sopenharmony_ci if (ret) { 2858c2ecf20Sopenharmony_ci dev_err(dev, "Failed adding memory mapped gpiochip\n"); 2868c2ecf20Sopenharmony_ci return ret; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2938c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_suspend(struct platform_device *pdev, 2948c2ecf20Sopenharmony_ci pm_message_t state) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci gs->csave_regs->gpio_mode0 = readl(gs->gpio_io + 2998c2ecf20Sopenharmony_ci YU_GPIO_MODE0); 3008c2ecf20Sopenharmony_ci gs->csave_regs->gpio_mode1 = readl(gs->gpio_io + 3018c2ecf20Sopenharmony_ci YU_GPIO_MODE1); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic int mlxbf2_gpio_resume(struct platform_device *pdev) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci writel(gs->csave_regs->gpio_mode0, gs->gpio_io + 3118c2ecf20Sopenharmony_ci YU_GPIO_MODE0); 3128c2ecf20Sopenharmony_ci writel(gs->csave_regs->gpio_mode1, gs->gpio_io + 3138c2ecf20Sopenharmony_ci YU_GPIO_MODE1); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci#endif 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = { 3208c2ecf20Sopenharmony_ci { "MLNXBF22", 0 }, 3218c2ecf20Sopenharmony_ci {}, 3228c2ecf20Sopenharmony_ci}; 3238c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic struct platform_driver mlxbf2_gpio_driver = { 3268c2ecf20Sopenharmony_ci .driver = { 3278c2ecf20Sopenharmony_ci .name = "mlxbf2_gpio", 3288c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), 3298c2ecf20Sopenharmony_ci }, 3308c2ecf20Sopenharmony_ci .probe = mlxbf2_gpio_probe, 3318c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 3328c2ecf20Sopenharmony_ci .suspend = mlxbf2_gpio_suspend, 3338c2ecf20Sopenharmony_ci .resume = mlxbf2_gpio_resume, 3348c2ecf20Sopenharmony_ci#endif 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cimodule_platform_driver(mlxbf2_gpio_driver); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); 3408c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mellanox Technologies"); 3418c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 342