Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: mlxbf2: Introduce IRQ support

Introduce standard IRQ handling in the gpio-mlxbf2.c
driver.

Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>

authored by

Asmaa Mnebhi and committed by
Bartosz Golaszewski
2b725265 f4a20dfa

+140 -2
+140 -2
drivers/gpio/gpio-mlxbf2.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 + /* 4 + * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES 5 + */ 6 + 3 7 #include <linux/bitfield.h> 4 8 #include <linux/bitops.h> 5 9 #include <linux/device.h> 6 10 #include <linux/gpio/driver.h> 11 + #include <linux/interrupt.h> 7 12 #include <linux/io.h> 8 13 #include <linux/ioport.h> 9 14 #include <linux/kernel.h> ··· 48 43 #define YU_GPIO_MODE0 0x0c 49 44 #define YU_GPIO_DATASET 0x14 50 45 #define YU_GPIO_DATACLEAR 0x18 46 + #define YU_GPIO_CAUSE_RISE_EN 0x44 47 + #define YU_GPIO_CAUSE_FALL_EN 0x48 51 48 #define YU_GPIO_MODE1_CLEAR 0x50 52 49 #define YU_GPIO_MODE0_SET 0x54 53 50 #define YU_GPIO_MODE0_CLEAR 0x58 51 + #define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80 52 + #define YU_GPIO_CAUSE_OR_EVTEN0 0x94 53 + #define YU_GPIO_CAUSE_OR_CLRCAUSE 0x98 54 54 55 55 struct mlxbf2_gpio_context_save_regs { 56 56 u32 gpio_mode0; ··· 65 55 /* BlueField-2 gpio block context structure. */ 66 56 struct mlxbf2_gpio_context { 67 57 struct gpio_chip gc; 58 + struct irq_chip irq_chip; 68 59 69 60 /* YU GPIO blocks address */ 70 61 void __iomem *gpio_io; ··· 229 218 return ret; 230 219 } 231 220 221 + static void mlxbf2_gpio_irq_enable(struct irq_data *irqd) 222 + { 223 + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 224 + struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); 225 + int offset = irqd_to_hwirq(irqd); 226 + unsigned long flags; 227 + u32 val; 228 + 229 + spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 230 + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); 231 + val |= BIT(offset); 232 + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); 233 + 234 + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); 235 + val |= BIT(offset); 236 + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); 237 + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 238 + } 239 + 240 + static void mlxbf2_gpio_irq_disable(struct irq_data *irqd) 241 + { 242 + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 243 + struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); 244 + int offset = irqd_to_hwirq(irqd); 245 + unsigned long flags; 246 + u32 val; 247 + 248 + spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 249 + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); 250 + val &= ~BIT(offset); 251 + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); 252 + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 253 + } 254 + 255 + static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr) 256 + { 257 + struct mlxbf2_gpio_context *gs = ptr; 258 + struct gpio_chip *gc = &gs->gc; 259 + unsigned long pending; 260 + u32 level; 261 + 262 + pending = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0); 263 + writel(pending, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); 264 + 265 + for_each_set_bit(level, &pending, gc->ngpio) { 266 + int gpio_irq = irq_find_mapping(gc->irq.domain, level); 267 + generic_handle_irq(gpio_irq); 268 + } 269 + 270 + return IRQ_RETVAL(pending); 271 + } 272 + 273 + static int 274 + mlxbf2_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 275 + { 276 + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 277 + struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); 278 + int offset = irqd_to_hwirq(irqd); 279 + unsigned long flags; 280 + bool fall = false; 281 + bool rise = false; 282 + u32 val; 283 + 284 + switch (type & IRQ_TYPE_SENSE_MASK) { 285 + case IRQ_TYPE_EDGE_BOTH: 286 + fall = true; 287 + rise = true; 288 + break; 289 + case IRQ_TYPE_EDGE_RISING: 290 + rise = true; 291 + break; 292 + case IRQ_TYPE_EDGE_FALLING: 293 + fall = true; 294 + break; 295 + default: 296 + return -EINVAL; 297 + } 298 + 299 + spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 300 + if (fall) { 301 + val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); 302 + val |= BIT(offset); 303 + writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); 304 + } 305 + 306 + if (rise) { 307 + val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); 308 + val |= BIT(offset); 309 + writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); 310 + } 311 + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 312 + 313 + return 0; 314 + } 315 + 232 316 /* BlueField-2 GPIO driver initialization routine. */ 233 317 static int 234 318 mlxbf2_gpio_probe(struct platform_device *pdev) 235 319 { 236 320 struct mlxbf2_gpio_context *gs; 237 321 struct device *dev = &pdev->dev; 322 + struct gpio_irq_chip *girq; 238 323 struct gpio_chip *gc; 239 324 unsigned int npins; 240 - int ret; 325 + const char *name; 326 + int ret, irq; 327 + 328 + name = dev_name(dev); 241 329 242 330 gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); 243 331 if (!gs) ··· 370 260 gc->direction_output = mlxbf2_gpio_direction_output; 371 261 gc->ngpio = npins; 372 262 gc->owner = THIS_MODULE; 263 + 264 + irq = platform_get_irq(pdev, 0); 265 + if (irq >= 0) { 266 + gs->irq_chip.name = name; 267 + gs->irq_chip.irq_set_type = mlxbf2_gpio_irq_set_type; 268 + gs->irq_chip.irq_enable = mlxbf2_gpio_irq_enable; 269 + gs->irq_chip.irq_disable = mlxbf2_gpio_irq_disable; 270 + 271 + girq = &gs->gc.irq; 272 + girq->chip = &gs->irq_chip; 273 + girq->handler = handle_simple_irq; 274 + girq->default_type = IRQ_TYPE_NONE; 275 + /* This will let us handle the parent IRQ in the driver */ 276 + girq->num_parents = 0; 277 + girq->parents = NULL; 278 + girq->parent_handler = NULL; 279 + 280 + /* 281 + * Directly request the irq here instead of passing 282 + * a flow-handler because the irq is shared. 283 + */ 284 + ret = devm_request_irq(dev, irq, mlxbf2_gpio_irq_handler, 285 + IRQF_SHARED, name, gs); 286 + if (ret) { 287 + dev_err(dev, "failed to request IRQ"); 288 + return ret; 289 + } 290 + } 373 291 374 292 platform_set_drvdata(pdev, gs); 375 293 ··· 453 315 module_platform_driver(mlxbf2_gpio_driver); 454 316 455 317 MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); 456 - MODULE_AUTHOR("Mellanox Technologies"); 318 + MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); 457 319 MODULE_LICENSE("GPL v2");