diff --cc arch/arm/mach-orion5x/include/mach/irqs.h index a6fa9d8,5c29a74..0000000 --- a/arch/arm/mach-orion5x/include/mach/irqs.h +++ b/arch/arm/mach-orion5x/include/mach/irqs.h diff --cc arch/arm/mach-orion5x/irq.c index ed85891,5e25704..0000000 --- a/arch/arm/mach-orion5x/irq.c +++ b/arch/arm/mach-orion5x/irq.c diff --cc arch/arm/mach-orion5x/ts78xx-setup.c index cdccd09,2f2a539..0000000 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@@ -62,6 -64,118 +62,121 @@@ void __init ts78xx_map_io(void } /***************************************************************************** ++<<<<<<< Updated upstream ++======= + * IRQ + ****************************************************************************/ + #define NR_TS78XX_FPGA_IRQS 32 + #define TS78XX_NR_IRQS (IRQ_BOARD_START + NR_TS78XX_FPGA_IRQS) + #define FPGA_IRQ(irq) (IRQ_BOARD_START + irq) + + static void ts78xx_irq_ack(u32 irq) + { + u32 addr; + + addr = readl(H2C_DOORBELL_REG); + addr &= ~(1 << (irq - FPGA_IRQ(0))); + writel(addr, H2C_DOORBELL_REG); + } + + static void ts78xx_irq_mask(u32 irq) + { + void __iomem *fpgaaddr = get_irq_chip_data(irq); + unsigned long reg; + + reg = readl(H2C_DOORBELL_MASK_REG); + reg &= ~(1 << (irq - FPGA_IRQ(0))); + writel(reg, H2C_DOORBELL_MASK_REG); + + reg = readl(fpgaaddr); + reg &= ~(1 << (irq - FPGA_IRQ(0))); + writel(reg, fpgaaddr); + } + + static void ts78xx_irq_unmask(u32 irq) + { + void __iomem *fpgaaddr = get_irq_chip_data(irq); + unsigned long reg; + + reg = readl(H2C_DOORBELL_MASK_REG); + reg |= 1 << (irq - FPGA_IRQ(0)); + writel(reg, H2C_DOORBELL_MASK_REG); + + reg = readl(H2C_DOORBELL_REG); + reg &= ~(1 << (irq - FPGA_IRQ(0))); + writel(reg, H2C_DOORBELL_REG); + + reg = readl(fpgaaddr); + reg |= 1 << (irq - FPGA_IRQ(0)); + writel(reg, fpgaaddr); + } + + static struct irq_chip ts78xx_irq_chip = { + .name = "ts78xx_irq", + .ack = ts78xx_irq_ack, + .mask = ts78xx_irq_mask, + .unmask = ts78xx_irq_unmask, + }; + + static void ts78xx_irq(unsigned int irq, struct irq_desc *desc) + { + unsigned long reg = readl(H2C_DOORBELL_REG); + + for_each_set_bit(irq, ®, 32) + generic_handle_irq(FPGA_IRQ(irq)); + } + + static int ts78xx_doorbell_irq_load(void) + { + void __iomem *fpgaaddr; + unsigned int irq; + + switch (ts78xx_fpga.id) { + case TS7800_REV_1: + case TS7800_REV_2: + case TS7800_REV_3: + case TS7800_REV_4: + case TS7800_REV_5: + case TS7800_REV_6: + case TS7800_REV_7: + case TS7800_REV_8: + case TS7800_REV_9: + fpgaaddr = (void __iomem *)(TS78XX_FPGA_REGS_VIRT_BASE | 0x204); + break; + default: + return -ENODEV; + } + + for (irq = FPGA_IRQ(0); irq < FPGA_IRQ(NR_TS78XX_FPGA_IRQS); irq++) { + struct irq_desc *desc = irq_to_desc(irq); + + set_irq_chip(irq, &ts78xx_irq_chip); + set_irq_chip_data(irq, fpgaaddr); + set_irq_handler(irq, handle_level_irq); + desc->status |= IRQ_LEVEL; + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_ORION5X_DOORBELL_H2C, ts78xx_irq); + + return 0; + } + + static void ts78xx_doorbell_irq_unload(void) + { + unsigned int irq; + + set_irq_chained_handler(IRQ_ORION5X_DOORBELL_H2C, NULL); + + for (irq = FPGA_IRQ(0); irq < FPGA_IRQ(NR_TS78XX_FPGA_IRQS); irq++) { + set_irq_flags(irq, 0); + set_irq_chip(irq, NULL); + set_irq_chip_data(irq, NULL); + } + } + + /***************************************************************************** ++>>>>>>> Stashed changes * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data ts78xx_eth_data = { @@@ -624,7 -740,7 +739,11 @@@ MACHINE_START(TS78XX, "Technologic Syst .boot_params = 0x00000100, .init_machine = ts78xx_init, .map_io = ts78xx_map_io, ++<<<<<<< Updated upstream + .init_early = orion5x_init_early, ++======= + .nr_irqs = TS78XX_NR_IRQS, ++>>>>>>> Stashed changes .init_irq = orion5x_init_irq, .timer = &orion5x_timer, MACHINE_END diff --cc arch/arm/plat-orion/gpio.c index 078894b,e65f649..0000000 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@@ -321,67 -232,51 +321,99 @@@ EXPORT_SYMBOL(orion_gpio_set_blink) * polarity LEVEL mask * ****************************************************************************/ - -static void gpio_irq_ack(u32 irq) +static void gpio_irq_ack(struct irq_data *d) { ++<<<<<<< Updated upstream + struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); + int type; + + type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; ++======= + struct irq_desc *desc = irq_to_desc(irq); + int type = desc->status & IRQ_TYPE_SENSE_MASK; ++>>>>>>> Stashed changes if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - int pin = irq_to_gpio(irq); - writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); + int pin = d->irq - ochip->secondary_irq_base; + + writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip)); } } -static void gpio_irq_mask(u32 irq) +static void gpio_irq_mask(struct irq_data *d) { ++<<<<<<< Updated upstream + struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); + int type; + void __iomem *reg; + int pin; + + type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + reg = GPIO_EDGE_MASK(ochip); + else + reg = GPIO_LEVEL_MASK(ochip); + + pin = d->irq - ochip->secondary_irq_base; + + writel(readl(reg) & ~(1 << pin), reg); ++======= + int pin = irq_to_gpio(irq); + struct irq_desc *desc = irq_to_desc(irq); + int type = desc->status & IRQ_TYPE_SENSE_MASK; + u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? + GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); + u32 u = readl(reg); + u &= ~(1 << (pin & 31)); + writel(u, reg); ++>>>>>>> Stashed changes } -static void gpio_irq_unmask(u32 irq) +static void gpio_irq_unmask(struct irq_data *d) { ++<<<<<<< Updated upstream + struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); + int type; + void __iomem *reg; + int pin; + + type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + reg = GPIO_EDGE_MASK(ochip); + else + reg = GPIO_LEVEL_MASK(ochip); + + pin = d->irq - ochip->secondary_irq_base; + + writel(readl(reg) | (1 << pin), reg); ++======= + int pin = irq_to_gpio(irq); + struct irq_desc *desc = irq_to_desc(irq); + int type = desc->status & IRQ_TYPE_SENSE_MASK; + u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? + GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); + u32 u = readl(reg); + u |= 1 << (pin & 31); + writel(u, reg); ++>>>>>>> Stashed changes } -static int gpio_irq_set_type(u32 irq, u32 type) +static int gpio_irq_set_type(struct irq_data *d, u32 type) { ++<<<<<<< Updated upstream + struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); + int pin; ++======= + int pin = irq_to_gpio(irq); + struct irq_desc *desc = irq_to_desc(irq); ++>>>>>>> Stashed changes u32 u; - u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)); + pin = d->irq - ochip->secondary_irq_base; + + u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); if (!u) { printk(KERN_ERR "orion gpio_irq_set_type failed " - "(irq %d, pin %d).\n", irq, pin); + "(irq %d, pin %d).\n", d->irq, pin); return -EINVAL; } @@@ -430,84 -326,27 +462,90 @@@ struct irq_chip orion_gpio_irq_chip = { .name = "orion_gpio_irq", - .ack = gpio_irq_ack, - .mask = gpio_irq_mask, - .unmask = gpio_irq_unmask, - .set_type = gpio_irq_set_type, + .irq_ack = gpio_irq_ack, + .irq_mask = gpio_irq_mask, + .irq_unmask = gpio_irq_unmask, + .irq_set_type = gpio_irq_set_type, }; +void __init orion_gpio_init(int gpio_base, int ngpio, + u32 base, int mask_offset, int secondary_irq_base) +{ + struct orion_gpio_chip *ochip; + int i; + + if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) + return; + + ochip = orion_gpio_chips + orion_gpio_chip_count; + ochip->chip.label = "orion_gpio"; + ochip->chip.request = orion_gpio_request; + ochip->chip.direction_input = orion_gpio_direction_input; + ochip->chip.get = orion_gpio_get; + ochip->chip.direction_output = orion_gpio_direction_output; + ochip->chip.set = orion_gpio_set; + ochip->chip.to_irq = orion_gpio_to_irq; + ochip->chip.base = gpio_base; + ochip->chip.ngpio = ngpio; + ochip->chip.can_sleep = 0; + spin_lock_init(&ochip->lock); + ochip->base = (void __iomem *)base; + ochip->valid_input = 0; + ochip->valid_output = 0; + ochip->mask_offset = mask_offset; + ochip->secondary_irq_base = secondary_irq_base; + + gpiochip_add(&ochip->chip); + + orion_gpio_chip_count++; + + /* + * Mask and clear GPIO interrupts. + */ + writel(0, GPIO_EDGE_CAUSE(ochip)); + writel(0, GPIO_EDGE_MASK(ochip)); + writel(0, GPIO_LEVEL_MASK(ochip)); + + for (i = 0; i < ngpio; i++) { + unsigned int irq = secondary_irq_base + i; + + set_irq_chip(irq, &orion_gpio_irq_chip); + set_irq_handler(irq, handle_level_irq); + set_irq_chip_data(irq, ochip); + irq_desc[irq].status |= IRQ_LEVEL; + set_irq_flags(irq, IRQF_VALID); + } +} + void orion_gpio_irq_handler(int pinoff) { + struct orion_gpio_chip *ochip; u32 cause; - int pin; + int i; - cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff)); - cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff)); + ochip = orion_gpio_chip_find(pinoff); + if (ochip == NULL) + return; ++<<<<<<< Updated upstream + cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip)); + cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip)); ++======= + for (pin = pinoff; pin < pinoff + 8; pin++) { + int irq = gpio_to_irq(pin); + struct irq_desc *desc = irq_to_desc(irq); ++>>>>>>> Stashed changes - if (!(cause & (1 << (pin & 31)))) + for (i = 0; i < ochip->chip.ngpio; i++) { + int irq; + struct irq_desc *desc; + + irq = ochip->secondary_irq_base + i; + + if (!(cause & (1 << i))) continue; + desc = irq_desc + irq; if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { /* Swap polarity (race with GPIO line) */ u32 polarity;