161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * S3C64xx specific support for pinctrl-samsung driver.
361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa *
461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa *
661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Based on pinctrl-exynos.c, please see the file for original copyrights.
761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa *
861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * This program is free software; you can redistribute it and/or modify
961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * it under the terms of the GNU General Public License as published by
1061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * the Free Software Foundation; either version 2 of the License, or
1161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * (at your option) any later version.
1261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa *
1361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * This file contains the Samsung S3C64xx specific information required by the
1461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
1561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * external gpio and wakeup interrupt support.
1661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
1761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
1861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/module.h>
1961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/device.h>
2061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/interrupt.h>
2161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/irqdomain.h>
2261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/irq.h>
2361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/of_irq.h>
2461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/io.h>
25a0d4262a25966aa34674397ba6b438dc025827efTomasz Figa#include <linux/irqchip/chained_irq.h>
2661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/slab.h>
2761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/err.h>
2861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
2961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include "pinctrl-samsung.h"
3061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
3161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define NUM_EINT0		28
3261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define NUM_EINT0_IRQ		4
3361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_MAX_PER_REG	16
3461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_MAX_PER_GROUP	16
3561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
3661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* External GPIO and wakeup interrupt related definitions */
3761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP_SHIFT		4
3861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP_MASK		0xf
3961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_NUM_MASK		0xf
4061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP(x)		((x >> SVC_GROUP_SHIFT) & \
4161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa						SVC_GROUP_MASK)
4261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
4361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12CON_REG		0x200
4461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12MASK_REG		0x240
4561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12PEND_REG		0x260
4661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
4761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_OFFS(i)		((i) % (2 * EINT_MAX_PER_GROUP))
4861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_GROUP(i)		((i) / EINT_MAX_PER_GROUP)
4961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_REG(g)		(4 * ((g) / 2))
5061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
5161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTCON_REG(i)		(EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
5261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTMASK_REG(i)		(EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
5361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTPEND_REG(i)		(EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
5461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
5561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SERVICE_REG		0x284
5661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SERVICEPEND_REG		0x288
5761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
5861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0CON0_REG		0x900
5961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0MASK_REG		0x920
6061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0PEND_REG		0x924
6161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
6261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* S3C64xx specific external interrupt trigger types */
6361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_LEVEL_LOW		0
6461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_LEVEL_HIGH		1
6561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_FALLING	2
6661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_RISING	4
6761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_BOTH		6
6861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_CON_MASK		0xF
6961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_CON_LEN		4
7061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
7161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit_off = {
7261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 4, 1, 2, 0, 2, 2, },
7361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
7461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
7561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
7661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit_alive = {
7761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 4, 1, 2, },
7861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x04, 0x08, },
7961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
8061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
8161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit2_off = {
8261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 4, 1, 2, 0, 2, 2, },
8361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
8461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
8561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
8661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit2_alive = {
8761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 4, 1, 2, },
8861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x08, 0x0c, },
8961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
9061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
9161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_2bit_off = {
9261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 2, 1, 2, 0, 2, 2, },
9361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
9461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
9561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
9661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_2bit_alive = {
9761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.fld_width = { 2, 1, 2, },
9861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.reg_offset = { 0x00, 0x04, 0x08, },
9961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
10061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
10161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT(pins, reg, id)			\
10261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
10361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit_off,	\
10461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
10561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
10661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_NONE,	\
10761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
10861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
10961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
11061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs)	\
11161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
11261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit_off,	\
11361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
11461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
11561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_GPIO,	\
11661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 7,			\
11761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= (1 << (pins)) - 1,	\
11861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
11961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
12061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
12161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
12261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
12361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
12461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit_alive,\
12561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
12661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
12761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_WKUP,	\
12861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 3,			\
12961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= emask,		\
13061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
13161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
13261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
13361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
13461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs)	\
13561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
13661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit2_off,	\
13761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
13861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
13961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_GPIO,	\
14061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 7,			\
14161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= (1 << (pins)) - 1,	\
14261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
14361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
14461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
14561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
14661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
14761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
14861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit2_alive,\
14961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
15061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
15161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_WKUP,	\
15261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 3,			\
15361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= emask,		\
15461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
15561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
15661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
15761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
15861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_ALIVE(pins, reg, id)		\
15961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
16061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_4bit2_alive,\
16161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
16261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
16361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_NONE,	\
16461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
16561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
16661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
16761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT(pins, reg, id)			\
16861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
16961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_2bit_off,	\
17061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
17161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
17261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_NONE,	\
17361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
17461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
17561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
17661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
17761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
17861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_2bit_off,	\
17961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
18061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
18161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_GPIO,	\
18261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 3,			\
18361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= emask,		\
18461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
18561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
18661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
18761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
18861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs)	\
18961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{						\
19061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.type		= &bank_type_2bit_alive,\
19161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pctl_offset	= reg,			\
19261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_pins	= pins,			\
19361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_type	= EINT_TYPE_WKUP,	\
19461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_func	= 2,			\
19561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_mask	= (1 << (pins)) - 1,	\
19661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_offset	= eoffs,		\
19761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.name		= id			\
19861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
19961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
20061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/**
20161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint0_data: EINT0 common data
20261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @drvdata: pin controller driver data
20361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @domains: IRQ domains of particular EINT0 interrupts
20461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @pins: pin offsets inside of banks of particular EINT0 interrupts
20561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
20661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint0_data {
20761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *drvdata;
20861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct irq_domain *domains[NUM_EINT0];
20961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u8 pins[NUM_EINT0];
21061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
21161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
21261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/**
21361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint0_domain_data: EINT0 per-domain data
21461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @bank: pin bank related to the domain
21561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @eints: EINT0 interrupts related to the domain
21661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
21761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint0_domain_data {
21861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank;
21961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u8 eints[];
22061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
22161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
22261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/**
22361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint_gpio_data: GPIO EINT data
22461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @drvdata: pin controller driver data
22561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @domains: array of domains related to EINT interrupt groups
22661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
22761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint_gpio_data {
22861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *drvdata;
22961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct irq_domain *domains[];
23061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
23161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
23261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
23361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Common functions for S3C64xx EINT configuration
23461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
23561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
23661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_irq_get_trigger(unsigned int type)
23761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
23861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	int trigger;
23961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
24061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	switch (type) {
24161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	case IRQ_TYPE_EDGE_RISING:
24261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		trigger = EINT_EDGE_RISING;
24361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		break;
24461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	case IRQ_TYPE_EDGE_FALLING:
24561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		trigger = EINT_EDGE_FALLING;
24661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		break;
24761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	case IRQ_TYPE_EDGE_BOTH:
24861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		trigger = EINT_EDGE_BOTH;
24961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		break;
25061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	case IRQ_TYPE_LEVEL_HIGH:
25161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		trigger = EINT_LEVEL_HIGH;
25261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		break;
25361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	case IRQ_TYPE_LEVEL_LOW:
25461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		trigger = EINT_LEVEL_LOW;
25561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		break;
25661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	default:
25761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
25861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
25961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
26061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return trigger;
26161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
26261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
26361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
26461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
26561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	/* Edge- and level-triggered interrupts need different handlers */
26661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (type & IRQ_TYPE_EDGE_BOTH)
26761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		__irq_set_handler_locked(irq, handle_edge_irq);
26861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	else
26961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		__irq_set_handler_locked(irq, handle_level_irq);
27061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
27161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
27261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
27361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					struct samsung_pin_bank *bank, int pin)
27461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
27561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank_type *bank_type = bank->type;
27661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned long flags;
27761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	void __iomem *reg;
27861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u8 shift;
27961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 mask;
28061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 val;
28161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
28261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	/* Make sure that pin is configured as interrupt */
28361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	reg = d->virt_base + bank->pctl_offset;
28461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = pin;
28561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
28661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		/* 4-bit bank type with 2 con regs */
28761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		reg += 4;
28861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		shift -= 8;
28961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
29061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
29161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
29261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
29361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
29461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	spin_lock_irqsave(&bank->slock, flags);
29561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
29661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val = readl(reg);
29761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val &= ~(mask << shift);
29861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val |= bank->eint_func << shift;
29961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(val, reg);
30061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
30161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	spin_unlock_irqrestore(&bank->slock, flags);
30261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
30361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
30461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
30561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Functions for EINT GPIO configuration (EINT groups 1-9)
30661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
30761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
30861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
30961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
31061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
31161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = bank->drvdata;
31261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
31361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
31461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 val;
31561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
31661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val = readl(reg);
31761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (mask)
31861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		val |= 1 << index;
31961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	else
32061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		val &= ~(1 << index);
32161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(val, reg);
32261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
32361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
32461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
32561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
32661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_gpio_irq_set_mask(irqd, false);
32761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
32861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
32961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
33061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
33161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_gpio_irq_set_mask(irqd, true);
33261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
33361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
33461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
33561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
33661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
33761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = bank->drvdata;
33861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
33961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
34061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
34161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(1 << index, reg);
34261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
34361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
34461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
34561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
34661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
34761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = bank->drvdata;
34861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	void __iomem *reg;
34961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	int trigger;
35061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u8 shift;
35161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 val;
35261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
35361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	trigger = s3c64xx_irq_get_trigger(type);
35461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (trigger < 0) {
35561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		pr_err("unsupported external interrupt type\n");
35661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
35761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
35861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
35961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_set_handler(irqd->irq, type);
36061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
36161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	/* Set up interrupt trigger */
36261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	reg = d->virt_base + EINTCON_REG(bank->eint_offset);
36361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
36461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
36561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
36661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val = readl(reg);
36761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val &= ~(EINT_CON_MASK << shift);
36861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val |= trigger << shift;
36961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(val, reg);
37061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
37161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
37261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
37361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
37461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
37561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
37661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
37761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq_chip for gpio interrupts.
37861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
37961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct irq_chip s3c64xx_gpio_irq_chip = {
38061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.name		= "GPIO",
38161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_unmask	= s3c64xx_gpio_irq_unmask,
38261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_mask	= s3c64xx_gpio_irq_mask,
38361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_ack	= s3c64xx_gpio_irq_ack,
38461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_set_type	= s3c64xx_gpio_irq_set_type,
38561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
38661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
38761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
38861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					irq_hw_number_t hw)
38961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
39061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = h->host_data;
39161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
39261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!(bank->eint_mask & (1 << hw)))
39361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
39461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
39561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_chip_and_handler(virq,
39661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				&s3c64xx_gpio_irq_chip, handle_level_irq);
39761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_chip_data(virq, bank);
39861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	set_irq_flags(virq, IRQF_VALID);
39961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
40061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
40161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
40261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
40361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
40461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq domain callbacks for external gpio interrupt controller.
40561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
40661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
40761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.map	= s3c64xx_gpio_irq_map,
40861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.xlate	= irq_domain_xlate_twocell,
40961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
41061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
41161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
41261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
41361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct irq_chip *chip = irq_get_chip(irq);
41461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
41561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
41661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
41761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	chained_irq_enter(chip, desc);
41861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
41961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	do {
42061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int svc;
42161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int group;
42261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int pin;
42361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int virq;
42461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
42561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		svc = readl(drvdata->virt_base + SERVICE_REG);
42661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		group = SVC_GROUP(svc);
42761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		pin = svc & SVC_NUM_MASK;
42861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
42961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (!group)
43061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			break;
43161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
43261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		/* Group 1 is used for two pin banks */
43361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (group == 1) {
43461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			if (pin < 8)
43561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				group = 0;
43661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			else
43761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				pin -= 8;
43861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
43961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
44061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		virq = irq_linear_revmap(data->domains[group], pin);
44161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		/*
44261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 * Something must be really wrong if an unmapped EINT
44361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 * was unmasked...
44461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 */
44561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		BUG_ON(!virq);
44661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
44761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		generic_handle_irq(virq);
44861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	} while (1);
44961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
45061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	chained_irq_exit(chip, desc);
45161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
45261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
45361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/**
45461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
45561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @d: driver data of samsung pinctrl driver.
45661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
45761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
45861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
45961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint_gpio_data *data;
46061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank;
46161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct device *dev = d->dev;
46261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned int nr_domains;
46361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned int i;
46461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
46561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!d->irq) {
46661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		dev_err(dev, "irq number not available\n");
46761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
46861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
46961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
47061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	nr_domains = 0;
47161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	bank = d->ctrl->pin_banks;
47261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
47361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int nr_eints;
47461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int mask;
47561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
47661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (bank->eint_type != EINT_TYPE_GPIO)
47761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			continue;
47861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
47961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		mask = bank->eint_mask;
48061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		nr_eints = fls(mask);
48161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
48261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		bank->irq_domain = irq_domain_add_linear(bank->of_node,
48361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					nr_eints, &s3c64xx_gpio_irqd_ops, bank);
48461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (!bank->irq_domain) {
48561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			dev_err(dev, "gpio irq domain add failed\n");
48661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			return -ENXIO;
48761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
48861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
48961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		++nr_domains;
49061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
49161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
49261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	data = devm_kzalloc(dev, sizeof(*data)
49361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
49461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!data) {
49561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		dev_err(dev, "failed to allocate handler data\n");
49661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -ENOMEM;
49761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
49861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	data->drvdata = d;
49961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
50061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	bank = d->ctrl->pin_banks;
50161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	nr_domains = 0;
50261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
50361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (bank->eint_type != EINT_TYPE_GPIO)
50461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			continue;
50561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
50661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		data->domains[nr_domains++] = bank->irq_domain;
50761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
50861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
50961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
51061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_handler_data(d->irq, data);
51161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
51261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
51361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
51461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
51561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
51661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Functions for configuration of EINT0 wake-up interrupts
51761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
51861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
51961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
52061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
52161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_domain_data *ddata =
52261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					irq_data_get_irq_chip_data(irqd);
52361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
52461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 val;
52561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
52661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val = readl(d->virt_base + EINT0MASK_REG);
52761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (mask)
52861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		val |= 1 << ddata->eints[irqd->hwirq];
52961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	else
53061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		val &= ~(1 << ddata->eints[irqd->hwirq]);
53161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(val, d->virt_base + EINT0MASK_REG);
53261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
53361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
53461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
53561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
53661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_eint0_irq_set_mask(irqd, false);
53761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
53861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
53961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
54061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
54161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_eint0_irq_set_mask(irqd, true);
54261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
54361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
54461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
54561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
54661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_domain_data *ddata =
54761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					irq_data_get_irq_chip_data(irqd);
54861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
54961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
55061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(1 << ddata->eints[irqd->hwirq],
55161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					d->virt_base + EINT0PEND_REG);
55261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
55361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
55461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
55561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
55661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_domain_data *ddata =
55761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					irq_data_get_irq_chip_data(irqd);
55861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = ddata->bank;
55961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *d = bank->drvdata;
56061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	void __iomem *reg;
56161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	int trigger;
56261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u8 shift;
56361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	u32 val;
56461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
56561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	trigger = s3c64xx_irq_get_trigger(type);
56661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (trigger < 0) {
56761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		pr_err("unsupported external interrupt type\n");
56861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
56961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
57061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
57161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_set_handler(irqd->irq, type);
57261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
57361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	/* Set up interrupt trigger */
57461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	reg = d->virt_base + EINT0CON0_REG;
57561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = ddata->eints[irqd->hwirq];
57661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (shift >= EINT_MAX_PER_REG) {
57761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		reg += 4;
57861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		shift -= EINT_MAX_PER_REG;
57961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
58061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	shift = EINT_CON_LEN * (shift / 2);
58161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
58261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val = readl(reg);
58361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val &= ~(EINT_CON_MASK << shift);
58461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	val |= trigger << shift;
58561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	writel(val, reg);
58661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
58761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_set_function(d, bank, irqd->hwirq);
58861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
58961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
59061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
59161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
59261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
59361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq_chip for wakeup interrupts
59461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
59561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct irq_chip s3c64xx_eint0_irq_chip = {
59661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.name		= "EINT0",
59761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_unmask	= s3c64xx_eint0_irq_unmask,
59861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_mask	= s3c64xx_eint0_irq_mask,
59961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_ack	= s3c64xx_eint0_irq_ack,
60061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.irq_set_type	= s3c64xx_eint0_irq_set_type,
60161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
60261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
60361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_irq_demux_eint(unsigned int irq,
60461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					struct irq_desc *desc, u32 range)
60561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
60661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct irq_chip *chip = irq_get_chip(irq);
60761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
60861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
60961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned int pend, mask;
61061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
61161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	chained_irq_enter(chip, desc);
61261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
61361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	pend = readl(drvdata->virt_base + EINT0PEND_REG);
61461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	mask = readl(drvdata->virt_base + EINT0MASK_REG);
61561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
61661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	pend = pend & range & ~mask;
61761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	pend &= range;
61861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
61961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	while (pend) {
62061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int virq;
62161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
62261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		irq = fls(pend) - 1;
62361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		pend &= ~(1 << irq);
62461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
62561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
62661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		/*
62761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 * Something must be really wrong if an unmapped EINT
62861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 * was unmasked...
62961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		 */
63061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		BUG_ON(!virq);
63161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
63261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		generic_handle_irq(virq);
63361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
63461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
63561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	chained_irq_exit(chip, desc);
63661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
63761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
63861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
63961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
64061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_demux_eint(irq, desc, 0xf);
64161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
64261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
64361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
64461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
64561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_demux_eint(irq, desc, 0xff0);
64661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
64761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
64861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
64961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
65061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_demux_eint(irq, desc, 0xff000);
65161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
65261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
65361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
65461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
65561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
65661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
65761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
65861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
65961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_demux_eint0_3,
66061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_demux_eint4_11,
66161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_demux_eint12_19,
66261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	s3c64xx_demux_eint20_27,
66361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
66461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
66561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
66661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa					irq_hw_number_t hw)
66761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
66861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_domain_data *ddata = h->host_data;
66961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank = ddata->bank;
67061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
67161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!(bank->eint_mask & (1 << hw)))
67261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -EINVAL;
67361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
67461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_chip_and_handler(virq,
67561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				&s3c64xx_eint0_irq_chip, handle_level_irq);
67661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	irq_set_chip_data(virq, ddata);
67761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	set_irq_flags(virq, IRQF_VALID);
67861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
67961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
68061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
68161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
68261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
68361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq domain callbacks for external wakeup interrupt controller.
68461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
68561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
68661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.map	= s3c64xx_eint0_irq_map,
68761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	.xlate	= irq_domain_xlate_twocell,
68861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
68961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
69061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* list of external wakeup controllers supported */
69161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct of_device_id s3c64xx_eint0_irq_ids[] = {
69261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{ .compatible = "samsung,s3c64xx-wakeup-eint", },
69361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{ }
69461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
69561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
69661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/**
69761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
69861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @d: driver data of samsung pinctrl driver.
69961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
70061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
70161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{
70261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct device *dev = d->dev;
70361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct device_node *eint0_np = NULL;
70461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct device_node *np;
70561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct samsung_pin_bank *bank;
70661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	struct s3c64xx_eint0_data *data;
70761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	unsigned int i;
70861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
70961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	for_each_child_of_node(dev->of_node, np) {
71061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
71161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			eint0_np = np;
71261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			break;
71361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
71461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
71561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!eint0_np)
71661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -ENODEV;
71761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
71861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
71961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	if (!data) {
72061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		dev_err(dev, "could not allocate memory for wkup eint data\n");
72161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		return -ENOMEM;
72261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
72361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	data->drvdata = d;
72461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
72561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	for (i = 0; i < NUM_EINT0_IRQ; ++i) {
72661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int irq;
72761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
72861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		irq = irq_of_parse_and_map(eint0_np, i);
72961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (!irq) {
73061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
73161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			return -ENXIO;
73261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
73361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
73461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
73561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		irq_set_handler_data(irq, data);
73661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
73761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
73861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	bank = d->ctrl->pin_banks;
73961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
74061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		struct s3c64xx_eint0_domain_data *ddata;
74161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int nr_eints;
74261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int mask;
74361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int irq;
74461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		unsigned int pin;
74561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
74661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (bank->eint_type != EINT_TYPE_WKUP)
74761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			continue;
74861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
74961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		mask = bank->eint_mask;
75061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		nr_eints = fls(mask);
75161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
75261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		ddata = devm_kzalloc(dev,
75361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				sizeof(*ddata) + nr_eints, GFP_KERNEL);
75461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (!ddata) {
75561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			dev_err(dev, "failed to allocate domain data\n");
75661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			return -ENOMEM;
75761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
75861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		ddata->bank = bank;
75961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
76061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		bank->irq_domain = irq_domain_add_linear(bank->of_node,
76161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
76261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		if (!bank->irq_domain) {
76361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			dev_err(dev, "wkup irq domain add failed\n");
76461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			return -ENXIO;
76561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
76661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
76761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		irq = bank->eint_offset;
76861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		mask = bank->eint_mask;
76961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		for (pin = 0; mask; ++pin, mask >>= 1) {
77061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			if (!(mask & 1))
77161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa				continue;
77261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			data->domains[irq] = bank->irq_domain;
77361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			data->pins[irq] = pin;
77461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			ddata->eints[pin] = irq;
77561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa			++irq;
77661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		}
77761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	}
77861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
77961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	return 0;
78061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}
78161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
78261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* pin banks of s3c64xx pin-controller 0 */
78361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank s3c64xx_pin_banks0[] = {
78461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
78561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
78661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
78761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
78861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT(5, 0x080, "gpe"),
78961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
79061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
79161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
79261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT(16, 0x100, "gpi"),
79361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT(12, 0x120, "gpj"),
79461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
79561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
79661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
79761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
79861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
79961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
80061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
80161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
80261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa
80361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/*
80461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
80561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * one gpio/pin-mux/pinconfig controller.
80661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */
80761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
80861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	{
80961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		/* pin-controller instance 1 data */
81061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.pin_banks	= s3c64xx_pin_banks0,
81161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.nr_banks	= ARRAY_SIZE(s3c64xx_pin_banks0),
81261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_gpio_init = s3c64xx_eint_gpio_init,
81361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.eint_wkup_init = s3c64xx_eint_eint0_init,
81461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa		.label		= "S3C64xx-GPIO",
81561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa	},
81661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa};
817