Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6a5c272 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "pinctrl: msm: Add support for tlmm irq chip"

parents 8e854b48 d9849ca9
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -26,9 +26,25 @@ semantics.
   - qcom,num-pins: number of pins of given type present on the MSM.
   Optional: A pintype may support gpio operations. In that case, a pintype
   node can have an additional child node representing a gpio controller.
   Additionally the pintype may also support using pins as interrupt triggers.
   In this case we augment the gpio controller node with interrupt controller
   attributes. The interrupt controller node, if present, needs to specify the
   number of pins that can be used as interrupts as well as the id of the
   processor core to which they need to be routed. Generally the apps id is
   fixed for a given TLMM block in all SOCs that use that TLMM block.
   However in some SOCs, the processor id can change. Override the default
   value in that case.
   - #gpio-controller: Can be used as a gpio controller
   - #gpio-cells: Should be two. The first cell is the pin number and the
			second cell is used to specify optional parameters
   - #interrupt-controller: Can be used as an interrupt controller
   - compatible: identifies the interrupt controller feature version.
			- "msm_tlmm_v3_gpio": TLMM V3 interrupt controller.
   - num_irqs: number of pins that can be used as an interrupt source.
   - apps_id: if present, override the default core id for given TLMM block.
   - #interrupt-cells: Should be two. The first cell is the pin number used as
			irq and the second cell is used to specify optional
			flags

- Pin groups as child nodes: The pin mux (selecting pin function
  mode) and pin config (pull up/down, driver strength, direction) settings are
@@ -101,6 +117,11 @@ semantics.
			msm_gpio: msm_gpio {
				#gpio-controller;
				#gpio-cells = <2>;
				compatible = "msm_tlmm_v3_gpio";
				#interrupt-controller;
				#interrupt-cells <2>;
				num_irqs = <117>;
				apps_id = <4>;
			};
		};
		/* Sdc pin type */
+381 −3
Original line number Diff line number Diff line
@@ -9,10 +9,18 @@
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#include <asm/mach/irq.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
#include "pinctrl-msm.h"

/* config translations */
@@ -62,6 +70,28 @@
#define TLMMV3_SDC2_DATA_PULL_MASK	0x3
#define TLMMV3_SDC2_CMD_PULL_SHFT	11
#define TLMMV3_SDC2_CMD_PULL_MASK	0x3
/* TLMM V3 IRQ REG fields */
#define INTR_ENABLE_BIT		0
#define	INTR_POL_CTL_BIT	1
#define	INTR_DECT_CTL_BIT	2
#define	INTR_RAW_STATUS_EN_BIT	4
#define	INTR_TARGET_PROC_BIT	5
#define	INTR_DIR_CONN_EN_BIT	8
#define INTR_STATUS_BIT		0
#define DC_POLARITY_BIT		8

/* Target processors for TLMM pin based interrupts */
#define INTR_TARGET_PROC_APPS(core_id)	((core_id) << INTR_TARGET_PROC_BIT)
#define TLMMV3_APPS_ID_DEFAULT	4
#define INTR_TARGET_PROC_NONE	(7 << INTR_TARGET_PROC_BIT)
/* Interrupt flag bits */
#define DC_POLARITY_HI		BIT(DC_POLARITY_BIT)
#define INTR_POL_CTL_HI		BIT(INTR_POL_CTL_BIT)
#define INTR_DECT_CTL_LEVEL	(0 << INTR_DECT_CTL_BIT)
#define INTR_DECT_CTL_POS_EDGE	(1 << INTR_DECT_CTL_BIT)
#define INTR_DECT_CTL_NEG_EDGE	(2 << INTR_DECT_CTL_BIT)
#define INTR_DECT_CTL_DUAL_EDGE	(3 << INTR_DECT_CTL_BIT)
#define INTR_DECT_CTL_MASK	(3 << INTR_DECT_CTL_BIT)

#define TLMMV3_GP_INOUT_BIT		1
#define TLMMV3_GP_OUT			BIT(TLMMV3_GP_INOUT_BIT)
@@ -69,6 +99,10 @@

#define gc_to_pintype(gc) \
		container_of(gc, struct msm_pintype_info, gc)
#define ic_to_pintype(ic) \
		((struct msm_pintype_info *)ic->pinfo)
#define pintype_get_gc(pinfo)	(&pinfo->gc)
#define pintype_get_ic(pinfo)	(pinfo->irq_chip)

/* SDC Pin type register offsets */
#define TLMMV3_SDC_OFFSET		0x2044
@@ -78,6 +112,8 @@
/* GP pin type register offsets */
#define TLMMV3_GP_CFG(base, pin)		(base + 0x1000 + 0x10 * (pin))
#define TLMMV3_GP_INOUT(base, pin)		(base + 0x1004 + 0x10 * (pin))
#define TLMMV3_GP_INTR_CFG(base, pin)		(base + 0x1008 + 0x10 * (pin))
#define TLMMV3_GP_INTR_STATUS(base, pin)	(base + 0x100c + 0x10 * (pin))

struct msm_sdc_regs {
	unsigned int offset;
@@ -355,7 +391,347 @@ static int msm_tlmm_v3_gp_dir_out(struct gpio_chip *gc, unsigned offset,

static int msm_tlmm_v3_gp_to_irq(struct gpio_chip *gc, unsigned offset)
{
	return -EINVAL;
	struct msm_pintype_info *pinfo = gc_to_pintype(gc);
	struct msm_tlmm_irq_chip *ic = pintype_get_ic(pinfo);
	return irq_create_mapping(ic->domain, offset);
}

/* Irq reg ops */
static void msm_tlmm_v3_set_intr_status(struct msm_tlmm_irq_chip *ic,
								unsigned pin)
{
	void __iomem *status_reg = TLMMV3_GP_INTR_STATUS(ic->chip_base, pin);
	writel_relaxed(0, status_reg);
}

static int msm_tlmm_v3_get_intr_status(struct msm_tlmm_irq_chip *ic,
								unsigned pin)
{
	void __iomem *status_reg = TLMMV3_GP_INTR_STATUS(ic->chip_base, pin);
	return readl_relaxed(status_reg) & BIT(INTR_STATUS_BIT);
}

static void msm_tlmm_v3_set_intr_cfg_enable(struct msm_tlmm_irq_chip *ic,
								unsigned pin,
								int enable)
{
	unsigned int val;
	void __iomem *cfg_reg = TLMMV3_GP_INTR_CFG(ic->chip_base, pin);

	val = readl_relaxed(cfg_reg);
	if (enable) {
		val &= ~BIT(INTR_DIR_CONN_EN_BIT);
		val |= BIT(INTR_ENABLE_BIT);
	} else
		val &= ~BIT(INTR_ENABLE_BIT);
	writel_relaxed(val, cfg_reg);
}

static int msm_tlmm_v3_get_intr_cfg_enable(struct msm_tlmm_irq_chip *ic,
								unsigned pin)
{
	void __iomem *cfg_reg = TLMMV3_GP_INTR_CFG(ic->chip_base, pin);
	return readl_relaxed(cfg_reg) & BIT(INTR_ENABLE_BIT);
}

static void msm_tlmm_v3_set_intr_cfg_type(struct msm_tlmm_irq_chip *ic,
							struct irq_data *d,
							unsigned int type)
{
	unsigned cfg;
	void __iomem *cfg_reg = TLMMV3_GP_INTR_CFG(ic->chip_base,
							(irqd_to_hwirq(d)));
	/*
	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the
	 * internal circuitry of TLMM, toggling the RAW_STATUS
	 * could cause the INTR_STATUS to be set for EDGE interrupts.
	 */
	cfg = BIT(INTR_RAW_STATUS_EN_BIT) | INTR_TARGET_PROC_APPS(ic->apps_id);
	writel_relaxed(cfg, cfg_reg);
	cfg &= ~INTR_DECT_CTL_MASK;
	if (type == IRQ_TYPE_EDGE_RISING)
		cfg |= INTR_DECT_CTL_POS_EDGE;
	else if (type == IRQ_TYPE_EDGE_FALLING)
		cfg |= INTR_DECT_CTL_NEG_EDGE;
	else if (type == IRQ_TYPE_EDGE_BOTH)
		cfg |= INTR_DECT_CTL_DUAL_EDGE;
	else
		cfg |= INTR_DECT_CTL_LEVEL;

	if (type & IRQ_TYPE_LEVEL_LOW)
		cfg &= ~INTR_POL_CTL_HI;
	else
		cfg |= INTR_POL_CTL_HI;

	writel_relaxed(cfg, cfg_reg);
	/*
	 * Sometimes it might take a little while to update
	 * the interrupt status after the RAW_STATUS is enabled
	 * We clear the interrupt status before enabling the
	 * interrupt in the unmask call-back.
	 */
	udelay(5);
}

static irqreturn_t msm_tlmm_v3_irq_handle(int irq, void *data)
{
	unsigned long i;
	unsigned int virq = 0;
	struct msm_tlmm_irq_chip *ic = (struct msm_tlmm_irq_chip *)data;
	struct irq_desc *desc = irq_to_desc(irq);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	struct msm_pintype_info *pinfo = ic_to_pintype(ic);
	struct gpio_chip *gc = pintype_get_gc(pinfo);

	chained_irq_enter(chip, desc);
	for_each_set_bit(i, ic->enabled_irqs, ic->num_irqs)
	 {
		dev_dbg(ic->dev, "hwirq in bit mask %d\n", (unsigned int)i);
		if (msm_tlmm_v3_get_intr_status(ic, i)) {
			dev_dbg(ic->dev, "hwirw %d fired\n", (unsigned int)i);
			virq = msm_tlmm_v3_gp_to_irq(gc, i);
			if (!virq) {
				dev_dbg(ic->dev, "invalid virq\n");
				return IRQ_NONE;
			}
			generic_handle_irq(virq);
		}

	}
	chained_irq_exit(chip, desc);
	return IRQ_HANDLED;
}

static void msm_tlmm_v3_irq_ack(struct irq_data *d)
{
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);

	msm_tlmm_v3_set_intr_status(ic, irqd_to_hwirq(d));
	mb();
}

static void msm_tlmm_v3_irq_mask(struct irq_data *d)
{
	unsigned long irq_flags;
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);

	spin_lock_irqsave(&ic->irq_lock, irq_flags);
	msm_tlmm_v3_set_intr_cfg_enable(ic, irqd_to_hwirq(d), 0);
	__clear_bit(irqd_to_hwirq(d), ic->enabled_irqs);
	mb();
	spin_unlock_irqrestore(&ic->irq_lock, irq_flags);
	if (ic->irq_chip_extn->irq_mask)
		ic->irq_chip_extn->irq_mask(d);
}

static void msm_tlmm_v3_irq_unmask(struct irq_data *d)
{
	unsigned long irq_flags;
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);

	spin_lock_irqsave(&ic->irq_lock, irq_flags);
	__set_bit(irqd_to_hwirq(d), ic->enabled_irqs);
	if (!msm_tlmm_v3_get_intr_cfg_enable(ic, irqd_to_hwirq(d))) {
		msm_tlmm_v3_set_intr_status(ic, irqd_to_hwirq(d));
		msm_tlmm_v3_set_intr_cfg_enable(ic, irqd_to_hwirq(d), 1);
		mb();
	}
	spin_unlock_irqrestore(&ic->irq_lock, irq_flags);
	if (ic->irq_chip_extn->irq_unmask)
		ic->irq_chip_extn->irq_unmask(d);
}

static void msm_tlmm_v3_irq_disable(struct irq_data *d)
{
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);
	if (ic->irq_chip_extn->irq_disable)
		ic->irq_chip_extn->irq_disable(d);
}

static int msm_tlmm_v3_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
	unsigned long irq_flags;
	unsigned int pin = irqd_to_hwirq(d);
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);


	spin_lock_irqsave(&ic->irq_lock, irq_flags);

	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
		__irq_set_handler_locked(d->irq, handle_edge_irq);
		if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
			__set_bit(pin, ic->dual_edge_irqs);
		else
			__clear_bit(pin, ic->dual_edge_irqs);
	} else {
		__irq_set_handler_locked(d->irq, handle_level_irq);
		__clear_bit(pin, ic->dual_edge_irqs);
	}

	msm_tlmm_v3_set_intr_cfg_type(ic, d, flow_type);

	mb();
	spin_unlock_irqrestore(&ic->irq_lock, irq_flags);

	if ((flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) {
		if (ic->irq_chip_extn->irq_set_type)
			ic->irq_chip_extn->irq_set_type(d, flow_type);
	}

	return 0;
}

static int msm_tlmm_v3_irq_set_wake(struct irq_data *d, unsigned int on)
{
	unsigned int pin = irqd_to_hwirq(d);
	struct msm_tlmm_irq_chip *ic = irq_data_get_irq_chip_data(d);

	if (on) {
		if (bitmap_empty(ic->wake_irqs, ic->num_irqs))
			irq_set_irq_wake(ic->irq, 1);
		set_bit(pin, ic->wake_irqs);
	} else {
		clear_bit(pin, ic->wake_irqs);
		if (bitmap_empty(ic->wake_irqs, ic->num_irqs))
			irq_set_irq_wake(ic->irq, 0);
	}

	if (ic->irq_chip_extn->irq_set_wake)
		ic->irq_chip_extn->irq_set_wake(d, on);

	return 0;
}

static struct lock_class_key msm_tlmm_irq_lock_class;

static int msm_tlmm_v3_irq_map(struct irq_domain *h, unsigned int virq,
					irq_hw_number_t hw)
{
	struct msm_tlmm_irq_chip *ic = h->host_data;

	irq_set_lockdep_class(virq, &msm_tlmm_irq_lock_class);
	irq_set_chip_data(virq, ic);
	irq_set_chip_and_handler(virq, &ic->chip,
					handle_level_irq);
	set_irq_flags(virq, IRQF_VALID);
	return 0;
}

/*
 * irq domain callbacks for interrupt controller.
 */
static const struct irq_domain_ops msm_tlmm_v3_gp_irqd_ops = {
	.map	= msm_tlmm_v3_irq_map,
	.xlate	= irq_domain_xlate_twocell,
};

struct irq_chip mpm_tlmm_irq_extn = {
	.irq_eoi	= NULL,
	.irq_mask	= NULL,
	.irq_unmask	= NULL,
	.irq_retrigger	= NULL,
	.irq_set_type	= NULL,
	.irq_set_wake	= NULL,
	.irq_disable	= NULL,
};

static struct msm_tlmm_irq_chip msm_tlmm_v3_gp_irq = {
			.irq_chip_extn = &mpm_tlmm_irq_extn,
			.chip = {
				.name		= "msm_tlmm_v3_irq",
				.irq_mask	= msm_tlmm_v3_irq_mask,
				.irq_unmask	= msm_tlmm_v3_irq_unmask,
				.irq_ack	= msm_tlmm_v3_irq_ack,
				.irq_set_type	= msm_tlmm_v3_irq_set_type,
				.irq_set_wake	= msm_tlmm_v3_irq_set_wake,
				.irq_disable	= msm_tlmm_v3_irq_disable,
			},
			.apps_id = TLMMV3_APPS_ID_DEFAULT,
			.domain_ops = &msm_tlmm_v3_gp_irqd_ops,
};

/* Power management core operations */

static int msm_tlmm_v3_gp_irq_suspend(void)
{
	unsigned long irq_flags;
	unsigned long i;
	struct msm_tlmm_irq_chip *ic = &msm_tlmm_v3_gp_irq;
	int num_irqs = ic->num_irqs;

	spin_lock_irqsave(&ic->irq_lock, irq_flags);
	for_each_set_bit(i, ic->enabled_irqs, num_irqs)
		msm_tlmm_v3_set_intr_cfg_enable(ic, i, 0);

	for_each_set_bit(i, ic->enabled_irqs, num_irqs)
		msm_tlmm_v3_set_intr_cfg_enable(ic, i, 1);
	mb();
	spin_unlock_irqrestore(&ic->irq_lock, irq_flags);
	return 0;
}

