linux-stable/arch/sparc64/kernel/auxio.c
David S. Miller 63b614522c [SPARC64]: Get rid of fast IRQ feature.
The only real user was the assembler floppy interrupt
handler, which does not need to be in assembly.

This makes it so that there are less pieces of code which
know about the internal layout of ivector_table[] and
friends.

Signed-off-by: David S. Miller <davem@davemloft.net>
2005-06-27 17:04:45 -07:00

152 lines
3.1 KiB
C

/* auxio.c: Probing for the Sparc AUXIO register at boot time.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*
* Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/sbus.h>
#include <asm/ebus.h>
#include <asm/auxio.h>
/* This cannot be static, as it is referenced in irq.c */
void __iomem *auxio_register = NULL;
enum auxio_type {
AUXIO_TYPE_NODEV,
AUXIO_TYPE_SBUS,
AUXIO_TYPE_EBUS
};
static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV;
static DEFINE_SPINLOCK(auxio_lock);
static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
{
if (auxio_register) {
unsigned char regval;
unsigned long flags;
unsigned char newval;
spin_lock_irqsave(&auxio_lock, flags);
regval = sbus_readb(auxio_register);
newval = regval | bits_on;
newval &= ~bits_off;
newval &= ~AUXIO_AUX1_MASK;
sbus_writeb(newval, auxio_register);
spin_unlock_irqrestore(&auxio_lock, flags);
}
}
static void __auxio_ebus_set(u8 bits_on, u8 bits_off)
{
if (auxio_register) {
unsigned char regval;
unsigned long flags;
unsigned char newval;
spin_lock_irqsave(&auxio_lock, flags);
regval = (u8)readl(auxio_register);
newval = regval | bits_on;
newval &= ~bits_off;
writel((u32)newval, auxio_register);
spin_unlock_irqrestore(&auxio_lock, flags);
}
}
static inline void __auxio_ebus_set_led(int on)
{
(on) ? __auxio_ebus_set(AUXIO_PCIO_LED, 0) :
__auxio_ebus_set(0, AUXIO_PCIO_LED) ;
}
static inline void __auxio_sbus_set_led(int on)
{
(on) ? __auxio_sbus_set(AUXIO_AUX1_LED, 0) :
__auxio_sbus_set(0, AUXIO_AUX1_LED) ;
}
void auxio_set_led(int on)
{
switch(auxio_devtype) {
case AUXIO_TYPE_SBUS:
__auxio_sbus_set_led(on);
break;
case AUXIO_TYPE_EBUS:
__auxio_ebus_set_led(on);
break;
default:
break;
}
}
static inline void __auxio_sbus_set_lte(int on)
{
(on) ? __auxio_sbus_set(AUXIO_AUX1_LTE, 0) :
__auxio_sbus_set(0, AUXIO_AUX1_LTE) ;
}
void auxio_set_lte(int on)
{
switch(auxio_devtype) {
case AUXIO_TYPE_SBUS:
__auxio_sbus_set_lte(on);
break;
case AUXIO_TYPE_EBUS:
/* FALL-THROUGH */
default:
break;
}
}
void __init auxio_probe(void)
{
struct sbus_bus *sbus;
struct sbus_dev *sdev = NULL;
for_each_sbus(sbus) {
for_each_sbusdev(sdev, sbus) {
if(!strcmp(sdev->prom_name, "auxio"))
goto found_sdev;
}
}
found_sdev:
if (sdev) {
auxio_devtype = AUXIO_TYPE_SBUS;
auxio_register = sbus_ioremap(&sdev->resource[0], 0,
sdev->reg_addrs[0].reg_size,
"auxiliaryIO");
}
#ifdef CONFIG_PCI
else {
struct linux_ebus *ebus;
struct linux_ebus_device *edev = NULL;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, "auxio"))
goto ebus_done;
}
}
ebus_done:
if (edev) {
auxio_devtype = AUXIO_TYPE_EBUS;
auxio_register =
ioremap(edev->resource[0].start, sizeof(u32));
}
}
auxio_set_led(AUXIO_LED_ON);
#endif
}