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)  * Based on linux/arch/mips/jmr3927/rbhma3100/irq.c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *	    linux/arch/mips/tx4927/common/tx4927_irq.c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *	    linux/arch/mips/tx4938/common/irq.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright 2001, 2003-2005 MontaVista Software Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *	   ahennessy@mvista.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *	   source@mvista.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Copyright (C) 2000-2001 Toshiba Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * License.  See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/txx9irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) struct txx9_irc_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	u32 cer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	u32 cr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	u32 unused0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	u32 ilr[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	u32 unused1[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	u32 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	u32 unused2[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	u32 scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	u32 unused3[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	u32 ssr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	u32 unused4[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u32 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /* IRCER : Int. Control Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define TXx9_IRCER_ICE	0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /* IRCR : Int. Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define TXx9_IRCR_LOW	0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define TXx9_IRCR_HIGH	0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define TXx9_IRCR_DOWN	0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define TXx9_IRCR_UP	0x00000003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define TXx9_IRCR_EDGE(cr)	((cr) & 0x00000002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /* IRSCR : Int. Status Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define TXx9_IRSCR_EIClrE	0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define TXx9_IRSCR_EIClr_MASK	0x0000000f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) /* IRCSR : Int. Current Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define TXx9_IRCSR_IF	0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define TXx9_IRCSR_ILV_MASK	0x00000700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define TXx9_IRCSR_IVL_MASK	0x0000001f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define irc_dlevel	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define irc_elevel	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static struct txx9_irc_reg __iomem *txx9_ircptr __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	unsigned char level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	unsigned char mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) } txx9irq[TXx9_MAX_IR] __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) static void txx9_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16 ) / 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	__raw_writel((__raw_readl(ilrp) & ~(0xff << ofs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		     | (txx9irq[irq_nr].level << ofs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		     ilrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #ifdef CONFIG_CPU_TX39XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	/* update IRCSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	__raw_writel(0, &txx9_ircptr->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	__raw_writel(irc_elevel, &txx9_ircptr->imr);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static inline void txx9_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16) / 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	__raw_writel((__raw_readl(ilrp) & ~(0xff << ofs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		     | (irc_dlevel << ofs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		     ilrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #ifdef CONFIG_CPU_TX39XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	/* update IRCSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	__raw_writel(0, &txx9_ircptr->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	__raw_writel(irc_elevel, &txx9_ircptr->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	/* flush write buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	__raw_readl(&txx9_ircptr->ssr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	mmiowb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void txx9_irq_mask_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	txx9_irq_mask(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	/* clear edge detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (unlikely(TXx9_IRCR_EDGE(txx9irq[irq_nr].mode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		__raw_writel(TXx9_IRSCR_EIClrE | irq_nr, &txx9_ircptr->scr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int txx9_irq_set_type(struct irq_data *d, unsigned int flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	u32 cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	u32 __iomem *crp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	int ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	if (flow_type & IRQF_TRIGGER_PROBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	switch (flow_type & IRQF_TRIGGER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	case IRQF_TRIGGER_RISING:	mode = TXx9_IRCR_UP;	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	case IRQF_TRIGGER_FALLING:	mode = TXx9_IRCR_DOWN;	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	case IRQF_TRIGGER_HIGH: mode = TXx9_IRCR_HIGH;	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	case IRQF_TRIGGER_LOW:	mode = TXx9_IRCR_LOW;	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	crp = &txx9_ircptr->cr[(unsigned int)irq_nr / 8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	cr = __raw_readl(crp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	ofs = (irq_nr & (8 - 1)) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	cr &= ~(0x3 << ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	cr |= (mode & 0x3) << ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	__raw_writel(cr, crp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	txx9irq[irq_nr].mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static struct irq_chip txx9_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	.name		= "TXX9",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	.irq_ack	= txx9_irq_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.irq_mask	= txx9_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	.irq_mask_ack	= txx9_irq_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	.irq_unmask	= txx9_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	.irq_set_type	= txx9_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) void __init txx9_irq_init(unsigned long baseaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	txx9_ircptr = ioremap(baseaddr, sizeof(struct txx9_irc_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	for (i = 0; i < TXx9_MAX_IR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		txx9irq[i].level = 4; /* middle level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		txx9irq[i].mode = TXx9_IRCR_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &txx9_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 					 handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	/* mask all IRC interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	__raw_writel(0, &txx9_ircptr->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		__raw_writel(0, &txx9_ircptr->ilr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	/* setup IRC interrupt mode (Low Active) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		__raw_writel(0, &txx9_ircptr->cr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* enable interrupt control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	__raw_writel(TXx9_IRCER_ICE, &txx9_ircptr->cer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	__raw_writel(irc_elevel, &txx9_ircptr->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int __init txx9_irq_set_pri(int irc_irq, int new_pri)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	int old_pri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if ((unsigned int)irc_irq >= TXx9_MAX_IR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	old_pri = txx9irq[irc_irq].level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	txx9irq[irc_irq].level = new_pri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return old_pri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int txx9_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	u32 csr = __raw_readl(&txx9_ircptr->csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (likely(!(csr & TXx9_IRCSR_IF)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		return TXX9_IRQ_BASE + (csr & (TXx9_MAX_IR - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }