m68k/atari: EtherNAT - add interrupt chip definition for CPLD interrupts
Add a dedicated interrupt chip definition for the EtherNAT CPLD interrupts. SMC91C111 and ISP1160 chips have separate interrupts that can be enabled and disabled in a CPLD register at offset 0x23 from the card base. Note the CPLD interrupt control register is mapped on demand, whenever any interrupt enable/disable action is requested. The EtherNAT USB driver still needs interrupts disabled around reset and start actions. In particular, we cannot entirely rely on the irq_startup being called first. The smc91x and isp116x-hcd drivers will use this feature. Signed-off-by: Michael Schmitz <schmitz@debian.org> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
This commit is contained in:
committed by
Geert Uytterhoeven
parent
1d87a8f291
commit
e6f80e87e0
@@ -49,6 +49,7 @@
|
|||||||
#include <asm/atari_stdma.h>
|
#include <asm/atari_stdma.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/entry.h>
|
#include <asm/entry.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -177,6 +178,80 @@ static struct irq_chip atari_mfptimer_chip = {
|
|||||||
.irq_disable = atari_mfptimer_disable,
|
.irq_disable = atari_mfptimer_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EtherNAT CPLD interrupt handling
|
||||||
|
* CPLD interrupt register is at phys. 0x80000023
|
||||||
|
* Need this mapped in at interrupt startup time
|
||||||
|
* Possibly need this mapped on demand anyway -
|
||||||
|
* EtherNAT USB driver needs to disable IRQ before
|
||||||
|
* startup!
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char *enat_cpld;
|
||||||
|
|
||||||
|
static unsigned int atari_ethernat_startup(struct irq_data *data)
|
||||||
|
{
|
||||||
|
int enat_num = 140 - data->irq + 1;
|
||||||
|
|
||||||
|
m68k_irq_startup(data);
|
||||||
|
/*
|
||||||
|
* map CPLD interrupt register
|
||||||
|
*/
|
||||||
|
if (!enat_cpld)
|
||||||
|
enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
|
||||||
|
/*
|
||||||
|
* do _not_ enable the USB chip interrupt here - causes interrupt storm
|
||||||
|
* and triggers dead interrupt watchdog
|
||||||
|
* Need to reset the USB chip to a sane state in early startup before
|
||||||
|
* removing this hack
|
||||||
|
*/
|
||||||
|
if (enat_num == 1)
|
||||||
|
*enat_cpld |= 1 << enat_num;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atari_ethernat_enable(struct irq_data *data)
|
||||||
|
{
|
||||||
|
int enat_num = 140 - data->irq + 1;
|
||||||
|
/*
|
||||||
|
* map CPLD interrupt register
|
||||||
|
*/
|
||||||
|
if (!enat_cpld)
|
||||||
|
enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
|
||||||
|
*enat_cpld |= 1 << enat_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atari_ethernat_disable(struct irq_data *data)
|
||||||
|
{
|
||||||
|
int enat_num = 140 - data->irq + 1;
|
||||||
|
/*
|
||||||
|
* map CPLD interrupt register
|
||||||
|
*/
|
||||||
|
if (!enat_cpld)
|
||||||
|
enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
|
||||||
|
*enat_cpld &= ~(1 << enat_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atari_ethernat_shutdown(struct irq_data *data)
|
||||||
|
{
|
||||||
|
int enat_num = 140 - data->irq + 1;
|
||||||
|
if (enat_cpld) {
|
||||||
|
*enat_cpld &= ~(1 << enat_num);
|
||||||
|
iounmap(enat_cpld);
|
||||||
|
enat_cpld = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_chip atari_ethernat_chip = {
|
||||||
|
.name = "ethernat",
|
||||||
|
.irq_startup = atari_ethernat_startup,
|
||||||
|
.irq_shutdown = atari_ethernat_shutdown,
|
||||||
|
.irq_enable = atari_ethernat_enable,
|
||||||
|
.irq_disable = atari_ethernat_disable,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void atari_init_IRQ (void)
|
* void atari_init_IRQ (void)
|
||||||
*
|
*
|
||||||
@@ -268,6 +343,13 @@ void __init atari_init_IRQ(void)
|
|||||||
if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
|
if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
|
||||||
stmfp_base.name, &stmfp_base))
|
stmfp_base.name, &stmfp_base))
|
||||||
pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
|
pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EtherNAT ethernet / USB interrupt handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
m68k_setup_irq_controller(&atari_ethernat_chip, handle_simple_irq,
|
||||||
|
139, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user