aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-integrator/impd1.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-integrator/impd1.c')
-rw-r--r--arch/arm/mach-integrator/impd1.c85
1 files changed, 48 insertions, 37 deletions
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 9f82f9dcbb98..0e870ea818c4 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -23,10 +23,11 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/platform_data/clk-integrator.h> 24#include <linux/platform_data/clk-integrator.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/irqchip/arm-vic.h>
26 27
27#include <mach/lm.h>
28#include <mach/impd1.h>
29#include <asm/sizes.h> 28#include <asm/sizes.h>
29#include "lm.h"
30#include "impd1.h"
30 31
31static int module_id; 32static int module_id;
32 33
@@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
35 36
36struct impd1_module { 37struct impd1_module {
37 void __iomem *base; 38 void __iomem *base;
39 void __iomem *vic_base;
38}; 40};
39 41
40void impd1_tweak_control(struct device *dev, u32 mask, u32 val) 42void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -262,9 +264,6 @@ struct impd1_device {
262 264
263static struct impd1_device impd1_devs[] = { 265static struct impd1_device impd1_devs[] = {
264 { 266 {
265 .offset = 0x03000000,
266 .id = 0x00041190,
267 }, {
268 .offset = 0x00100000, 267 .offset = 0x00100000,
269 .irq = { 1 }, 268 .irq = { 1 },
270 .id = 0x00141011, 269 .id = 0x00141011,
@@ -304,46 +303,72 @@ static struct impd1_device impd1_devs[] = {
304 } 303 }
305}; 304};
306 305
307static int impd1_probe(struct lm_device *dev) 306/*
307 * Valid IRQs: 0 thru 9 and 11, 10 unused.
308 */
309#define IMPD1_VALID_IRQS 0x00000bffU
310
311static int __init impd1_probe(struct lm_device *dev)
308{ 312{
309 struct impd1_module *impd1; 313 struct impd1_module *impd1;
310 int i, ret; 314 int irq_base;
315 int i;
311 316
312 if (dev->id != module_id) 317 if (dev->id != module_id)
313 return -EINVAL; 318 return -EINVAL;
314 319
315 if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers")) 320 if (!devm_request_mem_region(&dev->dev, dev->resource.start,
321 SZ_4K, "LM registers"))
316 return -EBUSY; 322 return -EBUSY;
317 323
318 impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL); 324 impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module),
319 if (!impd1) { 325 GFP_KERNEL);
320 ret = -ENOMEM; 326 if (!impd1)
321 goto release_lm; 327 return -ENOMEM;
322 }
323 328
324 impd1->base = ioremap(dev->resource.start, SZ_4K); 329 impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K);
325 if (!impd1->base) { 330 if (!impd1->base)
326 ret = -ENOMEM; 331 return -ENOMEM;
327 goto free_impd1;
328 }
329 332
330 lm_set_drvdata(dev, impd1); 333 integrator_impd1_clk_init(impd1->base, dev->id);
331 334
332 printk("IM-PD1 found at 0x%08lx\n", 335 if (!devm_request_mem_region(&dev->dev,
333 (unsigned long)dev->resource.start); 336 dev->resource.start + 0x03000000,
337 SZ_4K, "VIC"))
338 return -EBUSY;
334 339
335 integrator_impd1_clk_init(impd1->base, dev->id); 340 impd1->vic_base = devm_ioremap(&dev->dev,
341 dev->resource.start + 0x03000000,
342 SZ_4K);
343 if (!impd1->vic_base)
344 return -ENOMEM;
345
346 irq_base = vic_init_cascaded(impd1->vic_base, dev->irq,
347 IMPD1_VALID_IRQS, 0);
348
349 lm_set_drvdata(dev, impd1);
350
351 dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n",
352 (unsigned long)dev->resource.start);
336 353
337 for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { 354 for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
338 struct impd1_device *idev = impd1_devs + i; 355 struct impd1_device *idev = impd1_devs + i;
339 struct amba_device *d; 356 struct amba_device *d;
340 unsigned long pc_base; 357 unsigned long pc_base;
341 char devname[32]; 358 char devname[32];
359 int irq1 = idev->irq[0];
360 int irq2 = idev->irq[1];
361
362 /* Translate IRQs to IM-PD1 local numberspace */
363 if (irq1)
364 irq1 += irq_base;
365 if (irq2)
366 irq2 += irq_base;
342 367
343 pc_base = dev->resource.start + idev->offset; 368 pc_base = dev->resource.start + idev->offset;
344 snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12); 369 snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
345 d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, 370 d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K,
346 dev->irq, dev->irq, 371 irq1, irq2,
347 idev->platform_data, idev->id, 372 idev->platform_data, idev->id,
348 &dev->resource); 373 &dev->resource);
349 if (IS_ERR(d)) { 374 if (IS_ERR(d)) {
@@ -353,14 +378,6 @@ static int impd1_probe(struct lm_device *dev)
353 } 378 }
354 379
355 return 0; 380 return 0;
356
357 free_impd1:
358 if (impd1 && impd1->base)
359 iounmap(impd1->base);
360 kfree(impd1);
361 release_lm:
362 release_mem_region(dev->resource.start, SZ_4K);
363 return ret;
364} 381}
365 382
366static int impd1_remove_one(struct device *dev, void *data) 383static int impd1_remove_one(struct device *dev, void *data)
@@ -371,16 +388,10 @@ static int impd1_remove_one(struct device *dev, void *data)
371 388
372static void impd1_remove(struct lm_device *dev) 389static void impd1_remove(struct lm_device *dev)
373{ 390{
374 struct impd1_module *impd1 = lm_get_drvdata(dev);
375
376 device_for_each_child(&dev->dev, NULL, impd1_remove_one); 391 device_for_each_child(&dev->dev, NULL, impd1_remove_one);
377 integrator_impd1_clk_exit(dev->id); 392 integrator_impd1_clk_exit(dev->id);
378 393
379 lm_set_drvdata(dev, NULL); 394 lm_set_drvdata(dev, NULL);
380
381 iounmap(impd1->base);
382 kfree(impd1);
383 release_mem_region(dev->resource.start, SZ_4K);
384} 395}
385 396
386static struct lm_driver impd1_driver = { 397static struct lm_driver impd1_driver = {