|
@@ -56,7 +56,7 @@ struct jz4740_adc {
|
|
|
void __iomem *base;
|
|
|
|
|
|
int irq;
|
|
|
- int irq_base;
|
|
|
+ struct irq_chip_generic *gc;
|
|
|
|
|
|
struct clk *clk;
|
|
|
atomic_t clk_ref;
|
|
@@ -64,63 +64,17 @@ struct jz4740_adc {
|
|
|
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)
|
|
|
{
|
|
|
- struct jz4740_adc *adc = irq_desc_get_handler_data(desc);
|
|
|
+ struct irq_chip_generic *gc = irq_desc_get_handler_data(desc);
|
|
|
uint8_t status;
|
|
|
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) {
|
|
|
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)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ struct irq_chip_generic *gc;
|
|
|
+ struct irq_chip_type *ct;
|
|
|
struct jz4740_adc *adc;
|
|
|
struct resource *mem_base;
|
|
|
- int irq;
|
|
|
+ int ret;
|
|
|
+ int irq_base;
|
|
|
|
|
|
adc = kmalloc(sizeof(*adc), GFP_KERNEL);
|
|
|
if (!adc) {
|
|
@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
|
|
|
goto err_free;
|
|
|
}
|
|
|
|
|
|
- adc->irq_base = platform_get_irq(pdev, 1);
|
|
|
- if (adc->irq_base < 0) {
|
|
|
- ret = adc->irq_base;
|
|
|
+ irq_base = platform_get_irq(pdev, 1);
|
|
|
+ if (irq_base < 0) {
|
|
|
+ ret = irq_base;
|
|
|
dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
|
|
|
goto err_free;
|
|
|
}
|
|
@@ -309,20 +265,28 @@ 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) {
|
|
|
- irq_set_chip_data(irq, adc);
|
|
|
- irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
|
|
|
- handle_level_irq);
|
|
|
- }
|
|
|
+ gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
|
|
|
+ handle_level_irq);
|
|
|
+
|
|
|
+ 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, adc);
|
|
|
+ irq_set_handler_data(adc->irq, gc);
|
|
|
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);
|
|
|
|
|
|
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)
|
|
|
goto err_clk_put;
|
|
|
|
|
@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
|
|
|
|
|
|
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_chained_handler(adc->irq, NULL);
|
|
|
|