mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 05:38:00 +00:00
rtl838x: Add irq settings for RTL839x SoCs
This adds correct interrupt routing settings for IRQs on the RTL839x SoCs. It also speeds up irq handling based on work by biot for all SoCs. Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
This commit is contained in:
parent
e788e9bd87
commit
3c4063f715
@ -16,11 +16,13 @@
|
||||
#define rtl838x_w32(val, reg) __raw_writel(val, reg)
|
||||
#define rtl838x_w32_mask(clear, set, reg) rtl838x_w32((rtl838x_r32(reg) & ~(clear)) | (set), reg)
|
||||
|
||||
#define rtl838x_r8(reg) __raw_readb(reg)
|
||||
#define rtl838x_w8(val, reg) __raw_writeb(val, reg)
|
||||
|
||||
#define sw_r32(reg) __raw_readl(RTL838X_SW_BASE + reg)
|
||||
#define sw_w32(val, reg) __raw_writel(val, RTL838X_SW_BASE + reg)
|
||||
#define sw_w32_mask(clear, set, reg) \
|
||||
sw_w32((sw_r32(reg) & ~(clear)) | (set), reg)
|
||||
|
||||
#define sw_r64(reg) ((((u64)__raw_readl(RTL838X_SW_BASE + reg)) << 32) | \
|
||||
__raw_readl(RTL838X_SW_BASE + reg + 4))
|
||||
|
||||
@ -102,11 +104,15 @@
|
||||
|
||||
#define IRR1 (0x0c)
|
||||
|
||||
#define IRR1_SETTING ((GPIO_ABCD_RS << 28) | \
|
||||
#define IRR1_SETTING_RTL838X ((GPIO_ABCD_RS << 28) | \
|
||||
(GPIO_EFGH_RS << 24) | \
|
||||
(RTC_RS << 20) | \
|
||||
(SWCORE_RS << 16) \
|
||||
)
|
||||
#define IRR1_SETTING_RTL839X ((GPIO_ABCD_RS << 28) | \
|
||||
(SWCORE_RS << 16) \
|
||||
)
|
||||
|
||||
|
||||
#define IRR2 (0x10)
|
||||
#define IRR2_SETTING 0
|
||||
|
@ -29,36 +29,7 @@ extern struct rtl838x_soc_info soc_info;
|
||||
static DEFINE_RAW_SPINLOCK(irq_lock);
|
||||
|
||||
extern irqreturn_t c0_compare_interrupt(int irq, void *dev_id);
|
||||
unsigned int rtl838x_ictl_irq_dispatch1(void);
|
||||
unsigned int rtl838x_ictl_irq_dispatch2(void);
|
||||
unsigned int rtl838x_ictl_irq_dispatch3(void);
|
||||
unsigned int rtl838x_ictl_irq_dispatch4(void);
|
||||
unsigned int rtl838x_ictl_irq_dispatch5(void);
|
||||
|
||||
static struct irqaction irq_cascade1 = {
|
||||
.handler = no_action,
|
||||
.name = "RTL838X IRQ cascade1",
|
||||
};
|
||||
|
||||
static struct irqaction irq_cascade2 = {
|
||||
.handler = no_action,
|
||||
.name = "RTL838X IRQ cascade2",
|
||||
};
|
||||
|
||||
static struct irqaction irq_cascade3 = {
|
||||
.handler = no_action,
|
||||
.name = "RTL838X IRQ cascade3",
|
||||
};
|
||||
|
||||
static struct irqaction irq_cascade4 = {
|
||||
.handler = no_action,
|
||||
.name = "RTL838X IRQ cascade4",
|
||||
};
|
||||
|
||||
static struct irqaction irq_cascade5 = {
|
||||
.handler = no_action,
|
||||
.name = "RTL838X IRQ cascade5",
|
||||
};
|
||||
|
||||
static void rtl838x_ictl_enable_irq(struct irq_data *i)
|
||||
{
|
||||
@ -69,12 +40,6 @@ static void rtl838x_ictl_enable_irq(struct irq_data *i)
|
||||
raw_spin_unlock_irqrestore(&irq_lock, flags);
|
||||
}
|
||||
|
||||
static unsigned int rtl838x_ictl_startup_irq(struct irq_data *i)
|
||||
{
|
||||
rtl838x_ictl_enable_irq(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl838x_ictl_disable_irq(struct irq_data *i)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -94,9 +59,7 @@ static void rtl838x_ictl_eoi_irq(struct irq_data *i)
|
||||
}
|
||||
|
||||
static struct irq_chip rtl838x_ictl_irq = {
|
||||
.name = "RTL838X",
|
||||
.irq_startup = rtl838x_ictl_startup_irq,
|
||||
.irq_shutdown = rtl838x_ictl_disable_irq,
|
||||
.name = "RTL83xx",
|
||||
.irq_enable = rtl838x_ictl_enable_irq,
|
||||
.irq_disable = rtl838x_ictl_disable_irq,
|
||||
.irq_ack = rtl838x_ictl_disable_irq,
|
||||
@ -106,113 +69,57 @@ static struct irq_chip rtl838x_ictl_irq = {
|
||||
};
|
||||
|
||||
/*
|
||||
* RTL8390/80/28 Interrupt Scheme
|
||||
* RTL8390/80/28 Interrupt Scheme
|
||||
*
|
||||
* Source IRQ CPU INT
|
||||
* -------- ------- -------
|
||||
* UART0 31 IP3
|
||||
* UART1 30 IP2
|
||||
* TIMER0 29 IP6
|
||||
* TIMER1 28 IP2
|
||||
* OCPTO 27 IP2
|
||||
* HLXTO 26 IP2
|
||||
* SLXTO 25 IP2
|
||||
* NIC 24 IP5
|
||||
* GPIO_ABCD 23 IP5
|
||||
* SWCORE 20 IP4
|
||||
* Source IRQ CPU INT
|
||||
* -------- ------- -------
|
||||
* UART0 31 IP3
|
||||
* UART1 30 IP2
|
||||
* TIMER0 29 IP6
|
||||
* TIMER1 28 IP2
|
||||
* OCPTO 27 IP2
|
||||
* HLXTO 26 IP2
|
||||
* SLXTO 25 IP2
|
||||
* NIC 24 IP5
|
||||
* GPIO_ABCD 23 IP5
|
||||
* SWCORE 20 IP4
|
||||
*/
|
||||
|
||||
unsigned int rtl838x_ictl_irq_dispatch1(void)
|
||||
{
|
||||
/* Identify shared IRQ */
|
||||
unsigned int extint_ip = icu_r32(GIMR) & icu_r32(GISR);
|
||||
|
||||
if (extint_ip & TC1_IP)
|
||||
do_IRQ(TC1_IRQ);
|
||||
else if (extint_ip & UART1_IP)
|
||||
do_IRQ(UART1_IRQ);
|
||||
else
|
||||
spurious_interrupt();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
unsigned int rtl838x_ictl_irq_dispatch2(void)
|
||||
{
|
||||
do_IRQ(UART0_IRQ);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
unsigned int rtl838x_ictl_irq_dispatch3(void)
|
||||
{
|
||||
do_IRQ(SWCORE_IRQ);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
unsigned int rtl838x_ictl_irq_dispatch4(void)
|
||||
{
|
||||
/* Identify shared IRQ */
|
||||
unsigned int extint_ip = icu_r32(GIMR) & icu_r32(GISR);
|
||||
|
||||
if (extint_ip & NIC_IP)
|
||||
do_IRQ(NIC_IRQ);
|
||||
else if (extint_ip & GPIO_ABCD_IP)
|
||||
do_IRQ(GPIO_ABCD_IRQ);
|
||||
else if ((extint_ip & GPIO_EFGH_IP) && (soc_info.family == RTL8328_FAMILY_ID))
|
||||
do_IRQ(GPIO_EFGH_IRQ);
|
||||
else
|
||||
spurious_interrupt();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
unsigned int rtl838x_ictl_irq_dispatch5(void)
|
||||
{
|
||||
do_IRQ(TC0_IRQ);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
unsigned int pending;
|
||||
unsigned int pending, ext_int;
|
||||
|
||||
pending = read_c0_cause() & read_c0_status() & ST0_IM;
|
||||
pending = read_c0_cause();
|
||||
|
||||
if (pending & CAUSEF_IP7)
|
||||
if (pending & CAUSEF_IP7) {
|
||||
c0_compare_interrupt(7, NULL);
|
||||
else if (pending & CAUSEF_IP6)
|
||||
rtl838x_ictl_irq_dispatch5();
|
||||
else if (pending & CAUSEF_IP5)
|
||||
rtl838x_ictl_irq_dispatch4();
|
||||
else if (pending & CAUSEF_IP4)
|
||||
rtl838x_ictl_irq_dispatch3();
|
||||
else if (pending & CAUSEF_IP3)
|
||||
rtl838x_ictl_irq_dispatch2();
|
||||
else if (pending & CAUSEF_IP2)
|
||||
rtl838x_ictl_irq_dispatch1();
|
||||
else
|
||||
} else if (pending & CAUSEF_IP6) {
|
||||
do_IRQ(TC0_IRQ);
|
||||
} else if (pending & CAUSEF_IP5) {
|
||||
ext_int = icu_r32(GIMR) & icu_r32(GISR);
|
||||
if (ext_int & NIC_IP)
|
||||
do_IRQ(NIC_IRQ);
|
||||
else if (ext_int & GPIO_ABCD_IP)
|
||||
do_IRQ(GPIO_ABCD_IRQ);
|
||||
else if ((ext_int & GPIO_EFGH_IP) && (soc_info.family == RTL8328_FAMILY_ID))
|
||||
do_IRQ(GPIO_EFGH_IRQ);
|
||||
else
|
||||
spurious_interrupt();
|
||||
} else if (pending & CAUSEF_IP4) {
|
||||
do_IRQ(SWCORE_IRQ);
|
||||
} else if (pending & CAUSEF_IP3) {
|
||||
do_IRQ(UART0_IRQ);
|
||||
} else if (pending & CAUSEF_IP2) {
|
||||
ext_int = icu_r32(GIMR) & icu_r32(GISR);
|
||||
if (ext_int & TC1_IP)
|
||||
do_IRQ(TC1_IRQ);
|
||||
else if (ext_int & UART1_IP)
|
||||
do_IRQ(UART1_IRQ);
|
||||
else
|
||||
spurious_interrupt();
|
||||
} else {
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
static void __init rtl838x_ictl_irq_init(unsigned int irq_base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTL838X_IRQ_ICTL_NUM; i++)
|
||||
irq_set_chip_and_handler(irq_base + i, &rtl838x_ictl_irq, handle_level_irq);
|
||||
|
||||
setup_irq(RTL838X_ICTL1_IRQ, &irq_cascade1);
|
||||
setup_irq(RTL838X_ICTL2_IRQ, &irq_cascade2);
|
||||
setup_irq(RTL838X_ICTL3_IRQ, &irq_cascade3);
|
||||
setup_irq(RTL838X_ICTL4_IRQ, &irq_cascade4);
|
||||
setup_irq(RTL838X_ICTL5_IRQ, &irq_cascade5);
|
||||
|
||||
/* Set GIMR, IRR */
|
||||
icu_w32(TC0_IE | UART0_IE, GIMR);
|
||||
icu_w32(IRR0_SETTING, IRR0);
|
||||
icu_w32(IRR1_SETTING, IRR1);
|
||||
icu_w32(IRR2_SETTING, IRR2);
|
||||
icu_w32(IRR3_SETTING, IRR3);
|
||||
}
|
||||
}
|
||||
|
||||
static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
|
||||
@ -234,11 +141,12 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
|
||||
struct resource res;
|
||||
|
||||
pr_info("Found Interrupt controller: %s (%s)\n", node->name, node->full_name);
|
||||
if (of_address_to_resource(node, 0, &res)) {
|
||||
if (of_address_to_resource(node, 0, &res))
|
||||
panic("Failed to get icu memory range");
|
||||
}
|
||||
|
||||
if (!request_mem_region(res.start, resource_size(&res), res.name))
|
||||
pr_err("Failed to request icu memory\n");
|
||||
|
||||
soc_info.icu_base = ioremap(res.start, resource_size(&res));
|
||||
pr_info("ICU Memory: %08x\n", (u32)soc_info.icu_base);
|
||||
|
||||
@ -247,10 +155,44 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
|
||||
domain = irq_domain_add_simple(node, 32, 0, &irq_domain_ops, NULL);
|
||||
|
||||
/* Setup all external HW irqs */
|
||||
for (i = 8; i < 32; i++)
|
||||
for (i = 8; i < RTL838X_IRQ_ICTL_NUM; i++) {
|
||||
irq_domain_associate(domain, i, i);
|
||||
irq_set_chip_and_handler(RTL838X_IRQ_ICTL_BASE + i,
|
||||
&rtl838x_ictl_irq, handle_level_irq);
|
||||
}
|
||||
|
||||
rtl838x_ictl_irq_init(RTL838X_IRQ_ICTL_BASE);
|
||||
if (request_irq(RTL838X_ICTL1_IRQ, no_action, IRQF_NO_THREAD,
|
||||
"IRQ cascade 1", NULL)) {
|
||||
pr_err("request_irq() cascade 1 for irq %d failed\n", RTL838X_ICTL1_IRQ);
|
||||
}
|
||||
if (request_irq(RTL838X_ICTL2_IRQ, no_action, IRQF_NO_THREAD,
|
||||
"IRQ cascade 2", NULL)) {
|
||||
pr_err("request_irq() cascade 2 for irq %d failed\n", RTL838X_ICTL2_IRQ);
|
||||
}
|
||||
if (request_irq(RTL838X_ICTL3_IRQ, no_action, IRQF_NO_THREAD,
|
||||
"IRQ cascade 3", NULL)) {
|
||||
pr_err("request_irq() cascade 3 for irq %d failed\n", RTL838X_ICTL3_IRQ);
|
||||
}
|
||||
if (request_irq(RTL838X_ICTL4_IRQ, no_action, IRQF_NO_THREAD,
|
||||
"IRQ cascade 4", NULL)) {
|
||||
pr_err("request_irq() cascade 4 for irq %d failed\n", RTL838X_ICTL4_IRQ);
|
||||
}
|
||||
if (request_irq(RTL838X_ICTL5_IRQ, no_action, IRQF_NO_THREAD,
|
||||
"IRQ cascade 5", NULL)) {
|
||||
pr_err("request_irq() cascade 5 for irq %d failed\n", RTL838X_ICTL5_IRQ);
|
||||
}
|
||||
|
||||
/* Set up interrupt routing scheme */
|
||||
icu_w32(IRR0_SETTING, IRR0);
|
||||
if (soc_info.family == RTL8380_FAMILY_ID)
|
||||
icu_w32(IRR1_SETTING_RTL838X, IRR1);
|
||||
else
|
||||
icu_w32(IRR1_SETTING_RTL839X, IRR1);
|
||||
icu_w32(IRR2_SETTING, IRR2);
|
||||
icu_w32(IRR3_SETTING, IRR3);
|
||||
|
||||
/* Enable timer0 and uart0 interrupts */
|
||||
icu_w32(TC0_IE | UART0_IE, GIMR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user