Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * IRQ chip definitions for INTC IRQs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2007, 2008 Magnus Damm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2009 - 2012 Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * License.  See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/bsearch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "internals.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) void _intc_enable(struct irq_data *data, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	struct intc_desc_int *d = get_intc_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 		addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 						    [_INTC_FN(handle)], irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	intc_balancing_enable(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static void intc_enable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	_intc_enable(data, (unsigned long)irq_data_get_irq_chip_data(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static void intc_disable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct intc_desc_int *d = get_intc_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	unsigned long handle = (unsigned long)irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	intc_balancing_disable(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 						     [_INTC_FN(handle)], irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * This is held with the irq desc lock held, so we don't require any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * additional locking here at the intc desc level. The affinity mask is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * later tested in the enable/disable paths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static int intc_set_affinity(struct irq_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			     const struct cpumask *cpumask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			     bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (!cpumask_intersects(cpumask, cpu_online_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	cpumask_copy(irq_data_get_affinity_mask(data), cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	return IRQ_SET_MASK_OK_NOCOPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) static void intc_mask_ack(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	struct intc_desc_int *d = get_intc_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned long handle = intc_get_ack_handle(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	void __iomem *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	intc_disable(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	/* read register and write zero only to the associated bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		value = intc_set_field_from_handle(0, 1, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		switch (_INTC_FN(handle)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		case REG_FN_MODIFY_BASE + 0:	/* 8bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			__raw_readb(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			__raw_writeb(0xff ^ value, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		case REG_FN_MODIFY_BASE + 1:	/* 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			__raw_readw(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			__raw_writew(0xffff ^ value, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		case REG_FN_MODIFY_BASE + 3:	/* 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			__raw_readl(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			__raw_writel(0xffffffff ^ value, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 					     unsigned int nr_hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 					     unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct intc_handle_int key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	key.irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	key.handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return bsearch(&key, hp, nr_hp, sizeof(*hp), intc_handle_int_cmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int intc_set_priority(unsigned int irq, unsigned int prio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct intc_desc_int *d = get_intc_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	struct irq_data *data = irq_get_irq_data(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	struct intc_handle_int *ihp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (!intc_get_prio_level(irq) || prio <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	ihp = intc_find_irq(d->prio, d->nr_prio, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (ihp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		intc_set_prio_level(irq, prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		 * only set secondary masking method directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		 * primary masking method is using intc_prio_level[irq]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		 * priority level will be set during next enable()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		if (_INTC_FN(ihp->handle) != REG_FN_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			_intc_enable(data, ihp->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define SENSE_VALID_FLAG 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define VALID(x) (x | SENSE_VALID_FLAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	[IRQ_TYPE_EDGE_FALLING] = VALID(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	[IRQ_TYPE_EDGE_RISING] = VALID(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	[IRQ_TYPE_LEVEL_LOW] = VALID(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	/* SH7706, SH7707 and SH7709 do not support high level triggered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)     !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)     !defined(CONFIG_CPU_SUBTYPE_SH7709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	[IRQ_TYPE_LEVEL_HIGH] = VALID(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #if defined(CONFIG_ARM) /* all recent SH-Mobile / R-Mobile ARM support this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	[IRQ_TYPE_EDGE_BOTH] = VALID(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int intc_set_type(struct irq_data *data, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	struct intc_desc_int *d = get_intc_desc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	struct intc_handle_int *ihp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (!value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	value &= ~SENSE_VALID_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (ihp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		/* PINT has 2-bit sense registers, should fail on EDGE_BOTH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		if (value >= (1 << _INTC_WIDTH(ihp->handle)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct irq_chip intc_irq_chip	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	.irq_mask		= intc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	.irq_unmask		= intc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	.irq_mask_ack		= intc_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	.irq_enable		= intc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	.irq_disable		= intc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	.irq_set_type		= intc_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	.irq_set_affinity	= intc_set_affinity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	.flags			= IRQCHIP_SKIP_SET_WAKE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };