diff options
29 files changed, 117 insertions, 42 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ff9177c8f643..5629e2099130 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -101,10 +101,6 @@ config GENERIC_LOCKBREAK def_bool y depends on SMP && PREEMPT -config SYS_SUPPORTS_PM - bool - depends on !SMP - config ARCH_SUSPEND_POSSIBLE def_bool n @@ -649,7 +645,7 @@ config CRASH_DUMP a specially reserved region and then later executed after a crash by kdump/kexec. The crash dump kernel must be compiled to a memory address not used by the main kernel using - MEMORY_START. + PHYSICAL_START. For more details see Documentation/kdump/kdump.txt @@ -660,6 +656,17 @@ config KEXEC_JUMP Jump between original kernel and kexeced kernel and invoke code via KEXEC +config PHYSICAL_START + hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP) + default MEMORY_START + ---help--- + This gives the physical address where the kernel is loaded + and is ordinarily the same as MEMORY_START. + + Different values are primarily used in the case of kexec on panic + where the fail safe kernel needs to run at a different address + than the panic-ed kernel. + config SECCOMP bool "Enable seccomp to safely compute untrusted bytecode" depends on PROC_FS diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 99385d0b3f3b..3fc0f413777c 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -80,6 +80,7 @@ defaultimage-$(CONFIG_SH_RSK) := uImage defaultimage-$(CONFIG_SH_URQUELL) := uImage defaultimage-$(CONFIG_SH_MIGOR) := uImage defaultimage-$(CONFIG_SH_AP325RXA) := uImage +defaultimage-$(CONFIG_SH_SH7757LCR) := uImage defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE) := uImage defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c index 9da92ac36533..b3ae9d38cbc0 100644 --- a/arch/sh/boards/board-espt.c +++ b/arch/sh/boards/board-espt.c @@ -13,9 +13,9 @@ #include <linux/interrupt.h> #include <linux/mtd/physmap.h> #include <linux/io.h> +#include <linux/sh_eth.h> #include <asm/machvec.h> #include <asm/sizes.h> -#include <asm/sh_eth.h> /* NOR Flash */ static struct mtd_partition espt_nor_flash_partitions[] = { diff --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c index f968f17891a4..03820c3c93d4 100644 --- a/arch/sh/boards/board-secureedge5410.c +++ b/arch/sh/boards/board-secureedge5410.c @@ -41,8 +41,7 @@ static int __init eraseconfig_init(void) printk("SnapGear: EraseConfig init\n"); /* Setup "EraseConfig" switch on external IRQ 0 */ - if (request_irq(irq, eraseconfig_interrupt, IRQF_DISABLED, - "Erase Config", NULL)) + if (request_irq(irq, eraseconfig_interrupt, 0, "Erase Config", NULL)) printk("SnapGear: failed to register IRQ%d for Reset witch\n", irq); else diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index fa2a208ec6cb..ec8c84c14b17 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -18,8 +18,8 @@ #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mobile_sdhi.h> +#include <linux/sh_eth.h> #include <cpu/sh7757.h> -#include <asm/sh_eth.h> #include <asm/heartbeat.h> static struct resource heartbeat_resource = { diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c index 311bcebdbd07..724e8b7271f4 100644 --- a/arch/sh/boards/mach-cayman/irq.c +++ b/arch/sh/boards/mach-cayman/irq.c @@ -46,13 +46,11 @@ static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id) static struct irqaction cayman_action_smsc = { .name = "Cayman SMSC Mux", .handler = cayman_interrupt_smsc, - .flags = IRQF_DISABLED, }; static struct irqaction cayman_action_pci2 = { .name = "Cayman PCI2 Mux", .handler = cayman_interrupt_pci2, - .flags = IRQF_DISABLED, }; static void enable_cayman_irq(struct irq_data *data) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index b24d69d509e7..92ddce4b3456 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -28,13 +28,13 @@ #include <linux/spi/mmc_spi.h> #include <linux/input.h> #include <linux/input/sh_keysc.h> +#include <linux/sh_eth.h> #include <video/sh_mobile_lcdc.h> #include <sound/sh_fsi.h> #include <media/sh_mobile_ceu.h> #include <media/tw9910.h> #include <media/mt9t112.h> #include <asm/heartbeat.h> -#include <asm/sh_eth.h> #include <asm/clock.h> #include <asm/suspend.h> #include <cpu/sh7724.h> @@ -248,6 +248,10 @@ static struct renesas_usbhs_platform_info usbhs_info = { .driver_param = { .buswait_bwait = 4, .detection_delay = 5, + .d0_tx_id = SHDMA_SLAVE_USB1D0_TX, + .d0_rx_id = SHDMA_SLAVE_USB1D0_RX, + .d1_tx_id = SHDMA_SLAVE_USB1D1_TX, + .d1_rx_id = SHDMA_SLAVE_USB1D1_RX, }, }; diff --git a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c index b49535c0ddd9..865d8d6e823f 100644 --- a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c +++ b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c @@ -86,7 +86,7 @@ static int __init hp6x0_apm_init(void) int ret; ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt, - IRQF_DISABLED, MODNAME, NULL); + 0, MODNAME, NULL); if (unlikely(ret < 0)) { printk(KERN_ERR MODNAME ": IRQ %d request failed\n", HP680_BTN_IRQ); diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index d00756728bd2..b747c0ab9264 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -23,12 +23,12 @@ #include <linux/input.h> #include <linux/input/sh_keysc.h> #include <linux/usb/r8a66597.h> +#include <linux/sh_eth.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> #include <sound/sh_fsi.h> #include <asm/io.h> #include <asm/heartbeat.h> -#include <asm/sh_eth.h> #include <asm/clock.h> #include <asm/suspend.h> #include <cpu/sh7724.h> diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c index f3d828f133e5..dd036f1661db 100644 --- a/arch/sh/boards/mach-sh7763rdp/setup.c +++ b/arch/sh/boards/mach-sh7763rdp/setup.c @@ -17,8 +17,8 @@ #include <linux/mtd/physmap.h> #include <linux/fb.h> #include <linux/io.h> +#include <linux/sh_eth.h> #include <mach/sh7763rdp.h> -#include <asm/sh_eth.h> #include <asm/sh7760fb.h> /* NOR Flash */ diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index ba515d800245..e4ea31a62c55 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -19,6 +19,7 @@ CONFIG_MEMORY_START ?= 0x0c000000 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000 CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000 CONFIG_ENTRY_OFFSET ?= 0x00001000 +CONFIG_PHYSICAL_START ?= $(CONFIG_MEMORY_START) suffix-y := bin suffix-$(CONFIG_KERNEL_GZIP) := gz @@ -48,7 +49,7 @@ $(obj)/romimage/vmlinux: $(obj)/zImage FORCE $(Q)$(MAKE) $(build)=$(obj)/romimage $@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \ - $$[$(CONFIG_MEMORY_START) & 0x1fffffff]') + $$[$(CONFIG_PHYSICAL_START) & 0x1fffffff]') KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_PAGE_OFFSET) + \ @@ -114,4 +115,5 @@ $(obj)/uImage: $(obj)/uImage.$(suffix-y) @echo ' Image $@ is ready' export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \ - CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y + CONFIG_PHYSICAL_START CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET \ + KERNEL_MEMORY suffix-y diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index af7bb589c2c8..be9ca7ca0ce4 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -170,7 +170,7 @@ static int __init g2_dma_init(void) { int ret; - ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED, + ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, 0, "g2 DMA handler", &g2_dma_info); if (unlikely(ret)) return -EINVAL; diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index 3cee58e7f1e5..706a3434af7a 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -70,7 +70,6 @@ static int pvr2_xfer_dma(struct dma_channel *chan) static struct irqaction pvr2_dma_irq = { .name = "pvr2 DMA handler", .handler = pvr2_dma_interrupt, - .flags = IRQF_DISABLED, }; static struct dma_ops pvr2_dma_ops = { diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 827208781ed5..a60da6dd4d17 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -95,7 +95,7 @@ static int sh_dmac_request_dma(struct dma_channel *chan) #if defined(CONFIG_SH_DMA_IRQ_MULTI) IRQF_SHARED, #else - IRQF_DISABLED, + 0, #endif chan->dev_id, chan); } @@ -305,7 +305,7 @@ static int __init sh_dmac_init(void) #if defined(CONFIG_SH_DMA_IRQ_MULTI) IRQF_SHARED, #else - IRQF_DISABLED, + 0, #endif dmae_name[n], (void *)dmae_name[n]); if (unlikely(i < 0)) { diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c index 6ab9c4a15439..3d66a32ce610 100644 --- a/arch/sh/drivers/dma/dmabrg.c +++ b/arch/sh/drivers/dma/dmabrg.c @@ -174,17 +174,17 @@ static int __init dmabrg_init(void) or = __raw_readl(DMAOR); __raw_writel(or | DMAOR_BRG | DMAOR_DMEN, DMAOR); - ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED, + ret = request_irq(DMABRGI0, dmabrg_irq, 0, "DMABRG USB address error", NULL); if (ret) goto out0; - ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED, + ret = request_irq(DMABRGI1, dmabrg_irq, 0, "DMABRG Transfer End", NULL); if (ret) goto out1; - ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED, + ret = request_irq(DMABRGI2, dmabrg_irq, 0, "DMABRG Transfer Half", NULL); if (ret == 0) return ret; diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c index 0bf296c78795..16c1e721bf54 100644 --- a/arch/sh/drivers/pci/pci-sh5.c +++ b/arch/sh/drivers/pci/pci-sh5.c @@ -107,13 +107,13 @@ static int __init sh5pci_init(void) u32 uval; if (request_irq(IRQ_ERR, pcish5_err_irq, - IRQF_DISABLED, "PCI Error",NULL) < 0) { + 0, "PCI Error",NULL) < 0) { printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n"); return -EINVAL; } if (request_irq(IRQ_SERR, pcish5_serr_irq, - IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) { + 0, "PCI SERR interrupt", NULL) < 0) { printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n"); return -EINVAL; } diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index edb7cca14882..fa7b978cc727 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -172,7 +172,7 @@ static int __init sh7780_pci_setup_irqs(struct pci_channel *hose) PCI_STATUS_SIG_TARGET_ABORT | \ PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS); - ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED, + ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0, "PCI SERR interrupt", hose); if (unlikely(ret)) { printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n"); diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c index afc24556572b..637b79b09657 100644 --- a/arch/sh/drivers/push-switch.c +++ b/arch/sh/drivers/push-switch.c @@ -63,7 +63,7 @@ static int switch_drv_probe(struct platform_device *pdev) BUG_ON(!psw_info); ret = request_irq(irq, psw_info->irq_handler, - IRQF_DISABLED | psw_info->irq_flags, + psw_info->irq_flags, psw_info->name ? psw_info->name : DRV_NAME, pdev); if (unlikely(ret < 0)) goto err; diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 822d6084195b..0dca9a5c6be6 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -113,6 +113,16 @@ typedef struct page *pgtable_t; #define __MEMORY_SIZE CONFIG_MEMORY_SIZE /* + * PHYSICAL_OFFSET is the offset in physical memory where the base + * of the kernel is loaded. + */ +#ifdef CONFIG_PHYSICAL_START +#define PHYSICAL_OFFSET (CONFIG_PHYSICAL_START - __MEMORY_START) +#else +#define PHYSICAL_OFFSET 0 +#endif + +/* * PAGE_OFFSET is the virtual address of the start of kernel address * space. */ diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index 3b097b09a3ba..19222dae8233 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -113,7 +113,14 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]), - CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic3", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic4", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic5", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic6", &mstp_clks[MSTP000]), + CLKDEV_CON_ID("riic7", &mstp_clks[MSTP000]), CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]), CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]), @@ -121,6 +128,7 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]), CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]), + CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]), CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]), }; diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index de865cac02ee..03f2b55757cf 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -79,7 +79,7 @@ static void shx3_prepare_cpus(unsigned int max_cpus) for (i = 0; i < SMP_MSG_NR; i++) request_irq(104 + i, ipi_interrupt_handler, - IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); + IRQF_PERCPU, "IPI", (void *)(long)i); for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 58bff45d1156..1a0e946679a4 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -211,13 +211,16 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, } /* - * We don't know which RAM region contains kernel data, - * so we try it repeatedly and let the resource manager - * test it. + * We don't know which RAM region contains kernel data or + * the reserved crashkernel region, so try it repeatedly + * and let the resource manager test it. */ request_resource(res, &code_resource); request_resource(res, &data_resource); request_resource(res, &bss_resource); +#ifdef CONFIG_KEXEC + request_resource(res, &crashk_res); +#endif /* * Also make sure that there is a PMB mapping that covers this diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c index 38e862852dd0..ecc2d3d0f54a 100644 --- a/arch/sh/kernel/topology.c +++ b/arch/sh/kernel/topology.c @@ -11,6 +11,7 @@ #include <linux/cpumask.h> #include <linux/init.h> #include <linux/percpu.h> +#include <linux/topology.h> #include <linux/node.h> #include <linux/nodemask.h> diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 731c10ce67b5..c98905f71e28 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -23,7 +23,7 @@ OUTPUT_ARCH(sh) ENTRY(_start) SECTIONS { - . = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET; + . = PAGE_OFFSET + MEMORY_OFFSET + PHYSICAL_OFFSET + CONFIG_ZERO_PAGE_OFFSET; _text = .; /* Text and read-only data */ diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 58a93fb3d965..c9dbace35b16 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -287,6 +287,8 @@ static void __init do_init_bootmem(void) static void __init early_reserve_mem(void) { unsigned long start_pfn; + u32 zero_base = (u32)__MEMORY_START + (u32)PHYSICAL_OFFSET; + u32 start = zero_base + (u32)CONFIG_ZERO_PAGE_OFFSET; /* * Partially used pages are not usable - thus @@ -300,15 +302,13 @@ static void __init early_reserve_mem(void) * this catches the (definitely buggy) case of us accidentally * initializing the bootmem allocator with an invalid RAM area. */ - memblock_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, - (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - - (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); + memblock_reserve(start, (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - start); /* * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. */ if (CONFIG_ZERO_PAGE_OFFSET != 0) - memblock_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); + memblock_reserve(zero_base, CONFIG_ZERO_PAGE_OFFSET); /* * Handle additional early reservations diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c index 33b2ed451e09..e0ada3773786 100644 --- a/drivers/sh/intc/chip.c +++ b/drivers/sh/intc/chip.c @@ -202,11 +202,16 @@ static int intc_set_type(struct irq_data *data, unsigned int type) if (!value) return -EINVAL; + value &= ~SENSE_VALID_FLAG; + ihp = intc_find_irq(d->sense, d->nr_sense, irq); if (ihp) { + /* PINT has 2-bit sense registers, should fail on EDGE_BOTH */ + if (value >= (1 << _INTC_WIDTH(ihp->handle))) + return -EINVAL; + addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0); - intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, - value & ~SENSE_VALID_FLAG); + intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value); } return 0; diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c index e32304b66cf1..56bf9336b92b 100644 --- a/drivers/sh/intc/userimask.c +++ b/drivers/sh/intc/userimask.c @@ -13,6 +13,7 @@ #include <linux/sysdev.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/stat.h> #include <asm/sizes.h> #include "internals.h" diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c index 75934e3ea34e..e67fe170d8d5 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc.c @@ -217,7 +217,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, if (!r_width) break; - for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) { + for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) { if (config_reg->enum_ids[n] == enum_id) { *crp = config_reg; *indexp = n; @@ -577,6 +577,32 @@ static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) sh_gpio_set_value(chip_to_pinmux(chip), offset, value); } +static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct pinmux_info *gpioc = chip_to_pinmux(chip); + pinmux_enum_t enum_id; + pinmux_enum_t *enum_ids; + int i, k, pos; + + pos = 0; + enum_id = 0; + while (1) { + pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id); + if (pos <= 0 || !enum_id) + break; + + for (i = 0; i < gpioc->gpio_irq_size; i++) { + enum_ids = gpioc->gpio_irq[i].enum_ids; + for (k = 0; enum_ids[k]; k++) { + if (enum_ids[k] == enum_id) + return gpioc->gpio_irq[i].irq; + } + } + } + + return -ENOSYS; +} + int register_pinmux(struct pinmux_info *pip) { struct gpio_chip *chip = &pip->chip; @@ -592,6 +618,7 @@ int register_pinmux(struct pinmux_info *pip) chip->get = sh_gpio_get; chip->direction_output = sh_gpio_direction_output; chip->set = sh_gpio_set; + chip->to_irq = sh_gpio_to_irq; WARN_ON(pip->first_gpio != 0); /* needs testing */ diff --git a/include/linux/sh_pfc.h b/include/linux/sh_pfc.h index 30cae70874f4..bc8c9208f7e2 100644 --- a/include/linux/sh_pfc.h +++ b/include/linux/sh_pfc.h @@ -61,6 +61,14 @@ struct pinmux_data_reg { .reg = r, .reg_width = r_width, \ .enum_ids = (pinmux_enum_t [r_width]) \ +struct pinmux_irq { + int irq; + pinmux_enum_t *enum_ids; +}; + +#define PINMUX_IRQ(irq_nr, ids...) \ + { .irq = irq_nr, .enum_ids = (pinmux_enum_t []) { ids, 0 } } \ + struct pinmux_range { pinmux_enum_t begin; pinmux_enum_t end; @@ -87,7 +95,9 @@ struct pinmux_info { pinmux_enum_t *gpio_data; unsigned int gpio_data_size; - unsigned long *gpio_in_use; + struct pinmux_irq *gpio_irq; + unsigned int gpio_irq_size; + struct gpio_chip chip; }; |