1 // SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause 2 /* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ 3 4 #include <linux/bitfield.h> 5 #include <linux/bitops.h> 6 #include <linux/device.h> 7 #include <linux/err.h> 8 #include <linux/gpio/driver.h> 9 #include <linux/interrupt.h> 10 #include <linux/io.h> 11 #include <linux/module.h> 12 #include <linux/platform_device.h> 13 #include <linux/spinlock.h> 14 #include <linux/types.h> 15 16 /* 17 * There are 2 YU GPIO blocks: 18 * gpio[0]: HOST_GPIO0->HOST_GPIO31 19 * gpio[1]: HOST_GPIO32->HOST_GPIO55 20 */ 21 #define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 22 #define MLXBF3_GPIO_MAX_PINS_BLOCK0 32 23 #define MLXBF3_GPIO_MAX_PINS_BLOCK1 24 24 25 /* 26 * fw_gpio[x] block registers and their offset 27 */ 28 #define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00 29 #define MLXBF_GPIO_FW_DATA_OUT_SET 0x04 30 31 #define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00 32 #define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04 33 34 #define MLXBF_GPIO_CAUSE_RISE_EN 0x00 35 #define MLXBF_GPIO_CAUSE_FALL_EN 0x04 36 #define MLXBF_GPIO_READ_DATA_IN 0x08 37 38 #define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 39 #define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 40 #define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 41 42 struct mlxbf3_gpio_context { 43 struct gpio_chip gc; 44 45 /* YU GPIO block address */ 46 void __iomem *gpio_set_io; 47 void __iomem *gpio_clr_io; 48 void __iomem *gpio_io; 49 50 /* YU GPIO cause block address */ 51 void __iomem *gpio_cause_io; 52 }; 53 54 static void mlxbf3_gpio_irq_enable(struct irq_data *irqd) 55 { 56 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 57 struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 58 irq_hw_number_t offset = irqd_to_hwirq(irqd); 59 unsigned long flags; 60 u32 val; 61 62 gpiochip_enable_irq(gc, offset); 63 64 raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 65 writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 66 67 val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 68 val |= BIT(offset); 69 writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 70 raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 71 } 72 73 static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) 74 { 75 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 76 struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 77 irq_hw_number_t offset = irqd_to_hwirq(irqd); 78 unsigned long flags; 79 u32 val; 80 81 raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 82 val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 83 val &= ~BIT(offset); 84 writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 85 raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 86 87 gpiochip_disable_irq(gc, offset); 88 } 89 90 static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) 91 { 92 struct mlxbf3_gpio_context *gs = ptr; 93 struct gpio_chip *gc = &gs->gc; 94 unsigned long pending; 95 u32 level; 96 97 pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0); 98 writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 99 100 for_each_set_bit(level, &pending, gc->ngpio) 101 generic_handle_domain_irq(gc->irq.domain, level); 102 103 return IRQ_RETVAL(pending); 104 } 105 106 static int 107 mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 108 { 109 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 110 struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 111 irq_hw_number_t offset = irqd_to_hwirq(irqd); 112 unsigned long flags; 113 u32 val; 114 115 raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 116 117 switch (type & IRQ_TYPE_SENSE_MASK) { 118 case IRQ_TYPE_EDGE_BOTH: 119 val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 120 val |= BIT(offset); 121 writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 122 val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 123 val |= BIT(offset); 124 writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 125 break; 126 case IRQ_TYPE_EDGE_RISING: 127 val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 128 val |= BIT(offset); 129 writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 130 break; 131 case IRQ_TYPE_EDGE_FALLING: 132 val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 133 val |= BIT(offset); 134 writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 135 break; 136 default: 137 raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 138 return -EINVAL; 139 } 140 141 raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 142 143 irq_set_handler_locked(irqd, handle_edge_irq); 144 145 return 0; 146 } 147 148 /* This function needs to be defined for handle_edge_irq() */ 149 static void mlxbf3_gpio_irq_ack(struct irq_data *data) 150 { 151 } 152 153 static const struct irq_chip gpio_mlxbf3_irqchip = { 154 .name = "MLNXBF33", 155 .irq_ack = mlxbf3_gpio_irq_ack, 156 .irq_set_type = mlxbf3_gpio_irq_set_type, 157 .irq_enable = mlxbf3_gpio_irq_enable, 158 .irq_disable = mlxbf3_gpio_irq_disable, 159 .flags = IRQCHIP_IMMUTABLE, 160 GPIOCHIP_IRQ_RESOURCE_HELPERS, 161 }; 162 163 static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip) 164 { 165 unsigned int id; 166 167 switch(chip->ngpio) { 168 case MLXBF3_GPIO_MAX_PINS_BLOCK0: 169 id = 0; 170 break; 171 case MLXBF3_GPIO_MAX_PINS_BLOCK1: 172 id = 1; 173 break; 174 default: 175 return -EINVAL; 176 } 177 178 return gpiochip_add_pin_range(chip, "MLNXBF34:00", 179 chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK, 180 chip->ngpio); 181 } 182 183 static int mlxbf3_gpio_probe(struct platform_device *pdev) 184 { 185 struct device *dev = &pdev->dev; 186 struct mlxbf3_gpio_context *gs; 187 struct gpio_irq_chip *girq; 188 struct gpio_chip *gc; 189 int ret, irq; 190 191 gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); 192 if (!gs) 193 return -ENOMEM; 194 195 gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); 196 if (IS_ERR(gs->gpio_io)) 197 return PTR_ERR(gs->gpio_io); 198 199 gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); 200 if (IS_ERR(gs->gpio_cause_io)) 201 return PTR_ERR(gs->gpio_cause_io); 202 203 gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2); 204 if (IS_ERR(gs->gpio_set_io)) 205 return PTR_ERR(gs->gpio_set_io); 206 207 gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3); 208 if (IS_ERR(gs->gpio_clr_io)) 209 return PTR_ERR(gs->gpio_clr_io); 210 gc = &gs->gc; 211 212 ret = bgpio_init(gc, dev, 4, 213 gs->gpio_io + MLXBF_GPIO_READ_DATA_IN, 214 gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET, 215 gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR, 216 gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET, 217 gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0); 218 219 gc->request = gpiochip_generic_request; 220 gc->free = gpiochip_generic_free; 221 gc->owner = THIS_MODULE; 222 gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges; 223 224 irq = platform_get_irq(pdev, 0); 225 if (irq >= 0) { 226 girq = &gs->gc.irq; 227 gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); 228 girq->default_type = IRQ_TYPE_NONE; 229 /* This will let us handle the parent IRQ in the driver */ 230 girq->num_parents = 0; 231 girq->parents = NULL; 232 girq->parent_handler = NULL; 233 girq->handler = handle_bad_irq; 234 235 /* 236 * Directly request the irq here instead of passing 237 * a flow-handler because the irq is shared. 238 */ 239 ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, 240 IRQF_SHARED, dev_name(dev), gs); 241 if (ret) 242 return dev_err_probe(dev, ret, "failed to request IRQ"); 243 } 244 245 platform_set_drvdata(pdev, gs); 246 247 ret = devm_gpiochip_add_data(dev, &gs->gc, gs); 248 if (ret) 249 dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n"); 250 251 return 0; 252 } 253 254 static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { 255 { "MLNXBF33", 0 }, 256 {} 257 }; 258 MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); 259 260 static struct platform_driver mlxbf3_gpio_driver = { 261 .driver = { 262 .name = "mlxbf3_gpio", 263 .acpi_match_table = mlxbf3_gpio_acpi_match, 264 }, 265 .probe = mlxbf3_gpio_probe, 266 }; 267 module_platform_driver(mlxbf3_gpio_driver); 268 269 MODULE_SOFTDEP("pre: pinctrl-mlxbf3"); 270 MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); 271 MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); 272 MODULE_LICENSE("Dual BSD/GPL"); 273