mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
Updates to the interrupt core and driver subsystems:
Core changes: - The usual set of small fixes and improvements all over the place, but nothing outstanding MSI changes: - Further consolidation of the PCI/MSI interrupt chip code - Make MSI sysfs code independent of PCI/MSI and expose the MSI interrupts of platform devices in the same way as PCI exposes them. Driver changes: - Support for ARM GICv3 EPPI partitions - Treewide conversion to generic_handle_domain_irq() for all chained interrupt controllers - Conversion to bitmap_zalloc() throughout the irq chip drivers - The usual set of small fixes and improvements -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmEsnpsTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoS+/EACQdpRkzl3IDIYqThxVZ8KQzp2rKKVn qisAQiWg/6koNJx/yYy62KNAUyKjCIObNtRnWi7OAOx6OvNtQTD2WOLAwkh3Pgw1 8ePYYl55k+yCs8VoITsZM9jYeO+Tk878pU2A6R943zR+g6G7bskGJrxEyZ9TbzIe qKfusNKnRY9/jMQaRALUAAtA9VIVR867GqORX5X8hKz8yE2rqlpb4y+1CFba5BTV Vlxw7cIXvXBn7BKAom5diRqEGDNJEbX+56jJ7yDZshgLo7m11D7QLw72kmb6TNVC g7PchvFi4afpc1ifEAAp0tk4RiSIAQ91nS3n0+jLcLbodOjIkl14eY02ZCJGAP29 uslyzUbmy1wgejG6CA63JtZ4MYdrf/OSMGuoN78qnOKYcIsWFzOvlJmBWWNW34qW LCaUF9QdJ/slXu6B4vIx30GfN9q4myml8bFUobE5q9mBRrEk4R0B7iyBvPu1xKYr ZEan67prI5VEu+afJGpp4r294m4HNVkMLfl3nYmE5+y4MoLeMNKDY3IPTvI9iP4G kaFgoPvQo23WnuclNYpJ+CaA4aRASlB2nTY+oAXIYfehbey9EW5vq4/EK864ek6w oyUTepxxNhE81tG2jpQbf2tR4COsEHy986clxqPP4AvsZXcbypCw8O2FcflpQbHO 5DLEAfTmp7cziQ== =qyll -----END PGP SIGNATURE----- Merge tag 'irq-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull irq updates from Thomas Gleixner: "Updates to the interrupt core and driver subsystems: Core changes: - The usual set of small fixes and improvements all over the place, but nothing stands out MSI changes: - Further consolidation of the PCI/MSI interrupt chip code - Make MSI sysfs code independent of PCI/MSI and expose the MSI interrupts of platform devices in the same way as PCI exposes them. Driver changes: - Support for ARM GICv3 EPPI partitions - Treewide conversion to generic_handle_domain_irq() for all chained interrupt controllers - Conversion to bitmap_zalloc() throughout the irq chip drivers - The usual set of small fixes and improvements" * tag 'irq-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (57 commits) platform-msi: Add ABI to show msi_irqs of platform devices genirq/msi: Move MSI sysfs handling from PCI to MSI core genirq/cpuhotplug: Demote debug printk to KERN_DEBUG irqchip/qcom-pdc: Trim unused levels of the interrupt hierarchy irqdomain: Export irq_domain_disconnect_hierarchy() irqchip/gic-v3: Fix priority comparison when non-secure priorities are used irqchip/apple-aic: Fix irq_disable from within irq handlers pinctrl/rockchip: drop the gpio related codes gpio/rockchip: drop irq_gc_lock/irq_gc_unlock for irq set type gpio/rockchip: support next version gpio controller gpio/rockchip: use struct rockchip_gpio_regs for gpio controller gpio/rockchip: add driver for rockchip gpio dt-bindings: gpio: change items restriction of clock for rockchip,gpio-bank pinctrl/rockchip: add pinctrl device to gpio bank struct pinctrl/rockchip: separate struct rockchip_pin_bank to a head file pinctrl/rockchip: always enable clock for gpio controller genirq: Fix kernel doc indentation EDAC/altera: Convert to generic_handle_domain_irq() powerpc: Bulk conversion to generic_handle_domain_irq() nios2: Bulk conversion to generic_handle_domain_irq() ...
This commit is contained in:
commit
7d6e3fa87e
@ -28,3 +28,17 @@ Description:
|
||||
value comes from an ACPI _PXM method or a similar firmware
|
||||
source. Initial users for this file would be devices like
|
||||
arm smmu which are populated by arm64 acpi_iort.
|
||||
|
||||
What: /sys/bus/platform/devices/.../msi_irqs/
|
||||
Date: August 2021
|
||||
Contact: Barry Song <song.bao.hua@hisilicon.com>
|
||||
Description:
|
||||
The /sys/devices/.../msi_irqs directory contains a variable set
|
||||
of files, with each file being named after a corresponding msi
|
||||
irq vector allocated to that device.
|
||||
|
||||
What: /sys/bus/platform/devices/.../msi_irqs/<N>
|
||||
Date: August 2021
|
||||
Contact: Barry Song <song.bao.hua@hisilicon.com>
|
||||
Description:
|
||||
This attribute will show "msi" if <N> is a valid msi irq
|
||||
|
@ -55,8 +55,24 @@ exist then it will allocate a new Linux irq_desc, associate it with
|
||||
the hwirq, and call the .map() callback so the driver can perform any
|
||||
required hardware setup.
|
||||
|
||||
When an interrupt is received, irq_find_mapping() function should
|
||||
be used to find the Linux IRQ number from the hwirq number.
|
||||
Once a mapping has been established, it can be retrieved or used via a
|
||||
variety of methods:
|
||||
|
||||
- irq_resolve_mapping() returns a pointer to the irq_desc structure
|
||||
for a given domain and hwirq number, and NULL if there was no
|
||||
mapping.
|
||||
- irq_find_mapping() returns a Linux IRQ number for a given domain and
|
||||
hwirq number, and 0 if there was no mapping
|
||||
- irq_linear_revmap() is now identical to irq_find_mapping(), and is
|
||||
deprecated
|
||||
- generic_handle_domain_irq() handles an interrupt described by a
|
||||
domain and a hwirq number
|
||||
- handle_domain_irq() does the same thing for root interrupt
|
||||
controllers and deals with the set_irq_reg()/irq_enter() sequences
|
||||
that most architecture requires
|
||||
|
||||
Note that irq domain lookups must happen in contexts that are
|
||||
compatible with a RCU read-side critical section.
|
||||
|
||||
The irq_create_mapping() function must be called *atleast once*
|
||||
before any call to irq_find_mapping(), lest the descriptor will not
|
||||
@ -137,7 +153,9 @@ required. Calling irq_create_direct_mapping() will allocate a Linux
|
||||
IRQ number and call the .map() callback so that driver can program the
|
||||
Linux IRQ number into the hardware.
|
||||
|
||||
Most drivers cannot use this mapping.
|
||||
Most drivers cannot use this mapping, and it is now gated on the
|
||||
CONFIG_IRQ_DOMAIN_NOMAP option. Please refrain from introducing new
|
||||
users of this API.
|
||||
|
||||
Legacy
|
||||
------
|
||||
@ -157,6 +175,10 @@ for IRQ numbers that are passed to struct device registrations. In that
|
||||
case the Linux IRQ numbers cannot be dynamically assigned and the legacy
|
||||
mapping should be used.
|
||||
|
||||
As the name implies, the *_legacy() functions are deprecated and only
|
||||
exist to ease the support of ancient platforms. No new users should be
|
||||
added.
|
||||
|
||||
The legacy map assumes a contiguous range of IRQ numbers has already
|
||||
been allocated for the controller and that the IRQ number can be
|
||||
calculated by adding a fixed offset to the hwirq number, and
|
||||
|
@ -22,7 +22,10 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
items:
|
||||
- description: APB interface clock source
|
||||
- description: GPIO debounce reference clock source
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
|
@ -352,7 +352,7 @@ static void idu_cascade_isr(struct irq_desc *desc)
|
||||
irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
|
||||
|
||||
chained_irq_enter(core_chip, desc);
|
||||
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
|
||||
generic_handle_domain_irq(idu_domain, idu_hwirq);
|
||||
chained_irq_exit(core_chip, desc);
|
||||
}
|
||||
|
||||
|
@ -196,14 +196,6 @@ static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq)
|
||||
return irq_create_mapping(sachip->irqdomain, hwirq);
|
||||
}
|
||||
|
||||
static void sa1111_handle_irqdomain(struct irq_domain *irqdomain, int irq)
|
||||
{
|
||||
struct irq_desc *d = irq_to_desc(irq_linear_revmap(irqdomain, irq));
|
||||
|
||||
if (d)
|
||||
generic_handle_irq_desc(d);
|
||||
}
|
||||
|
||||
/*
|
||||
* SA1111 interrupt support. Since clearing an IRQ while there are
|
||||
* active IRQs causes the interrupt output to pulse, the upper levels
|
||||
@ -234,11 +226,11 @@ static void sa1111_irq_handler(struct irq_desc *desc)
|
||||
|
||||
for (i = 0; stat0; i++, stat0 >>= 1)
|
||||
if (stat0 & 1)
|
||||
sa1111_handle_irqdomain(irqdomain, i);
|
||||
generic_handle_domain_irq(irqdomain, i);
|
||||
|
||||
for (i = 32; stat1; i++, stat1 >>= 1)
|
||||
if (stat1 & 1)
|
||||
sa1111_handle_irqdomain(irqdomain, i);
|
||||
generic_handle_domain_irq(irqdomain, i);
|
||||
|
||||
/* For level-based interrupts */
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
|
@ -39,10 +39,8 @@ static irqreturn_t cplds_irq_handler(int in_irq, void *d)
|
||||
|
||||
do {
|
||||
pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
|
||||
for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) {
|
||||
generic_handle_irq(irq_find_mapping(fpga->irqdomain,
|
||||
bit));
|
||||
}
|
||||
for_each_set_bit(bit, &pending, CPLDS_NB_IRQ)
|
||||
generic_handle_domain_irq(fpga->irqdomain, bit);
|
||||
} while (pending);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -298,7 +298,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
|
||||
struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
|
||||
struct s3c_irq_intc *intc = irq_data->intc;
|
||||
struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
|
||||
unsigned int n, offset, irq;
|
||||
unsigned int n, offset;
|
||||
unsigned long src, msk;
|
||||
|
||||
/* we're using individual domains for the non-dt case
|
||||
@ -318,8 +318,7 @@ static void s3c_irq_demux(struct irq_desc *desc)
|
||||
while (src) {
|
||||
n = __ffs(src);
|
||||
src &= ~(1 << n);
|
||||
irq = irq_find_mapping(sub_intc->domain, offset + n);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(sub_intc->domain, offset + n);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
@ -69,24 +69,24 @@ static void ar2315_misc_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
|
||||
ar2315_rst_reg_read(AR2315_IMR);
|
||||
unsigned nr, misc_irq = 0;
|
||||
unsigned nr;
|
||||
int ret = 0;
|
||||
|
||||
if (pending) {
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
|
||||
nr = __ffs(pending);
|
||||
misc_irq = irq_find_mapping(domain, nr);
|
||||
}
|
||||
|
||||
if (misc_irq) {
|
||||
if (nr == AR2315_MISC_IRQ_GPIO)
|
||||
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO);
|
||||
else if (nr == AR2315_MISC_IRQ_WATCHDOG)
|
||||
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD);
|
||||
generic_handle_irq(misc_irq);
|
||||
} else {
|
||||
spurious_interrupt();
|
||||
|
||||
ret = generic_handle_domain_irq(domain, nr);
|
||||
}
|
||||
|
||||
if (!pending || ret)
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
static void ar2315_misc_irq_unmask(struct irq_data *d)
|
||||
|
@ -73,22 +73,21 @@ static void ar5312_misc_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
|
||||
ar5312_rst_reg_read(AR5312_IMR);
|
||||
unsigned nr, misc_irq = 0;
|
||||
unsigned nr;
|
||||
int ret = 0;
|
||||
|
||||
if (pending) {
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
|
||||
nr = __ffs(pending);
|
||||
misc_irq = irq_find_mapping(domain, nr);
|
||||
}
|
||||
|
||||
if (misc_irq) {
|
||||
generic_handle_irq(misc_irq);
|
||||
ret = generic_handle_domain_irq(domain, nr);
|
||||
if (nr == AR5312_MISC_IRQ_TIMER)
|
||||
ar5312_rst_reg_read(AR5312_TIMER);
|
||||
} else {
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
if (!pending || ret)
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
/* Enable the specified AR5312_MISC_IRQ interrupt */
|
||||
|
@ -300,7 +300,7 @@ static void ltq_hw_irq_handler(struct irq_desc *desc)
|
||||
*/
|
||||
irq = __fls(irq);
|
||||
hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
|
||||
generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
|
||||
generic_handle_domain_irq(ltq_domain, hwirq);
|
||||
|
||||
/* if this is a EBU irq, we need to ack it or get a deadlock */
|
||||
if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0)
|
||||
|
@ -337,14 +337,12 @@ static void ar2315_pci_irq_handler(struct irq_desc *desc)
|
||||
struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc);
|
||||
u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
|
||||
ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
|
||||
unsigned pci_irq = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (pending)
|
||||
pci_irq = irq_find_mapping(apc->domain, __ffs(pending));
|
||||
ret = generic_handle_domain_irq(apc->domain, __ffs(pending));
|
||||
|
||||
if (pci_irq)
|
||||
generic_handle_irq(pci_irq);
|
||||
else
|
||||
if (!pending || ret)
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
|
@ -140,10 +140,9 @@ static void rt3883_pci_irq_handler(struct irq_desc *desc)
|
||||
}
|
||||
|
||||
while (pending) {
|
||||
unsigned irq, bit = __ffs(pending);
|
||||
unsigned bit = __ffs(pending);
|
||||
|
||||
irq = irq_find_mapping(rpc->irq_domain, bit);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(rpc->irq_domain, bit);
|
||||
|
||||
pending &= ~BIT(bit);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ static void ralink_intc_irq_handler(struct irq_desc *desc)
|
||||
|
||||
if (pending) {
|
||||
struct irq_domain *domain = irq_desc_get_handler_data(desc);
|
||||
generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
|
||||
generic_handle_domain_irq(domain, __ffs(pending));
|
||||
} else {
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
|
||||
unsigned long *mask = per_cpu(irq_enable_mask, cpu);
|
||||
struct irq_domain *domain;
|
||||
u64 pend0;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
/* copied from Irix intpend0() */
|
||||
pend0 = LOCAL_HUB_L(PI_INT_PEND0);
|
||||
@ -216,10 +216,8 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
|
||||
#endif
|
||||
{
|
||||
domain = irq_desc_get_handler_data(desc);
|
||||
irq = irq_linear_revmap(domain, __ffs(pend0));
|
||||
if (irq)
|
||||
generic_handle_irq(irq);
|
||||
else
|
||||
ret = generic_handle_domain_irq(domain, __ffs(pend0));
|
||||
if (ret)
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
@ -232,7 +230,7 @@ static void ip27_do_irq_mask1(struct irq_desc *desc)
|
||||
unsigned long *mask = per_cpu(irq_enable_mask, cpu);
|
||||
struct irq_domain *domain;
|
||||
u64 pend1;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
/* copied from Irix intpend0() */
|
||||
pend1 = LOCAL_HUB_L(PI_INT_PEND1);
|
||||
@ -242,10 +240,8 @@ static void ip27_do_irq_mask1(struct irq_desc *desc)
|
||||
return;
|
||||
|
||||
domain = irq_desc_get_handler_data(desc);
|
||||
irq = irq_linear_revmap(domain, __ffs(pend1) + 64);
|
||||
if (irq)
|
||||
generic_handle_irq(irq);
|
||||
else
|
||||
ret = generic_handle_domain_irq(domain, __ffs(pend1) + 64);
|
||||
if (ret)
|
||||
spurious_interrupt();
|
||||
|
||||
LOCAL_HUB_L(PI_INT_PEND1);
|
||||
|
@ -99,7 +99,7 @@ static void ip30_normal_irq(struct irq_desc *desc)
|
||||
int cpu = smp_processor_id();
|
||||
struct irq_domain *domain;
|
||||
u64 pend, mask;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
pend = heart_read(&heart_regs->isr);
|
||||
mask = (heart_read(&heart_regs->imr[cpu]) &
|
||||
@ -130,10 +130,8 @@ static void ip30_normal_irq(struct irq_desc *desc)
|
||||
#endif
|
||||
{
|
||||
domain = irq_desc_get_handler_data(desc);
|
||||
irq = irq_linear_revmap(domain, __ffs(pend));
|
||||
if (irq)
|
||||
generic_handle_irq(irq);
|
||||
else
|
||||
ret = generic_handle_domain_irq(domain, __ffs(pend));
|
||||
if (ret)
|
||||
spurious_interrupt();
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,9 @@ static u32 ienable;
|
||||
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *oldregs = set_irq_regs(regs);
|
||||
int irq;
|
||||
|
||||
irq_enter();
|
||||
irq = irq_find_mapping(NULL, hwirq);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(NULL, hwirq);
|
||||
irq_exit();
|
||||
|
||||
set_irq_regs(oldregs);
|
||||
|
@ -198,7 +198,6 @@ static void uic_irq_cascade(struct irq_desc *desc)
|
||||
struct uic *uic = irq_desc_get_handler_data(desc);
|
||||
u32 msr;
|
||||
int src;
|
||||
int subvirq;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
if (irqd_is_level_type(idata))
|
||||
@ -213,8 +212,7 @@ static void uic_irq_cascade(struct irq_desc *desc)
|
||||
|
||||
src = 32 - ffs(msr);
|
||||
|
||||
subvirq = irq_linear_revmap(uic->irqhost, src);
|
||||
generic_handle_irq(subvirq);
|
||||
generic_handle_domain_irq(uic->irqhost, src);
|
||||
|
||||
uic_irq_ret:
|
||||
raw_spin_lock(&desc->lock);
|
||||
|
@ -81,11 +81,10 @@ static struct irq_chip cpld_pic = {
|
||||
.irq_unmask = cpld_unmask_irq,
|
||||
};
|
||||
|
||||
static int
|
||||
static unsigned int
|
||||
cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
|
||||
u8 __iomem *maskp)
|
||||
{
|
||||
int cpld_irq;
|
||||
u8 status = in_8(statusp);
|
||||
u8 mask = in_8(maskp);
|
||||
|
||||
@ -93,28 +92,26 @@ cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
|
||||
status |= (ignore | mask);
|
||||
|
||||
if (status == 0xff)
|
||||
return 0;
|
||||
return ~0;
|
||||
|
||||
cpld_irq = ffz(status) + offset;
|
||||
|
||||
return irq_linear_revmap(cpld_pic_host, cpld_irq);
|
||||
return ffz(status) + offset;
|
||||
}
|
||||
|
||||
static void cpld_pic_cascade(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq;
|
||||
unsigned int hwirq;
|
||||
|
||||
irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status,
|
||||
hwirq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status,
|
||||
&cpld_regs->pci_mask);
|
||||
if (irq) {
|
||||
generic_handle_irq(irq);
|
||||
if (hwirq != ~0) {
|
||||
generic_handle_domain_irq(cpld_pic_host, hwirq);
|
||||
return;
|
||||
}
|
||||
|
||||
irq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status,
|
||||
hwirq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status,
|
||||
&cpld_regs->misc_mask);
|
||||
if (irq) {
|
||||
generic_handle_irq(irq);
|
||||
if (hwirq != ~0) {
|
||||
generic_handle_domain_irq(cpld_pic_host, hwirq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ static struct irq_chip media5200_irq_chip = {
|
||||
static void media5200_irq_cascade(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
int sub_virq, val;
|
||||
int val;
|
||||
u32 status, enable;
|
||||
|
||||
/* Mask off the cascaded IRQ */
|
||||
@ -92,11 +92,10 @@ static void media5200_irq_cascade(struct irq_desc *desc)
|
||||
enable = in_be32(media5200_irq.regs + MEDIA5200_IRQ_STATUS);
|
||||
val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT);
|
||||
if (val) {
|
||||
sub_virq = irq_linear_revmap(media5200_irq.irqhost, val - 1);
|
||||
/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i subvirq=%i\n",
|
||||
* __func__, virq, status, enable, val - 1, sub_virq);
|
||||
generic_handle_domain_irq(media5200_irq.irqhost, val - 1);
|
||||
/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i\n",
|
||||
* __func__, virq, status, enable, val - 1);
|
||||
*/
|
||||
generic_handle_irq(sub_virq);
|
||||
}
|
||||
|
||||
/* Processing done; can reenable the cascade now */
|
||||
|
@ -190,14 +190,11 @@ static struct irq_chip mpc52xx_gpt_irq_chip = {
|
||||
static void mpc52xx_gpt_irq_cascade(struct irq_desc *desc)
|
||||
{
|
||||
struct mpc52xx_gpt_priv *gpt = irq_desc_get_handler_data(desc);
|
||||
int sub_virq;
|
||||
u32 status;
|
||||
|
||||
status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK;
|
||||
if (status) {
|
||||
sub_virq = irq_linear_revmap(gpt->irqhost, 0);
|
||||
generic_handle_irq(sub_virq);
|
||||
}
|
||||
if (status)
|
||||
generic_handle_domain_irq(gpt->irqhost, 0);
|
||||
}
|
||||
|
||||
static int mpc52xx_gpt_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
|
@ -91,10 +91,8 @@ static void pq2ads_pci_irq_demux(struct irq_desc *desc)
|
||||
break;
|
||||
|
||||
for (bit = 0; pend != 0; ++bit, pend <<= 1) {
|
||||
if (pend & 0x80000000) {
|
||||
int virq = irq_linear_revmap(priv->host, bit);
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
if (pend & 0x80000000)
|
||||
generic_handle_domain_irq(priv->host, bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,13 +106,9 @@ static void iic_ioexc_cascade(struct irq_desc *desc)
|
||||
out_be64(&node_iic->iic_is, ack);
|
||||
/* handle them */
|
||||
for (cascade = 63; cascade >= 0; cascade--)
|
||||
if (bits & (0x8000000000000000UL >> cascade)) {
|
||||
unsigned int cirq =
|
||||
irq_linear_revmap(iic_host,
|
||||
if (bits & (0x8000000000000000UL >> cascade))
|
||||
generic_handle_domain_irq(iic_host,
|
||||
base | cascade);
|
||||
if (cirq)
|
||||
generic_handle_irq(cirq);
|
||||
}
|
||||
/* post-ack level interrupts */
|
||||
ack = bits & ~IIC_ISR_EDGE_MASK;
|
||||
if (ack)
|
||||
|
@ -190,16 +190,11 @@ static void spider_irq_cascade(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct spider_pic *pic = irq_desc_get_handler_data(desc);
|
||||
unsigned int cs, virq;
|
||||
unsigned int cs;
|
||||
|
||||
cs = in_be32(pic->regs + TIR_CS) >> 24;
|
||||
if (cs == SPIDER_IRQ_INVALID)
|
||||
virq = 0;
|
||||
else
|
||||
virq = irq_linear_revmap(pic->host, cs);
|
||||
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
if (cs != SPIDER_IRQ_INVALID)
|
||||
generic_handle_domain_irq(pic->host, cs);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ static const struct irq_domain_ops hlwd_irq_domain_ops = {
|
||||
static unsigned int __hlwd_pic_get_irq(struct irq_domain *h)
|
||||
{
|
||||
void __iomem *io_base = h->host_data;
|
||||
int irq;
|
||||
u32 irq_status;
|
||||
|
||||
irq_status = in_be32(io_base + HW_BROADWAY_ICR) &
|
||||
@ -116,23 +115,22 @@ static unsigned int __hlwd_pic_get_irq(struct irq_domain *h)
|
||||
if (irq_status == 0)
|
||||
return 0; /* no more IRQs pending */
|
||||
|
||||
irq = __ffs(irq_status);
|
||||
return irq_linear_revmap(h, irq);
|
||||
return __ffs(irq_status);
|
||||
}
|
||||
|
||||
static void hlwd_pic_irq_cascade(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct irq_domain *irq_domain = irq_desc_get_handler_data(desc);
|
||||
unsigned int virq;
|
||||
unsigned int hwirq;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
|
||||
raw_spin_unlock(&desc->lock);
|
||||
|
||||
virq = __hlwd_pic_get_irq(irq_domain);
|
||||
if (virq)
|
||||
generic_handle_irq(virq);
|
||||
hwirq = __hlwd_pic_get_irq(irq_domain);
|
||||
if (hwirq)
|
||||
generic_handle_domain_irq(irq_domain, hwirq);
|
||||
else
|
||||
pr_err("spurious interrupt!\n");
|
||||
|
||||
@ -190,7 +188,8 @@ static struct irq_domain *hlwd_pic_init(struct device_node *np)
|
||||
|
||||
unsigned int hlwd_pic_get_irq(void)
|
||||
{
|
||||
return __hlwd_pic_get_irq(hlwd_irq_host);
|
||||
unsigned int hwirq = __hlwd_pic_get_irq(hlwd_irq_host);
|
||||
return hwirq ? irq_linear_revmap(hlwd_irq_host, hwirq) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -46,18 +46,15 @@ void opal_handle_events(void)
|
||||
e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask;
|
||||
again:
|
||||
while (e) {
|
||||
int virq, hwirq;
|
||||
int hwirq;
|
||||
|
||||
hwirq = fls64(e) - 1;
|
||||
e &= ~BIT_ULL(hwirq);
|
||||
|
||||
local_irq_disable();
|
||||
virq = irq_find_mapping(opal_event_irqchip.domain, hwirq);
|
||||
if (virq) {
|
||||
irq_enter();
|
||||
generic_handle_irq(virq);
|
||||
irq_exit();
|
||||
}
|
||||
irq_enter();
|
||||
generic_handle_domain_irq(opal_event_irqchip.domain, hwirq);
|
||||
irq_exit();
|
||||
local_irq_enable();
|
||||
|
||||
cond_resched();
|
||||
|
@ -99,7 +99,6 @@ static irqreturn_t fsl_error_int_handler(int irq, void *data)
|
||||
struct mpic *mpic = (struct mpic *) data;
|
||||
u32 eisr, eimr;
|
||||
int errint;
|
||||
unsigned int cascade_irq;
|
||||
|
||||
eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
|
||||
eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
|
||||
@ -108,13 +107,11 @@ static irqreturn_t fsl_error_int_handler(int irq, void *data)
|
||||
return IRQ_NONE;
|
||||
|
||||
while (eisr) {
|
||||
int ret;
|
||||
errint = __builtin_clz(eisr);
|
||||
cascade_irq = irq_linear_revmap(mpic->irqhost,
|
||||
mpic->err_int_vecs[errint]);
|
||||
WARN_ON(!cascade_irq);
|
||||
if (cascade_irq) {
|
||||
generic_handle_irq(cascade_irq);
|
||||
} else {
|
||||
ret = generic_handle_domain_irq(mpic->irqhost,
|
||||
mpic->err_int_vecs[errint]);
|
||||
if (WARN_ON(ret)) {
|
||||
eimr |= 1 << (31 - errint);
|
||||
mpic_fsl_err_write(mpic->err_regs, eimr);
|
||||
}
|
||||
|
@ -266,7 +266,6 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
|
||||
static irqreturn_t fsl_msi_cascade(int irq, void *data)
|
||||
{
|
||||
unsigned int cascade_irq;
|
||||
struct fsl_msi *msi_data;
|
||||
int msir_index = -1;
|
||||
u32 msir_value = 0;
|
||||
@ -279,9 +278,6 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
|
||||
|
||||
msir_index = cascade_data->index;
|
||||
|
||||
if (msir_index >= NR_MSI_REG_MAX)
|
||||
cascade_irq = 0;
|
||||
|
||||
switch (msi_data->feature & FSL_PIC_IP_MASK) {
|
||||
case FSL_PIC_IP_MPIC:
|
||||
msir_value = fsl_msi_read(msi_data->msi_regs,
|
||||
@ -305,15 +301,15 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
|
||||
}
|
||||
|
||||
while (msir_value) {
|
||||
int err;
|
||||
intr_index = ffs(msir_value) - 1;
|
||||
|
||||
cascade_irq = irq_linear_revmap(msi_data->irqhost,
|
||||
err = generic_handle_domain_irq(msi_data->irqhost,
|
||||
msi_hwirq(msi_data, msir_index,
|
||||
intr_index + have_shift));
|
||||
if (cascade_irq) {
|
||||
generic_handle_irq(cascade_irq);
|
||||
if (!err)
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
have_shift += intr_index + 1;
|
||||
msir_value = msir_value >> (intr_index + 1);
|
||||
}
|
||||
|
@ -365,10 +365,6 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
|
||||
for_each_pci_msi_entry(msi, pdev) {
|
||||
if (!msi->irq)
|
||||
continue;
|
||||
if (msi->msi_attrib.is_msix)
|
||||
__pci_msix_desc_mask_irq(msi, 1);
|
||||
else
|
||||
__pci_msi_desc_mask_irq(msi, 1, 1);
|
||||
irq_set_msi_desc(msi->irq, NULL);
|
||||
irq_free_desc(msi->irq);
|
||||
msi->msg.address_lo = 0;
|
||||
|
@ -38,7 +38,7 @@ static void se7343_irq_demux(struct irq_desc *desc)
|
||||
mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG);
|
||||
|
||||
for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR)
|
||||
generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit));
|
||||
generic_handle_domain_irq(se7343_irq_domain, bit);
|
||||
|
||||
chip->irq_unmask(data);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ static void se7722_irq_demux(struct irq_desc *desc)
|
||||
mask = ioread16(se7722_irq_regs + IRQ01_STS_REG);
|
||||
|
||||
for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR)
|
||||
generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit));
|
||||
generic_handle_domain_irq(se7722_irq_domain, bit);
|
||||
|
||||
chip->irq_unmask(data);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ static void x3proto_gpio_irq_handler(struct irq_desc *desc)
|
||||
|
||||
mask = __raw_readw(KEYDETR);
|
||||
for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
|
||||
generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin));
|
||||
generic_handle_domain_irq(x3proto_irq_domain, pin);
|
||||
|
||||
chip->irq_unmask(data);
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ DECLARE_PER_CPU(unsigned long, nmi_count);
|
||||
|
||||
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
int irq = irq_find_mapping(NULL, hwirq);
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
/* Debugging check for stack overflow: is there less than 1KB free? */
|
||||
{
|
||||
@ -48,7 +46,7 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
|
||||
sp - sizeof(struct thread_info));
|
||||
}
|
||||
#endif
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(NULL, hwirq);
|
||||
}
|
||||
|
||||
int arch_show_interrupts(struct seq_file *p, int prec)
|
||||
|
@ -606,7 +606,7 @@ static inline bool blk_mq_complete_need_ipi(struct request *rq)
|
||||
* This is probably worse than completing the request on a different
|
||||
* cache domain.
|
||||
*/
|
||||
if (force_irqthreads)
|
||||
if (force_irqthreads())
|
||||
return false;
|
||||
|
||||
/* same CPU or cache domain? Complete locally */
|
||||
|
@ -21,11 +21,12 @@
|
||||
* and the callback to write the MSI message.
|
||||
*/
|
||||
struct platform_msi_priv_data {
|
||||
struct device *dev;
|
||||
void *host_data;
|
||||
msi_alloc_info_t arg;
|
||||
irq_write_msi_msg_t write_msg;
|
||||
int devid;
|
||||
struct device *dev;
|
||||
void *host_data;
|
||||
const struct attribute_group **msi_irq_groups;
|
||||
msi_alloc_info_t arg;
|
||||
irq_write_msi_msg_t write_msg;
|
||||
int devid;
|
||||
};
|
||||
|
||||
/* The devid allocator */
|
||||
@ -272,8 +273,16 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
|
||||
if (err)
|
||||
goto out_free_desc;
|
||||
|
||||
priv_data->msi_irq_groups = msi_populate_sysfs(dev);
|
||||
if (IS_ERR(priv_data->msi_irq_groups)) {
|
||||
err = PTR_ERR(priv_data->msi_irq_groups);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_irqs:
|
||||
msi_domain_free_irqs(dev->msi_domain, dev);
|
||||
out_free_desc:
|
||||
platform_msi_free_descs(dev, 0, nvec);
|
||||
out_free_priv_data:
|
||||
@ -293,6 +302,7 @@ void platform_msi_domain_free_irqs(struct device *dev)
|
||||
struct msi_desc *desc;
|
||||
|
||||
desc = first_msi_entry(dev);
|
||||
msi_destroy_sysfs(dev, desc->platform.msi_priv_data->msi_irq_groups);
|
||||
platform_msi_free_priv_data(desc->platform.msi_priv_data);
|
||||
}
|
||||
|
||||
|
@ -1812,11 +1812,8 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc)
|
||||
regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
|
||||
|
||||
bits = irq_status;
|
||||
for_each_set_bit(bit, &bits, 32) {
|
||||
irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);
|
||||
if (irq)
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(bit, &bits, 32)
|
||||
generic_handle_domain_irq(edac->domain, dberr * 32 + bit);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
@ -520,6 +520,14 @@ config GPIO_REG
|
||||
A 32-bit single register GPIO fixed in/out implementation. This
|
||||
can be used to represent any register as a set of GPIO signals.
|
||||
|
||||
config GPIO_ROCKCHIP
|
||||
tristate "Rockchip GPIO support"
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
select GPIOLIB_IRQCHIP
|
||||
default ARCH_ROCKCHIP
|
||||
help
|
||||
Say yes here to support GPIO on Rockchip SoCs.
|
||||
|
||||
config GPIO_SAMA5D2_PIOBU
|
||||
tristate "SAMA5D2 PIOBU GPIO support"
|
||||
depends on MFD_SYSCON
|
||||
|
@ -128,6 +128,7 @@ obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
|
||||
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
|
||||
obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
|
||||
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
|
||||
obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
|
||||
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
|
||||
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
|
||||
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
|
||||
|
@ -336,8 +336,8 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
|
||||
unsigned long gpio;
|
||||
|
||||
for_each_set_bit(gpio, &irq_mask, 2)
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain,
|
||||
19 + gpio*24));
|
||||
generic_handle_domain_irq(chip->irq.domain,
|
||||
19 + gpio*24);
|
||||
|
||||
raw_spin_lock(&dio48egpio->lock);
|
||||
|
||||
|
@ -223,8 +223,8 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
|
||||
for_each_set_bit(bit_num, &irq_mask, 8) {
|
||||
gpio = bit_num + boundary * 8;
|
||||
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain,
|
||||
gpio));
|
||||
generic_handle_domain_irq(chip->irq.domain,
|
||||
gpio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
|
||||
int gpio;
|
||||
|
||||
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
|
||||
generic_handle_domain_irq(chip->irq.domain, gpio);
|
||||
|
||||
raw_spin_lock(&idio16gpio->lock);
|
||||
|
||||
|
@ -201,9 +201,8 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
|
||||
(readl(mm_gc->regs + ALTERA_GPIO_EDGE_CAP) &
|
||||
readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
|
||||
writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP);
|
||||
for_each_set_bit(i, &status, mm_gc->gc.ngpio) {
|
||||
generic_handle_irq(irq_find_mapping(irqdomain, i));
|
||||
}
|
||||
for_each_set_bit(i, &status, mm_gc->gc.ngpio)
|
||||
generic_handle_domain_irq(irqdomain, i);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
@ -228,9 +227,9 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
|
||||
status = readl(mm_gc->regs + ALTERA_GPIO_DATA);
|
||||
status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
|
||||
|
||||
for_each_set_bit(i, &status, mm_gc->gc.ngpio) {
|
||||
generic_handle_irq(irq_find_mapping(irqdomain, i));
|
||||
}
|
||||
for_each_set_bit(i, &status, mm_gc->gc.ngpio)
|
||||
generic_handle_domain_irq(irqdomain, i);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
|
@ -392,7 +392,7 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct aspeed_sgpio *data = gpiochip_get_data(gc);
|
||||
unsigned int i, p, girq;
|
||||
unsigned int i, p;
|
||||
unsigned long reg;
|
||||
|
||||
chained_irq_enter(ic, desc);
|
||||
@ -402,11 +402,8 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
|
||||
|
||||
reg = ioread32(bank_reg(data, bank, reg_irq_status));
|
||||
|
||||
for_each_set_bit(p, ®, 32) {
|
||||
girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
|
||||
generic_handle_irq(girq);
|
||||
}
|
||||
|
||||
for_each_set_bit(p, ®, 32)
|
||||
generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
|
||||
}
|
||||
|
||||
chained_irq_exit(ic, desc);
|
||||
|
@ -661,7 +661,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct aspeed_gpio *data = gpiochip_get_data(gc);
|
||||
unsigned int i, p, girq, banks;
|
||||
unsigned int i, p, banks;
|
||||
unsigned long reg;
|
||||
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
|
||||
|
||||
@ -673,11 +673,8 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
|
||||
|
||||
reg = ioread32(bank_reg(data, bank, reg_irq_status));
|
||||
|
||||
for_each_set_bit(p, ®, 32) {
|
||||
girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
|
||||
generic_handle_irq(girq);
|
||||
}
|
||||
|
||||
for_each_set_bit(p, ®, 32)
|
||||
generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
|
||||
}
|
||||
|
||||
chained_irq_exit(ic, desc);
|
||||
|
@ -204,11 +204,8 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
|
||||
|
||||
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
||||
|
||||
if (pending) {
|
||||
for_each_set_bit(irq, &pending, gc->ngpio)
|
||||
generic_handle_irq(
|
||||
irq_linear_revmap(gc->irq.domain, irq));
|
||||
}
|
||||
for_each_set_bit(irq, &pending, gc->ngpio)
|
||||
generic_handle_domain_irq(gc->irq.domain, irq);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
@ -466,9 +466,6 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
|
||||
(~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
|
||||
for_each_set_bit(bit, &sta, 32) {
|
||||
int hwirq = GPIO_PER_BANK * bank_id + bit;
|
||||
int child_irq =
|
||||
irq_find_mapping(bank->kona_gpio->irq_domain,
|
||||
hwirq);
|
||||
/*
|
||||
* Clear interrupt before handler is called so we don't
|
||||
* miss any interrupt occurred during executing them.
|
||||
@ -476,7 +473,8 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
|
||||
writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
|
||||
BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
|
||||
/* Invoke interrupt handler */
|
||||
generic_handle_irq(child_irq);
|
||||
generic_handle_domain_irq(bank->kona_gpio->irq_domain,
|
||||
hwirq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,15 +277,14 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
|
||||
unsigned long status;
|
||||
|
||||
while ((status = brcmstb_gpio_get_active_irqs(bank))) {
|
||||
unsigned int irq, offset;
|
||||
unsigned int offset;
|
||||
|
||||
for_each_set_bit(offset, &status, 32) {
|
||||
if (offset >= bank->width)
|
||||
dev_warn(&priv->pdev->dev,
|
||||
"IRQ for invalid GPIO (bank=%d, offset=%d)\n",
|
||||
bank->id, offset);
|
||||
irq = irq_linear_revmap(domain, hwbase + offset);
|
||||
generic_handle_irq(irq);
|
||||
generic_handle_domain_irq(domain, hwbase + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ static void cdns_gpio_irq_handler(struct irq_desc *desc)
|
||||
~ioread32(cgpio->regs + CDNS_GPIO_IRQ_MASK);
|
||||
|
||||
for_each_set_bit(hwirq, &status, chip->ngpio)
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain, hwirq));
|
||||
generic_handle_domain_irq(chip->irq.domain, hwirq);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
@ -369,8 +369,7 @@ static void gpio_irq_handler(struct irq_desc *desc)
|
||||
*/
|
||||
hw_irq = (bank_num / 2) * 32 + bit;
|
||||
|
||||
generic_handle_irq(
|
||||
irq_find_mapping(d->irq_domain, hw_irq));
|
||||
generic_handle_domain_irq(d->irq_domain, hw_irq);
|
||||
}
|
||||
}
|
||||
chained_irq_exit(irq_desc_get_chip(desc), desc);
|
||||
|
@ -395,7 +395,7 @@ static struct irq_chip dln2_gpio_irqchip = {
|
||||
static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
|
||||
const void *data, int len)
|
||||
{
|
||||
int pin, irq;
|
||||
int pin, ret;
|
||||
|
||||
const struct {
|
||||
__le16 count;
|
||||
@ -416,24 +416,20 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
|
||||
return;
|
||||
}
|
||||
|
||||
irq = irq_find_mapping(dln2->gpio.irq.domain, pin);
|
||||
if (!irq) {
|
||||
dev_err(dln2->gpio.parent, "pin %d not mapped to IRQ\n", pin);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dln2->irq_type[pin]) {
|
||||
case DLN2_GPIO_EVENT_CHANGE_RISING:
|
||||
if (event->value)
|
||||
generic_handle_irq(irq);
|
||||
if (!event->value)
|
||||
return;
|
||||
break;
|
||||
case DLN2_GPIO_EVENT_CHANGE_FALLING:
|
||||
if (!event->value)
|
||||
generic_handle_irq(irq);
|
||||
if (event->value)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
|
||||
ret = generic_handle_domain_irq(dln2->gpio.irq.domain, pin);
|
||||
if (unlikely(ret))
|
||||
dev_err(dln2->gpio.parent, "pin %d not mapped to IRQ\n", pin);
|
||||
}
|
||||
|
||||
static int dln2_gpio_probe(struct platform_device *pdev)
|
||||
|
@ -173,7 +173,7 @@ static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
|
||||
while ((pending = em_gio_read(p, GIO_MST))) {
|
||||
offset = __ffs(pending);
|
||||
em_gio_write(p, GIO_IIR, BIT(offset));
|
||||
generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
|
||||
generic_handle_domain_irq(p->irq_domain, offset);
|
||||
irqs_handled++;
|
||||
}
|
||||
|
||||
|
@ -128,13 +128,13 @@ static void ep93xx_gpio_ab_irq_handler(struct irq_desc *desc)
|
||||
*/
|
||||
stat = readb(epg->base + EP93XX_GPIO_A_INT_STATUS);
|
||||
for_each_set_bit(offset, &stat, 8)
|
||||
generic_handle_irq(irq_find_mapping(epg->gc[0].gc.irq.domain,
|
||||
offset));
|
||||
generic_handle_domain_irq(epg->gc[0].gc.irq.domain,
|
||||
offset);
|
||||
|
||||
stat = readb(epg->base + EP93XX_GPIO_B_INT_STATUS);
|
||||
for_each_set_bit(offset, &stat, 8)
|
||||
generic_handle_irq(irq_find_mapping(epg->gc[1].gc.irq.domain,
|
||||
offset));
|
||||
generic_handle_domain_irq(epg->gc[1].gc.irq.domain,
|
||||
offset);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
@ -149,8 +149,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
|
||||
stat = readl(g->base + GPIO_INT_STAT_RAW);
|
||||
if (stat)
|
||||
for_each_set_bit(offset, &stat, gc->ngpio)
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain,
|
||||
offset));
|
||||
generic_handle_domain_irq(gc->irq.domain, offset);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
@ -186,8 +186,8 @@ static void hisi_gpio_irq_handler(struct irq_desc *desc)
|
||||
|
||||
chained_irq_enter(irq_c, desc);
|
||||
for_each_set_bit(hwirq, &irq_msk, HISI_GPIO_LINE_NUM_MAX)
|
||||
generic_handle_irq(irq_find_mapping(hisi_gpio->chip.irq.domain,
|
||||
hwirq));
|
||||
generic_handle_domain_irq(hisi_gpio->chip.irq.domain,
|
||||
hwirq);
|
||||
chained_irq_exit(irq_c, desc);
|
||||
}
|
||||
|
||||
|
@ -97,11 +97,8 @@ static void hlwd_gpio_irqhandler(struct irq_desc *desc)
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
for_each_set_bit(hwirq, &pending, 32) {
|
||||
int irq = irq_find_mapping(hlwd->gpioc.irq.domain, hwirq);
|
||||
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(hwirq, &pending, 32)
|
||||
generic_handle_domain_irq(hlwd->gpioc.irq.domain, hwirq);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
@ -359,12 +359,8 @@ static void mrfld_irq_handler(struct irq_desc *desc)
|
||||
/* Only interrupts that are enabled */
|
||||
pending &= enabled;
|
||||
|
||||
for_each_set_bit(gpio, &pending, 32) {
|
||||
unsigned int irq;
|
||||
|
||||
irq = irq_find_mapping(gc->irq.domain, base + gpio);
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(gpio, &pending, 32)
|
||||
generic_handle_domain_irq(gc->irq.domain, base + gpio);
|
||||
}
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
|
@ -120,7 +120,7 @@ static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
|
||||
mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
|
||||
& gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
|
||||
for_each_set_bit(i, &mask, 32)
|
||||
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, 31 - i));
|
||||
generic_handle_domain_irq(mpc8xxx_gc->irq, 31 - i);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -95,9 +95,7 @@ mediatek_gpio_irq_handler(int irq, void *data)
|
||||
pending = mtk_gpio_r32(rg, GPIO_REG_STAT);
|
||||
|
||||
for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) {
|
||||
u32 map = irq_find_mapping(gc->irq.domain, bit);
|
||||
|
||||
generic_handle_irq(map);
|
||||
generic_handle_domain_irq(gc->irq.domain, bit);
|
||||
mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit));
|
||||
ret |= IRQ_HANDLED;
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
|
||||
if (port->both_edges & (1 << irqoffset))
|
||||
mxc_flip_edge(port, irqoffset);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
|
||||
generic_handle_domain_irq(port->domain, irqoffset);
|
||||
|
||||
irq_stat &= ~(1 << irqoffset);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ static void mxs_gpio_irq_handler(struct irq_desc *desc)
|
||||
if (port->both_edges & (1 << irqoffset))
|
||||
mxs_flip_edge(port, irqoffset);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
|
||||
generic_handle_domain_irq(port->domain, irqoffset);
|
||||
irq_stat &= ~(1 << irqoffset);
|
||||
}
|
||||
}
|
||||
|
@ -611,8 +611,7 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
|
||||
|
||||
raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(bank->chip.irq.domain,
|
||||
bit));
|
||||
generic_handle_domain_irq(bank->chip.irq.domain, bit);
|
||||
|
||||
raw_spin_unlock_irqrestore(&bank->wa_lock,
|
||||
wa_lock_flags);
|
||||
|
@ -260,7 +260,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
|
||||
return IRQ_NONE;
|
||||
|
||||
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
|
||||
generic_handle_domain_irq(chip->irq.domain, gpio);
|
||||
|
||||
raw_spin_lock(&idio16gpio->lock);
|
||||
|
||||
|
@ -468,8 +468,7 @@ static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
|
||||
irq_mask = idio24gpio->irq_mask & irq_status;
|
||||
|
||||
for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
|
||||
generic_handle_irq(irq_find_mapping(chip->irq.domain,
|
||||
gpio + 24));
|
||||
generic_handle_domain_irq(chip->irq.domain, gpio + 24);
|
||||
|
||||
raw_spin_lock(&idio24gpio->lock);
|
||||
|
||||
|
@ -223,8 +223,8 @@ static void pl061_irq_handler(struct irq_desc *desc)
|
||||
pending = readb(pl061->base + GPIOMIS);
|
||||
if (pending) {
|
||||
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain,
|
||||
offset));
|
||||
generic_handle_domain_irq(gc->irq.domain,
|
||||
offset);
|
||||
}
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
|
@ -455,9 +455,8 @@ static irqreturn_t pxa_gpio_demux_handler(int in_irq, void *d)
|
||||
for_each_set_bit(n, &gedr, BITS_PER_LONG) {
|
||||
loop = 1;
|
||||
|
||||
generic_handle_irq(
|
||||
irq_find_mapping(pchip->irqdomain,
|
||||
gpio + n));
|
||||
generic_handle_domain_irq(pchip->irqdomain,
|
||||
gpio + n);
|
||||
}
|
||||
}
|
||||
handled += loop;
|
||||
@ -471,9 +470,9 @@ static irqreturn_t pxa_gpio_direct_handler(int in_irq, void *d)
|
||||
struct pxa_gpio_chip *pchip = d;
|
||||
|
||||
if (in_irq == pchip->irq0) {
|
||||
generic_handle_irq(irq_find_mapping(pchip->irqdomain, 0));
|
||||
generic_handle_domain_irq(pchip->irqdomain, 0);
|
||||
} else if (in_irq == pchip->irq1) {
|
||||
generic_handle_irq(irq_find_mapping(pchip->irqdomain, 1));
|
||||
generic_handle_domain_irq(pchip->irqdomain, 1);
|
||||
} else {
|
||||
pr_err("%s() unknown irq %d\n", __func__, in_irq);
|
||||
return IRQ_NONE;
|
||||
|
@ -213,8 +213,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
|
||||
gpio_rcar_read(p, INTMSK))) {
|
||||
offset = __ffs(pending);
|
||||
gpio_rcar_write(p, INTCLR, BIT(offset));
|
||||
generic_handle_irq(irq_find_mapping(p->gpio_chip.irq.domain,
|
||||
offset));
|
||||
generic_handle_domain_irq(p->gpio_chip.irq.domain,
|
||||
offset);
|
||||
irqs_handled++;
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ static void rda_gpio_irq_handler(struct irq_desc *desc)
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
|
||||
unsigned long status;
|
||||
u32 n, girq;
|
||||
u32 n;
|
||||
|
||||
chained_irq_enter(ic, desc);
|
||||
|
||||
@ -189,10 +189,8 @@ static void rda_gpio_irq_handler(struct irq_desc *desc)
|
||||
/* Only lower 8 bits are capable of generating interrupts */
|
||||
status &= RDA_GPIO_IRQ_MASK;
|
||||
|
||||
for_each_set_bit(n, &status, RDA_GPIO_BANK_NR) {
|
||||
girq = irq_find_mapping(chip->irq.domain, n);
|
||||
generic_handle_irq(girq);
|
||||
}
|
||||
for_each_set_bit(n, &status, RDA_GPIO_BANK_NR)
|
||||
generic_handle_domain_irq(chip->irq.domain, n);
|
||||
|
||||
chained_irq_exit(ic, desc);
|
||||
}
|
||||
|
@ -196,7 +196,6 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc)
|
||||
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
|
||||
unsigned int lines_done;
|
||||
unsigned int port_pin_count;
|
||||
unsigned int irq;
|
||||
unsigned long status;
|
||||
int offset;
|
||||
|
||||
@ -205,10 +204,8 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc)
|
||||
for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
|
||||
status = realtek_gpio_read_isr(ctrl, lines_done / 8);
|
||||
port_pin_count = min(gc->ngpio - lines_done, 8U);
|
||||
for_each_set_bit(offset, &status, port_pin_count) {
|
||||
irq = irq_find_mapping(gc->irq.domain, offset);
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(offset, &status, port_pin_count)
|
||||
generic_handle_domain_irq(gc->irq.domain, offset);
|
||||
}
|
||||
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
|
771
drivers/gpio/gpio-rockchip.c
Normal file
771
drivers/gpio/gpio-rockchip.c
Normal file
@ -0,0 +1,771 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2013 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co. Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "../pinctrl/core.h"
|
||||
#include "../pinctrl/pinctrl-rockchip.h"
|
||||
|
||||
#define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */
|
||||
#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */
|
||||
|
||||
static const struct rockchip_gpio_regs gpio_regs_v1 = {
|
||||
.port_dr = 0x00,
|
||||
.port_ddr = 0x04,
|
||||
.int_en = 0x30,
|
||||
.int_mask = 0x34,
|
||||
.int_type = 0x38,
|
||||
.int_polarity = 0x3c,
|
||||
.int_status = 0x40,
|
||||
.int_rawstatus = 0x44,
|
||||
.debounce = 0x48,
|
||||
.port_eoi = 0x4c,
|
||||
.ext_port = 0x50,
|
||||
};
|
||||
|
||||
static const struct rockchip_gpio_regs gpio_regs_v2 = {
|
||||
.port_dr = 0x00,
|
||||
.port_ddr = 0x08,
|
||||
.int_en = 0x10,
|
||||
.int_mask = 0x18,
|
||||
.int_type = 0x20,
|
||||
.int_polarity = 0x28,
|
||||
.int_bothedge = 0x30,
|
||||
.int_status = 0x50,
|
||||
.int_rawstatus = 0x58,
|
||||
.debounce = 0x38,
|
||||
.dbclk_div_en = 0x40,
|
||||
.dbclk_div_con = 0x48,
|
||||
.port_eoi = 0x60,
|
||||
.ext_port = 0x70,
|
||||
.version_id = 0x78,
|
||||
};
|
||||
|
||||
static inline void gpio_writel_v2(u32 val, void __iomem *reg)
|
||||
{
|
||||
writel((val & 0xffff) | 0xffff0000, reg);
|
||||
writel((val >> 16) | 0xffff0000, reg + 0x4);
|
||||
}
|
||||
|
||||
static inline u32 gpio_readl_v2(void __iomem *reg)
|
||||
{
|
||||
return readl(reg + 0x4) << 16 | readl(reg);
|
||||
}
|
||||
|
||||
static inline void rockchip_gpio_writel(struct rockchip_pin_bank *bank,
|
||||
u32 value, unsigned int offset)
|
||||
{
|
||||
void __iomem *reg = bank->reg_base + offset;
|
||||
|
||||
if (bank->gpio_type == GPIO_TYPE_V2)
|
||||
gpio_writel_v2(value, reg);
|
||||
else
|
||||
writel(value, reg);
|
||||
}
|
||||
|
||||
static inline u32 rockchip_gpio_readl(struct rockchip_pin_bank *bank,
|
||||
unsigned int offset)
|
||||
{
|
||||
void __iomem *reg = bank->reg_base + offset;
|
||||
u32 value;
|
||||
|
||||
if (bank->gpio_type == GPIO_TYPE_V2)
|
||||
value = gpio_readl_v2(reg);
|
||||
else
|
||||
value = readl(reg);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void rockchip_gpio_writel_bit(struct rockchip_pin_bank *bank,
|
||||
u32 bit, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
void __iomem *reg = bank->reg_base + offset;
|
||||
u32 data;
|
||||
|
||||
if (bank->gpio_type == GPIO_TYPE_V2) {
|
||||
if (value)
|
||||
data = BIT(bit % 16) | BIT(bit % 16 + 16);
|
||||
else
|
||||
data = BIT(bit % 16 + 16);
|
||||
writel(data, bit >= 16 ? reg + 0x4 : reg);
|
||||
} else {
|
||||
data = readl(reg);
|
||||
data &= ~BIT(bit);
|
||||
if (value)
|
||||
data |= BIT(bit);
|
||||
writel(data, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u32 rockchip_gpio_readl_bit(struct rockchip_pin_bank *bank,
|
||||
u32 bit, unsigned int offset)
|
||||
{
|
||||
void __iomem *reg = bank->reg_base + offset;
|
||||
u32 data;
|
||||
|
||||
if (bank->gpio_type == GPIO_TYPE_V2) {
|
||||
data = readl(bit >= 16 ? reg + 0x4 : reg);
|
||||
data >>= bit % 16;
|
||||
} else {
|
||||
data = readl(reg);
|
||||
data >>= bit;
|
||||
}
|
||||
|
||||
return data & (0x1);
|
||||
}
|
||||
|
||||
static int rockchip_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(chip);
|
||||
u32 data;
|
||||
|
||||
data = rockchip_gpio_readl_bit(bank, offset, bank->gpio_regs->port_ddr);
|
||||
if (data & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int rockchip_gpio_set_direction(struct gpio_chip *chip,
|
||||
unsigned int offset, bool input)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
u32 data = input ? 0 : 1;
|
||||
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
rockchip_gpio_writel_bit(bank, offset, value, bank->gpio_regs->port_dr);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static int rockchip_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
|
||||
u32 data;
|
||||
|
||||
data = readl(bank->reg_base + bank->gpio_regs->ext_port);
|
||||
data >>= offset;
|
||||
data &= 1;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int rockchip_gpio_set_debounce(struct gpio_chip *gc,
|
||||
unsigned int offset,
|
||||
unsigned int debounce)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
|
||||
const struct rockchip_gpio_regs *reg = bank->gpio_regs;
|
||||
unsigned long flags, div_reg, freq, max_debounce;
|
||||
bool div_debounce_support;
|
||||
unsigned int cur_div_reg;
|
||||
u64 div;
|
||||
|
||||
if (!IS_ERR(bank->db_clk)) {
|
||||
div_debounce_support = true;
|
||||
freq = clk_get_rate(bank->db_clk);
|
||||
max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq;
|
||||
if (debounce > max_debounce)
|
||||
return -EINVAL;
|
||||
|
||||
div = debounce * freq;
|
||||
div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1;
|
||||
} else {
|
||||
div_debounce_support = false;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
/* Only the v1 needs to configure div_en and div_con for dbclk */
|
||||
if (debounce) {
|
||||
if (div_debounce_support) {
|
||||
/* Configure the max debounce from consumers */
|
||||
cur_div_reg = readl(bank->reg_base +
|
||||
reg->dbclk_div_con);
|
||||
if (cur_div_reg < div_reg)
|
||||
writel(div_reg, bank->reg_base +
|
||||
reg->dbclk_div_con);
|
||||
rockchip_gpio_writel_bit(bank, offset, 1,
|
||||
reg->dbclk_div_en);
|
||||
}
|
||||
|
||||
rockchip_gpio_writel_bit(bank, offset, 1, reg->debounce);
|
||||
} else {
|
||||
if (div_debounce_support)
|
||||
rockchip_gpio_writel_bit(bank, offset, 0,
|
||||
reg->dbclk_div_en);
|
||||
|
||||
rockchip_gpio_writel_bit(bank, offset, 0, reg->debounce);
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
/* Enable or disable dbclk at last */
|
||||
if (div_debounce_support) {
|
||||
if (debounce)
|
||||
clk_prepare_enable(bank->db_clk);
|
||||
else
|
||||
clk_disable_unprepare(bank->db_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_gpio_direction_input(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
return rockchip_gpio_set_direction(gc, offset, true);
|
||||
}
|
||||
|
||||
static int rockchip_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
rockchip_gpio_set(gc, offset, value);
|
||||
|
||||
return rockchip_gpio_set_direction(gc, offset, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* gpiolib set_config callback function. The setting of the pin
|
||||
* mux function as 'gpio output' will be handled by the pinctrl subsystem
|
||||
* interface.
|
||||
*/
|
||||
static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
rockchip_gpio_set_debounce(gc, offset, true);
|
||||
/*
|
||||
* Rockchip's gpio could only support up to one period
|
||||
* of the debounce clock(pclk), which is far away from
|
||||
* satisftying the requirement, as pclk is usually near
|
||||
* 100MHz shared by all peripherals. So the fact is it
|
||||
* has crippled debounce capability could only be useful
|
||||
* to prevent any spurious glitches from waking up the system
|
||||
* if the gpio is conguired as wakeup interrupt source. Let's
|
||||
* still return -ENOTSUPP as before, to make sure the caller
|
||||
* of gpiod_set_debounce won't change its behaviour.
|
||||
*/
|
||||
return -ENOTSUPP;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
|
||||
* and a virtual IRQ, if not already present.
|
||||
*/
|
||||
static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
|
||||
unsigned int virq;
|
||||
|
||||
if (!bank->domain)
|
||||
return -ENXIO;
|
||||
|
||||
virq = irq_create_mapping(bank->domain, offset);
|
||||
|
||||
return (virq) ? : -ENXIO;
|
||||
}
|
||||
|
||||
static const struct gpio_chip rockchip_gpiolib_chip = {
|
||||
.request = gpiochip_generic_request,
|
||||
.free = gpiochip_generic_free,
|
||||
.set = rockchip_gpio_set,
|
||||
.get = rockchip_gpio_get,
|
||||
.get_direction = rockchip_gpio_get_direction,
|
||||
.direction_input = rockchip_gpio_direction_input,
|
||||
.direction_output = rockchip_gpio_direction_output,
|
||||
.set_config = rockchip_gpio_set_config,
|
||||
.to_irq = rockchip_gpio_to_irq,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void rockchip_irq_demux(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
|
||||
u32 pend;
|
||||
|
||||
dev_dbg(bank->dev, "got irq for bank %s\n", bank->name);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
pend = readl_relaxed(bank->reg_base + bank->gpio_regs->int_status);
|
||||
|
||||
while (pend) {
|
||||
unsigned int irq, virq;
|
||||
|
||||
irq = __ffs(pend);
|
||||
pend &= ~BIT(irq);
|
||||
virq = irq_find_mapping(bank->domain, irq);
|
||||
|
||||
if (!virq) {
|
||||
dev_err(bank->dev, "unmapped irq %d\n", irq);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_dbg(bank->dev, "handling irq %d\n", irq);
|
||||
|
||||
/*
|
||||
* Triggering IRQ on both rising and falling edge
|
||||
* needs manual intervention.
|
||||
*/
|
||||
if (bank->toggle_edge_mode & BIT(irq)) {
|
||||
u32 data, data_old, polarity;
|
||||
unsigned long flags;
|
||||
|
||||
data = readl_relaxed(bank->reg_base +
|
||||
bank->gpio_regs->ext_port);
|
||||
do {
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
polarity = readl_relaxed(bank->reg_base +
|
||||
bank->gpio_regs->int_polarity);
|
||||
if (data & BIT(irq))
|
||||
polarity &= ~BIT(irq);
|
||||
else
|
||||
polarity |= BIT(irq);
|
||||
writel(polarity,
|
||||
bank->reg_base +
|
||||
bank->gpio_regs->int_polarity);
|
||||
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
data_old = data;
|
||||
data = readl_relaxed(bank->reg_base +
|
||||
bank->gpio_regs->ext_port);
|
||||
} while ((data & BIT(irq)) != (data_old & BIT(irq)));
|
||||
}
|
||||
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct rockchip_pin_bank *bank = gc->private;
|
||||
u32 mask = BIT(d->hwirq);
|
||||
u32 polarity;
|
||||
u32 level;
|
||||
u32 data;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
rockchip_gpio_writel_bit(bank, d->hwirq, 0,
|
||||
bank->gpio_regs->port_ddr);
|
||||
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
else
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
level = rockchip_gpio_readl(bank, bank->gpio_regs->int_type);
|
||||
polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
if (bank->gpio_type == GPIO_TYPE_V2) {
|
||||
bank->toggle_edge_mode &= ~mask;
|
||||
rockchip_gpio_writel_bit(bank, d->hwirq, 1,
|
||||
bank->gpio_regs->int_bothedge);
|
||||
goto out;
|
||||
} else {
|
||||
bank->toggle_edge_mode |= mask;
|
||||
level |= mask;
|
||||
|
||||
/*
|
||||
* Determine gpio state. If 1 next interrupt should be
|
||||
* falling otherwise rising.
|
||||
*/
|
||||
data = readl(bank->reg_base + bank->gpio_regs->ext_port);
|
||||
if (data & mask)
|
||||
polarity &= ~mask;
|
||||
else
|
||||
polarity |= mask;
|
||||
}
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
bank->toggle_edge_mode &= ~mask;
|
||||
level |= mask;
|
||||
polarity |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
bank->toggle_edge_mode &= ~mask;
|
||||
level |= mask;
|
||||
polarity &= ~mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
bank->toggle_edge_mode &= ~mask;
|
||||
level &= ~mask;
|
||||
polarity |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
bank->toggle_edge_mode &= ~mask;
|
||||
level &= ~mask;
|
||||
polarity &= ~mask;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rockchip_gpio_writel(bank, level, bank->gpio_regs->int_type);
|
||||
rockchip_gpio_writel(bank, polarity, bank->gpio_regs->int_polarity);
|
||||
out:
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_irq_suspend(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct rockchip_pin_bank *bank = gc->private;
|
||||
|
||||
bank->saved_masks = irq_reg_readl(gc, bank->gpio_regs->int_mask);
|
||||
irq_reg_writel(gc, ~gc->wake_active, bank->gpio_regs->int_mask);
|
||||
}
|
||||
|
||||
static void rockchip_irq_resume(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct rockchip_pin_bank *bank = gc->private;
|
||||
|
||||
irq_reg_writel(gc, bank->saved_masks, bank->gpio_regs->int_mask);
|
||||
}
|
||||
|
||||
static void rockchip_irq_enable(struct irq_data *d)
|
||||
{
|
||||
irq_gc_mask_clr_bit(d);
|
||||
}
|
||||
|
||||
static void rockchip_irq_disable(struct irq_data *d)
|
||||
{
|
||||
irq_gc_mask_set_bit(d);
|
||||
}
|
||||
|
||||
static int rockchip_interrupts_register(struct rockchip_pin_bank *bank)
|
||||
{
|
||||
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
|
||||
struct irq_chip_generic *gc;
|
||||
int ret;
|
||||
|
||||
bank->domain = irq_domain_add_linear(bank->of_node, 32,
|
||||
&irq_generic_chip_ops, NULL);
|
||||
if (!bank->domain) {
|
||||
dev_warn(bank->dev, "could not init irq domain for bank %s\n",
|
||||
bank->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1,
|
||||
"rockchip_gpio_irq",
|
||||
handle_level_irq,
|
||||
clr, 0, 0);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "could not alloc generic chips for bank %s\n",
|
||||
bank->name);
|
||||
irq_domain_remove(bank->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gc = irq_get_domain_generic_chip(bank->domain, 0);
|
||||
if (bank->gpio_type == GPIO_TYPE_V2) {
|
||||
gc->reg_writel = gpio_writel_v2;
|
||||
gc->reg_readl = gpio_readl_v2;
|
||||
}
|
||||
|
||||
gc->reg_base = bank->reg_base;
|
||||
gc->private = bank;
|
||||
gc->chip_types[0].regs.mask = bank->gpio_regs->int_mask;
|
||||
gc->chip_types[0].regs.ack = bank->gpio_regs->port_eoi;
|
||||
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
|
||||
gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
|
||||
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
|
||||
gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
|
||||
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
|
||||
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
|
||||
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
|
||||
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
|
||||
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
|
||||
|
||||
/*
|
||||
* Linux assumes that all interrupts start out disabled/masked.
|
||||
* Our driver only uses the concept of masked and always keeps
|
||||
* things enabled, so for us that's all masked and all enabled.
|
||||
*/
|
||||
rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->int_mask);
|
||||
rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->port_eoi);
|
||||
rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->int_en);
|
||||
gc->mask_cache = 0xffffffff;
|
||||
|
||||
irq_set_chained_handler_and_data(bank->irq,
|
||||
rockchip_irq_demux, bank);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
|
||||
{
|
||||
struct gpio_chip *gc;
|
||||
int ret;
|
||||
|
||||
bank->gpio_chip = rockchip_gpiolib_chip;
|
||||
|
||||
gc = &bank->gpio_chip;
|
||||
gc->base = bank->pin_base;
|
||||
gc->ngpio = bank->nr_pins;
|
||||
gc->label = bank->name;
|
||||
gc->parent = bank->dev;
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
gc->of_node = of_node_get(bank->of_node);
|
||||
#endif
|
||||
|
||||
ret = gpiochip_add_data(gc, bank);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "failed to add gpiochip %s, %d\n",
|
||||
gc->label, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* For DeviceTree-supported systems, the gpio core checks the
|
||||
* pinctrl's device node for the "gpio-ranges" property.
|
||||
* If it is present, it takes care of adding the pin ranges
|
||||
* for the driver. In this case the driver can skip ahead.
|
||||
*
|
||||
* In order to remain compatible with older, existing DeviceTree
|
||||
* files which don't set the "gpio-ranges" property or systems that
|
||||
* utilize ACPI the driver has to call gpiochip_add_pin_range().
|
||||
*/
|
||||
if (!of_property_read_bool(bank->of_node, "gpio-ranges")) {
|
||||
struct device_node *pctlnp = of_get_parent(bank->of_node);
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
|
||||
if (!pctlnp)
|
||||
return -ENODATA;
|
||||
|
||||
pctldev = of_pinctrl_get(pctlnp);
|
||||
if (!pctldev)
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
|
||||
gc->base, gc->ngpio);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "Failed to add pin range\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rockchip_interrupts_register(bank);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "failed to register interrupt, %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
gpiochip_remove(&bank->gpio_chip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
|
||||
{
|
||||
struct resource res;
|
||||
int id = 0;
|
||||
|
||||
if (of_address_to_resource(bank->of_node, 0, &res)) {
|
||||
dev_err(bank->dev, "cannot find IO resource for bank\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
bank->reg_base = devm_ioremap_resource(bank->dev, &res);
|
||||
if (IS_ERR(bank->reg_base))
|
||||
return PTR_ERR(bank->reg_base);
|
||||
|
||||
bank->irq = irq_of_parse_and_map(bank->of_node, 0);
|
||||
if (!bank->irq)
|
||||
return -EINVAL;
|
||||
|
||||
bank->clk = of_clk_get(bank->of_node, 0);
|
||||
if (IS_ERR(bank->clk))
|
||||
return PTR_ERR(bank->clk);
|
||||
|
||||
clk_prepare_enable(bank->clk);
|
||||
id = readl(bank->reg_base + gpio_regs_v2.version_id);
|
||||
|
||||
/* If not gpio v2, that is default to v1. */
|
||||
if (id == GPIO_TYPE_V2) {
|
||||
bank->gpio_regs = &gpio_regs_v2;
|
||||
bank->gpio_type = GPIO_TYPE_V2;
|
||||
bank->db_clk = of_clk_get(bank->of_node, 1);
|
||||
if (IS_ERR(bank->db_clk)) {
|
||||
dev_err(bank->dev, "cannot find debounce clk\n");
|
||||
clk_disable_unprepare(bank->clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
bank->gpio_regs = &gpio_regs_v1;
|
||||
bank->gpio_type = GPIO_TYPE_V1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rockchip_pin_bank *
|
||||
rockchip_gpio_find_bank(struct pinctrl_dev *pctldev, int id)
|
||||
{
|
||||
struct rockchip_pinctrl *info;
|
||||
struct rockchip_pin_bank *bank;
|
||||
int i, found = 0;
|
||||
|
||||
info = pinctrl_dev_get_drvdata(pctldev);
|
||||
bank = info->ctrl->pin_banks;
|
||||
for (i = 0; i < info->ctrl->nr_banks; i++, bank++) {
|
||||
if (bank->bank_num == id) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found ? bank : NULL;
|
||||
}
|
||||
|
||||
static int rockchip_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *pctlnp = of_get_parent(np);
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
struct rockchip_pin_bank *bank = NULL;
|
||||
static int gpio;
|
||||
int id, ret;
|
||||
|
||||
if (!np || !pctlnp)
|
||||
return -ENODEV;
|
||||
|
||||
pctldev = of_pinctrl_get(pctlnp);
|
||||
if (!pctldev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
id = of_alias_get_id(np, "gpio");
|
||||
if (id < 0)
|
||||
id = gpio++;
|
||||
|
||||
bank = rockchip_gpio_find_bank(pctldev, id);
|
||||
if (!bank)
|
||||
return -EINVAL;
|
||||
|
||||
bank->dev = dev;
|
||||
bank->of_node = np;
|
||||
|
||||
raw_spin_lock_init(&bank->slock);
|
||||
|
||||
ret = rockchip_get_bank_data(bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rockchip_gpiolib_register(bank);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(bank->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, bank);
|
||||
dev_info(dev, "probed %pOF\n", np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(bank->clk);
|
||||
gpiochip_remove(&bank->gpio_chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rockchip_gpio_match[] = {
|
||||
{ .compatible = "rockchip,gpio-bank", },
|
||||
{ .compatible = "rockchip,rk3188-gpio-bank0" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver rockchip_gpio_driver = {
|
||||
.probe = rockchip_gpio_probe,
|
||||
.remove = rockchip_gpio_remove,
|
||||
.driver = {
|
||||
.name = "rockchip-gpio",
|
||||
.of_match_table = rockchip_gpio_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init rockchip_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&rockchip_gpio_driver);
|
||||
}
|
||||
postcore_initcall(rockchip_gpio_init);
|
||||
|
||||
static void __exit rockchip_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rockchip_gpio_driver);
|
||||
}
|
||||
module_exit(rockchip_gpio_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Rockchip gpio driver");
|
||||
MODULE_ALIAS("platform:rockchip-gpio");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DEVICE_TABLE(of, rockchip_gpio_match);
|
@ -259,7 +259,7 @@ static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
|
||||
|
||||
pending = (resume_status << sch->resume_base) | core_status;
|
||||
for_each_set_bit(offset, &pending, sch->chip.ngpio)
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain, offset));
|
||||
generic_handle_domain_irq(gc->irq.domain, offset);
|
||||
|
||||
/* Set returning value depending on whether we handled an interrupt */
|
||||
ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
|
||||
|
@ -84,7 +84,7 @@ static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
|
||||
return IRQ_NONE;
|
||||
|
||||
for_each_set_bit(irq_bit, &irq_stat, 32)
|
||||
generic_handle_irq(irq_find_mapping(sd->id, irq_bit));
|
||||
generic_handle_domain_irq(sd->id, irq_bit);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ static void sprd_gpio_irq_handler(struct irq_desc *desc)
|
||||
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
|
||||
u32 bank, n, girq;
|
||||
u32 bank, n;
|
||||
|
||||
chained_irq_enter(ic, desc);
|
||||
|
||||
@ -198,13 +198,9 @@ static void sprd_gpio_irq_handler(struct irq_desc *desc)
|
||||
unsigned long reg = readl_relaxed(base + SPRD_GPIO_MIS) &
|
||||
SPRD_GPIO_BANK_MASK;
|
||||
|
||||
for_each_set_bit(n, ®, SPRD_GPIO_BANK_NR) {
|
||||
girq = irq_find_mapping(chip->irq.domain,
|
||||
bank * SPRD_GPIO_BANK_NR + n);
|
||||
|
||||
generic_handle_irq(girq);
|
||||
}
|
||||
|
||||
for_each_set_bit(n, ®, SPRD_GPIO_BANK_NR)
|
||||
generic_handle_domain_irq(chip->irq.domain,
|
||||
bank * SPRD_GPIO_BANK_NR + n);
|
||||
}
|
||||
chained_irq_exit(ic, desc);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data)
|
||||
int i;
|
||||
|
||||
for_each_set_bit(i, &bits, 32)
|
||||
generic_handle_irq(irq_find_mapping(tb10x_gpio->domain, i));
|
||||
generic_handle_domain_irq(tb10x_gpio->domain, i);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -408,6 +408,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc)
|
||||
lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
|
||||
|
||||
for_each_set_bit(pin, &sta, 8) {
|
||||
int ret;
|
||||
|
||||
tegra_gpio_writel(tgi, 1 << pin,
|
||||
GPIO_INT_CLR(tgi, gpio));
|
||||
|
||||
@ -420,11 +422,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
irq = irq_find_mapping(domain, gpio + pin);
|
||||
if (WARN_ON(irq == 0))
|
||||
continue;
|
||||
|
||||
generic_handle_irq(irq);
|
||||
ret = generic_handle_domain_irq(domain, gpio + pin);
|
||||
WARN_RATELIMIT(ret, "hwirq = %d", gpio + pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,7 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
|
||||
|
||||
for (i = 0; i < gpio->soc->num_ports; i++) {
|
||||
const struct tegra_gpio_port *port = &gpio->soc->ports[i];
|
||||
unsigned int pin, irq;
|
||||
unsigned int pin;
|
||||
unsigned long value;
|
||||
void __iomem *base;
|
||||
|
||||
@ -469,11 +469,8 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
|
||||
value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
|
||||
|
||||
for_each_set_bit(pin, &value, port->pins) {
|
||||
irq = irq_find_mapping(domain, offset + pin);
|
||||
if (WARN_ON(irq == 0))
|
||||
continue;
|
||||
|
||||
generic_handle_irq(irq);
|
||||
int ret = generic_handle_domain_irq(domain, offset + pin);
|
||||
WARN_RATELIMIT(ret, "hwirq = %d", offset + pin);
|
||||
}
|
||||
|
||||
skip:
|
||||
|
@ -183,7 +183,7 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
|
||||
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
|
||||
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
|
||||
unsigned long irq_bits;
|
||||
int i = 0, child_irq;
|
||||
int i = 0;
|
||||
u8 irq_status;
|
||||
|
||||
chained_irq_enter(irq_chip, desc);
|
||||
@ -192,11 +192,9 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
|
||||
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
|
||||
|
||||
irq_bits = irq_status;
|
||||
for_each_set_bit(i, &irq_bits, TQMX86_NGPI) {
|
||||
child_irq = irq_find_mapping(gpio->chip.irq.domain,
|
||||
i + TQMX86_NGPO);
|
||||
generic_handle_irq(child_irq);
|
||||
}
|
||||
for_each_set_bit(i, &irq_bits, TQMX86_NGPI)
|
||||
generic_handle_domain_irq(gpio->chip.irq.domain,
|
||||
i + TQMX86_NGPO);
|
||||
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ static void vf610_gpio_irq_handler(struct irq_desc *desc)
|
||||
for_each_set_bit(pin, &irq_isfr, VF610_GPIO_PER_PORT) {
|
||||
vf610_gpio_writel(BIT(pin), port->base + PORT_ISFR);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(port->gc.irq.domain, pin));
|
||||
generic_handle_domain_irq(port->gc.irq.domain, pin);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
@ -339,8 +339,8 @@ static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id)
|
||||
for_each_set_bit(port, &int_pending, 3) {
|
||||
int_id = inb(ws16c48gpio->base + 8 + port);
|
||||
for_each_set_bit(gpio, &int_id, 8)
|
||||
generic_handle_irq(irq_find_mapping(
|
||||
chip->irq.domain, gpio + 8*port));
|
||||
generic_handle_domain_irq(chip->irq.domain,
|
||||
gpio + 8*port);
|
||||
}
|
||||
|
||||
int_pending = inb(ws16c48gpio->base + 6) & 0x7;
|
||||
|
@ -185,7 +185,7 @@ static irqreturn_t iproc_gpio_irq_handler(int irq, void *data)
|
||||
int_bits = level | event;
|
||||
|
||||
for_each_set_bit(bit, &int_bits, gc->ngpio)
|
||||
generic_handle_irq(irq_linear_revmap(gc->irq.domain, bit));
|
||||
generic_handle_domain_irq(gc->irq.domain, bit);
|
||||
}
|
||||
|
||||
return int_bits ? IRQ_HANDLED : IRQ_NONE;
|
||||
|
@ -538,7 +538,7 @@ static void xgpio_irqhandler(struct irq_desc *desc)
|
||||
|
||||
for_each_set_bit(bit, all, 64) {
|
||||
irq_offset = xgpio_from_bit(chip, bit);
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain, irq_offset));
|
||||
generic_handle_domain_irq(gc->irq.domain, irq_offset);
|
||||
}
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
|
@ -216,8 +216,7 @@ static void xlp_gpio_generic_handler(struct irq_desc *desc)
|
||||
}
|
||||
|
||||
if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ))
|
||||
generic_handle_irq(irq_find_mapping(
|
||||
priv->chip.irq.domain, gpio));
|
||||
generic_handle_domain_irq(priv->chip.irq.domain, gpio);
|
||||
}
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
@ -628,12 +628,8 @@ static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
|
||||
if (!pending)
|
||||
return;
|
||||
|
||||
for_each_set_bit(offset, &pending, 32) {
|
||||
unsigned int gpio_irq;
|
||||
|
||||
gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset);
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
for_each_set_bit(offset, &pending, 32)
|
||||
generic_handle_domain_irq(irqdomain, offset + bank_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -502,7 +502,7 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
|
||||
} else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
|
||||
adev->irq.virq[src_id]) {
|
||||
generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id));
|
||||
generic_handle_domain_irq(adev->irq.domain, src_id);
|
||||
|
||||
} else if (!adev->irq.client[client_id].sources) {
|
||||
DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n",
|
||||
|
@ -45,20 +45,13 @@ static void dpu_mdss_irq(struct irq_desc *desc)
|
||||
|
||||
while (interrupts) {
|
||||
irq_hw_number_t hwirq = fls(interrupts) - 1;
|
||||
unsigned int mapping;
|
||||
int rc;
|
||||
|
||||
mapping = irq_find_mapping(dpu_mdss->irq_controller.domain,
|
||||
hwirq);
|
||||
if (mapping == 0) {
|
||||
DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = generic_handle_irq(mapping);
|
||||
rc = generic_handle_domain_irq(dpu_mdss->irq_controller.domain,
|
||||
hwirq);
|
||||
if (rc < 0) {
|
||||
DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n",
|
||||
hwirq, mapping, rc);
|
||||
DRM_ERROR("handle irq fail: irq=%lu rc=%d\n",
|
||||
hwirq, rc);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,7 @@ static irqreturn_t mdss_irq(int irq, void *arg)
|
||||
while (intr) {
|
||||
irq_hw_number_t hwirq = fls(intr) - 1;
|
||||
|
||||
generic_handle_irq(irq_find_mapping(
|
||||
mdp5_mdss->irqcontroller.domain, hwirq));
|
||||
generic_handle_domain_irq(mdp5_mdss->irqcontroller.domain, hwirq);
|
||||
intr &= ~(1 << hwirq);
|
||||
}
|
||||
|
||||
|
@ -1003,19 +1003,16 @@ static int ipu_submodules_init(struct ipu_soc *ipu,
|
||||
static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
|
||||
{
|
||||
unsigned long status;
|
||||
int i, bit, irq;
|
||||
int i, bit;
|
||||
|
||||
for (i = 0; i < num_regs; i++) {
|
||||
|
||||
status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
|
||||
status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
|
||||
|
||||
for_each_set_bit(bit, &status, 32) {
|
||||
irq = irq_linear_revmap(ipu->domain,
|
||||
regs[i] * 32 + bit);
|
||||
if (irq)
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
for_each_set_bit(bit, &status, 32)
|
||||
generic_handle_domain_irq(ipu->domain,
|
||||
regs[i] * 32 + bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,9 +267,7 @@ static int alpine_msix_init(struct device_node *node,
|
||||
goto err_priv;
|
||||
}
|
||||
|
||||
priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_spis),
|
||||
sizeof(*priv->msi_map),
|
||||
GFP_KERNEL);
|
||||
priv->msi_map = bitmap_zalloc(priv->num_spis, GFP_KERNEL);
|
||||
if (!priv->msi_map) {
|
||||
ret = -ENOMEM;
|
||||
goto err_priv;
|
||||
@ -285,7 +283,7 @@ static int alpine_msix_init(struct device_node *node,
|
||||
return 0;
|
||||
|
||||
err_map:
|
||||
kfree(priv->msi_map);
|
||||
bitmap_free(priv->msi_map);
|
||||
err_priv:
|
||||
kfree(priv);
|
||||
return ret;
|
||||
|
@ -226,7 +226,7 @@ static void aic_irq_eoi(struct irq_data *d)
|
||||
* Reading the interrupt reason automatically acknowledges and masks
|
||||
* the IRQ, so we just unmask it here if needed.
|
||||
*/
|
||||
if (!irqd_irq_disabled(d) && !irqd_irq_masked(d))
|
||||
if (!irqd_irq_masked(d))
|
||||
aic_irq_unmask(d);
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ static void gicv2m_teardown(void)
|
||||
|
||||
list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
|
||||
list_del(&v2m->entry);
|
||||
kfree(v2m->bm);
|
||||
bitmap_free(v2m->bm);
|
||||
iounmap(v2m->base);
|
||||
of_node_put(to_of_node(v2m->fwnode));
|
||||
if (is_fwnode_irqchip(v2m->fwnode))
|
||||
@ -386,8 +386,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
|
||||
break;
|
||||
}
|
||||
}
|
||||
v2m->bm = kcalloc(BITS_TO_LONGS(v2m->nr_spis), sizeof(long),
|
||||
GFP_KERNEL);
|
||||
v2m->bm = bitmap_zalloc(v2m->nr_spis, GFP_KERNEL);
|
||||
if (!v2m->bm) {
|
||||
ret = -ENOMEM;
|
||||
goto err_iounmap;
|
||||
|
@ -2140,7 +2140,7 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
bitmap = kcalloc(BITS_TO_LONGS(nr_irqs), sizeof (long), GFP_ATOMIC);
|
||||
bitmap = bitmap_zalloc(nr_irqs, GFP_ATOMIC);
|
||||
if (!bitmap)
|
||||
goto out;
|
||||
|
||||
@ -2156,7 +2156,7 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
|
||||
static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)
|
||||
{
|
||||
WARN_ON(free_lpi_range(base, nr_ids));
|
||||
kfree(bitmap);
|
||||
bitmap_free(bitmap);
|
||||
}
|
||||
|
||||
static void gic_reset_prop_table(void *va)
|
||||
@ -3387,7 +3387,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
||||
if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
|
||||
kfree(dev);
|
||||
kfree(itt);
|
||||
kfree(lpi_map);
|
||||
bitmap_free(lpi_map);
|
||||
kfree(col_map);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -290,8 +290,7 @@ int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
|
||||
if (ret)
|
||||
goto err_free_mbi;
|
||||
|
||||
mbi_ranges[n].bm = kcalloc(BITS_TO_LONGS(mbi_ranges[n].nr_spis),
|
||||
sizeof(long), GFP_KERNEL);
|
||||
mbi_ranges[n].bm = bitmap_zalloc(mbi_ranges[n].nr_spis, GFP_KERNEL);
|
||||
if (!mbi_ranges[n].bm) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_mbi;
|
||||
@ -329,7 +328,7 @@ int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
|
||||
err_free_mbi:
|
||||
if (mbi_ranges) {
|
||||
for (n = 0; n < mbi_range_nr; n++)
|
||||
kfree(mbi_ranges[n].bm);
|
||||
bitmap_free(mbi_ranges[n].bm);
|
||||
kfree(mbi_ranges);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,27 @@ EXPORT_SYMBOL(gic_pmr_sync);
|
||||
DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities);
|
||||
EXPORT_SYMBOL(gic_nonsecure_priorities);
|
||||
|
||||
/*
|
||||
* When the Non-secure world has access to group 0 interrupts (as a
|
||||
* consequence of SCR_EL3.FIQ == 0), reading the ICC_RPR_EL1 register will
|
||||
* return the Distributor's view of the interrupt priority.
|
||||
*
|
||||
* When GIC security is enabled (GICD_CTLR.DS == 0), the interrupt priority
|
||||
* written by software is moved to the Non-secure range by the Distributor.
|
||||
*
|
||||
* If both are true (which is when gic_nonsecure_priorities gets enabled),
|
||||
* we need to shift down the priority programmed by software to match it
|
||||
* against the value returned by ICC_RPR_EL1.
|
||||
*/
|
||||
#define GICD_INT_RPR_PRI(priority) \
|
||||
({ \
|
||||
u32 __priority = (priority); \
|
||||
if (static_branch_unlikely(&gic_nonsecure_priorities)) \
|
||||
__priority = 0x80 | (__priority >> 1); \
|
||||
\
|
||||
__priority; \
|
||||
})
|
||||
|
||||
/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
|
||||
static refcount_t *ppi_nmi_refs;
|
||||
|
||||
@ -446,18 +467,23 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
|
||||
writeb_relaxed(prio, base + offset + index);
|
||||
}
|
||||
|
||||
static u32 gic_get_ppi_index(struct irq_data *d)
|
||||
static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
|
||||
{
|
||||
switch (get_intid_range(d)) {
|
||||
switch (__get_intid_range(hwirq)) {
|
||||
case PPI_RANGE:
|
||||
return d->hwirq - 16;
|
||||
return hwirq - 16;
|
||||
case EPPI_RANGE:
|
||||
return d->hwirq - EPPI_BASE_INTID + 16;
|
||||
return hwirq - EPPI_BASE_INTID + 16;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gic_get_ppi_index(struct irq_data *d)
|
||||
{
|
||||
return __gic_get_ppi_index(d->hwirq);
|
||||
}
|
||||
|
||||
static int gic_irq_nmi_setup(struct irq_data *d)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
@ -687,7 +713,7 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
|
||||
return;
|
||||
|
||||
if (gic_supports_nmi() &&
|
||||
unlikely(gic_read_rpr() == GICD_INT_NMI_PRI)) {
|
||||
unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI))) {
|
||||
gic_handle_nmi(irqnr, regs);
|
||||
return;
|
||||
}
|
||||
@ -1467,10 +1493,34 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
}
|
||||
}
|
||||
|
||||
static bool fwspec_is_partitioned_ppi(struct irq_fwspec *fwspec,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
enum gic_intid_range range;
|
||||
|
||||
if (!gic_data.ppi_descs)
|
||||
return false;
|
||||
|
||||
if (!is_of_node(fwspec->fwnode))
|
||||
return false;
|
||||
|
||||
if (fwspec->param_count < 4 || !fwspec->param[3])
|
||||
return false;
|
||||
|
||||
range = __get_intid_range(hwirq);
|
||||
if (range != PPI_RANGE && range != EPPI_RANGE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int gic_irq_domain_select(struct irq_domain *d,
|
||||
struct irq_fwspec *fwspec,
|
||||
enum irq_domain_bus_token bus_token)
|
||||
{
|
||||
unsigned int type, ret, ppi_idx;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
/* Not for us */
|
||||
if (fwspec->fwnode != d->fwnode)
|
||||
return 0;
|
||||
@ -1479,16 +1529,19 @@ static int gic_irq_domain_select(struct irq_domain *d,
|
||||
if (!is_of_node(fwspec->fwnode))
|
||||
return 1;
|
||||
|
||||
ret = gic_irq_domain_translate(d, fwspec, &hwirq, &type);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
return 0;
|
||||
|
||||
if (!fwspec_is_partitioned_ppi(fwspec, hwirq))
|
||||
return d == gic_data.domain;
|
||||
|
||||
/*
|
||||
* If this is a PPI and we have a 4th (non-null) parameter,
|
||||
* then we need to match the partition domain.
|
||||
*/
|
||||
if (fwspec->param_count >= 4 &&
|
||||
fwspec->param[0] == 1 && fwspec->param[3] != 0 &&
|
||||
gic_data.ppi_descs)
|
||||
return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
|
||||
|
||||
return d == gic_data.domain;
|
||||
ppi_idx = __gic_get_ppi_index(hwirq);
|
||||
return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops gic_irq_domain_ops = {
|
||||
@ -1503,7 +1556,9 @@ static int partition_domain_translate(struct irq_domain *d,
|
||||
unsigned long *hwirq,
|
||||
unsigned int *type)
|
||||
{
|
||||
unsigned long ppi_intid;
|
||||
struct device_node *np;
|
||||
unsigned int ppi_idx;
|
||||
int ret;
|
||||
|
||||
if (!gic_data.ppi_descs)
|
||||
@ -1513,7 +1568,12 @@ static int partition_domain_translate(struct irq_domain *d,
|
||||
if (WARN_ON(!np))
|
||||
return -EINVAL;
|
||||
|
||||
ret = partition_translate_id(gic_data.ppi_descs[fwspec->param[1]],
|
||||
ret = gic_irq_domain_translate(d, fwspec, &ppi_intid, type);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
return 0;
|
||||
|
||||
ppi_idx = __gic_get_ppi_index(ppi_intid);
|
||||
ret = partition_translate_id(gic_data.ppi_descs[ppi_idx],
|
||||
of_node_to_fwnode(np));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -92,18 +92,22 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
|
||||
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
|
||||
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
|
||||
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
|
||||
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -113,11 +117,24 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pch_pic_ack_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int reg;
|
||||
struct pch_pic *priv = irq_data_get_irq_chip_data(d);
|
||||
|
||||
reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
|
||||
if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
|
||||
writel(BIT(PIC_REG_BIT(d->hwirq)),
|
||||
priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
|
||||
}
|
||||
irq_chip_ack_parent(d);
|
||||
}
|
||||
|
||||
static struct irq_chip pch_pic_irq_chip = {
|
||||
.name = "PCH PIC",
|
||||
.irq_mask = pch_pic_mask_irq,
|
||||
.irq_unmask = pch_pic_unmask_irq,
|
||||
.irq_ack = irq_chip_ack_parent,
|
||||
.irq_ack = pch_pic_ack_irq,
|
||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
.irq_set_type = pch_pic_set_type,
|
||||
};
|
||||
|
@ -362,10 +362,7 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
|
||||
|
||||
msi_data->irqs_num = MSI_IRQS_PER_MSIR *
|
||||
(1 << msi_data->cfg->ibs_shift);
|
||||
msi_data->used = devm_kcalloc(&pdev->dev,
|
||||
BITS_TO_LONGS(msi_data->irqs_num),
|
||||
sizeof(*msi_data->used),
|
||||
GFP_KERNEL);
|
||||
msi_data->used = devm_bitmap_zalloc(&pdev->dev, msi_data->irqs_num, GFP_KERNEL);
|
||||
if (!msi_data->used)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
|
@ -65,6 +65,7 @@ static struct irq_chip mtk_sysirq_chip = {
|
||||
.irq_set_type = mtk_sysirq_set_type,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
static int mtk_sysirq_domain_translate(struct irq_domain *d,
|
||||
|
@ -210,9 +210,7 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
|
||||
gicp->spi_cnt += gicp->spi_ranges[i].count;
|
||||
}
|
||||
|
||||
gicp->spi_bitmap = devm_kcalloc(&pdev->dev,
|
||||
BITS_TO_LONGS(gicp->spi_cnt), sizeof(long),
|
||||
GFP_KERNEL);
|
||||
gicp->spi_bitmap = devm_bitmap_zalloc(&pdev->dev, gicp->spi_cnt, GFP_KERNEL);
|
||||
if (!gicp->spi_bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -171,8 +171,7 @@ static int __init mvebu_odmi_init(struct device_node *node,
|
||||
if (!odmis)
|
||||
return -ENOMEM;
|
||||
|
||||
odmis_bm = kcalloc(BITS_TO_LONGS(odmis_count * NODMIS_PER_FRAME),
|
||||
sizeof(long), GFP_KERNEL);
|
||||
odmis_bm = bitmap_zalloc(odmis_count * NODMIS_PER_FRAME, GFP_KERNEL);
|
||||
if (!odmis_bm) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
@ -227,7 +226,7 @@ static int __init mvebu_odmi_init(struct device_node *node,
|
||||
if (odmi->base && !IS_ERR(odmi->base))
|
||||
iounmap(odmis[i].base);
|
||||
}
|
||||
kfree(odmis_bm);
|
||||
bitmap_free(odmis_bm);
|
||||
err_alloc:
|
||||
kfree(odmis);
|
||||
return ret;
|
||||
|
@ -215,8 +215,7 @@ struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode,
|
||||
goto out;
|
||||
desc->domain = d;
|
||||
|
||||
desc->bitmap = kcalloc(BITS_TO_LONGS(nr_parts), sizeof(long),
|
||||
GFP_KERNEL);
|
||||
desc->bitmap = bitmap_zalloc(nr_parts, GFP_KERNEL);
|
||||
if (WARN_ON(!desc->bitmap))
|
||||
goto out;
|
||||
|
||||
|
@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
|
||||
return readl_relaxed(pdc_base + reg + i * sizeof(u32));
|
||||
}
|
||||
|
||||
static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
|
||||
enum irqchip_irq_state which,
|
||||
bool *state)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return 0;
|
||||
|
||||
return irq_chip_get_parent_state(d, which, state);
|
||||
}
|
||||
|
||||
static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
|
||||
enum irqchip_irq_state which,
|
||||
bool value)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return 0;
|
||||
|
||||
return irq_chip_set_parent_state(d, which, value);
|
||||
}
|
||||
|
||||
static void pdc_enable_intr(struct irq_data *d, bool on)
|
||||
{
|
||||
int pin_out = d->hwirq;
|
||||
@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
|
||||
|
||||
static void qcom_pdc_gic_disable(struct irq_data *d)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return;
|
||||
|
||||
pdc_enable_intr(d, false);
|
||||
irq_chip_disable_parent(d);
|
||||
}
|
||||
|
||||
static void qcom_pdc_gic_enable(struct irq_data *d)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return;
|
||||
|
||||
pdc_enable_intr(d, true);
|
||||
irq_chip_enable_parent(d);
|
||||
}
|
||||
|
||||
static void qcom_pdc_gic_mask(struct irq_data *d)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return;
|
||||
|
||||
irq_chip_mask_parent(d);
|
||||
}
|
||||
|
||||
static void qcom_pdc_gic_unmask(struct irq_data *d)
|
||||
{
|
||||
if (d->hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return;
|
||||
|
||||
irq_chip_unmask_parent(d);
|
||||
}
|
||||
|
||||
/*
|
||||
* GIC does not handle falling edge or active low. To allow falling edge and
|
||||
* active low interrupts to be handled at GIC, PDC has an inverter that inverts
|
||||
@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
|
||||
*/
|
||||
static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
int pin_out = d->hwirq;
|
||||
enum pdc_irq_config_bits pdc_type;
|
||||
enum pdc_irq_config_bits old_pdc_type;
|
||||
int ret;
|
||||
|
||||
if (pin_out == GPIO_NO_WAKE_IRQ)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
pdc_type = PDC_EDGE_RISING;
|
||||
@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
|
||||
pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
|
||||
old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
|
||||
pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
|
||||
|
||||
ret = irq_chip_set_type_parent(d, type);
|
||||
if (ret)
|
||||
@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
|
||||
static struct irq_chip qcom_pdc_gic_chip = {
|
||||
.name = "PDC",
|
||||
.irq_eoi = irq_chip_eoi_parent,
|
||||
.irq_mask = qcom_pdc_gic_mask,
|
||||
.irq_unmask = qcom_pdc_gic_unmask,
|
||||
.irq_mask = irq_chip_mask_parent,
|
||||
.irq_unmask = irq_chip_unmask_parent,
|
||||
.irq_disable = qcom_pdc_gic_disable,
|
||||
.irq_enable = qcom_pdc_gic_enable,
|
||||
.irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state,
|
||||
.irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state,
|
||||
.irq_get_irqchip_state = irq_chip_get_parent_state,
|
||||
.irq_set_irqchip_state = irq_chip_set_parent_state,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_set_type = qcom_pdc_gic_set_type,
|
||||
.flags = IRQCHIP_MASK_ON_SUSPEND |
|
||||
@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
|
||||
parent_hwirq = get_parent_hwirq(hwirq);
|
||||
if (parent_hwirq == PDC_NO_PARENT_IRQ)
|
||||
return 0;
|
||||
return irq_domain_disconnect_hierarchy(domain->parent, virq);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
type = IRQ_TYPE_EDGE_RISING;
|
||||
@ -319,17 +273,17 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return irq_domain_disconnect_hierarchy(domain, virq);
|
||||
|
||||
ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
|
||||
&qcom_pdc_gic_chip, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hwirq == GPIO_NO_WAKE_IRQ)
|
||||
return 0;
|
||||
|
||||
parent_hwirq = get_parent_hwirq(hwirq);
|
||||
if (parent_hwirq == PDC_NO_PARENT_IRQ)
|
||||
return 0;
|
||||
return irq_domain_disconnect_hierarchy(domain->parent, virq);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
type = IRQ_TYPE_EDGE_RISING;
|
||||
|
@ -2364,7 +2364,7 @@ static bool read_mailbox_0(void)
|
||||
|
||||
for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
|
||||
if (ev & prcmu_irq_bit[n])
|
||||
generic_handle_irq(irq_find_mapping(db8500_irq_domain, n));
|
||||
generic_handle_domain_irq(db8500_irq_domain, n);
|
||||
}
|
||||
r = true;
|
||||
break;
|
||||
|
@ -35,10 +35,10 @@ static void mx25_tsadc_irq_handler(struct irq_desc *desc)
|
||||
regmap_read(tsadc->regs, MX25_TSC_TGSR, &status);
|
||||
|
||||
if (status & MX25_TGSR_GCQ_INT)
|
||||
generic_handle_irq(irq_find_mapping(tsadc->domain, 1));
|
||||
generic_handle_domain_irq(tsadc->domain, 1);
|
||||
|
||||
if (status & MX25_TGSR_TCQ_INT)
|
||||
generic_handle_irq(irq_find_mapping(tsadc->domain, 0));
|
||||
generic_handle_domain_irq(tsadc->domain, 0);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user