mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 19:21:28 +02:00
Merge "irqchip: qcom-pdc: Add PDC version 3.2 support"
This commit is contained in:
commit
1f10328ce0
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
|
|
@ -29,6 +30,14 @@
|
|||
|
||||
#define IRQ_ENABLE_BANK 0x10
|
||||
#define IRQ_i_CFG 0x110
|
||||
#define IRQ_i_CFG_IRQ_ENABLE BIT(3)
|
||||
#define IRQ_i_CFG_TYPE_MASK 0x7
|
||||
|
||||
#define VERSION 0x1000
|
||||
#define MAJOR_VER_MASK 0xFF
|
||||
#define MAJOR_VER_SHIFT 16
|
||||
#define MINOR_VER_MASK 0xFF
|
||||
#define MINOR_VER_SHIFT 8
|
||||
|
||||
struct pdc_pin_region {
|
||||
u32 pin_base;
|
||||
|
|
@ -53,6 +62,7 @@ static struct pdc_pin_region *pdc_region;
|
|||
static int pdc_region_cnt;
|
||||
static struct spi_cfg_regs *spi_cfg;
|
||||
static void *pdc_ipc_log;
|
||||
static bool enable_in_cfg;
|
||||
|
||||
static u32 __spi_pin_read(unsigned int pin)
|
||||
{
|
||||
|
|
@ -125,15 +135,21 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
|
|||
unsigned long flags;
|
||||
u32 index, mask;
|
||||
|
||||
index = pin_out / 32;
|
||||
mask = pin_out % 32;
|
||||
|
||||
raw_spin_lock_irqsave(&pdc_lock, flags);
|
||||
enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
|
||||
__assign_bit(mask, &enable, on);
|
||||
pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
|
||||
ipc_log_string(pdc_ipc_log, "PIN=%d enable=%d", d->hwirq, on);
|
||||
if (!enable_in_cfg) {
|
||||
index = pin_out / 32;
|
||||
mask = pin_out % 32;
|
||||
enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
|
||||
__assign_bit(mask, &enable, on);
|
||||
pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
|
||||
} else {
|
||||
index = d->hwirq;
|
||||
enable = pdc_reg_read(IRQ_i_CFG, index);
|
||||
__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
|
||||
pdc_reg_write(IRQ_i_CFG, index, enable);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&pdc_lock, flags);
|
||||
ipc_log_string(pdc_ipc_log, "PIN=%d enable=%d", d->hwirq, on);
|
||||
}
|
||||
|
||||
static void qcom_pdc_gic_disable(struct irq_data *d)
|
||||
|
|
@ -214,6 +230,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
|
|||
}
|
||||
|
||||
old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
|
||||
pdc_type |= (old_pdc_type & ~IRQ_i_CFG_TYPE_MASK);
|
||||
pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
|
||||
ipc_log_string(pdc_ipc_log, "Set type: PIN=%d pdc_type=%d gic_type=%d",
|
||||
d->hwirq, pdc_type, type);
|
||||
|
|
@ -325,8 +342,8 @@ static const struct irq_domain_ops qcom_pdc_ops = {
|
|||
|
||||
static int pdc_setup_pin_mapping(struct device_node *np)
|
||||
{
|
||||
int ret, n, i;
|
||||
u32 irq_index, reg_index, val;
|
||||
int ret, n, i, last_region;
|
||||
u32 irq_index, reg_index, val, max_irq;
|
||||
|
||||
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
|
||||
if (n <= 0 || n % 3)
|
||||
|
|
@ -355,14 +372,25 @@ static int pdc_setup_pin_mapping(struct device_node *np)
|
|||
&pdc_region[n].cnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdc_region[n].cnt; i++) {
|
||||
last_region = pdc_region_cnt - 1;
|
||||
max_irq = pdc_region[last_region].pin_base + pdc_region[last_region].cnt;
|
||||
|
||||
if (!enable_in_cfg) {
|
||||
for (i = 0; i < max_irq; i++) {
|
||||
reg_index = (i + pdc_region[n].pin_base) >> 5;
|
||||
irq_index = (i + pdc_region[n].pin_base) & 0x1f;
|
||||
val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
|
||||
val &= ~BIT(irq_index);
|
||||
pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < max_irq; i++) {
|
||||
val = pdc_reg_read(IRQ_i_CFG, i);
|
||||
val &= ~IRQ_i_CFG_IRQ_ENABLE;
|
||||
pdc_reg_write(IRQ_i_CFG, i, val);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -373,6 +401,7 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
|
|||
struct irq_domain *parent_domain, *pdc_domain;
|
||||
struct resource res;
|
||||
int ret;
|
||||
u32 version, major_ver, minor_ver;
|
||||
|
||||
pdc_base = of_iomap(node, 0);
|
||||
if (!pdc_base) {
|
||||
|
|
@ -380,6 +409,16 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
version = pdc_reg_read(VERSION, 0);
|
||||
major_ver = version & (MAJOR_VER_MASK << MAJOR_VER_SHIFT);
|
||||
major_ver >>= MAJOR_VER_SHIFT;
|
||||
minor_ver = version & (MINOR_VER_MASK << MINOR_VER_SHIFT);
|
||||
minor_ver >>= MINOR_VER_SHIFT;
|
||||
if (major_ver >= 3 && minor_ver > 1)
|
||||
enable_in_cfg = true;
|
||||
else
|
||||
enable_in_cfg = false;
|
||||
|
||||
parent_domain = irq_find_host(parent);
|
||||
if (!parent_domain) {
|
||||
pr_err("%pOF: unable to find PDC's parent domain\n", node);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user