Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");