diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2011-06-02 21:14:26 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-07-31 17:28:21 -0400 |
commit | 914e6d4e36015180bdcb6b99e96adc6293b7c2c6 (patch) | |
tree | fc2f37fcb8ab369a5bcbdcb5c4a8877e01111f16 /drivers/mfd | |
parent | f85dbda076a11c18b396f8acfff929e53159e56d (diff) |
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>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mfd/jz4740-adc.c | 90 |
2 files changed, 30 insertions, 63 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 37b83eb6d703..1e2c9f03629b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -662,8 +662,9 @@ config MFD_JANZ_CMODIO | |||
662 | CAN and GPIO controllers. | 662 | CAN and GPIO controllers. |
663 | 663 | ||
664 | config MFD_JZ4740_ADC | 664 | config MFD_JZ4740_ADC |
665 | tristate "Support for the JZ4740 SoC ADC core" | 665 | bool "Support for the JZ4740 SoC ADC core" |
666 | select MFD_CORE | 666 | select MFD_CORE |
667 | select GENERIC_IRQ_CHIP | ||
667 | depends on MACH_JZ4740 | 668 | depends on MACH_JZ4740 |
668 | help | 669 | help |
669 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | 670 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index a0bd0cf05af3..21131c7b0f1e 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -56,7 +56,7 @@ struct jz4740_adc { | |||
56 | void __iomem *base; | 56 | void __iomem *base; |
57 | 57 | ||
58 | int irq; | 58 | int irq; |
59 | int irq_base; | 59 | struct irq_chip_generic *gc; |
60 | 60 | ||
61 | struct clk *clk; | 61 | struct clk *clk; |
62 | atomic_t clk_ref; | 62 | atomic_t clk_ref; |
@@ -64,63 +64,17 @@ struct jz4740_adc { | |||
64 | spinlock_t lock; | 64 | spinlock_t lock; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, | ||
68 | bool masked) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | uint8_t val; | ||
72 | |||
73 | irq -= adc->irq_base; | ||
74 | |||
75 | spin_lock_irqsave(&adc->lock, flags); | ||
76 | |||
77 | val = readb(adc->base + JZ_REG_ADC_CTRL); | ||
78 | if (masked) | ||
79 | val |= BIT(irq); | ||
80 | else | ||
81 | val &= ~BIT(irq); | ||
82 | writeb(val, adc->base + JZ_REG_ADC_CTRL); | ||
83 | |||
84 | spin_unlock_irqrestore(&adc->lock, flags); | ||
85 | } | ||
86 | |||
87 | static void jz4740_adc_irq_mask(struct irq_data *data) | ||
88 | { | ||
89 | struct jz4740_adc *adc = irq_data_get_irq_chip_data(data); | ||
90 | jz4740_adc_irq_set_masked(adc, data->irq, true); | ||
91 | } | ||
92 | |||
93 | static void jz4740_adc_irq_unmask(struct irq_data *data) | ||
94 | { | ||
95 | struct jz4740_adc *adc = irq_data_get_irq_chip_data(data); | ||
96 | jz4740_adc_irq_set_masked(adc, data->irq, false); | ||
97 | } | ||
98 | |||
99 | static void jz4740_adc_irq_ack(struct irq_data *data) | ||
100 | { | ||
101 | struct jz4740_adc *adc = irq_data_get_irq_chip_data(data); | ||
102 | unsigned int irq = data->irq - adc->irq_base; | ||
103 | writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); | ||
104 | } | ||
105 | |||
106 | static struct irq_chip jz4740_adc_irq_chip = { | ||
107 | .name = "jz4740-adc", | ||
108 | .irq_mask = jz4740_adc_irq_mask, | ||
109 | .irq_unmask = jz4740_adc_irq_unmask, | ||
110 | .irq_ack = jz4740_adc_irq_ack, | ||
111 | }; | ||
112 | |||
113 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) | 67 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) |
114 | { | 68 | { |
115 | struct jz4740_adc *adc = irq_desc_get_handler_data(desc); | 69 | struct irq_chip_generic *gc = irq_desc_get_handler_data(desc); |
116 | uint8_t status; | 70 | uint8_t status; |
117 | unsigned int i; | 71 | unsigned int i; |
118 | 72 | ||
119 | status = readb(adc->base + JZ_REG_ADC_STATUS); | 73 | status = readb(gc->reg_base + JZ_REG_ADC_STATUS); |
120 | 74 | ||
121 | for (i = 0; i < 5; ++i) { | 75 | for (i = 0; i < 5; ++i) { |
122 | if (status & BIT(i)) | 76 | if (status & BIT(i)) |
123 | generic_handle_irq(adc->irq_base + i); | 77 | generic_handle_irq(gc->irq_base + i); |
124 | } | 78 | } |
125 | } | 79 | } |
126 | 80 | ||
@@ -249,10 +203,12 @@ const struct mfd_cell jz4740_adc_cells[] = { | |||
249 | 203 | ||
250 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) | 204 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) |
251 | { | 205 | { |
252 | int ret; | 206 | struct irq_chip_generic *gc; |
207 | struct irq_chip_type *ct; | ||
253 | struct jz4740_adc *adc; | 208 | struct jz4740_adc *adc; |
254 | struct resource *mem_base; | 209 | struct resource *mem_base; |
255 | int irq; | 210 | int ret; |
211 | int irq_base; | ||
256 | 212 | ||
257 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); | 213 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); |
258 | if (!adc) { | 214 | if (!adc) { |
@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) | |||
267 | goto err_free; | 223 | goto err_free; |
268 | } | 224 | } |
269 | 225 | ||
270 | adc->irq_base = platform_get_irq(pdev, 1); | 226 | irq_base = platform_get_irq(pdev, 1); |
271 | if (adc->irq_base < 0) { | 227 | if (irq_base < 0) { |
272 | ret = adc->irq_base; | 228 | ret = irq_base; |
273 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); | 229 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); |
274 | goto err_free; | 230 | goto err_free; |
275 | } | 231 | } |
@@ -309,20 +265,28 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) | |||
309 | 265 | ||
310 | platform_set_drvdata(pdev, adc); | 266 | platform_set_drvdata(pdev, adc); |
311 | 267 | ||
312 | for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { | 268 | gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base, |
313 | irq_set_chip_data(irq, adc); | 269 | handle_level_irq); |
314 | irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip, | 270 | |
315 | handle_level_irq); | 271 | ct = gc->chip_types; |
316 | } | 272 | ct->regs.mask = JZ_REG_ADC_CTRL; |
273 | ct->regs.ack = JZ_REG_ADC_STATUS; | ||
274 | ct->chip.irq_mask = irq_gc_mask_set_bit; | ||
275 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; | ||
276 | ct->chip.irq_ack = irq_gc_ack; | ||
277 | |||
278 | irq_setup_generic_chip(gc, IRQ_MSK(5), 0, 0, IRQ_NOPROBE | IRQ_LEVEL); | ||
279 | |||
280 | adc->gc = gc; | ||
317 | 281 | ||
318 | irq_set_handler_data(adc->irq, adc); | 282 | irq_set_handler_data(adc->irq, gc); |
319 | irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux); | 283 | irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux); |
320 | 284 | ||
321 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); | 285 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); |
322 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); | 286 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); |
323 | 287 | ||
324 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, | 288 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, |
325 | ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); | 289 | ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); |
326 | if (ret < 0) | 290 | if (ret < 0) |
327 | goto err_clk_put; | 291 | goto err_clk_put; |
328 | 292 | ||
@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev) | |||
347 | 311 | ||
348 | mfd_remove_devices(&pdev->dev); | 312 | mfd_remove_devices(&pdev->dev); |
349 | 313 | ||
314 | irq_remove_generic_chip(adc->gc, IRQ_MSK(5), IRQ_NOPROBE | IRQ_LEVEL, 0); | ||
315 | kfree(adc->gc); | ||
350 | irq_set_handler_data(adc->irq, NULL); | 316 | irq_set_handler_data(adc->irq, NULL); |
351 | irq_set_chained_handler(adc->irq, NULL); | 317 | irq_set_chained_handler(adc->irq, NULL); |
352 | 318 | ||