Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: mfd: Clean up max8997 IRQ namespace mfd: Fold irq_set_chip/irq_set_handler mfd: Cleanup irq namespace mfd: twl6030: Cleanup interrupt handling mfd: twl4030: Cleanup interrupt handling mfd: mx8925: Remove irq_desc leftovers mfd: htc-i2cpld: Cleanup interrupt handling mfd: htc-egpio: Cleanup interrupt handling mfd: ezx-pcap: Remvove open coded irq handling mfd: 88pm860x: Remove unused irq_desc leftovers mfd: asic3: Cleanup irq handling mfd: Select MFD_CORE if TPS6105X driver is configured mfd: Add MODULE_DEVICE_TABLE to rdc321x-southbridge mfd: Add MAX8997/8966 IRQ control mfd: Constify i2c_device_id tables mfd: OLPC: Clean up names to match what OLPC actually uses mfd: Add mfd_clone_cell(), convert cs5535-mfd/olpc-xo1 to it
This commit is contained in:
Коммит
551b0bda46
|
@ -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>");
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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 struct irq_chip max8997_irq_chip = {
|
||||
.name = "max8997",
|
||||
.irq_bus_lock = max8997_irq_lock,
|
||||
.irq_bus_sync_unlock = max8997_irq_sync_unlock,
|
||||
.irq_mask = max8997_irq_mask,
|
||||
.irq_unmask = max8997_irq_unmask,
|
||||
};
|
||||
|
||||
#define MAX8997_IRQSRC_PMIC (1 << 1)
|
||||
#define MAX8997_IRQSRC_FUELGAUGE (1 << 2)
|
||||
#define MAX8997_IRQSRC_MUIC (1 << 3)
|
||||
#define MAX8997_IRQSRC_GPIO (1 << 4)
|
||||
#define MAX8997_IRQSRC_FLASH (1 << 5)
|
||||
static irqreturn_t max8997_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct max8997_dev *max8997 = data;
|
||||
u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
|
||||
u8 irq_src;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
|
||||
if (ret < 0) {
|
||||
dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
|
||||
ret);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (irq_src & MAX8997_IRQSRC_PMIC) {
|
||||
/* PMIC INT1 ~ INT4 */
|
||||
max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
|
||||
&irq_reg[PMIC_INT1]);
|
||||
}
|
||||
if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
|
||||
/*
|
||||
* TODO: FUEL GAUGE
|
||||
*
|
||||
* This is to be supported by Max17042 driver. When
|
||||
* an interrupt incurs here, it should be relayed to a
|
||||
* Max17042 device that is connected (probably by
|
||||
* platform-data). However, we do not have interrupt
|
||||
* handling in Max17042 driver currently. The Max17042 IRQ
|
||||
* driver should be ready to be used as a stand-alone device and
|
||||
* a Max8997-dependent device. Because it is not ready in
|
||||
* Max17042-side and it is not too critical in operating
|
||||
* Max8997, we do not implement this in initial releases.
|
||||
*/
|
||||
irq_reg[FUEL_GAUGE] = 0;
|
||||
}
|
||||
if (irq_src & MAX8997_IRQSRC_MUIC) {
|
||||
/* MUIC INT1 ~ INT3 */
|
||||
max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
|
||||
&irq_reg[MUIC_INT1]);
|
||||
}
|
||||
if (irq_src & MAX8997_IRQSRC_GPIO) {
|
||||
/* GPIO Interrupt */
|
||||
u8 gpio_info[MAX8997_NUM_GPIO];
|
||||
|
||||
irq_reg[GPIO_LOW] = 0;
|
||||
irq_reg[GPIO_HI] = 0;
|
||||
|
||||
max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
|
||||
MAX8997_NUM_GPIO, gpio_info);
|
||||
for (i = 0; i < MAX8997_NUM_GPIO; i++) {
|
||||
bool interrupt = false;
|
||||
|
||||
switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
|
||||
case MAX8997_GPIO_INT_BOTH:
|
||||
if (max8997->gpio_status[i] != gpio_info[i])
|
||||
interrupt = true;
|
||||
break;
|
||||
case MAX8997_GPIO_INT_RISE:
|
||||
if ((max8997->gpio_status[i] != gpio_info[i]) &&
|
||||
(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
|
||||
interrupt = true;
|
||||
break;
|
||||
case MAX8997_GPIO_INT_FALL:
|
||||
if ((max8997->gpio_status[i] != gpio_info[i]) &&
|
||||
!(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
|
||||
interrupt = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (interrupt) {
|
||||
if (i < 8)
|
||||
irq_reg[GPIO_LOW] |= (1 << i);
|
||||
else
|
||||
irq_reg[GPIO_HI] |= (1 << (i - 8));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (irq_src & MAX8997_IRQSRC_FLASH) {
|
||||
/* Flash Status Interrupt */
|
||||
ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
|
||||
&irq_reg[FLASH_STATUS]);
|
||||
}
|
||||
|
||||
/* Apply masking */
|
||||
for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
|
||||
irq_reg[i] &= ~max8997->irq_masks_cur[i];
|
||||
|
||||
/* Report */
|
||||
for (i = 0; i < MAX8997_IRQ_NR; i++) {
|
||||
if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask)
|
||||
handle_nested_irq(max8997->irq_base + i);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int max8997_irq_resume(struct max8997_dev *max8997)
|
||||
{
|
||||
if (max8997->irq && max8997->irq_base)
|
||||
max8997_irq_thread(max8997->irq_base, max8997);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int max8997_irq_init(struct max8997_dev *max8997)
|
||||
{
|
||||
int i;
|
||||
int cur_irq;
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (!max8997->irq) {
|
||||
dev_warn(max8997->dev, "No interrupt specified.\n");
|
||||
max8997->irq_base = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!max8997->irq_base) {
|
||||
dev_err(max8997->dev, "No interrupt base specified.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_init(&max8997->irqlock);
|
||||
|
||||
/* Mask individual interrupt sources */
|
||||
for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
|
||||
struct i2c_client *i2c;
|
||||
|
||||
max8997->irq_masks_cur[i] = 0xff;
|
||||
max8997->irq_masks_cache[i] = 0xff;
|
||||
i2c = get_i2c(max8997, i);
|
||||
|
||||
if (IS_ERR_OR_NULL(i2c))
|
||||
continue;
|
||||
if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
|
||||
continue;
|
||||
|
||||
max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX8997_NUM_GPIO; i++) {
|
||||
max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
|
||||
MAX8997_REG_GPIOCNTL1 + i,
|
||||
&val)
|
||||
& MAX8997_GPIO_DATA_MASK) ?
|
||||
true : false;
|
||||
}
|
||||
|
||||
/* Register with genirq */
|
||||
for (i = 0; i < MAX8997_IRQ_NR; i++) {
|
||||
cur_irq = i + max8997->irq_base;
|
||||
irq_set_chip_data(cur_irq, max8997);
|
||||
irq_set_chip_and_handler(cur_irq, &max8997_irq_chip,
|
||||
handle_edge_irq);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"max8997-irq", max8997);
|
||||
|
||||
if (ret) {
|
||||
dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
|
||||
max8997->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!max8997->ono)
|
||||
return 0;
|
||||
|
||||
ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
|
||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT, "max8997-ono", max8997);
|
||||
|
||||
if (ret)
|
||||
dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
|
||||
max8997->ono, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void max8997_irq_exit(struct max8997_dev *max8997)
|
||||
{
|
||||
if (max8997->ono)
|
||||
free_irq(max8997->ono, max8997);
|
||||
|
||||
if (max8997->irq)
|
||||
free_irq(max8997->irq, max8997);
|
||||
}
|
|
@ -224,14 +224,14 @@ int max8998_irq_init(struct max8998_dev *max8998)
|
|||
/* register with genirq */
|
||||
for (i = 0; i < MAX8998_IRQ_NR; i++) {
|
||||
cur_irq = i + max8998->irq_base;
|
||||
set_irq_chip_data(cur_irq, max8998);
|
||||
set_irq_chip_and_handler(cur_irq, &max8998_irq_chip,
|
||||
irq_set_chip_data(cur_irq, max8998);
|
||||
irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
|
||||
handle_edge_irq);
|
||||
set_irq_nested_thread(cur_irq, 1);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
set_irq_noprobe(cur_irq);
|
||||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ static int max8998_suspend(struct device *dev)
|
|||
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (max8998->wakeup)
|
||||
set_irq_wake(max8998->irq, 1);
|
||||
irq_set_irq_wake(max8998->irq, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ static int max8998_resume(struct device *dev)
|
|||
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (max8998->wakeup)
|
||||
set_irq_wake(max8998->irq, 0);
|
||||
irq_set_irq_wake(max8998->irq, 0);
|
||||
/*
|
||||
* In LP3974, if IRQ registers are not "read & clear"
|
||||
* when it's set during sleep, the interrupt becomes
|
||||
|
|
|
@ -184,16 +184,12 @@ void mfd_remove_devices(struct device *parent)
|
|||
}
|
||||
EXPORT_SYMBOL(mfd_remove_devices);
|
||||
|
||||
static int add_shared_platform_device(const char *cell, const char *name)
|
||||
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
|
||||
{
|
||||
struct mfd_cell cell_entry;
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
int err;
|
||||
|
||||
/* check if we've already registered a device (don't fail if we have) */
|
||||
if (bus_find_device_by_name(&platform_bus_type, NULL, name))
|
||||
return 0;
|
||||
int i;
|
||||
|
||||
/* fetch the parent cell's device (should already be registered!) */
|
||||
dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
|
||||
|
@ -206,44 +202,17 @@ static int add_shared_platform_device(const char *cell, const char *name)
|
|||
|
||||
WARN_ON(!cell_entry.enable);
|
||||
|
||||
cell_entry.name = name;
|
||||
err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0);
|
||||
if (err)
|
||||
dev_err(dev, "MFD add devices failed: %d\n", err);
|
||||
return err;
|
||||
for (i = 0; i < n_clones; i++) {
|
||||
cell_entry.name = clones[i];
|
||||
/* don't give up if a single call fails; just report error */
|
||||
if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
|
||||
dev_err(dev, "failed to create platform device '%s'\n",
|
||||
clones[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfd_shared_platform_driver_register(struct platform_driver *drv,
|
||||
const char *cellname)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = add_shared_platform_device(cellname, drv->driver.name);
|
||||
if (err)
|
||||
printk(KERN_ERR "failed to add platform device %s\n",
|
||||
drv->driver.name);
|
||||
|
||||
err = platform_driver_register(drv);
|
||||
if (err)
|
||||
printk(KERN_ERR "failed to add platform driver %s\n",
|
||||
drv->driver.name);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_shared_platform_driver_register);
|
||||
|
||||
void mfd_shared_platform_driver_unregister(struct platform_driver *drv)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device_by_name(&platform_bus_type, NULL,
|
||||
drv->driver.name);
|
||||
if (dev)
|
||||
platform_device_unregister(to_platform_device(dev));
|
||||
|
||||
platform_driver_unregister(drv);
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_shared_platform_driver_unregister);
|
||||
EXPORT_SYMBOL(mfd_clone_cell);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
|
||||
|
|
|
@ -356,7 +356,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id pcf50633_id_table[] = {
|
||||
static const struct i2c_device_id pcf50633_id_table[] = {
|
||||
{"pcf50633", 0x73},
|
||||
{/* end of list */}
|
||||
};
|
||||
|
|
|
@ -97,6 +97,7 @@ static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, rdc321x_sb_table);
|
||||
|
||||
static struct pci_driver rdc321x_sb_driver = {
|
||||
.name = "RDC321x Southbridge",
|
||||
|
|
|
@ -762,14 +762,14 @@ static int __devinit stmpe_irq_init(struct stmpe *stmpe)
|
|||
int irq;
|
||||
|
||||
for (irq = base; irq < base + num_irqs; irq++) {
|
||||
set_irq_chip_data(irq, stmpe);
|
||||
set_irq_chip_and_handler(irq, &stmpe_irq_chip,
|
||||
irq_set_chip_data(irq, stmpe);
|
||||
irq_set_chip_and_handler(irq, &stmpe_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
|
||||
}
|
||||
|
||||
|
@ -786,8 +786,8 @@ static void stmpe_irq_remove(struct stmpe *stmpe)
|
|||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ static struct mfd_cell t7l66xb_cells[] = {
|
|||
/* Handle the T7L66XB interrupt mux */
|
||||
static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = get_irq_data(irq);
|
||||
struct t7l66xb *t7l66xb = irq_get_handler_data(irq);
|
||||
unsigned int isr;
|
||||
unsigned int i, irq_base;
|
||||
|
||||
|
@ -243,17 +243,16 @@ static void t7l66xb_attach_irq(struct platform_device *dev)
|
|||
irq_base = t7l66xb->irq_base;
|
||||
|
||||
for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
|
||||
set_irq_chip(irq, &t7l66xb_chip);
|
||||
set_irq_chip_data(irq, t7l66xb);
|
||||
set_irq_handler(irq, handle_level_irq);
|
||||
irq_set_chip_and_handler(irq, &t7l66xb_chip, handle_level_irq);
|
||||
irq_set_chip_data(irq, t7l66xb);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
#endif
|
||||
}
|
||||
|
||||
set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
|
||||
set_irq_data(t7l66xb->irq, t7l66xb);
|
||||
set_irq_chained_handler(t7l66xb->irq, t7l66xb_irq);
|
||||
irq_set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
|
||||
irq_set_handler_data(t7l66xb->irq, t7l66xb);
|
||||
irq_set_chained_handler(t7l66xb->irq, t7l66xb_irq);
|
||||
}
|
||||
|
||||
static void t7l66xb_detach_irq(struct platform_device *dev)
|
||||
|
@ -263,15 +262,15 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
|
|||
|
||||
irq_base = t7l66xb->irq_base;
|
||||
|
||||
set_irq_chained_handler(t7l66xb->irq, NULL);
|
||||
set_irq_data(t7l66xb->irq, NULL);
|
||||
irq_set_chained_handler(t7l66xb->irq, NULL);
|
||||
irq_set_handler_data(t7l66xb->irq, NULL);
|
||||
|
||||
for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, 0);
|
||||
#endif
|
||||
set_irq_chip(irq, NULL);
|
||||
set_irq_chip_data(irq, NULL);
|
||||
irq_set_chip(irq, NULL);
|
||||
irq_set_chip_data(irq, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -192,14 +192,14 @@ static int tc3589x_irq_init(struct tc3589x *tc3589x)
|
|||
int irq;
|
||||
|
||||
for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
|
||||
set_irq_chip_data(irq, tc3589x);
|
||||
set_irq_chip_and_handler(irq, &dummy_irq_chip,
|
||||
irq_set_chip_data(irq, tc3589x);
|
||||
irq_set_chip_and_handler(irq, &dummy_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
|
||||
}
|
||||
|
||||
|
@ -215,8 +215,8 @@ static void tc3589x_irq_remove(struct tc3589x *tc3589x)
|
|||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
|
|||
static void
|
||||
tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = get_irq_data(irq);
|
||||
struct tc6393xb *tc6393xb = irq_get_handler_data(irq);
|
||||
unsigned int isr;
|
||||
unsigned int i, irq_base;
|
||||
|
||||
|
@ -572,15 +572,14 @@ static void tc6393xb_attach_irq(struct platform_device *dev)
|
|||
irq_base = tc6393xb->irq_base;
|
||||
|
||||
for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
|
||||
set_irq_chip(irq, &tc6393xb_chip);
|
||||
set_irq_chip_data(irq, tc6393xb);
|
||||
set_irq_handler(irq, handle_edge_irq);
|
||||
irq_set_chip_and_handler(irq, &tc6393xb_chip, handle_edge_irq);
|
||||
irq_set_chip_data(irq, tc6393xb);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
|
||||
set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
|
||||
set_irq_data(tc6393xb->irq, tc6393xb);
|
||||
set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
|
||||
irq_set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
|
||||
irq_set_handler_data(tc6393xb->irq, tc6393xb);
|
||||
irq_set_chained_handler(tc6393xb->irq, tc6393xb_irq);
|
||||
}
|
||||
|
||||
static void tc6393xb_detach_irq(struct platform_device *dev)
|
||||
|
@ -588,15 +587,15 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
|
|||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
unsigned int irq, irq_base;
|
||||
|
||||
set_irq_chained_handler(tc6393xb->irq, NULL);
|
||||
set_irq_data(tc6393xb->irq, NULL);
|
||||
irq_set_chained_handler(tc6393xb->irq, NULL);
|
||||
irq_set_handler_data(tc6393xb->irq, NULL);
|
||||
|
||||
irq_base = tc6393xb->irq_base;
|
||||
|
||||
for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
|
||||
set_irq_flags(irq, 0);
|
||||
set_irq_chip(irq, NULL);
|
||||
set_irq_chip_data(irq, NULL);
|
||||
irq_set_chip(irq, NULL);
|
||||
irq_set_chip_data(irq, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -422,10 +422,10 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
|
||||
int __irq = i + tps6586x->irq_base;
|
||||
set_irq_chip_data(__irq, tps6586x);
|
||||
set_irq_chip_and_handler(__irq, &tps6586x->irq_chip,
|
||||
irq_set_chip_data(__irq, tps6586x);
|
||||
irq_set_chip_and_handler(__irq, &tps6586x->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);
|
||||
#endif
|
||||
|
|
|
@ -320,24 +320,8 @@ static int twl4030_irq_thread(void *data)
|
|||
for (module_irq = twl4030_irq_base;
|
||||
pih_isr;
|
||||
pih_isr >>= 1, module_irq++) {
|
||||
if (pih_isr & 0x1) {
|
||||
struct irq_desc *d = irq_to_desc(module_irq);
|
||||
|
||||
if (!d) {
|
||||
pr_err("twl4030: Invalid SIH IRQ: %d\n",
|
||||
module_irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* These can't be masked ... always warn
|
||||
* if we get any surprises.
|
||||
*/
|
||||
if (d->status & IRQ_DISABLED)
|
||||
note_interrupt(module_irq, d,
|
||||
IRQ_NONE);
|
||||
else
|
||||
d->handle_irq(module_irq, d);
|
||||
}
|
||||
if (pih_isr & 0x1)
|
||||
generic_handle_irq(module_irq);
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
|
@ -470,7 +454,7 @@ static inline void activate_irq(int irq)
|
|||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
/* same effect on other architectures */
|
||||
set_irq_noprobe(irq);
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -560,24 +544,18 @@ static void twl4030_sih_do_edge(struct work_struct *work)
|
|||
/* Modify only the bits we know must change */
|
||||
while (edge_change) {
|
||||
int i = fls(edge_change) - 1;
|
||||
struct irq_desc *d = irq_to_desc(i + agent->irq_base);
|
||||
struct irq_data *idata = irq_get_irq_data(i + agent->irq_base);
|
||||
int byte = 1 + (i >> 2);
|
||||
int off = (i & 0x3) * 2;
|
||||
|
||||
if (!d) {
|
||||
pr_err("twl4030: Invalid IRQ: %d\n",
|
||||
i + agent->irq_base);
|
||||
return;
|
||||
}
|
||||
unsigned int type;
|
||||
|
||||
bytes[byte] &= ~(0x03 << off);
|
||||
|
||||
raw_spin_lock_irq(&d->lock);
|
||||
if (d->status & IRQ_TYPE_EDGE_RISING)
|
||||
type = irqd_get_trigger_type(idata);
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
bytes[byte] |= BIT(off + 1);
|
||||
if (d->status & IRQ_TYPE_EDGE_FALLING)
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
bytes[byte] |= BIT(off + 0);
|
||||
raw_spin_unlock_irq(&d->lock);
|
||||
|
||||
edge_change &= ~BIT(i);
|
||||
}
|
||||
|
@ -626,21 +604,13 @@ static void twl4030_sih_unmask(struct irq_data *data)
|
|||
static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
|
||||
{
|
||||
struct sih_agent *sih = irq_data_get_irq_chip_data(data);
|
||||
struct irq_desc *desc = irq_to_desc(data->irq);
|
||||
unsigned long flags;
|
||||
|
||||
if (!desc) {
|
||||
pr_err("twl4030: Invalid IRQ: %d\n", data->irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&sih_agent_lock, flags);
|
||||
if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
|
||||
desc->status &= ~IRQ_TYPE_SENSE_MASK;
|
||||
desc->status |= trigger;
|
||||
if (irqd_get_trigger_type(data) != trigger) {
|
||||
sih->edge_change |= BIT(data->irq - sih->irq_base);
|
||||
queue_work(wq, &sih->edge_work);
|
||||
}
|
||||
|
@ -680,7 +650,7 @@ static inline int sih_read_isr(const struct sih *sih)
|
|||
*/
|
||||
static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct sih_agent *agent = get_irq_data(irq);
|
||||
struct sih_agent *agent = irq_get_handler_data(irq);
|
||||
const struct sih *sih = agent->sih;
|
||||
int isr;
|
||||
|
||||
|
@ -754,9 +724,9 @@ int twl4030_sih_setup(int module)
|
|||
for (i = 0; i < sih->bits; i++) {
|
||||
irq = irq_base + i;
|
||||
|
||||
set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip,
|
||||
handle_edge_irq);
|
||||
set_irq_chip_data(irq, agent);
|
||||
irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
|
||||
handle_edge_irq);
|
||||
irq_set_chip_data(irq, agent);
|
||||
activate_irq(irq);
|
||||
}
|
||||
|
||||
|
@ -765,8 +735,8 @@ int twl4030_sih_setup(int module)
|
|||
|
||||
/* replace generic PIH handler (handle_simple_irq) */
|
||||
irq = sih_mod + twl4030_irq_base;
|
||||
set_irq_data(irq, agent);
|
||||
set_irq_chained_handler(irq, handle_twl4030_sih);
|
||||
irq_set_handler_data(irq, agent);
|
||||
irq_set_chained_handler(irq, handle_twl4030_sih);
|
||||
|
||||
pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
|
||||
irq, irq_base, twl4030_irq_next - 1);
|
||||
|
@ -815,8 +785,8 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
|
||||
|
||||
for (i = irq_base; i < irq_end; i++) {
|
||||
set_irq_chip_and_handler(i, &twl4030_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_chip_and_handler(i, &twl4030_irq_chip,
|
||||
handle_simple_irq);
|
||||
activate_irq(i);
|
||||
}
|
||||
twl4030_irq_next = i;
|
||||
|
@ -856,7 +826,7 @@ fail_rqirq:
|
|||
/* clean up twl4030_sih_setup */
|
||||
fail:
|
||||
for (i = irq_base; i < irq_end; i++)
|
||||
set_irq_chip_and_handler(i, NULL, NULL);
|
||||
irq_set_chip_and_handler(i, NULL, NULL);
|
||||
destroy_workqueue(wq);
|
||||
wq = NULL;
|
||||
return status;
|
||||
|
|
|
@ -140,22 +140,7 @@ static int twl6030_irq_thread(void *data)
|
|||
if (sts.int_sts & 0x1) {
|
||||
int module_irq = twl6030_irq_base +
|
||||
twl6030_interrupt_mapping[i];
|
||||
struct irq_desc *d = irq_to_desc(module_irq);
|
||||
|
||||
if (!d) {
|
||||
pr_err("twl6030: Invalid SIH IRQ: %d\n",
|
||||
module_irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* These can't be masked ... always warn
|
||||
* if we get any surprises.
|
||||
*/
|
||||
if (d->status & IRQ_DISABLED)
|
||||
note_interrupt(module_irq, d,
|
||||
IRQ_NONE);
|
||||
else
|
||||
d->handle_irq(module_irq, d);
|
||||
generic_handle_irq(module_irq);
|
||||
|
||||
}
|
||||
local_irq_enable();
|
||||
|
@ -198,7 +183,7 @@ static inline void activate_irq(int irq)
|
|||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
/* same effect on other architectures */
|
||||
set_irq_noprobe(irq);
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -335,8 +320,8 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
twl6030_irq_chip.irq_set_type = NULL;
|
||||
|
||||
for (i = irq_base; i < irq_end; i++) {
|
||||
set_irq_chip_and_handler(i, &twl6030_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_chip_and_handler(i, &twl6030_irq_chip,
|
||||
handle_simple_irq);
|
||||
activate_irq(i);
|
||||
}
|
||||
|
||||
|
@ -365,7 +350,7 @@ fail_irq:
|
|||
|
||||
fail_kthread:
|
||||
for (i = irq_base; i < irq_end; i++)
|
||||
set_irq_chip_and_handler(i, NULL, NULL);
|
||||
irq_set_chip_and_handler(i, NULL, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#define DRIVER_DESC "WL1273 FM Radio Core"
|
||||
|
||||
static struct i2c_device_id wl1273_driver_id_table[] = {
|
||||
static const struct i2c_device_id wl1273_driver_id_table[] = {
|
||||
{ WL1273_FM_DRIVER_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -553,17 +553,17 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
for (cur_irq = wm831x->irq_base;
|
||||
cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
|
||||
cur_irq++) {
|
||||
set_irq_chip_data(cur_irq, wm831x);
|
||||
set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip,
|
||||
irq_set_chip_data(cur_irq, wm831x);
|
||||
irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip,
|
||||
handle_edge_irq);
|
||||
set_irq_nested_thread(cur_irq, 1);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
|
||||
/* ARM needs us to explicitly flag the IRQ as valid
|
||||
* and will set them noprobe when we do so. */
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
set_irq_noprobe(cur_irq);
|
||||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -518,17 +518,17 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
|
|||
for (cur_irq = wm8350->irq_base;
|
||||
cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
|
||||
cur_irq++) {
|
||||
set_irq_chip_data(cur_irq, wm8350);
|
||||
set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
|
||||
irq_set_chip_data(cur_irq, wm8350);
|
||||
irq_set_chip_and_handler(cur_irq, &wm8350_irq_chip,
|
||||
handle_edge_irq);
|
||||
set_irq_nested_thread(cur_irq, 1);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
|
||||
/* ARM needs us to explicitly flag the IRQ as valid
|
||||
* and will set them noprobe when we do so. */
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
set_irq_noprobe(cur_irq);
|
||||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -278,17 +278,17 @@ int wm8994_irq_init(struct wm8994 *wm8994)
|
|||
for (cur_irq = wm8994->irq_base;
|
||||
cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
|
||||
cur_irq++) {
|
||||
set_irq_chip_data(cur_irq, wm8994);
|
||||
set_irq_chip_and_handler(cur_irq, &wm8994_irq_chip,
|
||||
irq_set_chip_data(cur_irq, wm8994);
|
||||
irq_set_chip_and_handler(cur_irq, &wm8994_irq_chip,
|
||||
handle_edge_irq);
|
||||
set_irq_nested_thread(cur_irq, 1);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
|
||||
/* ARM needs us to explicitly flag the IRQ as valid
|
||||
* and will set them noprobe when we do so. */
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
set_irq_noprobe(cur_irq);
|
||||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,24 @@ struct mfd_cell {
|
|||
extern int mfd_cell_enable(struct platform_device *pdev);
|
||||
extern int mfd_cell_disable(struct platform_device *pdev);
|
||||
|
||||
/*
|
||||
* "Clone" multiple platform devices for a single cell. This is to be used
|
||||
* for devices that have multiple users of a cell. For example, if an mfd
|
||||
* driver wants the cell "foo" to be used by a GPIO driver, an MTD driver,
|
||||
* and a platform driver, the following bit of code would be use after first
|
||||
* calling mfd_add_devices():
|
||||
*
|
||||
* const char *fclones[] = { "foo-gpio", "foo-mtd" };
|
||||
* err = mfd_clone_cells("foo", fclones, ARRAY_SIZE(fclones));
|
||||
*
|
||||
* Each driver (MTD, GPIO, and platform driver) would then register
|
||||
* platform_drivers for "foo-mtd", "foo-gpio", and "foo", respectively.
|
||||
* The cell's .enable/.disable hooks should be used to deal with hardware
|
||||
* resource contention.
|
||||
*/
|
||||
extern int mfd_clone_cell(const char *cell, const char **clones,
|
||||
size_t n_clones);
|
||||
|
||||
/*
|
||||
* Given a platform device that's been created by mfd_add_devices(), fetch
|
||||
* the mfd_cell that created it.
|
||||
|
@ -87,13 +105,4 @@ extern int mfd_add_devices(struct device *parent, int id,
|
|||
|
||||
extern void mfd_remove_devices(struct device *parent);
|
||||
|
||||
/*
|
||||
* For MFD drivers with clients sharing access to resources, these create
|
||||
* multiple platform devices per cell. Contention handling must still be
|
||||
* handled via drivers (ie, with enable/disable hooks).
|
||||
*/
|
||||
extern int mfd_shared_platform_driver_register(struct platform_driver *drv,
|
||||
const char *cellname);
|
||||
extern void mfd_shared_platform_driver_unregister(struct platform_driver *drv);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#define MAX8997_REG_INVALID (0xff)
|
||||
|
||||
enum max8997_pmic_reg {
|
||||
MAX8997_REG_PMIC_ID0 = 0x00,
|
||||
MAX8997_REG_PMIC_ID1 = 0x01,
|
||||
|
@ -313,6 +315,7 @@ enum max8997_irq {
|
|||
#define MAX8997_REG_BUCK2DVS(x) (MAX8997_REG_BUCK2DVS1 + (x) - 1)
|
||||
#define MAX8997_REG_BUCK5DVS(x) (MAX8997_REG_BUCK5DVS1 + (x) - 1)
|
||||
|
||||
#define MAX8997_NUM_GPIO 12
|
||||
struct max8997_dev {
|
||||
struct device *dev;
|
||||
struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
|
||||
|
@ -324,11 +327,19 @@ struct max8997_dev {
|
|||
int type;
|
||||
struct platform_device *battery; /* battery control (not fuel gauge) */
|
||||
|
||||
int irq;
|
||||
int ono;
|
||||
int irq_base;
|
||||
bool wakeup;
|
||||
struct mutex irqlock;
|
||||
int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
|
||||
int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
|
||||
|
||||
/* For hibernation */
|
||||
u8 reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
|
||||
MAX8997_HAPTIC_REG_END];
|
||||
|
||||
bool gpio_status[MAX8997_NUM_GPIO];
|
||||
};
|
||||
|
||||
enum max8997_types {
|
||||
|
@ -336,6 +347,10 @@ enum max8997_types {
|
|||
TYPE_MAX8966,
|
||||
};
|
||||
|
||||
extern int max8997_irq_init(struct max8997_dev *max8997);
|
||||
extern void max8997_irq_exit(struct max8997_dev *max8997);
|
||||
extern int max8997_irq_resume(struct max8997_dev *max8997);
|
||||
|
||||
extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
|
||||
extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
|
||||
u8 *buf);
|
||||
|
@ -344,4 +359,10 @@ extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
|
|||
u8 *buf);
|
||||
extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
|
||||
|
||||
#define MAX8997_GPIO_INT_BOTH (0x3 << 4)
|
||||
#define MAX8997_GPIO_INT_RISE (0x2 << 4)
|
||||
#define MAX8997_GPIO_INT_FALL (0x1 << 4)
|
||||
|
||||
#define MAX8997_GPIO_INT_MASK (0x3 << 4)
|
||||
#define MAX8997_GPIO_DATA_MASK (0x1 << 2)
|
||||
#endif /* __LINUX_MFD_MAX8997_PRIV_H */
|
||||
|
|
|
@ -78,8 +78,11 @@ struct max8997_regulator_data {
|
|||
};
|
||||
|
||||
struct max8997_platform_data {
|
||||
bool wakeup;
|
||||
/* IRQ: Not implemented */
|
||||
/* IRQ */
|
||||
int irq_base;
|
||||
int ono;
|
||||
int wakeup;
|
||||
|
||||
/* ---- PMIC ---- */
|
||||
struct max8997_regulator_data *regulators;
|
||||
int num_regulators;
|
||||
|
|
Загрузка…
Ссылка в новой задаче