diff options
Diffstat (limited to 'arch/arm/mach-integrator/impd1.c')
-rw-r--r-- | arch/arm/mach-integrator/impd1.c | 85 |
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 | ||
31 | static int module_id; | 32 | static int module_id; |
32 | 33 | ||
@@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position"); | |||
35 | 36 | ||
36 | struct impd1_module { | 37 | struct impd1_module { |
37 | void __iomem *base; | 38 | void __iomem *base; |
39 | void __iomem *vic_base; | ||
38 | }; | 40 | }; |
39 | 41 | ||
40 | void impd1_tweak_control(struct device *dev, u32 mask, u32 val) | 42 | void impd1_tweak_control(struct device *dev, u32 mask, u32 val) |
@@ -262,9 +264,6 @@ struct impd1_device { | |||
262 | 264 | ||
263 | static struct impd1_device impd1_devs[] = { | 265 | static 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 | ||
307 | static 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 | |||
311 | static 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 | ||
366 | static int impd1_remove_one(struct device *dev, void *data) | 383 | static 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 | ||
372 | static void impd1_remove(struct lm_device *dev) | 389 | static 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 | ||
386 | static struct lm_driver impd1_driver = { | 397 | static struct lm_driver impd1_driver = { |