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

misc: microchip: pci1xxxx: Add GPIO Wakeup Support

The patch adds PIO asynchronous wakeup support while PIO PCIe Endpoint
function is in D3 state. When such a wakeup event occurs, the PIO
asserts a PIO_WAKE signal, which in turn triggers PCIe Wake signaling.
This wake request should trigger the PCIe Host to take the PIO PCIe
Endpoint function into the D0 device state.

The device supports up to 96 PIOs distributed across three GPIO banks.
During suspend and resume, the driver checks the status of each GPIO bank
to determine if any GPIOs with wake masking enabled have triggered an
event. Upon resume, PIOxx_STATUS register must be cleared by software
explicitly to enable the detection of the next transition.

Signed-off-by: Rengarajan S <rengarajan.s@microchip.com>
Link: https://lore.kernel.org/r/20250513091557.3660-3-rengarajan.s@microchip.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Rengarajan S and committed by
Greg Kroah-Hartman
fb410aa4 7c970c65

+61
+61
drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
··· 42 42 raw_spinlock_t wa_lock; 43 43 struct gpio_chip gpio; 44 44 spinlock_t lock; 45 + u32 gpio_wake_mask[3]; 45 46 int irq_base; 46 47 u8 dev_rev; 47 48 }; ··· 274 273 return true; 275 274 } 276 275 276 + static int pci1xxxx_gpio_set_wake(struct irq_data *data, unsigned int enable) 277 + { 278 + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 279 + struct pci1xxxx_gpio *priv = gpiochip_get_data(chip); 280 + unsigned int gpio = irqd_to_hwirq(data); 281 + unsigned int bitpos = gpio % 32; 282 + unsigned int bank = gpio / 32; 283 + 284 + if (enable) 285 + priv->gpio_wake_mask[bank] |= (1 << bitpos); 286 + else 287 + priv->gpio_wake_mask[bank] &= ~(1 << bitpos); 288 + 289 + return 0; 290 + } 291 + 277 292 static irqreturn_t pci1xxxx_gpio_irq_handler(int irq, void *dev_id) 278 293 { 279 294 struct pci1xxxx_gpio *priv = dev_id; ··· 337 320 .irq_mask = pci1xxxx_gpio_irq_mask, 338 321 .irq_unmask = pci1xxxx_gpio_irq_unmask, 339 322 .irq_set_type = pci1xxxx_gpio_set_type, 323 + .irq_set_wake = pci1xxxx_gpio_set_wake, 340 324 .flags = IRQCHIP_IMMUTABLE, 341 325 GPIOCHIP_IRQ_RESOURCE_HELPERS, 342 326 }; ··· 345 327 static int pci1xxxx_gpio_suspend(struct device *dev) 346 328 { 347 329 struct pci1xxxx_gpio *priv = dev_get_drvdata(dev); 330 + struct device *parent = priv->aux_dev->dev.parent; 331 + struct pci_dev *pcidev = to_pci_dev(parent); 332 + unsigned int gpio_bank_base; 333 + unsigned int wake_mask; 334 + unsigned int gpiobank; 348 335 unsigned long flags; 336 + 337 + for (gpiobank = 0; gpiobank < 3; gpiobank++) { 338 + wake_mask = priv->gpio_wake_mask[gpiobank]; 339 + 340 + if (wake_mask) { 341 + gpio_bank_base = gpiobank * 32; 342 + 343 + pci1xxx_assign_bit(priv->reg_base, 344 + PIO_PCI_CTRL_REG_OFFSET, 0, true); 345 + writel(~wake_mask, priv->reg_base + 346 + WAKEMASK_OFFSET(gpio_bank_base)); 347 + } 348 + } 349 349 350 350 spin_lock_irqsave(&priv->lock, flags); 351 351 pci1xxx_assign_bit(priv->reg_base, PIO_GLOBAL_CONFIG_OFFSET, ··· 377 341 378 342 spin_unlock_irqrestore(&priv->lock, flags); 379 343 344 + device_set_wakeup_enable(&pcidev->dev, true); 345 + pci_wake_from_d3(pcidev, true); 346 + 380 347 return 0; 381 348 } 382 349 383 350 static int pci1xxxx_gpio_resume(struct device *dev) 384 351 { 385 352 struct pci1xxxx_gpio *priv = dev_get_drvdata(dev); 353 + struct device *parent = priv->aux_dev->dev.parent; 354 + struct pci_dev *pcidev = to_pci_dev(parent); 355 + unsigned int gpio_bank_base; 356 + unsigned int wake_mask; 357 + unsigned int gpiobank; 386 358 unsigned long flags; 359 + 360 + for (gpiobank = 0; gpiobank < 3; gpiobank++) { 361 + wake_mask = priv->gpio_wake_mask[gpiobank]; 362 + 363 + if (wake_mask) { 364 + gpio_bank_base = gpiobank * 32; 365 + 366 + writel(wake_mask, priv->reg_base + 367 + INTR_STAT_OFFSET(gpio_bank_base)); 368 + pci1xxx_assign_bit(priv->reg_base, 369 + PIO_PCI_CTRL_REG_OFFSET, 0, false); 370 + writel(0xffffffff, priv->reg_base + 371 + WAKEMASK_OFFSET(gpio_bank_base)); 372 + } 373 + } 387 374 388 375 spin_lock_irqsave(&priv->lock, flags); 389 376 pci1xxx_assign_bit(priv->reg_base, PIO_GLOBAL_CONFIG_OFFSET, ··· 419 360 pci1xxx_assign_bit(priv->reg_base, PERI_GEN_RESET, 17, false); 420 361 421 362 spin_unlock_irqrestore(&priv->lock, flags); 363 + 364 + pci_wake_from_d3(pcidev, false); 422 365 423 366 return 0; 424 367 }