diff options
Diffstat (limited to 'arch/sh/boards/mach-dreamcast')
| -rw-r--r-- | arch/sh/boards/mach-dreamcast/irq.c | 221 | ||||
| -rw-r--r-- | arch/sh/boards/mach-dreamcast/rtc.c | 20 | ||||
| -rw-r--r-- | arch/sh/boards/mach-dreamcast/setup.c | 25 |
3 files changed, 123 insertions, 143 deletions
diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index 67bdc33dd41..2789647abeb 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c @@ -8,108 +8,96 @@ * This file is part of the LinuxDC project (www.linuxdc.org) * Released under the terms of the GNU GPL v2.0 */ - #include <linux/irq.h> -#include <asm/io.h> -#include <asm/irq.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/export.h> +#include <linux/err.h> #include <mach/sysasic.h> -/* Dreamcast System ASIC Hardware Events - - - The Dreamcast's System ASIC (a.k.a. Holly) is responsible for receiving - hardware events from system peripherals and triggering an SH7750 IRQ. - Hardware events can trigger IRQs 13, 11, or 9 depending on which bits are - set in the Event Mask Registers (EMRs). When a hardware event is - triggered, it's corresponding bit in the Event Status Registers (ESRs) - is set, and that bit should be rewritten to the ESR to acknowledge that - event. - - There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event - types can be found in include/asm-sh/dreamcast/sysasic.h. There are three - groups of EMRs that parallel the ESRs. Each EMR group corresponds to an - IRQ, so 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 - triggers IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9. - - In the kernel, these events are mapped to virtual IRQs so that drivers can - respond to them as they would a normal interrupt. In order to keep this - mapping simple, the events are mapped as: - - 6900/6910 - Events 0-31, IRQ 13 - 6904/6924 - Events 32-63, IRQ 11 - 6908/6938 - Events 64-95, IRQ 9 - -*/ +/* + * Dreamcast System ASIC Hardware Events - + * + * The Dreamcast's System ASIC (a.k.a. Holly) is responsible for receiving + * hardware events from system peripherals and triggering an SH7750 IRQ. + * Hardware events can trigger IRQs 13, 11, or 9 depending on which bits are + * set in the Event Mask Registers (EMRs). When a hardware event is + * triggered, its corresponding bit in the Event Status Registers (ESRs) + * is set, and that bit should be rewritten to the ESR to acknowledge that + * event. + * + * There are three 32-bit ESRs located at 0xa05f6900 - 0xa05f6908. Event + * types can be found in arch/sh/include/mach-dreamcast/mach/sysasic.h. + * There are three groups of EMRs that parallel the ESRs. Each EMR group + * corresponds to an IRQ, so 0xa05f6910 - 0xa05f6918 triggers IRQ 13, + * 0xa05f6920 - 0xa05f6928 triggers IRQ 11, and 0xa05f6930 - 0xa05f6938 + * triggers IRQ 9. + * + * In the kernel, these events are mapped to virtual IRQs so that drivers can + * respond to them as they would a normal interrupt. In order to keep this + * mapping simple, the events are mapped as: + * + * 6900/6910 - Events 0-31, IRQ 13 + * 6904/6924 - Events 32-63, IRQ 11 + * 6908/6938 - Events 64-95, IRQ 9 + * + */ #define ESR_BASE 0x005f6900 /* Base event status register */ #define EMR_BASE 0x005f6910 /* Base event mask register */ -/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910, - 1 = 0x6920, 2 = 0x6930; also determine the event offset */ +/* + * Helps us determine the EMR group that this event belongs to: 0 = 0x6910, + * 1 = 0x6920, 2 = 0x6930; also determine the event offset. + */ #define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32) -/* Return the hardware event's bit positon within the EMR/ESR */ +/* Return the hardware event's bit position within the EMR/ESR */ #define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31) -/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ - (logically mapped to the corresponding bit for the hardware event). */ +/* + * For each of these *_irq routines, the IRQ passed in is the virtual IRQ + * (logically mapped to the corresponding bit for the hardware event). + */ /* Disable the hardware event by masking its bit in its EMR */ -static inline void disable_systemasic_irq(unsigned int irq) +static inline void disable_systemasic_irq(struct irq_data *data) { - __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); - __u32 mask; + unsigned int irq = data->irq; + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; - mask = inl(emr); - mask &= ~(1 << EVENT_BIT(irq)); - outl(mask, emr); + mask = inl(emr); + mask &= ~(1 << EVENT_BIT(irq)); + outl(mask, emr); } /* Enable the hardware event by setting its bit in its EMR */ -static inline void enable_systemasic_irq(unsigned int irq) +static inline void enable_systemasic_irq(struct irq_data *data) { - __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); - __u32 mask; + unsigned int irq = data->irq; + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; - mask = inl(emr); - mask |= (1 << EVENT_BIT(irq)); - outl(mask, emr); + mask = inl(emr); + mask |= (1 << EVENT_BIT(irq)); + outl(mask, emr); } /* Acknowledge a hardware event by writing its bit back to its ESR */ -static void ack_systemasic_irq(unsigned int irq) -{ - __u32 esr = ESR_BASE + (LEVEL(irq) << 2); - disable_systemasic_irq(irq); - outl((1 << EVENT_BIT(irq)), esr); -} - -/* After a IRQ has been ack'd and responded to, it needs to be renabled */ -static void end_systemasic_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_systemasic_irq(irq); -} - -static unsigned int startup_systemasic_irq(unsigned int irq) -{ - enable_systemasic_irq(irq); - - return 0; -} - -static void shutdown_systemasic_irq(unsigned int irq) +static void mask_ack_systemasic_irq(struct irq_data *data) { - disable_systemasic_irq(irq); + unsigned int irq = data->irq; + __u32 esr = ESR_BASE + (LEVEL(irq) << 2); + disable_systemasic_irq(data); + outl((1 << EVENT_BIT(irq)), esr); } -struct hw_interrupt_type systemasic_int = { - .typename = "System ASIC", - .startup = startup_systemasic_irq, - .shutdown = shutdown_systemasic_irq, - .enable = enable_systemasic_irq, - .disable = disable_systemasic_irq, - .ack = ack_systemasic_irq, - .end = end_systemasic_irq, +struct irq_chip systemasic_int = { + .name = "System ASIC", + .irq_mask = disable_systemasic_irq, + .irq_mask_ack = mask_ack_systemasic_irq, + .irq_unmask = enable_systemasic_irq, }; /* @@ -117,37 +105,52 @@ struct hw_interrupt_type systemasic_int = { */ int systemasic_irq_demux(int irq) { - __u32 emr, esr, status, level; - __u32 j, bit; - - switch (irq) { - case 13: - level = 0; - break; - case 11: - level = 1; - break; - case 9: - level = 2; - break; - default: - return irq; - } - emr = EMR_BASE + (level << 4) + (level << 2); - esr = ESR_BASE + (level << 2); - - /* Mask the ESR to filter any spurious, unwanted interrupts */ - status = inl(esr); - status &= inl(emr); - - /* Now scan and find the first set bit as the event to map */ - for (bit = 1, j = 0; j < 32; bit <<= 1, j++) { - if (status & bit) { - irq = HW_EVENT_IRQ_BASE + j + (level << 5); - return irq; - } - } - - /* Not reached */ - return irq; + __u32 emr, esr, status, level; + __u32 j, bit; + + switch (irq) { + case 13: + level = 0; + break; + case 11: + level = 1; + break; + case 9: + level = 2; + break; + default: + return irq; + } + emr = EMR_BASE + (level << 4) + (level << 2); + esr = ESR_BASE + (level << 2); + + /* Mask the ESR to filter any spurious, unwanted interrupts */ + status = inl(esr); + status &= inl(emr); + + /* Now scan and find the first set bit as the event to map */ + for (bit = 1, j = 0; j < 32; bit <<= 1, j++) { + if (status & bit) { + irq = HW_EVENT_IRQ_BASE + j + (level << 5); + return irq; + } + } + + /* Not reached */ + return irq; +} + +void systemasic_irq_init(void) +{ + int irq_base, i; + + irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE, + HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1); + if (IS_ERR_VALUE(irq_base)) { + pr_err("%s: failed hooking irqs\n", __func__); + return; + } + + for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) + irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq); } diff --git a/arch/sh/boards/mach-dreamcast/rtc.c b/arch/sh/boards/mach-dreamcast/rtc.c index a7433685798..061d65714fc 100644 --- a/arch/sh/boards/mach-dreamcast/rtc.c +++ b/arch/sh/boards/mach-dreamcast/rtc.c @@ -35,11 +35,11 @@ static void aica_rtc_gettimeofday(struct timespec *ts) unsigned long val1, val2; do { - val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + val1 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (__raw_readl(AICA_RTC_SECS_L) & 0xffff); - val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + val2 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (__raw_readl(AICA_RTC_SECS_L) & 0xffff); } while (val1 != val2); ts->tv_sec = val1 - TWENTY_YEARS; @@ -60,14 +60,14 @@ static int aica_rtc_settimeofday(const time_t secs) unsigned long adj = secs + TWENTY_YEARS; do { - ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H); - ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L); + __raw_writel((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H); + __raw_writel((adj & 0xffff), AICA_RTC_SECS_L); - val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + val1 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (__raw_readl(AICA_RTC_SECS_L) & 0xffff); - val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + val2 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (__raw_readl(AICA_RTC_SECS_L) & 0xffff); } while (val1 != val2); return 0; diff --git a/arch/sh/boards/mach-dreamcast/setup.c b/arch/sh/boards/mach-dreamcast/setup.c index 7d944fc75e9..ad1a4db72e0 100644 --- a/arch/sh/boards/mach-dreamcast/setup.c +++ b/arch/sh/boards/mach-dreamcast/setup.c @@ -28,37 +28,14 @@ #include <asm/machvec.h> #include <mach/sysasic.h> -extern struct hw_interrupt_type systemasic_int; -extern void aica_time_init(void); -extern int gapspci_init(void); -extern int systemasic_irq_demux(int); - static void __init dreamcast_setup(char **cmdline_p) { - int i; - - /* Mask all hardware events */ - /* XXX */ - - /* Acknowledge any previous events */ - /* XXX */ - - __set_io_port_base(0xa0000000); - - /* Assign all virtual IRQs to the System ASIC int. handler */ - for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) - irq_desc[i].chip = &systemasic_int; - board_time_init = aica_time_init; - -#ifdef CONFIG_PCI - if (gapspci_init() < 0) - printk(KERN_WARNING "GAPSPCI was not detected.\n"); -#endif } static struct sh_machine_vector mv_dreamcast __initmv = { .mv_name = "Sega Dreamcast", .mv_setup = dreamcast_setup, .mv_irq_demux = systemasic_irq_demux, + .mv_init_irq = systemasic_irq_init, }; |
