Merge "irqchip: qcom-pdc: Add PDC version 3.2 support"

This commit is contained in:
qctecmdr 2022-05-27 04:12:25 -07:00 committed by Gerrit - the friendly Code Review server
commit 1f10328ce0

View File

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