static void msm_tlmm_v3_gp_irq_resume(void)
{
	unsigned long irq_flags;
	unsigned long i;
	struct msm_tlmm_irq_chip *ic = &msm_tlmm_v3_gp_irq;
	int num_irqs = ic->num_irqs;

	spin_lock_irqsave(&ic->irq_lock, irq_flags);
	for_each_set_bit(i, ic->wake_irqs, num_irqs)
		msm_tlmm_v3_set_intr_cfg_enable(ic, i, 0);

	for_each_set_bit(i, ic->enabled_irqs, num_irqs)
		msm_tlmm_v3_set_intr_cfg_enable(ic, i, 1);
	mb();
	spin_unlock_irqrestore(&ic->irq_lock, irq_flags);
}

static struct syscore_ops msm_tlmm_v3_irq_syscore_ops = {
	.suspend = msm_tlmm_v3_gp_irq_suspend,
	.resume = msm_tlmm_v3_gp_irq_resume,
};

static int msm_tlmm_v3_gp_irq_init(int irq, struct msm_pintype_info *pinfo,
						struct device *tlmm_dev)
{
	int ret, num_irqs;
	struct msm_tlmm_irq_chip *ic = pinfo->irq_chip;

	num_irqs = ic->num_irqs;
	ret = devm_request_irq(tlmm_dev, irq, msm_tlmm_v3_irq_handle,
						IRQF_TRIGGER_HIGH,
						dev_name(tlmm_dev), ic);
	if (ret) {
		dev_err(tlmm_dev, "unable to register irq %d\n", irq);
		return ret;
	}
	ic->enabled_irqs = devm_kzalloc(tlmm_dev, sizeof(unsigned long)
					* BITS_TO_LONGS(num_irqs), GFP_KERNEL);
	if (IS_ERR(ic->enabled_irqs)) {
		dev_err(tlmm_dev, "Unable to allocate enabled irqs bitmap\n");
		return PTR_ERR(ic->enabled_irqs);
	}
	ic->dual_edge_irqs = devm_kzalloc(tlmm_dev, sizeof(unsigned long)
					* BITS_TO_LONGS(num_irqs), GFP_KERNEL);
	if (IS_ERR(ic->dual_edge_irqs)) {
		dev_err(tlmm_dev, "Unable to allocate dual edge irqs bitmap\n");
		return PTR_ERR(ic->dual_edge_irqs);
	}
	ic->wake_irqs = devm_kzalloc(tlmm_dev, sizeof(unsigned long)
					* BITS_TO_LONGS(num_irqs), GFP_KERNEL);
	if (IS_ERR(ic->wake_irqs)) {
		dev_err(tlmm_dev, "Unable to allocate dual edge irqs bitmap\n");
		return PTR_ERR(ic->wake_irqs);
	}
	spin_lock_init(&ic->irq_lock);
	ic->chip_base = pinfo->reg_base;
	ic->irq = irq;
	ic->dev = tlmm_dev;
	ic->num_irqs = pinfo->num_pins;
	ic->pinfo = pinfo;
	register_syscore_ops(&msm_tlmm_v3_irq_syscore_ops);
	return 0;
}

static struct msm_pintype_info tlmm_v3_pininfo[] = {
@@ -374,6 +750,8 @@ static struct msm_pintype_info tlmm_v3_pininfo[] = {
				.set              = msm_tlmm_v3_gp_set,
				.to_irq           = msm_tlmm_v3_gp_to_irq,
		},
		.init_irq = msm_tlmm_v3_gp_irq_init,
		.irq_chip = &msm_tlmm_v3_gp_irq,
	},
	{
		.prg_cfg = msm_tlmm_v3_sdc_cfg,
+32 −0
Original line number Diff line number Diff line
@@ -553,6 +553,21 @@ static bool msm_pintype_supports_gpio(struct msm_pintype_info *pinfo)
	return false;
}

static bool msm_pintype_supports_irq(struct msm_pintype_info *pinfo)
{
	struct device_node *pt_node;

	if (!pinfo->init_irq)
		return false;
	for_each_child_of_node(pinfo->node, pt_node) {
		if (of_find_property(pt_node, "interrupt-controller", NULL)) {
			pinfo->irq_chip->node = pt_node;
			return true;
		}
	}
	return false;
}

static int msm_pinctrl_dt_parse_pintype(struct device_node *dev_node,
						struct msm_pinctrl_dd *dd)
{
@@ -743,6 +758,22 @@ static void msm_register_gpiochip(struct msm_pinctrl_dd *dd)
	}
}

static int msm_register_irqchip(struct msm_pinctrl_dd *dd)
{
	struct msm_pintype_info *pintype, *pinfo;
	int i, ret = 0;

	pinfo = dd->msm_pintype;
	for (i = 0; i < dd->num_pintypes; i++) {
		pintype = &pinfo[i];
		if (!msm_pintype_supports_irq(pintype))
			continue;
		ret = pintype->init_irq(dd->irq, pintype, dd->dev);
		return ret;
	}
	return 0;
}

static int msm_pinctrl_probe(struct platform_device *pdev)
{
	struct msm_pinctrl_dd *dd;
@@ -780,6 +811,7 @@ static int msm_pinctrl_probe(struct platform_device *pdev)
		msm_pinctrl_cleanup_dd(dd);
		return ret;
	}
	msm_register_irqchip(dd);
	platform_set_drvdata(pdev, dd);
	return 0;
}
+40 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#define __PINCTRL_MSM_H__

#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
@@ -44,12 +45,47 @@ struct msm_pmx_funcs {
	unsigned num_grps;
};

/**
 * struct msm_tlmm_irq_chip: represents interrupt controller descriptor
 * @irq: irq number for tlmm summary interrupt.
 * @chip_base: base register for TLMM.
 * @num_irqs: number of pins that can be used as irq lines.
 * @apps_id: id assigned to the apps processor.
 * @enabled_irqs: bitmask of pins enabled as interrupts.
 * @wake_irqs: bitmask of pins enabled as wake up interrupts.
 * @irq_lock: protect against concurrent access.
 * @domain: irq domain of given interrupt controller
 * @irq_chip: irq chip operations.
 * @irq_chip_extn: extension of irq chip operations.
 * @dev: TLMM device.
 * @device_node: device tree node of interrupt controller.
 * @pinfo: pintype information.
 */
struct msm_tlmm_irq_chip {
	int irq;
	void *__iomem chip_base;
	unsigned int num_irqs;
	unsigned int apps_id;
	unsigned long *enabled_irqs;
	unsigned long *dual_edge_irqs;
	unsigned long *wake_irqs;
	spinlock_t irq_lock;
	struct irq_domain *domain;
	const struct irq_domain_ops *domain_ops;
	struct irq_chip chip;
	struct irq_chip *irq_chip_extn;
	struct device *dev;
	struct device_node *node;
	void *pinfo;
};

/**
 * struct msm_pintype_info: represent a pin type supported by the TLMM.
 * @prg_cfg: helper to program a given config for a pintype.
 * @prg_func: helper to program a given func for a pintype.
 * @pack_cfg: helper to pack a parsed config as per a pintype.
 * @set_reg_base: helper to set the register base address for a pintype.
 * @init_irq: helper to initialize any irq functionality.
 * @reg_data: register base for a pintype.
 * @prop_name: DT property name for a pintype.
 * @name: name of pintype.
@@ -57,6 +93,7 @@ struct msm_pmx_funcs {
 * @pin_start: starting pin number for the given pintype within pinctroller.
 * @pin_end: ending pin number for the given pintype within pinctroller.
 * @gc: gpio chip implementation for pin type.
 * @irq_chip: interrupt controller support for given pintype.
 * @supports_gpio: pintype supports gpio function.
 * @grange: pins that map to gpios.
 * @node: device node for the pintype.
@@ -67,6 +104,8 @@ struct msm_pintype_info {
	void (*prg_func)(uint pin_no, u32 func, void *reg_data, bool enable);
	void (*set_reg_base)(void __iomem **ptype_base,
						void __iomem *tlmm_base);
	int (*init_irq)(int irq, struct msm_pintype_info *pinfo,
						struct device *tlmm_dev);
	void __iomem *reg_base;
	const char *prop_name;
	const char *name;
@@ -74,6 +113,7 @@ struct msm_pintype_info {
	int pin_start;
	int pin_end;
	struct gpio_chip gc;
	struct msm_tlmm_irq_chip *irq_chip;
	bool supports_gpio;
	struct pinctrl_gpio_range grange;
	struct device_node *node;