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: Lars-Peter Clausen <lars@metafoo.de> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
f85dbda076
commit
914e6d4e36
2 changed files with 30 additions and 63 deletions
|
@ -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 {
|
||||||
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 {
|
||||||
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[] = {
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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);
|
handle_level_irq);
|
||||||
irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
|
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue