^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * AppliedMicro X-Gene SoC GPIO-Standby Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014, Applied Micro Circuits Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Tin Huynh <tnhuynh@apm.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Y Vo <yvo@apm.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Quan Nguyen <qnguyen@apm.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "gpiolib.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "gpiolib-acpi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Common property names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define XGENE_NGPIO_PROPERTY "apm,nr-gpios"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define XGENE_IRQ_START_PROPERTY "apm,irq-start"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define XGENE_DFLT_MAX_NGPIO 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define XGENE_DFLT_MAX_NIRQ 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define XGENE_DFLT_IRQ_START_PIN 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define GPIO_MASK(x) (1U << ((x) % 32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MPA_GPIO_INT_LVL 0x0290
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MPA_GPIO_OE_ADDR 0x029c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MPA_GPIO_OUT_ADDR 0x02a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MPA_GPIO_IN_ADDR 0x02a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MPA_GPIO_SEL_LO 0x0294
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define GPIO_INT_LEVEL_H 0x000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define GPIO_INT_LEVEL_L 0x000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * struct xgene_gpio_sb - GPIO-Standby private data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * @gc: memory-mapped GPIO controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * @regs: GPIO register base offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @irq_domain: GPIO interrupt domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @irq_start: GPIO pin that start support interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @nirq: Number of GPIO pins that supports interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @parent_irq_base: Start parent HWIRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct xgene_gpio_sb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct gpio_chip gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct irq_domain *irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u16 irq_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u16 nirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u16 parent_irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define HWIRQ_TO_GPIO(priv, hwirq) ((hwirq) + (priv)->irq_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define GPIO_TO_HWIRQ(priv, gpio) ((gpio) - (priv)->irq_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void xgene_gpio_set_bit(struct gpio_chip *gc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) void __iomem *reg, u32 gpio, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) data = gc->read_reg(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) data |= GPIO_MASK(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) data &= ~GPIO_MASK(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) gc->write_reg(reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct xgene_gpio_sb *priv = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int gpio = HWIRQ_TO_GPIO(priv, d->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int lvl_type = GPIO_INT_LEVEL_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) switch (type & IRQ_TYPE_SENSE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case IRQ_TYPE_LEVEL_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) lvl_type = GPIO_INT_LEVEL_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) lvl_type = GPIO_INT_LEVEL_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) gpio * 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_INT_LVL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) d->hwirq, lvl_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Propagate IRQ type setting to parent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (type & IRQ_TYPE_EDGE_BOTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return irq_chip_set_type_parent(d, IRQ_TYPE_EDGE_RISING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct irq_chip xgene_gpio_sb_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .name = "sbgpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .irq_eoi = irq_chip_eoi_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .irq_mask = irq_chip_mask_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .irq_unmask = irq_chip_unmask_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .irq_set_type = xgene_gpio_sb_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct xgene_gpio_sb *priv = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct irq_fwspec fwspec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if ((gpio < priv->irq_start) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) (gpio > HWIRQ_TO_GPIO(priv, priv->nirq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) fwspec.fwnode = gc->parent->fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fwspec.param_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fwspec.param[0] = GPIO_TO_HWIRQ(priv, gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return irq_create_fwspec_mapping(&fwspec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int xgene_gpio_sb_domain_activate(struct irq_domain *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct irq_data *irq_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) bool reserve)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct xgene_gpio_sb *priv = d->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret = gpiochip_lock_as_irq(&priv->gc, gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_err(priv->gc.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) "Unable to configure XGene GPIO standby pin %d as IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) gpio * 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void xgene_gpio_sb_domain_deactivate(struct irq_domain *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct irq_data *irq_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct xgene_gpio_sb *priv = d->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) gpiochip_unlock_as_irq(&priv->gc, gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) gpio * 2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int xgene_gpio_sb_domain_translate(struct irq_domain *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct irq_fwspec *fwspec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned long *hwirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct xgene_gpio_sb *priv = d->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if ((fwspec->param_count != 2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (fwspec->param[0] >= priv->nirq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *hwirq = fwspec->param[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *type = fwspec->param[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int xgene_gpio_sb_domain_alloc(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned int nr_irqs, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct irq_fwspec *fwspec = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct irq_fwspec parent_fwspec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct xgene_gpio_sb *priv = domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) irq_hw_number_t hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) hwirq = fwspec->param[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; i < nr_irqs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) &xgene_gpio_sb_irq_chip, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) parent_fwspec.fwnode = domain->parent->fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (is_of_node(parent_fwspec.fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) parent_fwspec.param_count = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) parent_fwspec.param[0] = 0;/* SPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Skip SGIs and PPIs*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) parent_fwspec.param[1] = hwirq + priv->parent_irq_base - 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) parent_fwspec.param[2] = fwspec->param[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) } else if (is_fwnode_irqchip(parent_fwspec.fwnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) parent_fwspec.param_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) parent_fwspec.param[0] = hwirq + priv->parent_irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) parent_fwspec.param[1] = fwspec->param[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) &parent_fwspec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static const struct irq_domain_ops xgene_gpio_sb_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .translate = xgene_gpio_sb_domain_translate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .alloc = xgene_gpio_sb_domain_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .free = irq_domain_free_irqs_common,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .activate = xgene_gpio_sb_domain_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .deactivate = xgene_gpio_sb_domain_deactivate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int xgene_gpio_sb_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct xgene_gpio_sb *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct irq_domain *parent_domain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 val32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (IS_ERR(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) priv->regs = regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ret = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) priv->parent_irq_base = irq_get_irq_data(ret)->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) parent_domain = irq_get_irq_data(ret)->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!parent_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dev_err(&pdev->dev, "unable to obtain parent domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = bgpio_init(&priv->gc, &pdev->dev, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) regs + MPA_GPIO_IN_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) regs + MPA_GPIO_OUT_ADDR, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) regs + MPA_GPIO_OE_ADDR, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) priv->gc.to_irq = xgene_gpio_sb_to_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* Retrieve start irq pin, use default if property not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) priv->irq_start = XGENE_DFLT_IRQ_START_PIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!device_property_read_u32(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) XGENE_IRQ_START_PROPERTY, &val32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) priv->irq_start = val32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Retrieve number irqs, use default if property not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) priv->nirq = XGENE_DFLT_MAX_NIRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!device_property_read_u32(&pdev->dev, XGENE_NIRQ_PROPERTY, &val32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) priv->nirq = val32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Retrieve number gpio, use default if property not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) priv->gc.ngpio = XGENE_DFLT_MAX_NGPIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!device_property_read_u32(&pdev->dev, XGENE_NGPIO_PROPERTY, &val32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) priv->gc.ngpio = val32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dev_info(&pdev->dev, "Support %d gpios, %d irqs start from pin %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) priv->gc.ngpio, priv->nirq, priv->irq_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) priv->irq_domain = irq_domain_create_hierarchy(parent_domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 0, priv->nirq, pdev->dev.fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) &xgene_gpio_sb_domain_ops, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!priv->irq_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) priv->gc.irq.domain = priv->irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret = devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) "failed to register X-Gene GPIO Standby driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) irq_domain_remove(priv->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* Register interrupt handlers for GPIO signaled ACPI Events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) acpi_gpiochip_request_interrupts(&priv->gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int xgene_gpio_sb_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) acpi_gpiochip_free_interrupts(&priv->gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) irq_domain_remove(priv->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static const struct of_device_id xgene_gpio_sb_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {.compatible = "apm,xgene-gpio-sb", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) #ifdef CONFIG_ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static const struct acpi_device_id xgene_gpio_sb_acpi_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {"APMC0D15", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) MODULE_DEVICE_TABLE(acpi, xgene_gpio_sb_acpi_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static struct platform_driver xgene_gpio_sb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .name = "xgene-gpio-sb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .of_match_table = xgene_gpio_sb_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .probe = xgene_gpio_sb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .remove = xgene_gpio_sb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) module_platform_driver(xgene_gpio_sb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) MODULE_AUTHOR("AppliedMicro");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) MODULE_DESCRIPTION("APM X-Gene GPIO Standby driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) MODULE_LICENSE("GPL");