GIT 0f13804ae9d894c1fbd90bde38ae2aa0f01b0edd git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git commit Author: Paul Mundt Date: Fri Oct 6 17:55:25 2006 +0900 sh: Convert IPR-IRQ to IRQ chip. One more initial conversion.. Signed-off-by: Paul Mundt commit 525ccc452c79db41874c5edac3f67618a0997d6f Author: Paul Mundt Date: Fri Oct 6 17:35:48 2006 +0900 sh: Convert INTC2 IRQ handler to irq_chip. More struct irq_chip conversions, this time the INTC2 handlers. Signed-off-by: Paul Mundt commit 580410005daecd8e9f0e1baa9ddadbb7f706e7e2 Author: Jamie Lenehan Date: Fri Oct 6 15:36:15 2006 +0900 sh: Fix pr_debug statements for sh4 Fix a problem uncovered by the recent change to always check the arguments to pr_debug. The sh7751 was using the wrong name for the PCI IO base address. Signed-off-by: Jamie Lenehan Signed-off-by: Paul Mundt commit 257440b00ba42a96522255029aa9406ffb7e2f62 Author: Paul Mundt Date: Fri Oct 6 15:33:00 2006 +0900 sh: Convert r7780rp IRQ handler to IRQ chip. Simple conversion of the R7780RP IRQ handler to struct irq_chip. Signed-off-by: Paul Mundt commit 35f3c5185b1e28e6591aa649db8bf4fa16f1a7f3 Author: Paul Mundt Date: Fri Oct 6 15:31:16 2006 +0900 sh: Updates for IRQ handler changes. Trivial fixes for build breakage introduced by IRQ handler changes. Signed-off-by: Paul Mundt commit a700f3594d63a85af196ac64984f7375d903afad Author: Paul Mundt Date: Wed Oct 4 13:27:32 2006 +0900 sh: Kill off timer_ops get_frequency(). We're not using this anywhere these days, kill it off. Signed-off-by: Paul Mundt commit 458821452642fd5dc2377b73cd1323fd4a9653e7 Author: Paul Mundt Date: Wed Oct 4 13:21:45 2006 +0900 sh: First step at generic timeofday support. At the moment we wrap GENERIC_TIME around our existing timer API. As boards start providing their own clocksources, they're able to select GENERIC_TIME accordingly and optimize out most of the timer API. Once the current timers have been reworked as proper clocksource drivers, the rest of the place holders for the timer API can go away and we can flip on GENERIC_TIME unconditionally. Signed-off-by: Paul Mundt arch/sh/Kconfig | 4 + arch/sh/boards/hp6xx/hp6xx_apm.c | 4 - arch/sh/boards/landisk/landisk_pwb.c | 2 arch/sh/boards/mpc1211/setup.c | 5 - arch/sh/boards/renesas/r7780rp/irq.c | 105 +++++------------------- arch/sh/boards/snapgear/setup.c | 2 arch/sh/cchips/hd6446x/hd64461/setup.c | 2 arch/sh/cchips/hd6446x/hd64465/gpio.c | 2 arch/sh/cchips/hd6446x/hd64465/setup.c | 2 arch/sh/cchips/voyagergx/irq.c | 3 - arch/sh/drivers/dma/dma-g2.c | 2 arch/sh/drivers/dma/dma-pvr2.c | 2 arch/sh/drivers/dma/dma-sh.c | 6 + arch/sh/drivers/pci/pci-sh7751.c | 4 - arch/sh/drivers/pci/pci-st40.c | 2 arch/sh/kernel/cpu/irq/intc2.c | 138 ++++++-------------------------- arch/sh/kernel/cpu/irq/ipr.c | 102 ++++++------------------ arch/sh/kernel/irq.c | 19 +++- arch/sh/kernel/time.c | 9 +- arch/sh/kernel/timers/timer-tmu.c | 63 +-------------- drivers/rtc/rtc-sh.c | 6 + drivers/serial/sh-sci.c | 4 - include/asm-sh/hw_irq.h | 4 + include/asm-sh/irq.h | 14 ++- include/asm-sh/irq_regs.h | 1 include/asm-sh/timer.h | 13 +-- 26 files changed, 141 insertions(+), 379 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index f6a0c44..6a461d4 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -45,6 +45,9 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_IOMAP bool +config GENERIC_TIME + def_bool n + config ARCH_MAY_HAVE_PC_FDC bool @@ -357,6 +360,7 @@ config CPU_HAS_SR_RB endmenu menu "Timer support" +depends on !GENERIC_TIME config SH_TMU bool "TMU timer support" diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c index 75f91aa..2191791 100644 --- a/arch/sh/boards/hp6xx/hp6xx_apm.c +++ b/arch/sh/boards/hp6xx/hp6xx_apm.c @@ -83,7 +83,7 @@ static int hp6x0_apm_get_info(char *buf, return p - buf; } -static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev) { if (!apm_suspended) apm_queue_event(APM_USER_SUSPEND); @@ -96,7 +96,7 @@ static int __init hp6x0_apm_init(void) int ret; ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt, - SA_INTERRUPT, MODNAME, 0); + IRQF_DISABLED, MODNAME, 0); if (unlikely(ret < 0)) { printk(KERN_ERR MODNAME ": IRQ %d request failed\n", HP680_BTN_IRQ); diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c index 0b7bee1..e625249 100644 --- a/arch/sh/boards/landisk/landisk_pwb.c +++ b/arch/sh/boards/landisk/landisk_pwb.c @@ -135,7 +135,7 @@ static int swdrv_write(struct file *filp return count; } -static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sw_interrupt(int irq, void *dev_id) { landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS))); disable_irq(IRQ_BUTTON); diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c index 01c10fa..7c3d1d3 100644 --- a/arch/sh/boards/mpc1211/setup.c +++ b/arch/sh/boards/mpc1211/setup.c @@ -69,7 +69,6 @@ static void __init pci_write_config(unsi static unsigned char m_irq_mask = 0xfb; static unsigned char s_irq_mask = 0xff; -volatile unsigned long irq_err_count; static void disable_mpc1211_irq(unsigned int irq) { @@ -118,7 +117,7 @@ static void mask_and_ack_mpc1211(unsigne if(irq < 8) { if(m_irq_mask & (1< #include #include -#include -#include #ifdef CONFIG_SH_R7780MP static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0}; @@ -20,71 +18,26 @@ #else static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0}; #endif -static void enable_r7780rp_irq(unsigned int irq); -static void disable_r7780rp_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_r7780rp_irq disable_r7780rp_irq - -static void ack_r7780rp_irq(unsigned int irq); -static void end_r7780rp_irq(unsigned int irq); - -static unsigned int startup_r7780rp_irq(unsigned int irq) -{ - enable_r7780rp_irq(irq); - return 0; /* never anything pending */ -} - -static void disable_r7780rp_irq(unsigned int irq) -{ - unsigned short val; - unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]); - - /* Set the priority in IPR to 0 */ - val = ctrl_inw(IRLCNTR1); - val &= mask; - ctrl_outw(val, IRLCNTR1); -} - static void enable_r7780rp_irq(unsigned int irq) { - unsigned short val; - unsigned short value = (0x0001 << mask_pos[irq]); - /* Set priority in IPR back to original value */ - val = ctrl_inw(IRLCNTR1); - val |= value; - ctrl_outw(val, IRLCNTR1); -} - -static void ack_r7780rp_irq(unsigned int irq) -{ - disable_r7780rp_irq(irq); + ctrl_outw(ctrl_inw(IRLCNTR1) | (1 << mask_pos[irq]), IRLCNTR1); } -static void end_r7780rp_irq(unsigned int irq) +static void disable_r7780rp_irq(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_r7780rp_irq(irq); + /* Set the priority in IPR to 0 */ + ctrl_outw(ctrl_inw(IRLCNTR1) & (0xffff ^ (1 << mask_pos[irq])), + IRLCNTR1); } -static struct hw_interrupt_type r7780rp_irq_type = { - .typename = "R7780RP-IRQ", - .startup = startup_r7780rp_irq, - .shutdown = shutdown_r7780rp_irq, - .enable = enable_r7780rp_irq, - .disable = disable_r7780rp_irq, - .ack = ack_r7780rp_irq, - .end = end_r7780rp_irq, +static struct irq_chip r7780rp_irq_chip __read_mostly = { + .name = "r7780rp", + .mask = disable_r7780rp_irq, + .unmask = enable_r7780rp_irq, + .mask_ack = disable_r7780rp_irq, }; -static void make_r7780rp_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].chip = &r7780rp_irq_type; - disable_r7780rp_irq(irq); -} - /* * Initialize IRQ setting */ @@ -92,24 +45,10 @@ void __init init_r7780rp_IRQ(void) { int i; - /* IRL0=PCI Slot #A - * IRL1=PCI Slot #B - * IRL2=PCI Slot #C - * IRL3=PCI Slot #D - * IRL4=CF Card - * IRL5=CF Card Insert - * IRL6=M66596 - * IRL7=SD Card - * IRL8=Touch Panel - * IRL9=SCI - * IRL10=Serial - * IRL11=Extention #A - * IRL11=Extention #B - * IRL12=Debug LAN - * IRL13=Push Switch - * IRL14=ZiggBee IO - */ - - for (i=0; i<15; i++) - make_r7780rp_irq(i); + for (i = 0; i < 15; i++) { + disable_irq_nosync(i); + set_irq_chip_and_handler(i, &r7780rp_irq_chip, + handle_level_irq); + disable_r7780rp_irq(i); + } } diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c index f5e98c5..540d0bf 100644 --- a/arch/sh/boards/snapgear/setup.c +++ b/arch/sh/boards/snapgear/setup.c @@ -33,7 +33,7 @@ extern void pcibios_init(void); * EraseConfig handling functions */ -static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id) { volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000; diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c index 38f1e81..4d49b5c 100644 --- a/arch/sh/cchips/hd6446x/hd64461/setup.c +++ b/arch/sh/cchips/hd6446x/hd64461/setup.c @@ -71,7 +71,7 @@ static struct hw_interrupt_type hd64461_ .end = end_hd64461_irq, }; -static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t hd64461_interrupt(int irq, void *dev_id) { printk(KERN_INFO "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c index 72320d0..4343185 100644 --- a/arch/sh/cchips/hd6446x/hd64465/gpio.c +++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c @@ -85,7 +85,7 @@ static struct { void *dev; } handlers[GPIO_NPORTS * 8]; -static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev) { unsigned short port, pin, isr, mask, portpin; diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c index 30573d3..d126e1f 100644 --- a/arch/sh/cchips/hd6446x/hd64465/setup.c +++ b/arch/sh/cchips/hd6446x/hd64465/setup.c @@ -84,7 +84,7 @@ static struct hw_interrupt_type hd64465_ }; -static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t hd64465_interrupt(int irq, void *dev_id) { printk(KERN_INFO "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c index 392c8b1..bf1b28f 100644 --- a/arch/sh/cchips/voyagergx/irq.c +++ b/arch/sh/cchips/voyagergx/irq.c @@ -88,8 +88,7 @@ static struct hw_interrupt_type voyagerg .end = end_voyagergx_irq, }; -static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t voyagergx_interrupt(int irq, void *dev_id) { printk(KERN_INFO "VoyagerGX: spurious interrupt, status: 0x%x\n", diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 9cb0709..0caf11b 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -51,7 +51,7 @@ #define g2_bytes_remaining(i) \ ((g2_dma->channel[i].size - \ g2_dma->status[i].size) & 0x0fffffff) -static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t g2_dma_interrupt(int irq, void *dev_id) { int i; diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index c1b6bc2..838fad5 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -21,7 +21,7 @@ #include static unsigned int xfer_complete; static int count; -static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id) { if (get_dma_residue(PVR2_CASCADE_CHAN)) { printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index cbbe8bc..d8ece20 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -60,9 +60,9 @@ static inline unsigned int calc_xmit_shi * Besides that it needs to waken any waiting process, which should handle * setting up the next transfer. */ -static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dma_tei(int irq, void *dev_id) { - struct dma_channel *chan = (struct dma_channel *)dev_id; + struct dma_channel *chan = dev_id; u32 chcr; chcr = ctrl_inl(CHCR[chan->chan]); @@ -228,7 +228,7 @@ static inline int dmaor_reset(void) } #if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dma_err(int irq, void *dummy) { dmaor_reset(); disable_irq(irq); diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index dbe8378..85e1ee2 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c @@ -155,7 +155,7 @@ int __init sh7751_pcic_init(struct sh4_p */ pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, (64 << 10), - SH4_PCI_IO_BASE + PCIBIOS_MIN_IO); + SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO); /* * XXX: For now, leave this board-specific. In the event we have other @@ -163,7 +163,7 @@ int __init sh7751_pcic_init(struct sh4_p */ #ifdef CONFIG_SH_BIGSUR bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10), - SH4_PCI_IO_BASE + PCIBIOS_MIN_IO, 0); + SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO, 0); #endif /* Make sure the MSB's of IO window are set to access PCI space diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c index 4ab5ea6..efecb3d 100644 --- a/arch/sh/drivers/pci/pci-st40.c +++ b/arch/sh/drivers/pci/pci-st40.c @@ -161,7 +161,7 @@ static char * pci_commands[16]={ "Memory Write-and-Invalidate" }; -static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) +static irqreturn_t st40_pci_irq(int irq, void *dev_instance) { unsigned pci_int, pci_air, pci_cir, pci_aint; static int count=0; diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index e30e4b7..d4b2bb7 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -10,93 +10,32 @@ * These are the "new Hitachi style" interrupts, as present on the * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ - #include #include #include #include #include -#include - -struct intc2_data { - unsigned char msk_offset; - unsigned char msk_shift; - - int (*clear_irq) (int); -}; - -static struct intc2_data intc2_data[NR_INTC2_IRQS]; - -static void enable_intc2_irq(unsigned int irq); -static void disable_intc2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_intc2_irq disable_intc2_irq - -static void mask_and_ack_intc2(unsigned int); -static void end_intc2_irq(unsigned int irq); - -static unsigned int startup_intc2_irq(unsigned int irq) -{ - enable_intc2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type intc2_irq_type = { - .typename = "INTC2-IRQ", - .startup = startup_intc2_irq, - .shutdown = shutdown_intc2_irq, - .enable = enable_intc2_irq, - .disable = disable_intc2_irq, - .ack = mask_and_ack_intc2, - .end = end_intc2_irq -}; static void disable_intc2_irq(unsigned int irq) { - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - /* Sanity check */ - if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1 << msk_shift, - INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); + struct intc2_data *p = get_irq_chip_data(irq); + ctrl_outl(1 << p->msk_shift, + INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); } static void enable_intc2_irq(unsigned int irq) { - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - /* Sanity check */ - if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1 << msk_shift, - INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); -} - -static void mask_and_ack_intc2(unsigned int irq) -{ - disable_intc2_irq(irq); + struct intc2_data *p = get_irq_chip_data(irq); + ctrl_outl(1 << p->msk_shift, + INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); } -static void end_intc2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_intc2_irq(irq); - - if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); -} +static struct irq_chip intc2_irq_chip = { + .typename = "intc2", + .mask = disable_intc2_irq, + .unmask = enable_intc2_irq, + .mask_ack = disable_intc2_irq, +}; /* * Setup an INTC2 style interrupt. @@ -108,46 +47,30 @@ static void end_intc2_irq(unsigned int i * | | | | * make_intc2_irq(84, 0, 16, 0, 13); */ -void make_intc2_irq(unsigned int irq, - unsigned int ipr_offset, unsigned int ipr_shift, - unsigned int msk_offset, unsigned int msk_shift, - unsigned int priority) +void make_intc2_irq(struct intc2_data *p) { - int irq_offset = irq - INTC2_FIRST_IRQ; unsigned int flags; unsigned long ipr; - if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) - return; - - disable_irq_nosync(irq); - - /* Fill the data we need */ - intc2_data[irq_offset].msk_offset = msk_offset; - intc2_data[irq_offset].msk_shift = msk_shift; - intc2_data[irq_offset].clear_irq = NULL; + disable_irq_nosync(p->irq); /* Set the priority level */ local_irq_save(flags); - ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); - ipr &= ~(0xf << ipr_shift); - ipr |= priority << ipr_shift; - ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); + ipr &= ~(0xf << p->ipr_shift); + ipr |= p->priority << p->ipr_shift; + ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); local_irq_restore(flags); - irq_desc[irq].chip = &intc2_irq_type; + set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); + set_irq_chip_data(p->irq, p); - disable_intc2_irq(irq); + enable_intc2_irq(p->irq); } -static struct intc2_init { - unsigned short irq; - unsigned char ipr_offset, ipr_shift; - unsigned char msk_offset, msk_shift; - unsigned char priority; -} intc2_init_data[] __initdata = { +static struct intc2_data intc2_irq_table[] = { #if defined(CONFIG_CPU_SUBTYPE_ST40) {64, 0, 0, 0, 0, 13}, /* PCI serr */ {65, 0, 4, 0, 1, 13}, /* PCI err */ @@ -266,19 +189,6 @@ void __init init_IRQ_intc2(void) { int i; - for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { - struct intc2_init *p = intc2_init_data + i; - make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, - p-> msk_offset, p->msk_shift, p->priority); - } -} - -/* Adds a termination callback to the interrupt */ -void intc2_add_clear_irq(int irq, int (*fn)(int)) -{ - if (unlikely(irq < INTC2_FIRST_IRQ)) - return; - - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; + for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) + make_intc2_irq(intc2_irq_table + i); } - diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index f785822..8944abd 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -1,11 +1,10 @@ /* - * arch/sh/kernel/cpu/irq/ipr.c + * Interrupt handling for IPR-based IRQ. * * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2003 Takashi Kusuda - * - * Interrupt handling for IPR-based IRQ. + * Copyright (C) 2003 Takashi Kusuda + * Copyright (C) 2006 Paul Mundt * * Supported system: * On-chip supporting modules (TMU, RTC, etc.). @@ -13,12 +12,13 @@ * Hitachi SolutionEngine external I/O: * MS7709SE01, MS7709ASE01, and MS7750SE01 * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ - #include #include #include - #include #include #include @@ -28,93 +28,45 @@ struct ipr_data { int shift; /* Shifts of the 16-bit data */ int priority; /* The priority */ }; -static struct ipr_data ipr_data[NR_IRQS]; - -static void enable_ipr_irq(unsigned int irq); -static void disable_ipr_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_ipr_irq disable_ipr_irq - -static void mask_and_ack_ipr(unsigned int); -static void end_ipr_irq(unsigned int irq); - -static unsigned int startup_ipr_irq(unsigned int irq) -{ - enable_ipr_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type ipr_irq_type = { - .typename = "IPR-IRQ", - .startup = startup_ipr_irq, - .shutdown = shutdown_ipr_irq, - .enable = enable_ipr_irq, - .disable = disable_ipr_irq, - .ack = mask_and_ack_ipr, - .end = end_ipr_irq -}; static void disable_ipr_irq(unsigned int irq) { - unsigned long val; - unsigned int addr = ipr_data[irq].addr; - unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); - + struct ipr_data *p = get_irq_chip_data(irq); /* Set the priority in IPR to 0 */ - val = ctrl_inw(addr); - val &= mask; - ctrl_outw(val, addr); + ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); } static void enable_ipr_irq(unsigned int irq) { - unsigned long val; - unsigned int addr = ipr_data[irq].addr; - int priority = ipr_data[irq].priority; - unsigned short value = (priority << ipr_data[irq].shift); - + struct ipr_data *p = get_irq_chip_data(irq); /* Set priority in IPR back to original value */ - val = ctrl_inw(addr); - val |= value; - ctrl_outw(val, addr); + ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); } -static void mask_and_ack_ipr(unsigned int irq) -{ - disable_ipr_irq(irq); - -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) - /* This is needed when we use edge triggered setting */ - /* XXX: Is it really needed? */ - if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { - /* Clear external interrupt request */ - int a = ctrl_inb(INTC_IRR0); - a &= ~(1 << (irq - IRQ0_IRQ)); - ctrl_outb(a, INTC_IRR0); - } -#endif -} - -static void end_ipr_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_ipr_irq(irq); -} +static struct irq_chip ipr_irq_chip = { + .name = "ipr", + .mask = disable_ipr_irq, + .unmask = enable_ipr_irq, + .mask_ack = disable_ipr_irq, +}; void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) { + struct ipr_data ipr_data; + disable_irq_nosync(irq); - ipr_data[irq].addr = addr; - ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ - ipr_data[irq].priority = priority; - irq_desc[irq].chip = &ipr_irq_type; - disable_ipr_irq(irq); + ipr_data.addr = addr; + ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */ + ipr_data.priority = priority; + + set_irq_chip_and_handler(irq, &ipr_irq_chip, handle_level_irq); + set_irq_chip_data(irq, &ipr_data); + + enable_ipr_irq(irq); } +/* XXX: This needs to die a horrible death.. */ void __init init_IRQ(void) { #ifndef CONFIG_CPU_SUBTYPE_SH7780 diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index c7ebd6a..3b93682 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -17,6 +17,8 @@ #include #include #include +atomic_t irq_err_count; + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves, it doesn't deserve @@ -47,8 +49,10 @@ int show_interrupts(struct seq_file *p, if (!action) goto unlock; seq_printf(p, "%3d: ",i); - seq_printf(p, "%10u ", kstat_irqs(i)); - seq_printf(p, " %14s", irq_desc[i].chip->typename); + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, " %14s", irq_desc[i].chip->name); + seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) @@ -56,7 +60,9 @@ int show_interrupts(struct seq_file *p, seq_putc(p, '\n'); unlock: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } + } else if (i == NR_IRQS) + seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); + return 0; } #endif @@ -78,6 +84,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r6, unsigned long r7, struct pt_regs regs) { + struct pt_regs *old_regs = set_irq_regs(®s); int irq = r4; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; @@ -139,7 +146,6 @@ #ifdef CONFIG_4KSTACKS __asm__ __volatile__ ( "mov %0, r4 \n" - "mov %1, r5 \n" "mov r15, r9 \n" "jsr @%2 \n" /* swith to the irq stack */ @@ -147,17 +153,18 @@ #ifdef CONFIG_4KSTACKS /* restore the stack (ring zero) */ "mov r9, r15 \n" : /* no outputs */ - : "r" (irq), "r" (®s), "r" (__do_IRQ), "r" (isp) + : "r" (irq), "r" (generic_handle_irq), "r" (isp) /* XXX: A somewhat excessive clobber list? -PFM */ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "t", "pr" ); } else #endif - __do_IRQ(irq, ®s); + generic_handle_irq(irq); irq_exit(); + set_irq_regs(old_regs); return 1; } diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 450c68f..57e708d 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -47,6 +47,7 @@ unsigned long long __attribute__ ((weak) return (unsigned long long)jiffies * (1000000000 / HZ); } +#ifndef CONFIG_GENERIC_TIME void do_gettimeofday(struct timeval *tv) { unsigned long seq; @@ -99,6 +100,7 @@ int do_settimeofday(struct timespec *tv) return 0; } EXPORT_SYMBOL(do_settimeofday); +#endif /* !CONFIG_GENERIC_TIME */ /* last time the RTC clock got updated */ static long last_rtc_update; @@ -107,13 +109,14 @@ static long last_rtc_update; * handle_timer_tick() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -void handle_timer_tick(struct pt_regs *regs) +void handle_timer_tick(void) { do_timer(1); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode(get_irq_regs())); #endif - profile_tick(CPU_PROFILING, regs); + if (current->pid) + profile_tick(CPU_PROFILING); #ifdef CONFIG_HEARTBEAT if (sh_mv.mv_heartbeat != NULL) diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 205816f..2492701 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -80,8 +80,7 @@ static unsigned long tmu_timer_get_offse return count; } -static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) { unsigned long timer_status; @@ -98,7 +97,7 @@ static irqreturn_t tmu_timer_interrupt(i * locally disabled. -arca */ write_seqlock(&xtime_lock); - handle_timer_tick(regs); + handle_timer_tick(); write_sequnlock(&xtime_lock); return IRQ_HANDLED; @@ -111,60 +110,6 @@ static struct irqaction tmu_irq = { .mask = CPU_MASK_NONE, }; -/* - * Hah! We'll see if this works (switching from usecs to nsecs). - */ -static unsigned long tmu_timer_get_frequency(void) -{ - u32 freq; - struct timespec ts1, ts2; - unsigned long diff_nsec; - unsigned long factor; - - /* Setup the timer: We don't want to generate interrupts, just - * have it count down at its natural rate. - */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); - ctrl_outl(0xffffffff, TMU0_TCOR); - ctrl_outl(0xffffffff, TMU0_TCNT); - - rtc_sh_get_time(&ts2); - - do { - rtc_sh_get_time(&ts1); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - /* actually start the timer */ - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); - - do { - rtc_sh_get_time(&ts2); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - freq = 0xffffffff - ctrl_inl(TMU0_TCNT); - if (ts2.tv_nsec < ts1.tv_nsec) { - ts2.tv_nsec += 1000000000; - ts2.tv_sec--; - } - - diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); - - /* this should work well if the RTC has a precision of n Hz, where - * n is an integer. I don't think we have to worry about the other - * cases. */ - factor = (1000000000 + diff_nsec/2) / diff_nsec; - - if (factor * diff_nsec > 1100000000 || - factor * diff_nsec < 900000000) - panic("weird RTC (diff_nsec %ld)", diff_nsec); - - return freq * factor; -} - static void tmu_clk_init(struct clk *clk) { u8 divisor = TMU0_TCR_INIT & 0x7; @@ -232,12 +177,12 @@ struct sys_timer_ops tmu_timer_ops = { .init = tmu_timer_init, .start = tmu_timer_start, .stop = tmu_timer_stop, - .get_frequency = tmu_timer_get_frequency, +#ifndef CONFIG_GENERIC_TIME .get_offset = tmu_timer_get_offset, +#endif }; struct sys_timer tmu_timer = { .name = "tmu", .ops = &tmu_timer_ops, }; - diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 8b6efcc..143302a 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -160,7 +160,7 @@ static int sh_rtc_open(struct device *de tmp |= RCR1_CIE; writeb(tmp, rtc->regbase + RCR1); - ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, SA_INTERRUPT, + ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED, "sh-rtc period", dev); if (unlikely(ret)) { dev_err(dev, "request period IRQ failed with %d, IRQ %d\n", @@ -168,7 +168,7 @@ static int sh_rtc_open(struct device *de return ret; } - ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, SA_INTERRUPT, + ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED, "sh-rtc carry", dev); if (unlikely(ret)) { dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n", @@ -177,7 +177,7 @@ static int sh_rtc_open(struct device *de goto err_bad_carry; } - ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT, + ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED, "sh-rtc alarm", dev); if (unlikely(ret)) { dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n", diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 266aa32..cfcc3ca 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -808,7 +808,7 @@ static int sci_request_irq(struct sci_po } if (request_irq(port->irqs[0], sci_mpxed_interrupt, - SA_INTERRUPT, "sci", port)) { + IRQF_DISABLED, "sci", port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); return -ENODEV; } @@ -817,7 +817,7 @@ static int sci_request_irq(struct sci_po if (!port->irqs[i]) continue; if (request_irq(port->irqs[i], handlers[i], - SA_INTERRUPT, desc[i], port)) { + IRQF_DISABLED, desc[i], port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); return -ENODEV; } diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h index fed2661..80ee1cd 100644 --- a/include/asm-sh/hw_irq.h +++ b/include/asm-sh/hw_irq.h @@ -1,4 +1,8 @@ #ifndef __ASM_SH_HW_IRQ_H #define __ASM_SH_HW_IRQ_H +#include + +extern atomic_t irq_err_count; + #endif /* __ASM_SH_HW_IRQ_H */ diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 0e5f365..28996f9 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -697,13 +697,15 @@ #endif #define INTC2_INTPRI_OFFSET 0x00 -void make_intc2_irq(unsigned int irq, - unsigned int ipr_offset, unsigned int ipr_shift, - unsigned int msk_offset, unsigned int msk_shift, - unsigned int priority); +struct intc2_data { + unsigned short irq; + unsigned char ipr_offset, ipr_shift; + unsigned char msk_offset, msk_shift; + unsigned char priority; +}; + +void make_intc2_irq(struct intc2_data *); void init_IRQ_intc2(void); -void intc2_add_clear_irq(int irq, int (*fn)(int)); - #endif extern int shmse_irq_demux(int irq); diff --git a/include/asm-sh/irq_regs.h b/include/asm-sh/irq_regs.h new file mode 100644 index 0000000..3dd9c0b --- /dev/null +++ b/include/asm-sh/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h index c7ab280..5df842b 100644 --- a/include/asm-sh/timer.h +++ b/include/asm-sh/timer.h @@ -8,8 +8,9 @@ struct sys_timer_ops { int (*init)(void); int (*start)(void); int (*stop)(void); +#ifndef CONFIG_GENERIC_TIME unsigned long (*get_offset)(void); - unsigned long (*get_frequency)(void); +#endif }; struct sys_timer { @@ -24,21 +25,17 @@ #define TICK_SIZE (tick_nsec / 1000) extern struct sys_timer tmu_timer; extern struct sys_timer *sys_timer; +#ifndef CONFIG_GENERIC_TIME static inline unsigned long get_timer_offset(void) { return sys_timer->ops->get_offset(); } - -static inline unsigned long get_timer_frequency(void) -{ - return sys_timer->ops->get_frequency(); -} +#endif /* arch/sh/kernel/timers/timer.c */ struct sys_timer *get_sys_timer(void); /* arch/sh/kernel/time.c */ -void handle_timer_tick(struct pt_regs *); +void handle_timer_tick(void); #endif /* __ASM_SH_TIMER_H */ -