diff options
Diffstat (limited to 'arch/sh/boards/mach-se/7722')
| -rw-r--r-- | arch/sh/boards/mach-se/7722/irq.c | 134 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7722/setup.c | 78 |
2 files changed, 129 insertions, 83 deletions
diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c index 02d21a3e2a8..f5e2af1bf04 100644 --- a/arch/sh/boards/mach-se/7722/irq.c +++ b/arch/sh/boards/mach-se/7722/irq.c @@ -1,76 +1,122 @@ /* - * linux/arch/sh/boards/se/7722/irq.c + * Hitachi UL SolutionEngine 7722 FPGA IRQ Support. * * Copyright (C) 2007 Nobuhiro Iwamatsu - * - * Hitachi UL SolutionEngine 7722 Support. + * Copyright (C) 2012 Paul Mundt * * 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. */ +#define DRV_NAME "SE7722-FPGA" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#define irq_reg_readl ioread16 +#define irq_reg_writel iowrite16 + #include <linux/init.h> #include <linux/irq.h> #include <linux/interrupt.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <linux/irqdomain.h> +#include <linux/io.h> +#include <linux/err.h> +#include <asm/sizes.h> #include <mach-se/mach/se7722.h> -static void disable_se7722_irq(unsigned int irq) -{ - unsigned int bit = irq - SE7722_FPGA_IRQ_BASE; - ctrl_outw(ctrl_inw(IRQ01_MASK) | 1 << bit, IRQ01_MASK); -} +#define IRQ01_BASE_ADDR 0x11800000 +#define IRQ01_MODE_REG 0 +#define IRQ01_STS_REG 4 +#define IRQ01_MASK_REG 8 + +static void __iomem *se7722_irq_regs; +struct irq_domain *se7722_irq_domain; -static void enable_se7722_irq(unsigned int irq) +static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) { - unsigned int bit = irq - SE7722_FPGA_IRQ_BASE; - ctrl_outw(ctrl_inw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK); -} + struct irq_data *data = irq_get_irq_data(irq); + struct irq_chip *chip = irq_data_get_irq_chip(data); + unsigned long mask; + int bit; -static struct irq_chip se7722_irq_chip __read_mostly = { - .name = "SE7722-FPGA", - .mask = disable_se7722_irq, - .unmask = enable_se7722_irq, - .mask_ack = disable_se7722_irq, -}; + chip->irq_mask_ack(data); -static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) + mask = ioread16(se7722_irq_regs + IRQ01_STS_REG); + + for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR) + generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit)); + + chip->irq_unmask(data); +} + +static void __init se7722_domain_init(void) { - unsigned short intv = ctrl_inw(IRQ01_STS); - struct irq_desc *ext_desc; - unsigned int ext_irq = SE7722_FPGA_IRQ_BASE; + int i; - intv &= (1 << SE7722_FPGA_IRQ_NR) - 1; + se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR, + &irq_domain_simple_ops, NULL); + if (unlikely(!se7722_irq_domain)) { + printk("Failed to get IRQ domain\n"); + return; + } - while (intv) { - if (intv & 1) { - ext_desc = irq_desc + ext_irq; - handle_level_irq(ext_irq, ext_desc); + for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { + int irq = irq_create_mapping(se7722_irq_domain, i); + + if (unlikely(irq == 0)) { + printk("Failed to allocate IRQ %d\n", i); + return; } - intv >>= 1; - ext_irq++; } } +static void __init se7722_gc_init(void) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int irq_base; + + irq_base = irq_linear_revmap(se7722_irq_domain, 0); + + gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs, + handle_level_irq); + if (unlikely(!gc)) + return; + + ct = gc->chip_types; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + + ct->regs.mask = IRQ01_MASK_REG; + + irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); + + irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux); + irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); + + irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux); + irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); +} + /* - * Initialize IRQ setting + * Initialize FPGA IRQs */ void __init init_se7722_IRQ(void) { - int i; - - ctrl_outw(0, IRQ01_MASK); /* disable all irqs */ - ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */ + se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16); + if (unlikely(!se7722_irq_regs)) { + printk("Failed to remap IRQ01 regs\n"); + return; + } - for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) - set_irq_chip_and_handler_name(SE7722_FPGA_IRQ_BASE + i, - &se7722_irq_chip, - handle_level_irq, "level"); + /* + * All FPGA IRQs disabled by default + */ + iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG); - set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux); - set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); + __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ - set_irq_chained_handler(IRQ1_IRQ, se7722_irq_demux); - set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); + se7722_domain_init(); + se7722_gc_init(); } diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index af84904ed86..e04e2bc4698 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c @@ -2,6 +2,7 @@ * linux/arch/sh/boards/se/7722/setup.c * * Copyright (C) 2007 Nobuhiro Iwamatsu + * Copyright (C) 2012 Paul Mundt * * Hitachi UL SolutionEngine 7722 Support. * @@ -14,36 +15,30 @@ #include <linux/platform_device.h> #include <linux/ata_platform.h> #include <linux/input.h> +#include <linux/input/sh_keysc.h> +#include <linux/irqdomain.h> #include <linux/smc91x.h> +#include <linux/sh_intc.h> #include <mach-se/mach/se7722.h> #include <mach-se/mach/mrshpc.h> #include <asm/machvec.h> #include <asm/clock.h> #include <asm/io.h> #include <asm/heartbeat.h> -#include <asm/sh_keysc.h> +#include <cpu/sh7722.h> /* Heartbeat */ -static struct heartbeat_data heartbeat_data = { - .regsize = 16, -}; - -static struct resource heartbeat_resources[] = { - [0] = { - .start = PA_LED, - .end = PA_LED, - .flags = IORESOURCE_MEM, - }, +static struct resource heartbeat_resource = { + .start = PA_LED, + .end = PA_LED, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_16BIT, }; static struct platform_device heartbeat_device = { .name = "heartbeat", .id = -1, - .dev = { - .platform_data = &heartbeat_data, - }, - .num_resources = ARRAY_SIZE(heartbeat_resources), - .resource = heartbeat_resources, + .num_resources = 1, + .resource = &heartbeat_resource, }; /* SMC91x */ @@ -59,8 +54,7 @@ static struct resource smc91x_eth_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = SMC_IRQ, - .end = SMC_IRQ, + /* Filled in later */ .flags = IORESOURCE_IRQ, }, }; @@ -89,8 +83,7 @@ static struct resource cf_ide_resources[] = { .flags = IORESOURCE_IO, }, [2] = { - .start = MRSHPC_IRQ0, - .end = MRSHPC_IRQ0, + /* Filled in later */ .flags = IORESOURCE_IRQ, }, }; @@ -124,7 +117,7 @@ static struct resource sh_keysc_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = 79, + .start = evt2irq(0xbe0), .flags = IORESOURCE_IRQ, }, }; @@ -149,38 +142,46 @@ static struct platform_device *se7722_devices[] __initdata = { static int __init se7722_devices_setup(void) { mrshpc_setup_windows(); + + /* Wire-up dynamic vectors */ + cf_ide_resources[2].start = cf_ide_resources[2].end = + irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0); + + smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = + irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC); + return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); } device_initcall(se7722_devices_setup); static void __init se7722_setup(char **cmdline_p) { - ctrl_outw(0x010D, FPGA_OUT); /* FPGA */ + __raw_writew(0x010D, FPGA_OUT); /* FPGA */ - ctrl_outw(0x0000, PORT_PECR); /* PORT E 1 = IRQ5 ,E 0 = BS */ - ctrl_outw(0x1000, PORT_PJCR); /* PORT J 1 = IRQ1,J 0 =IRQ0 */ + __raw_writew(0x0000, PORT_PECR); /* PORT E 1 = IRQ5 ,E 0 = BS */ + __raw_writew(0x1000, PORT_PJCR); /* PORT J 1 = IRQ1,J 0 =IRQ0 */ /* LCDC I/O */ - ctrl_outw(0x0020, PORT_PSELD); + __raw_writew(0x0020, PORT_PSELD); /* SIOF1*/ - ctrl_outw(0x0003, PORT_PSELB); - ctrl_outw(0xe000, PORT_PSELC); - ctrl_outw(0x0000, PORT_PKCR); + __raw_writew(0x0003, PORT_PSELB); + __raw_writew(0xe000, PORT_PSELC); + __raw_writew(0x0000, PORT_PKCR); /* LCDC */ - ctrl_outw(0x4020, PORT_PHCR); - ctrl_outw(0x0000, PORT_PLCR); - ctrl_outw(0x0000, PORT_PMCR); - ctrl_outw(0x0002, PORT_PRCR); - ctrl_outw(0x0000, PORT_PXCR); /* LCDC,CS6A */ + __raw_writew(0x4020, PORT_PHCR); + __raw_writew(0x0000, PORT_PLCR); + __raw_writew(0x0000, PORT_PMCR); + __raw_writew(0x0002, PORT_PRCR); + __raw_writew(0x0000, PORT_PXCR); /* LCDC,CS6A */ /* KEYSC */ - ctrl_outw(0x0A10, PORT_PSELA); /* BS,SHHID2 */ - ctrl_outw(0x0000, PORT_PYCR); - ctrl_outw(0x0000, PORT_PZCR); - ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA); - ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC); + __raw_writew(0x0A10, PORT_PSELA); /* BS,SHHID2 */ + __raw_writew(0x0000, PORT_PYCR); + __raw_writew(0x0000, PORT_PZCR); + __raw_writew(__raw_readw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA); + __raw_writew(__raw_readw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC); } /* @@ -189,6 +190,5 @@ static void __init se7722_setup(char **cmdline_p) static struct sh_machine_vector mv_se7722 __initmv = { .mv_name = "Solution Engine 7722" , .mv_setup = se7722_setup , - .mv_nr_irqs = SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_NR, .mv_init_irq = init_se7722_IRQ, }; |
