2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-16 01:04:08 +08: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:
Linus Torvalds 2021-08-30 14:38:37 -07:00
commit 7d6e3fa87e
147 changed files with 1828 additions and 1679 deletions

View File

@ -28,3 +28,17 @@ Description:
value comes from an ACPI _PXM method or a similar firmware value comes from an ACPI _PXM method or a similar firmware
source. Initial users for this file would be devices like source. Initial users for this file would be devices like
arm smmu which are populated by arm64 acpi_iort. 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

View File

@ -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 the hwirq, and call the .map() callback so the driver can perform any
required hardware setup. required hardware setup.
When an interrupt is received, irq_find_mapping() function should Once a mapping has been established, it can be retrieved or used via a
be used to find the Linux IRQ number from the hwirq number. 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* The irq_create_mapping() function must be called *atleast once*
before any call to irq_find_mapping(), lest the descriptor will not 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 IRQ number and call the .map() callback so that driver can program the
Linux IRQ number into the hardware. 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 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 case the Linux IRQ numbers cannot be dynamically assigned and the legacy
mapping should be used. 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 The legacy map assumes a contiguous range of IRQ numbers has already
been allocated for the controller and that the IRQ number can be been allocated for the controller and that the IRQ number can be
calculated by adding a fixed offset to the hwirq number, and calculated by adding a fixed offset to the hwirq number, and

View File

@ -22,7 +22,10 @@ properties:
maxItems: 1 maxItems: 1
clocks: clocks:
maxItems: 1 minItems: 1
items:
- description: APB interface clock source
- description: GPIO debounce reference clock source
gpio-controller: true gpio-controller: true

View File

@ -352,7 +352,7 @@ static void idu_cascade_isr(struct irq_desc *desc)
irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ; irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
chained_irq_enter(core_chip, desc); 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); chained_irq_exit(core_chip, desc);
} }

View File

@ -196,14 +196,6 @@ static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq)
return irq_create_mapping(sachip->irqdomain, 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 * SA1111 interrupt support. Since clearing an IRQ while there are
* active IRQs causes the interrupt output to pulse, the upper levels * 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) for (i = 0; stat0; i++, stat0 >>= 1)
if (stat0 & 1) if (stat0 & 1)
sa1111_handle_irqdomain(irqdomain, i); generic_handle_domain_irq(irqdomain, i);
for (i = 32; stat1; i++, stat1 >>= 1) for (i = 32; stat1; i++, stat1 >>= 1)
if (stat1 & 1) if (stat1 & 1)
sa1111_handle_irqdomain(irqdomain, i); generic_handle_domain_irq(irqdomain, i);
/* For level-based interrupts */ /* For level-based interrupts */
desc->irq_data.chip->irq_unmask(&desc->irq_data); desc->irq_data.chip->irq_unmask(&desc->irq_data);

View File

@ -39,10 +39,8 @@ static irqreturn_t cplds_irq_handler(int in_irq, void *d)
do { do {
pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask; pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) { for_each_set_bit(bit, &pending, CPLDS_NB_IRQ)
generic_handle_irq(irq_find_mapping(fpga->irqdomain, generic_handle_domain_irq(fpga->irqdomain, bit);
bit));
}
} while (pending); } while (pending);
return IRQ_HANDLED; return IRQ_HANDLED;

View File

@ -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_data *irq_data = irq_desc_get_chip_data(desc);
struct s3c_irq_intc *intc = irq_data->intc; struct s3c_irq_intc *intc = irq_data->intc;
struct s3c_irq_intc *sub_intc = irq_data->sub_intc; struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
unsigned int n, offset, irq; unsigned int n, offset;
unsigned long src, msk; unsigned long src, msk;
/* we're using individual domains for the non-dt case /* 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) { while (src) {
n = __ffs(src); n = __ffs(src);
src &= ~(1 << n); src &= ~(1 << n);
irq = irq_find_mapping(sub_intc->domain, offset + n); generic_handle_domain_irq(sub_intc->domain, offset + n);
generic_handle_irq(irq);
} }
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);

View File

@ -69,24 +69,24 @@ static void ar2315_misc_irq_handler(struct irq_desc *desc)
{ {
u32 pending = ar2315_rst_reg_read(AR2315_ISR) & u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
ar2315_rst_reg_read(AR2315_IMR); ar2315_rst_reg_read(AR2315_IMR);
unsigned nr, misc_irq = 0; unsigned nr;
int ret = 0;
if (pending) { if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc); struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending); nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
}
if (misc_irq) {
if (nr == AR2315_MISC_IRQ_GPIO) if (nr == AR2315_MISC_IRQ_GPIO)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO); ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO);
else if (nr == AR2315_MISC_IRQ_WATCHDOG) else if (nr == AR2315_MISC_IRQ_WATCHDOG)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD); ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD);
generic_handle_irq(misc_irq);
} else { ret = generic_handle_domain_irq(domain, nr);
spurious_interrupt();
} }
if (!pending || ret)
spurious_interrupt();
} }
static void ar2315_misc_irq_unmask(struct irq_data *d) static void ar2315_misc_irq_unmask(struct irq_data *d)

View File

@ -73,22 +73,21 @@ static void ar5312_misc_irq_handler(struct irq_desc *desc)
{ {
u32 pending = ar5312_rst_reg_read(AR5312_ISR) & u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
ar5312_rst_reg_read(AR5312_IMR); ar5312_rst_reg_read(AR5312_IMR);
unsigned nr, misc_irq = 0; unsigned nr;
int ret = 0;
if (pending) { if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc); struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending); nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
}
if (misc_irq) { ret = generic_handle_domain_irq(domain, nr);
generic_handle_irq(misc_irq);
if (nr == AR5312_MISC_IRQ_TIMER) if (nr == AR5312_MISC_IRQ_TIMER)
ar5312_rst_reg_read(AR5312_TIMER); ar5312_rst_reg_read(AR5312_TIMER);
} else {
spurious_interrupt();
} }
if (!pending || ret)
spurious_interrupt();
} }
/* Enable the specified AR5312_MISC_IRQ interrupt */ /* Enable the specified AR5312_MISC_IRQ interrupt */

View File

@ -300,7 +300,7 @@ static void ltq_hw_irq_handler(struct irq_desc *desc)
*/ */
irq = __fls(irq); irq = __fls(irq);
hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module); 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 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) if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0)

View File

@ -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); struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc);
u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) & u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
ar2315_pci_reg_read(apc, AR2315_PCI_IMR); ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
unsigned pci_irq = 0; int ret = 0;
if (pending) if (pending)
pci_irq = irq_find_mapping(apc->domain, __ffs(pending)); ret = generic_handle_domain_irq(apc->domain, __ffs(pending));
if (pci_irq) if (!pending || ret)
generic_handle_irq(pci_irq);
else
spurious_interrupt(); spurious_interrupt();
} }

View File

@ -140,10 +140,9 @@ static void rt3883_pci_irq_handler(struct irq_desc *desc)
} }
while (pending) { while (pending) {
unsigned irq, bit = __ffs(pending); unsigned bit = __ffs(pending);
irq = irq_find_mapping(rpc->irq_domain, bit); generic_handle_domain_irq(rpc->irq_domain, bit);
generic_handle_irq(irq);
pending &= ~BIT(bit); pending &= ~BIT(bit);
} }

View File

