Commit 914e6d4e authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Samuel Ortiz

mfd: Use generic irq chip for jz4740-adc

Use the generic irq chip framework for implementing the irq chip for
the jz4740-adc driver.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent f85dbda0
...@@ -662,8 +662,9 @@ config MFD_JANZ_CMODIO ...@@ -662,8 +662,9 @@ config MFD_JANZ_CMODIO
CAN and GPIO controllers. CAN and GPIO controllers.
config MFD_JZ4740_ADC config MFD_JZ4740_ADC
tristate "Support for the JZ4740 SoC ADC core" bool "Support for the JZ4740 SoC ADC core"
select MFD_CORE select MFD_CORE
select GENERIC_IRQ_CHIP
depends on MACH_JZ4740 depends on MACH_JZ4740
help help
Say yes here if you want support for the ADC unit in the JZ4740 SoC. Say yes here if you want support for the ADC unit in the JZ4740 SoC.
......
...@@ -56,7 +56,7 @@ struct jz4740_adc { ...@@ -56,7 +56,7 @@ struct jz4740_adc {
void __iomem *base; void __iomem *base;
int irq; int irq;
int irq_base; struct irq_chip_generic *gc;
struct clk *clk; struct clk *clk;
atomic_t clk_ref; atomic_t clk_ref;
...@@ -64,63 +64,17 @@ struct jz4740_adc { ...@@ -64,63 +64,17 @@ struct jz4740_adc {
spinlock_t lock; spinlock_t lock;
}; };
static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq,
bool masked)
{
unsigned long flags;
uint8_t val;
irq -= adc->irq_base;
spin_lock_irqsave(&adc->lock, flags);
val = readb(adc->base + JZ_REG_ADC_CTRL);
if (masked)
val |= BIT(irq);
else
val &= ~BIT(irq);
writeb(val, adc->base + JZ_REG_ADC_CTRL);
spin_unlock_irqrestore(&adc->lock, flags);
}
static void jz4740_adc_irq_mask(struct irq_data *data)
{
struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
jz4740_adc_irq_set_masked(adc, data->irq, true);
}
static void jz4740_adc_irq_unmask(struct irq_data *data)
{
struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
jz4740_adc_irq_set_masked(adc, data->irq, false);
}
static void jz4740_adc_irq_ack(struct irq_data *data)
{
struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
unsigned int irq = data->irq - adc->irq_base;
writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS);
}
static struct irq_chip jz4740_adc_irq_chip = {
.name = "jz4740-adc",
.irq_mask = jz4740_adc_irq_mask,
.irq_unmask = jz4740_adc_irq_unmask,
.irq_ack = jz4740_adc_irq_ack,
};
static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
{ {
struct jz4740_adc *adc = irq_desc_get_handler_data(desc); struct irq_chip_generic *gc = irq_desc_get_handler_data(desc);
uint8_t status; uint8_t status;
unsigned int i; unsigned int i;
status = readb(adc->base + JZ_REG_ADC_STATUS); status = readb(gc->reg_base + JZ_REG_ADC_STATUS);
for (i = 0; i < 5; ++i) { for (i = 0; i < 5; ++i) {
if (status & BIT(i)) if (status & BIT(i))
generic_handle_irq(adc->irq_base + i); generic_handle_irq(gc->irq_base + i);
} }
} }
...@@ -249,10 +203,12 @@ const struct mfd_cell jz4740_adc_cells[] = { ...@@ -249,10 +203,12 @@ const struct mfd_cell jz4740_adc_cells[] = {
static int __devinit jz4740_adc_probe(struct platform_device *pdev) static int __devinit jz4740_adc_probe(struct platform_device *pdev)
{ {
int ret; struct irq_chip_generic *gc;
struct irq_chip_type *ct;
struct jz4740_adc *adc; struct jz4740_adc *adc;
struct resource *mem_base; struct resource *mem_base;
int irq; int ret;
int irq_base;
adc = kmalloc(sizeof(*adc), GFP_KERNEL); adc = kmalloc(sizeof(*adc), GFP_KERNEL);
if (!adc) { if (!adc) {
...@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) ...@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
goto err_free; goto err_free;
} }
adc->irq_base = platform_get_irq(pdev, 1); irq_base = platform_get_irq(pdev, 1);
if (adc->irq_base < 0) { if (irq_base < 0) {
ret = adc->irq_base; ret = irq_base;
dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
goto err_free; goto err_free;
} }
...@@ -309,20 +265,28 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) ...@@ -309,20 +265,28 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, adc); platform_set_drvdata(pdev, adc);
for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
irq_set_chip_data(irq, adc);
irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
handle_level_irq); handle_level_irq);
}
irq_set_handler_data(adc->irq, adc); ct = gc->chip_types;
ct->regs.mask = JZ_REG_ADC_CTRL;
ct->regs.ack = JZ_REG_ADC_STATUS;
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
ct->chip.irq_ack = irq_gc_ack;
irq_setup_generic_chip(gc, IRQ_MSK(5), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
adc->gc = gc;
irq_set_handler_data(adc->irq, gc);
irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux); irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);
writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
writeb(0xff, adc->base + JZ_REG_ADC_CTRL); writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base);
if (ret < 0) if (ret < 0)
goto err_clk_put; goto err_clk_put;
...@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev) ...@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
irq_remove_generic_chip(adc->gc, IRQ_MSK(5), IRQ_NOPROBE | IRQ_LEVEL, 0);
kfree(adc->gc);
irq_set_handler_data(adc->irq, NULL); irq_set_handler_data(adc->irq, NULL);
irq_set_chained_handler(adc->irq, NULL); irq_set_chained_handler(adc->irq, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment