Skip to content

Commit fb410aa

Browse files
RengarajanSSgregkh
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7c970c6 commit fb410aa

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct pci1xxxx_gpio {
4242
raw_spinlock_t wa_lock;
4343
struct gpio_chip gpio;
4444
spinlock_t lock;
45+
u32 gpio_wake_mask[3];
4546
int irq_base;
4647
u8 dev_rev;
4748
};
@@ -273,6 +274,22 @@ static int pci1xxxx_gpio_set_type(struct irq_data *data, unsigned int trigger_ty
273274
return true;
274275
}
275276

277+
static int pci1xxxx_gpio_set_wake(struct irq_data *data, unsigned int enable)
278+
{
279+
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
280+
struct pci1xxxx_gpio *priv = gpiochip_get_data(chip);
281+
unsigned int gpio = irqd_to_hwirq(data);
282+
unsigned int bitpos = gpio % 32;
283+
unsigned int bank = gpio / 32;
284+
285+
if (enable)
286+
priv->gpio_wake_mask[bank] |= (1 << bitpos);
287+
else
288+
priv->gpio_wake_mask[bank] &= ~(1 << bitpos);
289+
290+
return 0;
291+
}
292+
276293
static irqreturn_t pci1xxxx_gpio_irq_handler(int irq, void *dev_id)
277294
{
278295
struct pci1xxxx_gpio *priv = dev_id;
@@ -320,15 +337,34 @@ static const struct irq_chip pci1xxxx_gpio_irqchip = {
320337
.irq_mask = pci1xxxx_gpio_irq_mask,
321338
.irq_unmask = pci1xxxx_gpio_irq_unmask,
322339
.irq_set_type = pci1xxxx_gpio_set_type,
340+
.irq_set_wake = pci1xxxx_gpio_set_wake,
323341
.flags = IRQCHIP_IMMUTABLE,
324342
GPIOCHIP_IRQ_RESOURCE_HELPERS,
325343
};
326344

327345
static int pci1xxxx_gpio_suspend(struct device *dev)
328346
{
329347
struct pci1xxxx_gpio *priv = dev_get_drvdata(dev);
348+
struct device *parent = priv->aux_dev->dev.parent;
349+
struct pci_dev *pcidev = to_pci_dev(parent);
350+
unsigned int gpio_bank_base;
351+
unsigned int wake_mask;
352+
unsigned int gpiobank;
330353
unsigned long flags;
331354

355+
for (gpiobank = 0; gpiobank < 3; gpiobank++) {
356+
wake_mask = priv->gpio_wake_mask[gpiobank];
357+
358+
if (wake_mask) {
359+
gpio_bank_base = gpiobank * 32;
360+
361+
pci1xxx_assign_bit(priv->reg_base,
362+
PIO_PCI_CTRL_REG_OFFSET, 0, true);
363+
writel(~wake_mask, priv->reg_base +
364+
WAKEMASK_OFFSET(gpio_bank_base));
365+
}
366+
}
367+
332368
spin_lock_irqsave(&priv->lock, flags);
333369
pci1xxx_assign_bit(priv->reg_base, PIO_GLOBAL_CONFIG_OFFSET,
334370
16, true);
@@ -341,14 +377,37 @@ static int pci1xxxx_gpio_suspend(struct device *dev)
341377

342378
spin_unlock_irqrestore(&priv->lock, flags);
343379

380+
device_set_wakeup_enable(&pcidev->dev, true);
381+
pci_wake_from_d3(pcidev, true);
382+
344383
return 0;
345384
}
346385

347386
static int pci1xxxx_gpio_resume(struct device *dev)
348387
{
349388
struct pci1xxxx_gpio *priv = dev_get_drvdata(dev);
389+
struct device *parent = priv->aux_dev->dev.parent;
390+
struct pci_dev *pcidev = to_pci_dev(parent);
391+
unsigned int gpio_bank_base;
392+
unsigned int wake_mask;
393+
unsigned int gpiobank;
350394
unsigned long flags;
351395

396+
for (gpiobank = 0; gpiobank < 3; gpiobank++) {
397+
wake_mask = priv->gpio_wake_mask[gpiobank];
398+
399+
if (wake_mask) {
400+
gpio_bank_base = gpiobank * 32;
401+
402+
writel(wake_mask, priv->reg_base +
403+
INTR_STAT_OFFSET(gpio_bank_base));
404+
pci1xxx_assign_bit(priv->reg_base,
405+
PIO_PCI_CTRL_REG_OFFSET, 0, false);
406+
writel(0xffffffff, priv->reg_base +
407+
WAKEMASK_OFFSET(gpio_bank_base));
408+
}
409+
}
410+
352411
spin_lock_irqsave(&priv->lock, flags);
353412
pci1xxx_assign_bit(priv->reg_base, PIO_GLOBAL_CONFIG_OFFSET,
354413
17, true);
@@ -361,6 +420,8 @@ static int pci1xxxx_gpio_resume(struct device *dev)
361420

362421
spin_unlock_irqrestore(&priv->lock, flags);
363422

423+
pci_wake_from_d3(pcidev, false);
424+
364425
return 0;
365426
}
366427

0 commit comments

Comments
 (0)