@ -100,7 +100,7 @@ static void ralink_intc_irq_handler(struct irq_desc *desc)
if (pending) { if (pending) {
struct irq_domain *domain = irq_desc_get_handler_data(desc); 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 { } else {
spurious_interrupt(); spurious_interrupt();
} }

View File

@ -190,7 +190,7 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
unsigned long *mask = per_cpu(irq_enable_mask, cpu); unsigned long *mask = per_cpu(irq_enable_mask, cpu);
struct irq_domain *domain; struct irq_domain *domain;
u64 pend0; u64 pend0;
int irq; int ret;
/* copied from Irix intpend0() */ /* copied from Irix intpend0() */
pend0 = LOCAL_HUB_L(PI_INT_PEND0); pend0 = LOCAL_HUB_L(PI_INT_PEND0);
@ -216,10 +216,8 @@ static void ip27_do_irq_mask0(struct irq_desc *desc)
#endif #endif
{ {
domain = irq_desc_get_handler_data(desc); domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend0)); ret = generic_handle_domain_irq(domain, __ffs(pend0));
if (irq) if (ret)
generic_handle_irq(irq);
else
spurious_interrupt(); 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); unsigned long *mask = per_cpu(irq_enable_mask, cpu);
struct irq_domain *domain; struct irq_domain *domain;
u64 pend1; u64 pend1;
int irq; int ret;
/* copied from Irix intpend0() */ /* copied from Irix intpend0() */
pend1 = LOCAL_HUB_L(PI_INT_PEND1); pend1 = LOCAL_HUB_L(PI_INT_PEND1);
@ -242,10 +240,8 @@ static void ip27_do_irq_mask1(struct irq_desc *desc)
return; return;
domain = irq_desc_get_handler_data(desc); domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend1) + 64); ret = generic_handle_domain_irq(domain, __ffs(pend1) + 64);
if (irq) if (ret)
generic_handle_irq(irq);
else
spurious_interrupt(); spurious_interrupt();
LOCAL_HUB_L(PI_INT_PEND1); LOCAL_HUB_L(PI_INT_PEND1);

View File

@ -99,7 +99,7 @@ static void ip30_normal_irq(struct irq_desc *desc)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
struct irq_domain *domain; struct irq_domain *domain;
u64 pend, mask; u64 pend, mask;
int irq; int ret;
pend = heart_read(&heart_regs->isr); pend = heart_read(&heart_regs->isr);
mask = (heart_read(&heart_regs->imr[cpu]) & mask = (heart_read(&heart_regs->imr[cpu]) &
@ -130,10 +130,8 @@ static void ip30_normal_irq(struct irq_desc *desc)
#endif #endif
{ {
domain = irq_desc_get_handler_data(desc); domain = irq_desc_get_handler_data(desc);
irq = irq_linear_revmap(domain, __ffs(pend)); ret = generic_handle_domain_irq(domain, __ffs(pend));
if (irq) if (ret)
generic_handle_irq(irq);
else
spurious_interrupt(); spurious_interrupt();
} }
} }

View File

@ -19,11 +19,9 @@ static u32 ienable;
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
{ {
struct pt_regs *oldregs = set_irq_regs(regs); struct pt_regs *oldregs = set_irq_regs(regs);
int irq;
irq_enter(); irq_enter();
irq = irq_find_mapping(NULL, hwirq); generic_handle_domain_irq(NULL, hwirq);
generic_handle_irq(irq);
irq_exit(); irq_exit();
set_irq_regs(oldregs); set_irq_regs(oldregs);

View File

@ -198,7 +198,6 @@ static void uic_irq_cascade(struct irq_desc *desc)
struct uic *uic = irq_desc_get_handler_data(desc); struct uic *uic = irq_desc_get_handler_data(desc);
u32 msr; u32 msr;
int src; int src;
int subvirq;
raw_spin_lock(&desc->lock); raw_spin_lock(&desc->lock);
if (irqd_is_level_type(idata)) if (irqd_is_level_type(idata))
@ -213,8 +212,7 @@ static void uic_irq_cascade(struct irq_desc *desc)
src = 32 - ffs(msr); src = 32 - ffs(msr);
subvirq = irq_linear_revmap(uic->irqhost, src); generic_handle_domain_irq(uic->irqhost, src);
generic_handle_irq(subvirq);
uic_irq_ret: uic_irq_ret:
raw_spin_lock(&desc->lock); raw_spin_lock(&desc->lock);

View File

@ -81,11 +81,10 @@ static struct irq_chip cpld_pic = {
.irq_unmask = cpld_unmask_irq, .irq_unmask = cpld_unmask_irq,
}; };
static int static unsigned int
cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp, cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
u8 __iomem *maskp) u8 __iomem *maskp)
{ {
int cpld_irq;
u8 status = in_8(statusp); u8 status = in_8(statusp);
u8 mask = in_8(maskp); u8 mask = in_8(maskp);
@ -93,28 +92,26 @@ cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
status |= (ignore | mask); status |= (ignore | mask);
if (status == 0xff) if (status == 0xff)
return 0; return ~0;
cpld_irq = ffz(status) + offset; return ffz(status) + offset;
return irq_linear_revmap(cpld_pic_host, cpld_irq);
} }
static void cpld_pic_cascade(struct irq_desc *desc) 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); &cpld_regs->pci_mask);
if (irq) { if (hwirq != ~0) {
generic_handle_irq(irq); generic_handle_domain_irq(cpld_pic_host, hwirq);
return; 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); &cpld_regs->misc_mask);
if (irq) { if (hwirq != ~0) {
generic_handle_irq(irq); generic_handle_domain_irq(cpld_pic_host, hwirq);
return; return;
} }
} }

View File

@ -78,7 +78,7 @@ static struct irq_chip media5200_irq_chip = {
static void media5200_irq_cascade(struct irq_desc *desc) static void media5200_irq_cascade(struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip *chip = irq_desc_get_chip(desc);
int sub_virq, val; int val;
u32 status, enable; u32 status, enable;
/* Mask off the cascaded IRQ */ /* 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); enable = in_be32(media5200_irq.regs + MEDIA5200_IRQ_STATUS);
val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT); val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT);
if (val) { if (val) {
sub_virq = irq_linear_revmap(media5200_irq.irqhost, val - 1); generic_handle_domain_irq(media5200_irq.irqhost, val - 1);
/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i subvirq=%i\n", /* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i\n",
* __func__, virq, status, enable, val - 1, sub_virq); * __func__, virq, status, enable, val - 1);
*/ */
generic_handle_irq(sub_virq);
} }
/* Processing done; can reenable the cascade now */ /* Processing done; can reenable the cascade now */

View File

@ -190,14 +190,11 @@ static struct irq_chip mpc52xx_gpt_irq_chip = {
static void mpc52xx_gpt_irq_cascade(struct irq_desc *desc) static void mpc52xx_gpt_irq_cascade(struct irq_desc *desc)
{ {
struct mpc52xx_gpt_priv *gpt = irq_desc_get_handler_data(desc); struct mpc52xx_gpt_priv *gpt = irq_desc_get_handler_data(desc);
int sub_virq;
u32 status; u32 status;
status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK; status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK;
if (status) { if (status)
sub_virq = irq_linear_revmap(gpt->irqhost, 0); generic_handle_domain_irq(gpt->irqhost, 0);
generic_handle_irq(sub_virq);
}
} }
static int mpc52xx_gpt_irq_map(struct irq_domain *h, unsigned int virq, static int mpc52xx_gpt_irq_map(struct irq_domain *h, unsigned int virq,

View File

@ -91,10 +91,8 @@ static void pq2ads_pci_irq_demux(struct irq_desc *desc)
break; break;
for (bit = 0; pend != 0; ++bit, pend <<= 1) { for (bit = 0; pend != 0; ++bit, pend <<= 1) {
if (pend & 0x80000000) { if (pend & 0x80000000)
int virq = irq_linear_revmap(priv->host, bit); generic_handle_domain_irq(priv->host, bit);
generic_handle_irq(virq);
}
} }
} }
} }

View File

@ -106,13 +106,9 @@ static void iic_ioexc_cascade(struct irq_desc *desc)
out_be64(&node_iic->iic_is, ack); out_be64(&node_iic->iic_is, ack);
/* handle them */ /* handle them */
for (cascade = 63; cascade >= 0; cascade--) for (cascade = 63; cascade >= 0; cascade--)
if (bits & (0x8000000000000000UL >> cascade)) { if (bits & (0x8000000000000000UL >> cascade))
unsigned int cirq = generic_handle_domain_irq(iic_host,
irq_linear_revmap(iic_host,
base | cascade); base | cascade);
if (cirq)
generic_handle_irq(cirq);
}
/* post-ack level interrupts */ /* post-ack level interrupts */
ack = bits & ~IIC_ISR_EDGE_MASK; ack = bits & ~IIC_ISR_EDGE_MASK;
if (ack) if (ack)

View File

@ -190,16 +190,11 @@ static void spider_irq_cascade(struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip *chip = irq_desc_get_chip(desc);
struct spider_pic *pic = irq_desc_get_handler_data(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; cs = in_be32(pic->regs + TIR_CS) >> 24;
if (cs == SPIDER_IRQ_INVALID) if (cs != SPIDER_IRQ_INVALID)
virq = 0; generic_handle_domain_irq(pic->host, cs);
else
virq = irq_linear_revmap(pic->host, cs);
if (virq)
generic_handle_irq(virq);
chip->irq_eoi(&desc->irq_data); chip->irq_eoi(&desc->irq_data);
} }

View File

@ -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) static unsigned int __hlwd_pic_get_irq(struct irq_domain *h)
{ {
void __iomem *io_base = h->host_data; void __iomem *io_base = h->host_data;
int irq;
u32 irq_status; u32 irq_status;
irq_status = in_be32(io_base + HW_BROADWAY_ICR) & 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) if (irq_status == 0)
return 0; /* no more IRQs pending */ return 0; /* no more IRQs pending */
irq = __ffs(irq_status); return __ffs(irq_status);
return irq_linear_revmap(h, irq);
} }
static void hlwd_pic_irq_cascade(struct irq_desc *desc) static void hlwd_pic_irq_cascade(struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *irq_domain = irq_desc_get_handler_data(desc); struct irq_domain *irq_domain = irq_desc_get_handler_data(desc);
unsigned int virq; unsigned int hwirq;
raw_spin_lock(&desc->lock); raw_spin_lock(&desc->lock);
chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */ chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
raw_spin_unlock(&desc->lock); raw_spin_unlock(&desc->lock);
virq = __hlwd_pic_get_irq(irq_domain); hwirq = __hlwd_pic_get_irq(irq_domain);
if (virq) if (hwirq)
generic_handle_irq(virq); generic_handle_domain_irq(irq_domain, hwirq);
else else
pr_err("spurious interrupt!\n"); 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) 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;
} }
/* /*

View File

@ -46,18 +46,15 @@ void opal_handle_events(void)
e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask; e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask;
again: again:
while (e) { while (e) {
int virq, hwirq; int hwirq;
hwirq = fls64(e) - 1; hwirq = fls64(e) - 1;
e &= ~BIT_ULL(hwirq); e &= ~BIT_ULL(hwirq);
local_irq_disable(); local_irq_disable();
virq = irq_find_mapping(opal_event_irqchip.domain, hwirq); irq_enter();
if (virq) { generic_handle_domain_irq(opal_event_irqchip.domain, hwirq);
irq_enter(); irq_exit();
generic_handle_irq(virq);
irq_exit();
}
local_irq_enable(); local_irq_enable();
cond_resched(); cond_resched();

View File

@ -99,7 +99,6 @@ static irqreturn_t fsl_error_int_handler(int irq, void *data)
struct mpic *mpic = (struct mpic *) data; struct mpic *mpic = (struct mpic *) data;
u32 eisr, eimr; u32 eisr, eimr;
int errint; int errint;
unsigned int cascade_irq;
eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR); eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR); 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; return IRQ_NONE;
while (eisr) { while (eisr) {
int ret;
errint = __builtin_clz(eisr); errint = __builtin_clz(eisr);
cascade_irq = irq_linear_revmap(mpic->irqhost, ret = generic_handle_domain_irq(mpic->irqhost,
mpic->err_int_vecs[errint]); mpic->err_int_vecs[errint]);
WARN_ON(!cascade_irq); if (WARN_ON(ret)) {
if (cascade_irq) {
generic_handle_irq(cascade_irq);
} else {
eimr |= 1 << (31 - errint); eimr |= 1 << (31 - errint);
mpic_fsl_err_write(mpic->err_regs, eimr); mpic_fsl_err_write(mpic->err_regs, eimr);
} }

View File

@ -266,7 +266,6 @@ out_free:
static irqreturn_t fsl_msi_cascade(int irq, void *data) static irqreturn_t fsl_msi_cascade(int irq, void *data)
{ {
unsigned int cascade_irq;
struct fsl_msi *msi_data; struct fsl_msi *msi_data;
int msir_index = -1; int msir_index = -1;
u32 msir_value = 0; u32 msir_value = 0;
@ -279,9 +278,6 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
msir_index = cascade_data->index; msir_index = cascade_data->index;
if (msir_index >= NR_MSI_REG_MAX)
cascade_irq = 0;
switch (msi_data->feature & FSL_PIC_IP_MASK) { switch (msi_data->feature & FSL_PIC_IP_MASK) {
case FSL_PIC_IP_MPIC: case FSL_PIC_IP_MPIC:
msir_value = fsl_msi_read(msi_data->msi_regs, 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) { while (msir_value) {
int err;
intr_index = ffs(msir_value) - 1; 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, msi_hwirq(msi_data, msir_index,
intr_index + have_shift)); intr_index + have_shift));
if (cascade_irq) { if (!err)
generic_handle_irq(cascade_irq);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
}
have_shift += intr_index + 1; have_shift += intr_index + 1;
msir_value = msir_value >> (intr_index + 1); msir_value = msir_value >> (intr_index + 1);
} }

View File

@ -365,10 +365,6 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
for_each_pci_msi_entry(msi, pdev) { for_each_pci_msi_entry(msi, pdev) {
if (!msi->irq) if (!msi->irq)
continue; 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_set_msi_desc(msi->irq, NULL);
irq_free_desc(msi->irq); irq_free_desc(msi->irq);
msi->msg.address_lo = 0; msi->msg.address_lo = 0;

View File

@ -38,7 +38,7 @@ static void se7343_irq_demux(struct irq_desc *desc)
mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG); mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG);
for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR) 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); chip->irq_unmask(data);
} }

View File

@ -37,7 +37,7 @@ static void se7722_irq_demux(struct irq_desc *desc)
mask = ioread16(se7722_irq_regs + IRQ01_STS_REG); mask = ioread16(se7722_irq_regs + IRQ01_STS_REG);
for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR) 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); chip->irq_unmask(data);
} }

View File

@ -68,7 +68,7 @@ static void x3proto_gpio_irq_handler(struct irq_desc *desc)
mask = __raw_readw(KEYDETR); mask = __raw_readw(KEYDETR);
for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) 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); chip->irq_unmask(data);
} }

View File

@ -33,8 +33,6 @@ DECLARE_PER_CPU(unsigned long, nmi_count);
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
{ {
int irq = irq_find_mapping(NULL, hwirq);
#ifdef CONFIG_DEBUG_STACKOVERFLOW #ifdef CONFIG_DEBUG_STACKOVERFLOW
/* Debugging check for stack overflow: is there less than 1KB free? */ /* 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)); sp - sizeof(struct thread_info));
} }
#endif #endif
generic_handle_irq(irq); generic_handle_domain_irq(NULL, hwirq);
} }
int arch_show_interrupts(struct seq_file *p, int prec) int arch_show_interrupts(struct seq_file *p, int prec)

View File

@ -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 * This is probably worse than completing the request on a different
* cache domain. * cache domain.
*/ */
if (force_irqthreads) if (force_irqthreads())
return false; return false;
/* same CPU or cache domain? Complete locally */ /* same CPU or cache domain? Complete locally */

View File

@ -21,11 +21,12 @@
* and the callback to write the MSI message. * and the callback to write the MSI message.
*/ */
struct platform_msi_priv_data { struct platform_msi_priv_data {
struct device *dev; struct device *dev;
void *host_data; void *host_data;
msi_alloc_info_t arg; const struct attribute_group **msi_irq_groups;
irq_write_msi_msg_t write_msg; msi_alloc_info_t arg;
int devid; irq_write_msi_msg_t write_msg;
int devid;
}; };
/* The devid allocator */ /* The devid allocator */
@ -272,8 +273,16 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
if (err) if (err)
goto out_free_desc; 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; return 0;
out_free_irqs:
msi_domain_free_irqs(dev->msi_domain, dev);
out_free_desc: out_free_desc:
platform_msi_free_descs(dev, 0, nvec); platform_msi_free_descs(dev, 0, nvec);
out_free_priv_data: out_free_priv_data:
@ -293,6 +302,7 @@ void platform_msi_domain_free_irqs(struct device *dev)
struct msi_desc *desc; struct msi_desc *desc;
desc = first_msi_entry(dev); 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); platform_msi_free_priv_data(desc->platform.msi_priv_data);
} }

