diff options
33 files changed, 618 insertions, 302 deletions
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c index 99513642a0e6..ab81fb271760 100644 --- a/arch/x86/platform/olpc/olpc-xo1.c +++ b/arch/x86/platform/olpc/olpc-xo1.c @@ -72,9 +72,9 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't fetch device resource info\n"); return -EIO; } - if (strcmp(pdev->name, "olpc-xo1-pms") == 0) + if (strcmp(pdev->name, "cs5535-pms") == 0) pms_base = res->start; - else if (strcmp(pdev->name, "olpc-xo1-ac-acpi") == 0) + else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0) acpi_base = res->start; /* If we have both addresses, we can override the poweroff hook */ @@ -90,9 +90,9 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev) { mfd_cell_disable(pdev); - if (strcmp(pdev->name, "olpc-xo1-pms") == 0) + if (strcmp(pdev->name, "cs5535-pms") == 0) pms_base = 0; - else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0) + else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0) acpi_base = 0; pm_power_off = NULL; @@ -101,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev) static struct platform_driver cs5535_pms_drv = { .driver = { - .name = "olpc-xo1-pms", + .name = "cs5535-pms", .owner = THIS_MODULE, }, .probe = olpc_xo1_probe, @@ -110,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = { static struct platform_driver cs5535_acpi_drv = { .driver = { - .name = "olpc-xo1-acpi", + .name = "olpc-xo1-pm-acpi", .owner = THIS_MODULE, }, .probe = olpc_xo1_probe, @@ -121,22 +121,21 @@ static int __init olpc_xo1_init(void) { int r; - r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms"); + r = platform_driver_register(&cs5535_pms_drv); if (r) return r; - r = mfd_shared_platform_driver_register(&cs5535_acpi_drv, - "cs5535-acpi"); + r = platform_driver_register(&cs5535_acpi_drv); if (r) - mfd_shared_platform_driver_unregister(&cs5535_pms_drv); + platform_driver_unregister(&cs5535_pms_drv); return r; } static void __exit olpc_xo1_exit(void) { - mfd_shared_platform_driver_unregister(&cs5535_acpi_drv); - mfd_shared_platform_driver_unregister(&cs5535_pms_drv); + platform_driver_unregister(&cs5535_acpi_drv); + platform_driver_unregister(&cs5535_pms_drv); } MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 9c511c1604a5..011cb6ce861b 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -416,7 +416,6 @@ static int __devinit device_irq_init(struct pm860x_chip *chip, : chip->companion; unsigned char status_buf[INT_STATUS_NUM]; unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - struct irq_desc *desc; int i, data, mask, ret = -EINVAL; int __irq; @@ -468,19 +467,17 @@ static int __devinit device_irq_init(struct pm860x_chip *chip, if (!chip->core_irq) goto out; - desc = irq_to_desc(chip->core_irq); - /* register IRQ by genirq */ for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { __irq = i + chip->irq_base; - set_irq_chip_data(__irq, chip); - set_irq_chip_and_handler(__irq, &pm860x_irq_chip, + irq_set_chip_data(__irq, chip); + irq_set_chip_and_handler(__irq, &pm860x_irq_chip, handle_edge_irq); - set_irq_nested_thread(__irq, 1); + irq_set_nested_thread(__irq, 1); #ifdef CONFIG_ARM set_irq_flags(__irq, IRQF_VALID); #else - set_irq_noprobe(__irq); + irq_set_noprobe(__irq); #endif } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a9a1af49281e..e986f91fff9c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -133,6 +133,7 @@ config TPS6105X tristate "TPS61050/61052 Boost Converters" depends on I2C select REGULATOR + select MFD_CORE select REGULATOR_FIXED_VOLTAGE help This option enables a driver for the TP61050/TPS61052 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 47f5709f3828..ef489f253402 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -63,7 +63,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o obj-$(CONFIG_PMIC_DA903X) += da903x.o max8925-objs := max8925-core.o max8925-i2c.o obj-$(CONFIG_MFD_MAX8925) += max8925.o -obj-$(CONFIG_MFD_MAX8997) += max8997.o +obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o pcf50633-objs := pcf50633-core.o pcf50633-irq.o diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index c12d04285226..ff86acf3e6bd 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c @@ -668,7 +668,7 @@ static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) struct ab3550_platform_data *plf_data; bool val; - ab = get_irq_chip_data(irq); + ab = irq_get_chip_data(irq); plf_data = ab->i2c_client[0]->dev.platform_data; irq -= plf_data->irq.base; val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0); @@ -1296,14 +1296,14 @@ static int __init ab3550_probe(struct i2c_client *client, unsigned int irq; irq = ab3550_plf_data->irq.base + i; - set_irq_chip_data(irq, ab); - set_irq_chip_and_handler(irq, &ab3550_irq_chip, - handle_simple_irq); - set_irq_nested_thread(irq, 1); + irq_set_chip_data(irq, ab); + irq_set_chip_and_handler(irq, &ab3550_irq_chip, + handle_simple_irq); + irq_set_nested_thread(irq, 1); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else - set_irq_noprobe(irq); + irq_set_noprobe(irq); #endif } diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 6e185b272d00..62e33e2258d4 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -334,14 +334,14 @@ static int ab8500_irq_init(struct ab8500 *ab8500) int irq; for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { - set_irq_chip_data(irq, ab8500); - set_irq_chip_and_handler(irq, &ab8500_irq_chip, + irq_set_chip_data(irq, ab8500); + irq_set_chip_and_handler(irq, &ab8500_irq_chip, handle_simple_irq); - set_irq_nested_thread(irq, 1); + irq_set_nested_thread(irq, 1); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else - set_irq_noprobe(irq); + irq_set_noprobe(irq); #endif } @@ -357,8 +357,8 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) #ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif - set_irq_chip_and_handler(irq, NULL, NULL); - set_irq_chip_data(irq, NULL); + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); } } diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 0241f08fc00d..d4a851c6b5bf 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -139,13 +139,12 @@ static void asic3_irq_flip_edge(struct asic3 *asic, static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) { + struct asic3 *asic = irq_desc_get_handler_data(desc); + struct irq_data *data = irq_desc_get_irq_data(desc); int iter, i; unsigned long flags; - struct asic3 *asic; - - desc->irq_data.chip->irq_ack(&desc->irq_data); - asic = get_irq_data(irq); + data->chip->irq_ack(irq_data); for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) { u32 status; @@ -188,8 +187,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) irqnr = asic->irq_base + (ASIC3_GPIOS_PER_BANK * bank) + i; - desc = irq_to_desc(irqnr); - desc->handle_irq(irqnr, desc); + generic_handle_irq(irqnr); if (asic->irq_bothedge[bank] & bit) asic3_irq_flip_edge(asic, base, bit); @@ -200,11 +198,8 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) /* Handle remaining IRQs in the status register */ for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { /* They start at bit 4 and go up */ - if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { - desc = irq_to_desc(asic->irq_base + i); - desc->handle_irq(asic->irq_base + i, - desc); - } + if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) + generic_handle_irq(asic->irq_base + i); } } @@ -393,21 +388,21 @@ static int __init asic3_irq_probe(struct platform_device *pdev) for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) { if (irq < asic->irq_base + ASIC3_NUM_GPIOS) - set_irq_chip(irq, &asic3_gpio_irq_chip); + irq_set_chip(irq, &asic3_gpio_irq_chip); else - set_irq_chip(irq, &asic3_irq_chip); + irq_set_chip(irq, &asic3_irq_chip); - set_irq_chip_data(irq, asic); - set_irq_handler(irq, handle_level_irq); + irq_set_chip_data(irq, asic); + irq_set_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK), ASIC3_INTMASK_GINTMASK); - set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); - set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING); - set_irq_data(asic->irq_nr, asic); + irq_set_chained_handler(asic->irq_nr, asic3_irq_demux); + irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING); + irq_set_handler_data(asic->irq_nr, asic); return 0; } @@ -421,11 +416,10 @@ static void asic3_irq_remove(struct platform_device *pdev) for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) { set_irq_flags(irq, 0); - set_irq_handler(irq, NULL); - set_irq_chip(irq, NULL); - set_irq_chip_data(irq, NULL); + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); } - set_irq_chained_handler(asic->irq_nr, NULL); + irq_set_chained_handler(asic->irq_nr, NULL); } /* GPIOs */ diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 886a06871065..155fa0407882 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -27,6 +27,7 @@ #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/pci.h> +#include <asm/olpc.h> #define DRV_NAME "cs5535-mfd" @@ -111,6 +112,20 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { }, }; +#ifdef CONFIG_OLPC +static void __devinit cs5535_clone_olpc_cells(void) +{ + const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" }; + + if (!machine_is_olpc()) + return; + + mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones)); +} +#else +static void cs5535_clone_olpc_cells(void) { } +#endif + static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -139,6 +154,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); goto err_disable; } + cs5535_clone_olpc_cells(); dev_info(&pdev->dev, "%zu devices registered.\n", ARRAY_SIZE(cs5535_mfd_cells)); diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 9e2d8dd5f9e5..f2f4029e21a0 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -162,6 +162,7 @@ static void pcap_unmask_irq(struct irq_data *d) static struct irq_chip pcap_irq_chip = { .name = "pcap", + .irq_disable = pcap_mask_irq, .irq_mask = pcap_mask_irq, .irq_unmask = pcap_unmask_irq, }; @@ -196,17 +197,8 @@ static void pcap_isr_work(struct work_struct *work) local_irq_disable(); service = isr & ~msr; for (irq = pcap->irq_base; service; service >>= 1, irq++) { - if (service & 1) { - struct irq_desc *desc = irq_to_desc(irq); - - if (WARN(!desc, "Invalid PCAP IRQ %d\n", irq)) - break; - - if (desc->status & IRQ_DISABLED) - note_interrupt(irq, desc, IRQ_NONE); - else - desc->handle_irq(irq, desc); - } + if (service & 1) + generic_handle_irq(irq); } local_irq_enable(); ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); @@ -215,7 +207,7 @@ static void pcap_isr_work(struct work_struct *work) static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) { - struct pcap_chip *pcap = get_irq_data(irq); + struct pcap_chip *pcap = irq_get_handler_data(irq); desc->irq_data.chip->irq_ack(&desc->irq_data); queue_work(pcap->workqueue, &pcap->isr_work); @@ -419,7 +411,7 @@ static int __devexit ezx_pcap_remove(struct spi_device *spi) /* cleanup irqchip */ for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) - set_irq_chip_and_handler(i, NULL, NULL); + irq_set_chip_and_handler(i, NULL, NULL); destroy_workqueue(pcap->workqueue); @@ -476,12 +468,12 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi) /* setup irq chip */ for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) { - set_irq_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq); - set_irq_chip_data(i, pcap); + irq_set_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq); + irq_set_chip_data(i, pcap); #ifdef CONFIG_ARM set_irq_flags(i, IRQF_VALID); #else - set_irq_noprobe(i); + irq_set_noprobe(i); #endif } @@ -490,10 +482,10 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi) ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER); pcap->msr = PCAP_MASK_ALL_INTERRUPT; - set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING); - set_irq_data(spi->irq, pcap); - set_irq_chained_handler(spi->irq, pcap_irq_handler); - set_irq_wake(spi->irq, 1); + irq_set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING); + irq_set_handler_data(spi->irq, pcap); + irq_set_chained_handler(spi->irq, pcap_irq_handler); + irq_set_irq_wake(spi->irq, 1); /* ADC */ adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ? @@ -522,7 +514,7 @@ remove_subdevs: free_irq(adc_irq, pcap); free_irqchip: for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) - set_irq_chip_and_handler(i, NULL, NULL); + irq_set_chip_and_handler(i, NULL, NULL); /* destroy_workqueue: */ destroy_workqueue(pcap->workqueue); free_pcap: diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index d00b6d1a69e5..bbaec0ccba8f 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -100,7 +100,7 @@ static struct irq_chip egpio_muxed_chip = { static void egpio_handler(unsigned int irq, struct irq_desc *desc) { - struct egpio_info *ei = get_irq_data(irq); + struct egpio_info *ei = irq_desc_get_handler_data(desc); int irqpin; /* Read current pins. */ @@ -113,9 +113,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc) for_each_set_bit(irqpin, &readval, ei->nirqs) { /* Run irq handler */ pr_debug("got IRQ %d\n", irqpin); - irq = ei->irq_start + irqpin; - desc = irq_to_desc(irq); - desc->handle_irq(irq, desc); + generic_handle_irq(ei->irq_start + irqpin); } } @@ -346,14 +344,14 @@ static int __init egpio_probe(struct platform_device *pdev) ei->ack_write = 0; irq_end = ei->irq_start + ei->nirqs; for (irq = ei->irq_start; irq < irq_end; irq++) { - set_irq_chip(irq, &egpio_muxed_chip); - set_irq_chip_data(irq, ei); - set_irq_handler(irq, handle_simple_irq); + irq_set_chip_and_handler(irq, &egpio_muxed_chip, + handle_simple_irq); + irq_set_chip_data(irq, ei); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING); - set_irq_data(ei->chained_irq, ei); - set_irq_chained_handler(ei->chained_irq, egpio_handler); + irq_set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING); + irq_set_handler_data(ei->chained_irq, ei); + irq_set_chained_handler(ei->chained_irq, egpio_handler); ack_irqs(ei); device_init_wakeup(&pdev->dev, 1); @@ -375,11 +373,10 @@ static int __exit egpio_remove(struct platform_device *pdev) if (ei->chained_irq) { irq_end = ei->irq_start + ei->nirqs; for (irq = ei->irq_start; irq < irq_end; irq++) { - set_irq_chip(irq, NULL); - set_irq_handler(irq, NULL); + irq_set_chip_and_handler(irq, NULL, NULL); set_irq_flags(irq, 0); } - set_irq_chained_handler(ei->chained_irq, NULL); + irq_set_chained_handler(ei->chained_irq, NULL); device_init_wakeup(&pdev->dev, 0); } iounmap(ei->base_addr); diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index 296ad1562f69..d55065cc324c 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -58,6 +58,7 @@ struct htcpld_chip { uint irq_start; int nirqs; + unsigned int flow_type; /* * Work structure to allow for setting values outside of any * possible interrupt context @@ -97,12 +98,7 @@ static void htcpld_unmask(struct irq_data *data) static int htcpld_set_type(struct irq_data *data, unsigned int flags) { - struct irq_desc *d = irq_to_desc(data->irq); - - if (!d) { - pr_err("HTCPLD invalid IRQ: %d\n", data->irq); - return -EINVAL; - } + struct htcpld_chip *chip = irq_data_get_irq_chip_data(data); if (flags & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; @@ -111,9 +107,7 @@ static int htcpld_set_type(struct irq_data *data, unsigned int flags) if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)) return -EINVAL; - d->status &= ~IRQ_TYPE_SENSE_MASK; - d->status |= flags; - + chip->flow_type = flags; return 0; } @@ -135,7 +129,6 @@ static irqreturn_t htcpld_handler(int irq, void *dev) unsigned int i; unsigned long flags; int irqpin; - struct irq_desc *desc; if (!htcpld) { pr_debug("htcpld is null in ISR\n"); @@ -195,23 +188,19 @@ static irqreturn_t htcpld_handler(int irq, void *dev) * associated interrupts. */ for (irqpin = 0; irqpin < chip->nirqs; irqpin++) { - unsigned oldb, newb; - int flags; + unsigned oldb, newb, type = chip->flow_type; irq = chip->irq_start + irqpin; - desc = irq_to_desc(irq); - flags = desc->status; /* Run the IRQ handler, but only if the bit value * changed, and the proper flags are set */ oldb = (old_val >> irqpin) & 1; newb = (uval >> irqpin) & 1; - if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) || - (oldb && !newb && - (flags & IRQ_TYPE_EDGE_FALLING))) { + if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) || + (oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) { pr_debug("fire IRQ %d\n", irqpin); - desc->handle_irq(irq, desc); + generic_handle_irq(irq); } } } @@ -359,13 +348,13 @@ static int __devinit htcpld_setup_chip_irq( /* Setup irq handlers */ irq_end = chip->irq_start + chip->nirqs; for (irq = chip->irq_start; irq < irq_end; irq++) { - set_irq_chip(irq, &htcpld_muxed_chip); - set_irq_chip_data(irq, chip); - set_irq_handler(irq, handle_simple_irq); + irq_set_chip_and_handler(irq, &htcpld_muxed_chip, + handle_simple_irq); + irq_set_chip_data(irq, chip); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); #else - set_irq_probe(irq); + irq_set_probe(irq); #endif } diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index aa518b9beaf5..a0bd0cf05af3 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -112,7 +112,7 @@ static struct irq_chip jz4740_adc_irq_chip = { static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) { - struct jz4740_adc *adc = get_irq_desc_data(desc); + struct jz4740_adc *adc = irq_desc_get_handler_data(desc); uint8_t status; unsigned int i; @@ -310,13 +310,13 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, adc); for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { - set_irq_chip_data(irq, adc); - set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip, - handle_level_irq); + irq_set_chip_data(irq, adc); + irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip, + handle_level_irq); } - set_irq_data(adc->irq, adc); - set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux); + irq_set_handler_data(adc->irq, adc); + irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux); writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); writeb(0xff, adc->base + JZ_REG_ADC_CTRL); @@ -347,8 +347,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev) mfd_remove_devices(&pdev->dev); - set_irq_data(adc->irq, NULL); - set_irq_chained_handler(adc->irq, NULL); + irq_set_handler_data(adc->irq, NULL); + irq_set_chained_handler(adc->irq, NULL); iounmap(adc->base); release_mem_region(adc->mem->start, resource_size(adc->mem)); diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 0e998dc4e7d8..58cc5fdde016 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -517,7 +517,6 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, struct max8925_platform_data *pdata) { unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - struct irq_desc *desc; int i, ret; int __irq; @@ -544,19 +543,18 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, mutex_init(&chip->irq_lock); chip->core_irq = irq; chip->irq_base = pdata->irq_base; - desc = irq_to_desc(chip->core_irq); /* register with genirq */ for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { __irq = i + chip->irq_base; - set_irq_chip_data(__irq, chip); - set_irq_chip_and_handler(__irq, &max8925_irq_chip, + irq_set_chip_data(__irq, chip); + irq_set_chip_and_handler(__irq, &max8925_irq_chip, handle_edge_irq); - set_irq_nested_thread(__irq, 1); + irq_set_nested_thread(__irq, 1); #ifdef CONFIG_ARM set_irq_flags(__irq, IRQF_VALID); #else - set_irq_noprobe(__irq); + irq_set_noprobe(__irq); #endif } if (!irq) { diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c new file mode 100644 index 000000000000..638bf7e4d3b3 --- /dev/null +++ b/drivers/mfd/max8997-irq.c @@ -0,0 +1,377 @@ +/* + * max8997-irq.c - Interrupt controller support for MAX8997 + * + * Copyright (C) 2011 Samsung Electronics Co.Ltd + * MyungJoo Ham <myungjoo.ham@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This driver is based on max8998-irq.c + */ + +#include <linux/err.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/mfd/max8997.h> +#include <linux/mfd/max8997-private.h> + +static const u8 max8997_mask_reg[] = { + [PMIC_INT1] = MAX8997_REG_INT1MSK, + [PMIC_INT2] = MAX8997_REG_INT2MSK, + [PMIC_INT3] = MAX8997_REG_INT3MSK, + [PMIC_INT4] = MAX8997_REG_INT4MSK, + [FUEL_GAUGE] = MAX8997_REG_INVALID, + [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1, + [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2, + [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3, + [GPIO_LOW] = MAX8997_REG_INVALID, + [GPIO_HI] = MAX8997_REG_INVALID, + [FLASH_STATUS] = MAX8997_REG_INVALID, +}; + +static struct i2c_client *get_i2c(struct max8997_dev *max8997, + enum max8997_irq_source src) +{ + switch (src) { + case PMIC_INT1 ... PMIC_INT4: + return max8997->i2c; + case FUEL_GAUGE: + return NULL; + case MUIC_INT1 ... MUIC_INT3: + return max8997->muic; + case GPIO_LOW ... GPIO_HI: + return max8997->i2c; + case FLASH_STATUS: + return max8997->i2c; + default: + return ERR_PTR(-EINVAL); + } + + return ERR_PTR(-EINVAL); +} + +struct max8997_irq_data { + int mask; + enum max8997_irq_source group; +}; + +#define DECLARE_IRQ(idx, _group, _mask) \ + [(idx)] = { .group = (_group), .mask = (_mask) } +static const struct max8997_irq_data max8997_irqs[] = { + DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR, PMIC_INT1, 1 << 0), + DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF, PMIC_INT1, 1 << 1), + DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC, PMIC_INT1, 1 << 3), + DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR, PMIC_INT1, 1 << 4), + DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF, PMIC_INT1, 1 << 5), + DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2, PMIC_INT1, 1 << 6), + DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1, PMIC_INT1, 1 << 7), + + DECLARE_IRQ(MAX8997_PMICIRQ_JIGR, PMIC_INT2, 1 << 0), + DECLARE_IRQ(MAX8997_PMICIRQ_JIGF, PMIC_INT2, 1 << 1), + DECLARE_IRQ(MAX8997_PMICIRQ_MR, PMIC_INT2, 1 << 2), + DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK, PMIC_INT2, 1 << 3), + DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK, PMIC_INT2, 1 << 4), + DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK, PMIC_INT2, 1 << 5), + DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK, PMIC_INT2, 1 << 6), + + DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS, PMIC_INT3, 1 << 0), + DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM, PMIC_INT3, 1 << 1), + DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP, PMIC_INT3, 1 << 2), + DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR, PMIC_INT3, 1 << 3), + DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF, PMIC_INT3, 1 << 5), + DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD, PMIC_INT3, 1 << 7), + + DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S, PMIC_INT4, 1 << 0), + DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1, PMIC_INT4, 1 << 1), + DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2, PMIC_INT4, 1 << 2), + DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT, PMIC_INT4, 1 << 3), + DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S, PMIC_INT4, 1 << 4), + DECLARE_IRQ(MAX8997_PMICIRQ_WTSR, PMIC_INT4, 1 << 5), + + DECLARE_IRQ(MAX8997_MUICIRQ_ADCError, MUIC_INT1, 1 << 2), + DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow, MUIC_INT1, 1 << 1), + DECLARE_IRQ(MAX8997_MUICIRQ_ADC, MUIC_INT1, 1 << 0), + + DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt, MUIC_INT2, 1 << 4), + DECLARE_IRQ(MAX8997_MUICIRQ_DBChg, MUIC_INT2, 1 << 3), + DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr, MUIC_INT2, 1 << 2), + DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun, MUIC_INT2, 1 << 1), + DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp, MUIC_INT2, 1 << 0), + + DECLARE_IRQ(MAX8997_MUICIRQ_OVP, MUIC_INT3, 1 << 2), +}; + +static void max8997_irq_lock(struct irq_data *data) +{ + struct max8997_dev *max8997 = irq_get_chip_data(data->irq); + + mutex_lock(&max8997->irqlock); +} + +static void max8997_irq_sync_unlock(struct irq_data *data) +{ + struct max8997_dev *max8997 = irq_get_chip_data(data->irq); + int i; + + for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) { + u8 mask_reg = max8997_mask_reg[i]; + struct i2c_client *i2c = get_i2c(max8997, i); + + if (mask_reg == MAX8997_REG_INVALID || + IS_ERR_OR_NULL(i2c)) + continue; + max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i]; + + max8997_write_reg(i2c, max8997_mask_reg[i], + max8997->irq_masks_cur[i]); + } + + mutex_unlock(&max8997->irqlock); +} + +static const inline struct max8997_irq_data * +irq_to_max8997_irq(struct max8997_dev *max8997, int irq) +{ + return &max8997_irqs[irq - max8997->irq_base]; +} + +static void max8997_irq_mask(struct irq_data *data) +{ + struct max8997_dev *max8997 = irq_get_chip_data(data->irq); + const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997, + data->irq); + + max8997->irq_masks_cur[irq_data->group] |= irq_data->mask; +} + +static void max8997_irq_unmask(struct irq_data *data) + |