0001
0002
0003 #include <linux/acpi.h>
0004 #include <linux/bitops.h>
0005 #include <linux/device.h>
0006 #include <linux/gpio/driver.h>
0007 #include <linux/io.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/pm.h>
0012 #include <linux/resource.h>
0013 #include <linux/types.h>
0014
0015
0016 #define MLXBF_GPIO_NR 54
0017
0018
0019 #define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
0020 #define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
0021 #define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
0022 #define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
0023
0024 #define MLXBF_GPIO_PIN_DIR_I 0x1040
0025 #define MLXBF_GPIO_PIN_DIR_O 0x1048
0026 #define MLXBF_GPIO_PIN_STATE 0x1000
0027 #define MLXBF_GPIO_SCRATCHPAD 0x20
0028
0029 #ifdef CONFIG_PM
0030 struct mlxbf_gpio_context_save_regs {
0031 u64 scratchpad;
0032 u64 pad_control[MLXBF_GPIO_NR];
0033 u64 pin_dir_i;
0034 u64 pin_dir_o;
0035 };
0036 #endif
0037
0038
0039 struct mlxbf_gpio_state {
0040 struct gpio_chip gc;
0041
0042
0043 void __iomem *base;
0044
0045 #ifdef CONFIG_PM
0046 struct mlxbf_gpio_context_save_regs csave_regs;
0047 #endif
0048 };
0049
0050 static int mlxbf_gpio_probe(struct platform_device *pdev)
0051 {
0052 struct mlxbf_gpio_state *gs;
0053 struct device *dev = &pdev->dev;
0054 struct gpio_chip *gc;
0055 int ret;
0056
0057 gs = devm_kzalloc(&pdev->dev, sizeof(*gs), GFP_KERNEL);
0058 if (!gs)
0059 return -ENOMEM;
0060
0061 gs->base = devm_platform_ioremap_resource(pdev, 0);
0062 if (IS_ERR(gs->base))
0063 return PTR_ERR(gs->base);
0064
0065 gc = &gs->gc;
0066 ret = bgpio_init(gc, dev, 8,
0067 gs->base + MLXBF_GPIO_PIN_STATE,
0068 NULL,
0069 NULL,
0070 gs->base + MLXBF_GPIO_PIN_DIR_O,
0071 gs->base + MLXBF_GPIO_PIN_DIR_I,
0072 0);
0073 if (ret)
0074 return -ENODEV;
0075
0076 gc->owner = THIS_MODULE;
0077 gc->ngpio = MLXBF_GPIO_NR;
0078
0079 ret = devm_gpiochip_add_data(dev, &gs->gc, gs);
0080 if (ret) {
0081 dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
0082 return ret;
0083 }
0084
0085 platform_set_drvdata(pdev, gs);
0086 dev_info(&pdev->dev, "registered Mellanox BlueField GPIO");
0087 return 0;
0088 }
0089
0090 #ifdef CONFIG_PM
0091 static int mlxbf_gpio_suspend(struct platform_device *pdev, pm_message_t state)
0092 {
0093 struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);
0094
0095 gs->csave_regs.scratchpad = readq(gs->base + MLXBF_GPIO_SCRATCHPAD);
0096 gs->csave_regs.pad_control[0] =
0097 readq(gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD);
0098 gs->csave_regs.pad_control[1] =
0099 readq(gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD);
0100 gs->csave_regs.pad_control[2] =
0101 readq(gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD);
0102 gs->csave_regs.pad_control[3] =
0103 readq(gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD);
0104 gs->csave_regs.pin_dir_i = readq(gs->base + MLXBF_GPIO_PIN_DIR_I);
0105 gs->csave_regs.pin_dir_o = readq(gs->base + MLXBF_GPIO_PIN_DIR_O);
0106
0107 return 0;
0108 }
0109
0110 static int mlxbf_gpio_resume(struct platform_device *pdev)
0111 {
0112 struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev);
0113
0114 writeq(gs->csave_regs.scratchpad, gs->base + MLXBF_GPIO_SCRATCHPAD);
0115 writeq(gs->csave_regs.pad_control[0],
0116 gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD);
0117 writeq(gs->csave_regs.pad_control[1],
0118 gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD);
0119 writeq(gs->csave_regs.pad_control[2],
0120 gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD);
0121 writeq(gs->csave_regs.pad_control[3],
0122 gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD);
0123 writeq(gs->csave_regs.pin_dir_i, gs->base + MLXBF_GPIO_PIN_DIR_I);
0124 writeq(gs->csave_regs.pin_dir_o, gs->base + MLXBF_GPIO_PIN_DIR_O);
0125
0126 return 0;
0127 }
0128 #endif
0129
0130 static const struct acpi_device_id __maybe_unused mlxbf_gpio_acpi_match[] = {
0131 { "MLNXBF02", 0 },
0132 {}
0133 };
0134 MODULE_DEVICE_TABLE(acpi, mlxbf_gpio_acpi_match);
0135
0136 static struct platform_driver mlxbf_gpio_driver = {
0137 .driver = {
0138 .name = "mlxbf_gpio",
0139 .acpi_match_table = ACPI_PTR(mlxbf_gpio_acpi_match),
0140 },
0141 .probe = mlxbf_gpio_probe,
0142 #ifdef CONFIG_PM
0143 .suspend = mlxbf_gpio_suspend,
0144 .resume = mlxbf_gpio_resume,
0145 #endif
0146 };
0147
0148 module_platform_driver(mlxbf_gpio_driver);
0149
0150 MODULE_DESCRIPTION("Mellanox BlueField GPIO Driver");
0151 MODULE_AUTHOR("Mellanox Technologies");
0152 MODULE_LICENSE("GPL");