View File

@ -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); regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
bits = irq_status; bits = irq_status;
for_each_set_bit(bit, &bits, 32) { for_each_set_bit(bit, &bits, 32)
irq = irq_linear_revmap(edac->domain, dberr * 32 + bit); generic_handle_domain_irq(edac->domain, dberr * 32 + bit);
if (irq)
generic_handle_irq(irq);
}
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }

View File

@ -520,6 +520,14 @@ config GPIO_REG
A 32-bit single register GPIO fixed in/out implementation. This A 32-bit single register GPIO fixed in/out implementation. This
can be used to represent any register as a set of GPIO signals. 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 config GPIO_SAMA5D2_PIOBU
tristate "SAMA5D2 PIOBU GPIO support" tristate "SAMA5D2 PIOBU GPIO support"
depends on MFD_SYSCON depends on MFD_SYSCON

View File

@ -128,6 +128,7 @@ obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o

View File

@ -336,8 +336,8 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
unsigned long gpio; unsigned long gpio;
for_each_set_bit(gpio, &irq_mask, 2) for_each_set_bit(gpio, &irq_mask, 2)
generic_handle_irq(irq_find_mapping(chip->irq.domain, generic_handle_domain_irq(chip->irq.domain,
19 + gpio*24)); 19 + gpio*24);
raw_spin_lock(&dio48egpio->lock); raw_spin_lock(&dio48egpio->lock);

View File

@ -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) { for_each_set_bit(bit_num, &irq_mask, 8) {
gpio = bit_num + boundary * 8; gpio = bit_num + boundary * 8;
generic_handle_irq(irq_find_mapping(chip->irq.domain, generic_handle_domain_irq(chip->irq.domain,
gpio)); gpio);
} }
} }

View File

@ -208,7 +208,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
int gpio; int gpio;
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) 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); raw_spin_lock(&idio16gpio->lock);

View File

@ -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_EDGE_CAP) &
readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) { readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP); writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP);
for_each_set_bit(i, &status, mm_gc->gc.ngpio) { for_each_set_bit(i, &status, mm_gc->gc.ngpio)
generic_handle_irq(irq_find_mapping(irqdomain, i)); generic_handle_domain_irq(irqdomain, i);
}
} }
chained_irq_exit(chip, desc); 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_DATA);
status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
for_each_set_bit(i, &status, mm_gc->gc.ngpio) { for_each_set_bit(i, &status, mm_gc->gc.ngpio)
generic_handle_irq(irq_find_mapping(irqdomain, i)); generic_handle_domain_irq(irqdomain, i);
}
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }

View File

@ -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 gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc); struct irq_chip *ic = irq_desc_get_chip(desc);
struct aspeed_sgpio *data = gpiochip_get_data(gc); struct aspeed_sgpio *data = gpiochip_get_data(gc);
unsigned int i, p, girq; unsigned int i, p;
unsigned long reg; unsigned long reg;
chained_irq_enter(ic, desc); 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)); reg = ioread32(bank_reg(data, bank, reg_irq_status));
for_each_set_bit(p, &reg, 32) { for_each_set_bit(p, &reg, 32)
girq = irq_find_mapping(gc->irq.domain, i * 32 + p); generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
generic_handle_irq(girq);
}
} }
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);

View File

@ -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 gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc); struct irq_chip *ic = irq_desc_get_chip(desc);
struct aspeed_gpio *data = gpiochip_get_data(gc); struct aspeed_gpio *data = gpiochip_get_data(gc);
unsigned int i, p, girq, banks; unsigned int i, p, banks;
unsigned long reg; unsigned long reg;
struct aspeed_gpio *gpio = gpiochip_get_data(gc); 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)); reg = ioread32(bank_reg(data, bank, reg_irq_status));
for_each_set_bit(p, &reg, 32) { for_each_set_bit(p, &reg, 32)
girq = irq_find_mapping(gc->irq.domain, i * 32 + p); generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
generic_handle_irq(girq);
}
} }
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);

View File

@ -204,11 +204,8 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
raw_spin_unlock_irqrestore(&ctrl->lock, flags); raw_spin_unlock_irqrestore(&ctrl->lock, flags);
if (pending) { for_each_set_bit(irq, &pending, gc->ngpio)
for_each_set_bit(irq, &pending, gc->ngpio) generic_handle_domain_irq(gc->irq.domain, irq);
generic_handle_irq(
irq_linear_revmap(gc->irq.domain, irq));
}
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);
} }

View File

@ -466,9 +466,6 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
(~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) { (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
for_each_set_bit(bit, &sta, 32) { for_each_set_bit(bit, &sta, 32) {
int hwirq = GPIO_PER_BANK * bank_id + bit; 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 * Clear interrupt before handler is called so we don't
* miss any interrupt occurred during executing them. * 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)) | writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
BIT(bit), reg_base + GPIO_INT_STATUS(bank_id)); BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
/* Invoke interrupt handler */ /* Invoke interrupt handler */
generic_handle_irq(child_irq); generic_handle_domain_irq(bank->kona_gpio->irq_domain,
hwirq);
} }
} }

View File

@ -277,15 +277,14 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
unsigned long status; unsigned long status;
while ((status = brcmstb_gpio_get_active_irqs(bank))) { while ((status = brcmstb_gpio_get_active_irqs(bank))) {
unsigned int irq, offset; unsigned int offset;
for_each_set_bit(offset, &status, 32) { for_each_set_bit(offset, &status, 32) {
if (offset >= bank->width) if (offset >= bank->width)
dev_warn(&priv->pdev->dev, dev_warn(&priv->pdev->dev,
"IRQ for invalid GPIO (bank=%d, offset=%d)\n", "IRQ for invalid GPIO (bank=%d, offset=%d)\n",
bank->id, offset); bank->id, offset);
irq = irq_linear_revmap(domain, hwbase + offset); generic_handle_domain_irq(domain, hwbase + offset);
generic_handle_irq(irq);
} }
} }
} }

View File

@ -133,7 +133,7 @@ static void cdns_gpio_irq_handler(struct irq_desc *desc)
~ioread32(cgpio->regs + CDNS_GPIO_IRQ_MASK); ~ioread32(cgpio->regs + CDNS_GPIO_IRQ_MASK);
for_each_set_bit(hwirq, &status, chip->ngpio) 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); chained_irq_exit(irqchip, desc);
} }

View File

@ -369,8 +369,7 @@ static void gpio_irq_handler(struct irq_desc *desc)
*/ */
hw_irq = (bank_num / 2) * 32 + bit; hw_irq = (bank_num / 2) * 32 + bit;
generic_handle_irq( generic_handle_domain_irq(d->irq_domain, hw_irq);
irq_find_mapping(d->irq_domain, hw_irq));
} }
} }
chained_irq_exit(irq_desc_get_chip(desc), desc); chained_irq_exit(irq_desc_get_chip(desc), desc);

View File

