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:
parent
1d87a8f291
commit
e6f80e87e0
|
@ -49,6 +49,7 @@
|
|||
#include <asm/atari_stdma.h>
|
||||
#include <asm/irq.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,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
|
@ -268,6 +343,13 @@ void __init atari_init_IRQ(void)
|
|||
if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
|
||||
stmfp_base.name, &stmfp_base))
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue