Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -662,8 +662,9 @@ config MFD_JANZ_CMODIO
	  CAN and GPIO controllers.

config MFD_JZ4740_ADC
	tristate "Support for the JZ4740 SoC ADC core"
	bool "Support for the JZ4740 SoC ADC core"
	select MFD_CORE
	select GENERIC_IRQ_CHIP
	depends on MACH_JZ4740
	help
	  Say yes here if you want support for the ADC unit in the JZ4740 SoC.
+28 −62
Original line number Diff line number Diff line
@@ -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,
	gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
		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);

	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);