@ -395,7 +395,7 @@ static struct irq_chip dln2_gpio_irqchip = {
static void dln2_gpio_event(struct platform_device *pdev, u16 echo, static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
const void *data, int len) const void *data, int len)
{ {
int pin, irq; int pin, ret;
const struct { const struct {
__le16 count; __le16 count;
@ -416,24 +416,20 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
return; 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]) { switch (dln2->irq_type[pin]) {
case DLN2_GPIO_EVENT_CHANGE_RISING: case DLN2_GPIO_EVENT_CHANGE_RISING:
if (event->value) if (!event->value)
generic_handle_irq(irq); return;
break; break;
case DLN2_GPIO_EVENT_CHANGE_FALLING: case DLN2_GPIO_EVENT_CHANGE_FALLING:
if (!event->value) if (event->value)
generic_handle_irq(irq); return;
break; 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) static int dln2_gpio_probe(struct platform_device *pdev)

View File

@ -173,7 +173,7 @@ static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
while ((pending = em_gio_read(p, GIO_MST))) { while ((pending = em_gio_read(p, GIO_MST))) {
offset = __ffs(pending); offset = __ffs(pending);
em_gio_write(p, GIO_IIR, BIT(offset)); 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++; irqs_handled++;
} }

View File

@ -128,13 +128,13 @@ static void ep93xx_gpio_ab_irq_handler(struct irq_desc *desc)
*/ */
stat = readb(epg->base + EP93XX_GPIO_A_INT_STATUS); stat = readb(epg->base + EP93XX_GPIO_A_INT_STATUS);
for_each_set_bit(offset, &stat, 8) for_each_set_bit(offset, &stat, 8)
generic_handle_irq(irq_find_mapping(epg->gc[0].gc.irq.domain, generic_handle_domain_irq(epg->gc[0].gc.irq.domain,
offset)); offset);
stat = readb(epg->base + EP93XX_GPIO_B_INT_STATUS); stat = readb(epg->base + EP93XX_GPIO_B_INT_STATUS);
for_each_set_bit(offset, &stat, 8) for_each_set_bit(offset, &stat, 8)
generic_handle_irq(irq_find_mapping(epg->gc[1].gc.irq.domain, generic_handle_domain_irq(epg->gc[1].gc.irq.domain,
offset)); offset);
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);
} }

View File

@ -149,8 +149,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
stat = readl(g->base + GPIO_INT_STAT_RAW); stat = readl(g->base + GPIO_INT_STAT_RAW);
if (stat) if (stat)
for_each_set_bit(offset, &stat, gc->ngpio) for_each_set_bit(offset, &stat, gc->ngpio)
generic_handle_irq(irq_find_mapping(gc->irq.domain, generic_handle_domain_irq(gc->irq.domain, offset);
offset));
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);
} }

View File

@ -186,8 +186,8 @@ static void hisi_gpio_irq_handler(struct irq_desc *desc)
chained_irq_enter(irq_c, desc); chained_irq_enter(irq_c, desc);
for_each_set_bit(hwirq, &irq_msk, HISI_GPIO_LINE_NUM_MAX) for_each_set_bit(hwirq, &irq_msk, HISI_GPIO_LINE_NUM_MAX)
generic_handle_irq(irq_find_mapping(hisi_gpio->chip.irq.domain, generic_handle_domain_irq(hisi_gpio->chip.irq.domain,
hwirq)); hwirq);
chained_irq_exit(irq_c, desc); chained_irq_exit(irq_c, desc);
} }

View File

@ -97,11 +97,8 @@ static void hlwd_gpio_irqhandler(struct irq_desc *desc)
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
for_each_set_bit(hwirq, &pending, 32) { for_each_set_bit(hwirq, &pending, 32)
int irq = irq_find_mapping(hlwd->gpioc.irq.domain, hwirq); generic_handle_domain_irq(hlwd->gpioc.irq.domain, hwirq);
generic_handle_irq(irq);
}
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }

View File

@ -359,12 +359,8 @@ static void mrfld_irq_handler(struct irq_desc *desc)
/* Only interrupts that are enabled */ /* Only interrupts that are enabled */
pending &= enabled; pending &= enabled;
for_each_set_bit(gpio, &pending, 32) { for_each_set_bit(gpio, &pending, 32)
unsigned int irq; generic_handle_domain_irq(gc->irq.domain, base + gpio);
irq = irq_find_mapping(gc->irq.domain, base + gpio);
generic_handle_irq(irq);
}
} }
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);

View File

@ -120,7 +120,7 @@ static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER) mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
& gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR); & gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
for_each_set_bit(i, &mask, 32) 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; return IRQ_HANDLED;
} }

View File

@ -95,9 +95,7 @@ mediatek_gpio_irq_handler(int irq, void *data)
pending = mtk_gpio_r32(rg, GPIO_REG_STAT); pending = mtk_gpio_r32(rg, GPIO_REG_STAT);
for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) {
u32 map = irq_find_mapping(gc->irq.domain, bit); generic_handle_domain_irq(gc->irq.domain, bit);
generic_handle_irq(map);
mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit));
ret |= IRQ_HANDLED; ret |= IRQ_HANDLED;
} }

View File

@ -241,7 +241,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
if (port->both_edges & (1 << irqoffset)) if (port->both_edges & (1 << irqoffset))
mxc_flip_edge(port, 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); irq_stat &= ~(1 << irqoffset);
} }

View File

@ -157,7 +157,7 @@ static void mxs_gpio_irq_handler(struct irq_desc *desc)
if (port->both_edges & (1 << irqoffset)) if (port->both_edges & (1 << irqoffset))
mxs_flip_edge(port, 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); irq_stat &= ~(1 << irqoffset);
} }
} }

View File

@ -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); raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, generic_handle_domain_irq(bank->chip.irq.domain, bit);
bit));
raw_spin_unlock_irqrestore(&bank->wa_lock, raw_spin_unlock_irqrestore(&bank->wa_lock,
wa_lock_flags); wa_lock_flags);

View File

@ -260,7 +260,7 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) 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); raw_spin_lock(&idio16gpio->lock);

View File

@ -468,8 +468,7 @@ static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
irq_mask = idio24gpio->irq_mask & irq_status; irq_mask = idio24gpio->irq_mask & irq_status;
for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24) for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
generic_handle_irq(irq_find_mapping(chip->irq.domain, generic_handle_domain_irq(chip->irq.domain, gpio + 24);
gpio + 24));
raw_spin_lock(&idio24gpio->lock); raw_spin_lock(&idio24gpio->lock);

View File

@ -223,8 +223,8 @@ static void pl061_irq_handler(struct irq_desc *desc)
pending = readb(pl061->base + GPIOMIS); pending = readb(pl061->base + GPIOMIS);
if (pending) { if (pending) {
for_each_set_bit(offset, &pending, PL061_GPIO_NR) for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(irq_find_mapping(gc->irq.domain, generic_handle_domain_irq(gc->irq.domain,
offset)); offset);
} }
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);

View File

@ -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) { for_each_set_bit(n, &gedr, BITS_PER_LONG) {
loop = 1; loop = 1;
generic_handle_irq( generic_handle_domain_irq(pchip->irqdomain,
irq_find_mapping(pchip->irqdomain, gpio + n);
gpio + n));
} }
} }
handled += loop; handled += loop;
@ -471,9 +470,9 @@ static irqreturn_t pxa_gpio_direct_handler(int in_irq, void *d)
struct pxa_gpio_chip *pchip = d; struct pxa_gpio_chip *pchip = d;
if (in_irq == pchip->irq0) { 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) { } else if (in_irq == pchip->irq1) {
generic_handle_irq(irq_find_mapping(pchip->irqdomain, 1)); generic_handle_domain_irq(pchip->irqdomain, 1);
} else { } else {
pr_err("%s() unknown irq %d\n", __func__, in_irq); pr_err("%s() unknown irq %d\n", __func__, in_irq);
return IRQ_NONE; return IRQ_NONE;

View File

@ -213,8 +213,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
gpio_rcar_read(p, INTMSK))) { gpio_rcar_read(p, INTMSK))) {
offset = __ffs(pending); offset = __ffs(pending);
gpio_rcar_write(p, INTCLR, BIT(offset)); gpio_rcar_write(p, INTCLR, BIT(offset));
generic_handle_irq(irq_find_mapping(p->gpio_chip.irq.domain, generic_handle_domain_irq(p->gpio_chip.irq.domain,
offset)); offset);
irqs_handled++; irqs_handled++;
} }

View File

@ -181,7 +181,7 @@ static void rda_gpio_irq_handler(struct irq_desc *desc)
struct irq_chip *ic = irq_desc_get_chip(desc); struct irq_chip *ic = irq_desc_get_chip(desc);
struct rda_gpio *rda_gpio = gpiochip_get_data(chip); struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
unsigned long status; unsigned long status;
u32 n, girq; u32 n;
chained_irq_enter(ic, desc); 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 */ /* Only lower 8 bits are capable of generating interrupts */
status &= RDA_GPIO_IRQ_MASK; status &= RDA_GPIO_IRQ_MASK;
for_each_set_bit(n, &status, RDA_GPIO_BANK_NR) { for_each_set_bit(n, &status, RDA_GPIO_BANK_NR)
girq = irq_find_mapping(chip->irq.domain, n); generic_handle_domain_irq(chip->irq.domain, n);
generic_handle_irq(girq);
}
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);
} }

View File

@ -196,7 +196,6 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc)
struct irq_chip *irq_chip = irq_desc_get_chip(desc); struct irq_chip *irq_chip = irq_desc_get_chip(desc);
unsigned int lines_done; unsigned int lines_done;
unsigned int port_pin_count; unsigned int port_pin_count;
unsigned int irq;
unsigned long status; unsigned long status;
int offset; 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) { for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
status = realtek_gpio_read_isr(ctrl, lines_done / 8); status = realtek_gpio_read_isr(ctrl, lines_done / 8);
port_pin_count = min(gc->ngpio - lines_done, 8U); port_pin_count = min(gc->ngpio - lines_done, 8U);
for_each_set_bit(offset, &status, port_pin_count) { for_each_set_bit(offset, &status, port_pin_count)
irq = irq_find_mapping(gc->irq.domain, offset); generic_handle_domain_irq(gc->irq.domain, offset);
generic_handle_irq(irq);
}
} }
chained_irq_exit(irq_chip, desc); chained_irq_exit(irq_chip, desc);

View 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);

View File

@ -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; pending = (resume_status << sch->resume_base) | core_status;
for_each_set_bit(offset, &pending, sch->chip.ngpio) 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 */ /* Set returning value depending on whether we handled an interrupt */
ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;

View File

@ -84,7 +84,7 @@ static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
return IRQ_NONE; return IRQ_NONE;
for_each_set_bit(irq_bit, &irq_stat, 32) 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; return IRQ_HANDLED;
} }

View File

@ -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 gpio_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc); struct irq_chip *ic = irq_desc_get_chip(desc);
struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
u32 bank, n, girq; u32 bank, n;
chained_irq_enter(ic, desc); 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) & unsigned long reg = readl_relaxed(base + SPRD_GPIO_MIS) &
SPRD_GPIO_BANK_MASK; SPRD_GPIO_BANK_MASK;
for_each_set_bit(n, &reg, SPRD_GPIO_BANK_NR) { for_each_set_bit(n, &reg, SPRD_GPIO_BANK_NR)
girq = irq_find_mapping(chip->irq.domain, generic_handle_domain_irq(chip->irq.domain,
bank * SPRD_GPIO_BANK_NR + n); bank * SPRD_GPIO_BANK_NR + n);
generic_handle_irq(girq);
}
} }
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);
} }

View File

@ -100,7 +100,7 @@ static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data)
int i; int i;
for_each_set_bit(i, &bits, 32) 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; return IRQ_HANDLED;
} }

View File

@ -408,6 +408,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc)
lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
for_each_set_bit(pin, &sta, 8) { for_each_set_bit(pin, &sta, 8) {
int ret;
tegra_gpio_writel(tgi, 1 << pin, tegra_gpio_writel(tgi, 1 << pin,
GPIO_INT_CLR(tgi, gpio)); GPIO_INT_CLR(tgi, gpio));
@ -420,11 +422,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }
irq = irq_find_mapping(domain, gpio + pin); ret = generic_handle_domain_irq(domain, gpio + pin);
if (WARN_ON(irq == 0)) WARN_RATELIMIT(ret, "hwirq = %d", gpio + pin);
continue;
generic_handle_irq(irq);
} }
} }

View File

@ -456,7 +456,7 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
for (i = 0; i < gpio->soc->num_ports; i++) { for (i = 0; i < gpio->soc->num_ports; i++) {
const struct tegra_gpio_port *port = &gpio->soc->ports[i]; const struct tegra_gpio_port *port = &gpio->soc->ports[i];
unsigned int pin, irq; unsigned int pin;
unsigned long value; unsigned long value;
void __iomem *base; void __iomem *base;
@ -469,11 +469,8 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1)); value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
for_each_set_bit(pin, &value, port->pins) { for_each_set_bit(pin, &value, port->pins) {
irq = irq_find_mapping(domain, offset + pin); int ret = generic_handle_domain_irq(domain, offset + pin);
if (WARN_ON(irq == 0)) WARN_RATELIMIT(ret, "hwirq = %d", offset + pin);
continue;
generic_handle_irq(irq);
} }
skip: skip:

View File

@ -183,7 +183,7 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
struct irq_chip *irq_chip = irq_desc_get_chip(desc); struct irq_chip *irq_chip = irq_desc_get_chip(desc);
unsigned long irq_bits; unsigned long irq_bits;
int i = 0, child_irq; int i = 0;
u8 irq_status; u8 irq_status;
chained_irq_enter(irq_chip, desc); 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); tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
irq_bits = irq_status; irq_bits = irq_status;
for_each_set_bit(i, &irq_bits, TQMX86_NGPI) { for_each_set_bit(i, &irq_bits, TQMX86_NGPI)
child_irq = irq_find_mapping(gpio->chip.irq.domain, generic_handle_domain_irq(gpio->chip.irq.domain,
i + TQMX86_NGPO); i + TQMX86_NGPO);
generic_handle_irq(child_irq);
}
chained_irq_exit(irq_chip, desc); chained_irq_exit(irq_chip, desc);
} }

View File

@ -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) { for_each_set_bit(pin, &irq_isfr, VF610_GPIO_PER_PORT) {
vf610_gpio_writel(BIT(pin), port->base + PORT_ISFR); 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); chained_irq_exit(chip, desc);

View File

@ -339,8 +339,8 @@ static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id)
for_each_set_bit(port, &int_pending, 3) { for_each_set_bit(port, &int_pending, 3) {
int_id = inb(ws16c48gpio->base + 8 + port); int_id = inb(ws16c48gpio->base + 8 + port);
for_each_set_bit(gpio, &int_id, 8) for_each_set_bit(gpio, &int_id, 8)
generic_handle_irq(irq_find_mapping( generic_handle_domain_irq(chip->irq.domain,
chip->irq.domain, gpio + 8*port)); gpio + 8*port);
} }
int_pending = inb(ws16c48gpio->base + 6) & 0x7; int_pending = inb(ws16c48gpio->base + 6) & 0x7;

View File

@ -185,7 +185,7 @@ static irqreturn_t iproc_gpio_irq_handler(int irq, void *data)
int_bits = level | event; int_bits = level | event;
for_each_set_bit(bit, &int_bits, gc->ngpio) 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; return int_bits ? IRQ_HANDLED : IRQ_NONE;

View File

@ -538,7 +538,7 @@ static void xgpio_irqhandler(struct irq_desc *desc)
for_each_set_bit(bit, all, 64) { for_each_set_bit(bit, all, 64) {
irq_offset = xgpio_from_bit(chip, bit); 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); chained_irq_exit(irqchip, desc);

View File

@ -216,8 +216,7 @@ static void xlp_gpio_generic_handler(struct irq_desc *desc)
} }
if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ)) if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ))
generic_handle_irq(irq_find_mapping( generic_handle_domain_irq(priv->chip.irq.domain, gpio);
priv->chip.irq.domain, gpio));
} }
chained_irq_exit(irqchip, desc); chained_irq_exit(irqchip, desc);
} }

View File

@ -628,12 +628,8 @@ static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
if (!pending) if (!pending)
return; return;
for_each_set_bit(offset, &pending, 32) { for_each_set_bit(offset, &pending, 32)
unsigned int gpio_irq; generic_handle_domain_irq(irqdomain, offset + bank_offset);
gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset);
generic_handle_irq(gpio_irq);
}
} }
/** /**

View File

@ -502,7 +502,7 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
} else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) && } else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
adev->irq.virq[src_id]) { 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) { } else if (!adev->irq.client[client_id].sources) {
DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n", DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n",

View File

@ -45,20 +45,13 @@ static void dpu_mdss_irq(struct irq_desc *desc)
while (interrupts) { while (interrupts) {
irq_hw_number_t hwirq = fls(interrupts) - 1; irq_hw_number_t hwirq = fls(interrupts) - 1;
unsigned int mapping;
int rc; int rc;
mapping = irq_find_mapping(dpu_mdss->irq_controller.domain, rc = generic_handle_domain_irq(dpu_mdss->irq_controller.domain,
hwirq); hwirq);
if (mapping == 0) {
DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq);
break;
}
rc = generic_handle_irq(mapping);
if (rc < 0) { if (rc < 0) {
DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n", DRM_ERROR("handle irq fail: irq=%lu rc=%d\n",
hwirq, mapping, rc); hwirq, rc);
break; break;
} }

View File

@ -50,8 +50,7 @@ static irqreturn_t mdss_irq(int irq, void *arg)
while (intr) { while (intr) {
irq_hw_number_t hwirq = fls(intr) - 1; irq_hw_number_t hwirq = fls(intr) - 1;
generic_handle_irq(irq_find_mapping( generic_handle_domain_irq(mdp5_mdss->irqcontroller.domain, hwirq);
mdp5_mdss->irqcontroller.domain, hwirq));
intr &= ~(1 << hwirq); intr &= ~(1 << hwirq);
} }

View File

@ -1003,19 +1003,16 @@ err_cpmem:
static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
{ {
unsigned long status; unsigned long status;
int i, bit, irq; int i, bit;
for (i = 0; i < num_regs; i++) { for (i = 0; i < num_regs; i++) {
status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i])); status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i])); status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
for_each_set_bit(bit, &status, 32) { for_each_set_bit(bit, &status, 32)
irq = irq_linear_revmap(ipu->domain, generic_handle_domain_irq(ipu->domain,
regs[i] * 32 + bit); regs[i] * 32 + bit);
if (irq)
generic_handle_irq(irq);
}
} }
} }

View File

@ -267,9 +267,7 @@ static int alpine_msix_init(struct device_node *node,
goto err_priv; goto err_priv;
} }
priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_spis), priv->msi_map = bitmap_zalloc(priv->num_spis, GFP_KERNEL);
sizeof(*priv->msi_map),
GFP_KERNEL);
if (!priv->msi_map) { if (!priv->msi_map) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_priv; goto err_priv;
@ -285,7 +283,7 @@ static int alpine_msix_init(struct device_node *node,
return 0; return 0;
err_map: err_map:
kfree(priv->msi_map); bitmap_free(priv->msi_map);
err_priv: err_priv:
kfree(priv); kfree(priv);
return ret; return ret;

View File

@ -226,7 +226,7 @@ static void aic_irq_eoi(struct irq_data *d)
* Reading the interrupt reason automatically acknowledges and masks * Reading the interrupt reason automatically acknowledges and masks
* the IRQ, so we just unmask it here if needed. * 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); aic_irq_unmask(d);
} }

View File

@ -269,7 +269,7 @@ static void gicv2m_teardown(void)
list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) { list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
list_del(&v2m->entry); list_del(&v2m->entry);
kfree(v2m->bm); bitmap_free(v2m->bm);
iounmap(v2m->base); iounmap(v2m->base);
of_node_put(to_of_node(v2m->fwnode)); of_node_put(to_of_node(v2m->fwnode));
if (is_fwnode_irqchip(v2m->fwnode)) if (is_fwnode_irqchip(v2m->fwnode))
@ -386,8 +386,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
break; break;
} }
} }
v2m->bm = kcalloc(BITS_TO_LONGS(v2m->nr_spis), sizeof(long), v2m->bm = bitmap_zalloc(v2m->nr_spis, GFP_KERNEL);
GFP_KERNEL);
if (!v2m->bm) { if (!v2m->bm) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_iounmap; goto err_iounmap;

View File

@ -2140,7 +2140,7 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
if (err) if (err)
goto out; goto out;
bitmap = kcalloc(BITS_TO_LONGS(nr_irqs), sizeof (long), GFP_ATOMIC); bitmap = bitmap_zalloc(nr_irqs, GFP_ATOMIC);
if (!bitmap) if (!bitmap)
goto out; goto out;
@ -2156,7 +2156,7 @@ out:
static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids) static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)
{ {
WARN_ON(free_lpi_range(base, nr_ids)); WARN_ON(free_lpi_range(base, nr_ids));
kfree(bitmap); bitmap_free(bitmap);
} }
static void gic_reset_prop_table(void *va) 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)) { if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
kfree(dev); kfree(dev);
kfree(itt); kfree(itt);
kfree(lpi_map); bitmap_free(lpi_map);
kfree(col_map); kfree(col_map);
return NULL; return NULL;
} }

View File

@ -290,8 +290,7 @@ int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
if (ret) if (ret)
goto err_free_mbi; goto err_free_mbi;
mbi_ranges[n].bm = kcalloc(BITS_TO_LONGS(mbi_ranges[n].nr_spis), mbi_ranges[n].bm = bitmap_zalloc(mbi_ranges[n].nr_spis, GFP_KERNEL);
sizeof(long), GFP_KERNEL);
if (!mbi_ranges[n].bm) { if (!mbi_ranges[n].bm) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_mbi; goto err_free_mbi;
@ -329,7 +328,7 @@ int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
err_free_mbi: err_free_mbi:
if (mbi_ranges) { if (mbi_ranges) {
for (n = 0; n < mbi_range_nr; n++) for (n = 0; n < mbi_range_nr; n++)
kfree(mbi_ranges[n].bm); bitmap_free(mbi_ranges[n].bm);
kfree(mbi_ranges); kfree(mbi_ranges);
} }

View File

@ -100,6 +100,27 @@ EXPORT_SYMBOL(gic_pmr_sync);
DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities); DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities);
EXPORT_SYMBOL(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 */ /* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
static refcount_t *ppi_nmi_refs; 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); 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: case PPI_RANGE:
return d->hwirq - 16; return hwirq - 16;
case EPPI_RANGE: case EPPI_RANGE:
return d->hwirq - EPPI_BASE_INTID + 16; return hwirq - EPPI_BASE_INTID + 16;
default: default:
unreachable(); 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) static int gic_irq_nmi_setup(struct irq_data *d)
{ {
struct irq_desc *desc = irq_to_desc(d->irq); 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; return;
if (gic_supports_nmi() && 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); gic_handle_nmi(irqnr, regs);
return; 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, static int gic_irq_domain_select(struct irq_domain *d,
struct irq_fwspec *fwspec, struct irq_fwspec *fwspec,
enum irq_domain_bus_token bus_token) enum irq_domain_bus_token bus_token)
{ {
unsigned int type, ret, ppi_idx;
irq_hw_number_t hwirq;
/* Not for us */ /* Not for us */
if (fwspec->fwnode != d->fwnode) if (fwspec->fwnode != d->fwnode)
return 0; return 0;
@ -1479,16 +1529,19 @@ static int gic_irq_domain_select(struct irq_domain *d,
if (!is_of_node(fwspec->fwnode)) if (!is_of_node(fwspec->fwnode))
return 1; 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, * If this is a PPI and we have a 4th (non-null) parameter,
* then we need to match the partition domain. * then we need to match the partition domain.
*/ */
if (fwspec->param_count >= 4 && ppi_idx = __gic_get_ppi_index(hwirq);
fwspec->param[0] == 1 && fwspec->param[3] != 0 && return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
gic_data.ppi_descs)
return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
return d == gic_data.domain;
} }
static const struct irq_domain_ops gic_irq_domain_ops = { 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 long *hwirq,
unsigned int *type) unsigned int *type)
{ {
unsigned long ppi_intid;
struct device_node *np; struct device_node *np;
unsigned int ppi_idx;
int ret; int ret;
if (!gic_data.ppi_descs) if (!gic_data.ppi_descs)
@ -1513,7 +1568,12 @@ static int partition_domain_translate(struct irq_domain *d,
if (WARN_ON(!np)) if (WARN_ON(!np))
return -EINVAL; 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)); of_node_to_fwnode(np));
if (ret < 0) if (ret < 0)
return ret; return ret;

View File

@ -92,18 +92,22 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq); pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq); pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
irq_set_handler_locked(d, handle_edge_irq);
break; break;
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq); pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq); pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
irq_set_handler_locked(d, handle_edge_irq);
break; break;
case IRQ_TYPE_LEVEL_HIGH: case IRQ_TYPE_LEVEL_HIGH:
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq); pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq); pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
irq_set_handler_locked(d, handle_level_irq);
break; break;
case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_LOW:
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq); pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq); pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
irq_set_handler_locked(d, handle_level_irq);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
@ -113,11 +117,24 @@ static int pch_pic_set_type(struct irq_data *d, unsigned int type)
return ret; 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 = { static struct irq_chip pch_pic_irq_chip = {
.name = "PCH PIC", .name = "PCH PIC",
.irq_mask = pch_pic_mask_irq, .irq_mask = pch_pic_mask_irq,
.irq_unmask = pch_pic_unmask_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_affinity = irq_chip_set_affinity_parent,
.irq_set_type = pch_pic_set_type, .irq_set_type = pch_pic_set_type,
}; };

View File

@ -362,10 +362,7 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
msi_data->irqs_num = MSI_IRQS_PER_MSIR * msi_data->irqs_num = MSI_IRQS_PER_MSIR *
(1 << msi_data->cfg->ibs_shift); (1 << msi_data->cfg->ibs_shift);
msi_data->used = devm_kcalloc(&pdev->dev, msi_data->used = devm_bitmap_zalloc(&pdev->dev, msi_data->irqs_num, GFP_KERNEL);
BITS_TO_LONGS(msi_data->irqs_num),
sizeof(*msi_data->used),
GFP_KERNEL);
if (!msi_data->used) if (!msi_data->used)
return -ENOMEM; return -ENOMEM;
/* /*

View File

@ -65,6 +65,7 @@ static struct irq_chip mtk_sysirq_chip = {
.irq_set_type = mtk_sysirq_set_type, .irq_set_type = mtk_sysirq_set_type,
.irq_retrigger = irq_chip_retrigger_hierarchy, .irq_retrigger = irq_chip_retrigger_hierarchy,
.irq_set_affinity = irq_chip_set_affinity_parent, .irq_set_affinity = irq_chip_set_affinity_parent,
.flags = IRQCHIP_SKIP_SET_WAKE,
}; };
static int mtk_sysirq_domain_translate(struct irq_domain *d, static int mtk_sysirq_domain_translate(struct irq_domain *d,

View File

@ -210,9 +210,7 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
gicp->spi_cnt += gicp->spi_ranges[i].count; gicp->spi_cnt += gicp->spi_ranges[i].count;
} }
gicp->spi_bitmap = devm_kcalloc(&pdev->dev, gicp->spi_bitmap = devm_bitmap_zalloc(&pdev->dev, gicp->spi_cnt, GFP_KERNEL);
BITS_TO_LONGS(gicp->spi_cnt), sizeof(long),
GFP_KERNEL);
if (!gicp->spi_bitmap) if (!gicp->spi_bitmap)
return -ENOMEM; return -ENOMEM;

View File

@ -171,8 +171,7 @@ static int __init mvebu_odmi_init(struct device_node *node,
if (!odmis) if (!odmis)
return -ENOMEM; return -ENOMEM;
odmis_bm = kcalloc(BITS_TO_LONGS(odmis_count * NODMIS_PER_FRAME), odmis_bm = bitmap_zalloc(odmis_count * NODMIS_PER_FRAME, GFP_KERNEL);
sizeof(long), GFP_KERNEL);
if (!odmis_bm) { if (!odmis_bm) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_alloc; goto err_alloc;
@ -227,7 +226,7 @@ err_unmap:
if (odmi->base && !IS_ERR(odmi->base)) if (odmi->base && !IS_ERR(odmi->base))
iounmap(odmis[i].base); iounmap(odmis[i].base);
} }
kfree(odmis_bm); bitmap_free(odmis_bm);
err_alloc: err_alloc:
kfree(odmis); kfree(odmis);
return ret; return ret;

View File

@ -215,8 +215,7 @@ struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode,
goto out; goto out;
desc->domain = d; desc->domain = d;
desc->bitmap = kcalloc(BITS_TO_LONGS(nr_parts), sizeof(long), desc->bitmap = bitmap_zalloc(nr_parts, GFP_KERNEL);
GFP_KERNEL);
if (WARN_ON(!desc->bitmap)) if (WARN_ON(!desc->bitmap))
goto out; goto out;

View File

@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
return readl_relaxed(pdc_base + reg + i * sizeof(u32)); 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) static void pdc_enable_intr(struct irq_data *d, bool on)
{ {
int pin_out = d->hwirq; 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) static void qcom_pdc_gic_disable(struct irq_data *d)
{ {
if (d->hwirq == GPIO_NO_WAKE_IRQ)
return;
pdc_enable_intr(d, false); pdc_enable_intr(d, false);
irq_chip_disable_parent(d); irq_chip_disable_parent(d);
} }
static void qcom_pdc_gic_enable(struct irq_data *d) static void qcom_pdc_gic_enable(struct irq_data *d)
{ {
if (d->hwirq == GPIO_NO_WAKE_IRQ)
return;
pdc_enable_intr(d, true); pdc_enable_intr(d, true);
irq_chip_enable_parent(d); 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 * 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 * 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) 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 pdc_type;
enum pdc_irq_config_bits old_pdc_type; enum pdc_irq_config_bits old_pdc_type;
int ret; int ret;
if (pin_out == GPIO_NO_WAKE_IRQ)
return 0;
switch (type) { switch (type) {
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
pdc_type = PDC_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; return -EINVAL;
} }
old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out); old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type); pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
ret = irq_chip_set_type_parent(d, type); ret = irq_chip_set_type_parent(d, type);
if (ret) 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 = { static struct irq_chip qcom_pdc_gic_chip = {
.name = "PDC", .name = "PDC",
.irq_eoi = irq_chip_eoi_parent, .irq_eoi = irq_chip_eoi_parent,
.irq_mask = qcom_pdc_gic_mask, .irq_mask = irq_chip_mask_parent,
.irq_unmask = qcom_pdc_gic_unmask, .irq_unmask = irq_chip_unmask_parent,
.irq_disable = qcom_pdc_gic_disable, .irq_disable = qcom_pdc_gic_disable,
.irq_enable = qcom_pdc_gic_enable, .irq_enable = qcom_pdc_gic_enable,
.irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state, .irq_get_irqchip_state = irq_chip_get_parent_state,
.irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state, .irq_set_irqchip_state = irq_chip_set_parent_state,
.irq_retrigger = irq_chip_retrigger_hierarchy, .irq_retrigger = irq_chip_retrigger_hierarchy,
.irq_set_type = qcom_pdc_gic_set_type, .irq_set_type = qcom_pdc_gic_set_type,
.flags = IRQCHIP_MASK_ON_SUSPEND | .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); parent_hwirq = get_parent_hwirq(hwirq);
if (parent_hwirq == PDC_NO_PARENT_IRQ) if (parent_hwirq == PDC_NO_PARENT_IRQ)
return 0; return irq_domain_disconnect_hierarchy(domain->parent, virq);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
type = IRQ_TYPE_EDGE_RISING; type = IRQ_TYPE_EDGE_RISING;
@ -319,17 +273,17 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
if (ret) if (ret)
return 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, ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
&qcom_pdc_gic_chip, NULL); &qcom_pdc_gic_chip, NULL);
if (ret) if (ret)
return ret; return ret;
if (hwirq == GPIO_NO_WAKE_IRQ)
return 0;
parent_hwirq = get_parent_hwirq(hwirq); parent_hwirq = get_parent_hwirq(hwirq);
if (parent_hwirq == PDC_NO_PARENT_IRQ) if (parent_hwirq == PDC_NO_PARENT_IRQ)
return 0; return irq_domain_disconnect_hierarchy(domain->parent, virq);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
type = IRQ_TYPE_EDGE_RISING; type = IRQ_TYPE_EDGE_RISING;

View File

@ -2364,7 +2364,7 @@ static bool read_mailbox_0(void)
for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
if (ev & prcmu_irq_bit[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; r = true;
break; break;

View File

@ -35,10 +35,10 @@ static void mx25_tsadc_irq_handler(struct irq_desc *desc)
regmap_read(tsadc->regs, MX25_TSC_TGSR, &status); regmap_read(tsadc->regs, MX25_TSC_TGSR, &status);
if (status & MX25_TGSR_GCQ_INT) 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) 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); chained_irq_exit(chip, desc);
} }

Some files were not shown because too many files have changed in this diff Show More