aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2011-06-02 21:14:26 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-07-31 17:28:21 -0400
commit914e6d4e36015180bdcb6b99e96adc6293b7c2c6 (patch)
treefc2f37fcb8ab369a5bcbdcb5c4a8877e01111f16 /drivers/mfd
parentf85dbda076a11c18b396f8acfff929e53159e56d (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/Kconfig3
-rw-r--r--drivers/mfd/jz4740-adc.c90
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
664config MFD_JZ4740_ADC 664config 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
67static 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
87static 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
93static 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
99static 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
106static 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
113static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) 67static 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
250static int __devinit jz4740_adc_probe(struct platform_device *pdev) 204static 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