diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-11-30 18:31:04 -0500 |
---|---|---|
committer | Samuel Ortiz <samuel@sortiz.org> | 2009-01-04 06:17:39 -0500 |
commit | 5725d66b9d18e630bb63e3b76bedf25fd1027265 (patch) | |
tree | e90fbe3972de8cdbc6971ea814334c42bb0c1873 /drivers | |
parent | 4008e879e1325c29362aa2c3fa4b527273ae15a8 (diff) |
mfd: twl4030: simplified child creation code
Minor cleanup to twl4030-core: define a helper function to populate
a single child node, and use it to replace six inconsistent versions
of the same logic. Both object and source code shrink.
As part of this, some devices now have more IRQ resources: battery
charger, keypad, ADC, and USB transceiver. That helps to remove some
irq #defines that block the children's drivers code from compiling on
non-OMAP platforms.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Samuel Ortiz <sameo@openedhand.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/twl4030-core.c | 300 |
1 files changed, 84 insertions, 216 deletions
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index ef9a971e3ead..f5486cce86f4 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c | |||
@@ -352,258 +352,126 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8); | |||
352 | 352 | ||
353 | /*----------------------------------------------------------------------*/ | 353 | /*----------------------------------------------------------------------*/ |
354 | 354 | ||
355 | /* | 355 | static struct device *add_child(unsigned chip, const char *name, |
356 | * NOTE: We know the first 8 IRQs after pdata->base_irq are | 356 | void *pdata, unsigned pdata_len, |
357 | * for the PIH, and the next are for the PWR_INT SIH, since | 357 | bool can_wakeup, int irq0, int irq1) |
358 | * that's how twl_init_irq() sets things up. | ||
359 | */ | ||
360 | |||
361 | static int add_children(struct twl4030_platform_data *pdata) | ||
362 | { | 358 | { |
363 | struct platform_device *pdev = NULL; | 359 | struct platform_device *pdev; |
364 | struct twl4030_client *twl = NULL; | 360 | struct twl4030_client *twl = &twl4030_modules[chip]; |
365 | int status = 0; | 361 | int status; |
362 | |||
363 | pdev = platform_device_alloc(name, -1); | ||
364 | if (!pdev) { | ||
365 | dev_dbg(&twl->client->dev, "can't alloc dev\n"); | ||
366 | status = -ENOMEM; | ||
367 | goto err; | ||
368 | } | ||
366 | 369 | ||
367 | if (twl_has_bci() && pdata->bci) { | 370 | device_init_wakeup(&pdev->dev, can_wakeup); |
368 | twl = &twl4030_modules[3]; | 371 | pdev->dev.parent = &twl->client->dev; |
369 | 372 | ||
370 | pdev = platform_device_alloc("twl4030_bci", -1); | 373 | if (pdata) { |
371 | if (!pdev) { | 374 | status = platform_device_add_data(pdev, pdata, pdata_len); |
372 | pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME); | 375 | if (status < 0) { |
373 | status = -ENOMEM; | 376 | dev_dbg(&pdev->dev, "can't add platform_data\n"); |
374 | goto err; | 377 | goto err; |
375 | } | 378 | } |
379 | } | ||
376 | 380 | ||
377 | if (status == 0) { | 381 | if (irq0) { |
378 | pdev->dev.parent = &twl->client->dev; | 382 | struct resource r[2] = { |
379 | status = platform_device_add_data(pdev, pdata->bci, | 383 | { .start = irq0, .flags = IORESOURCE_IRQ, }, |
380 | sizeof(*pdata->bci)); | 384 | { .start = irq1, .flags = IORESOURCE_IRQ, }, |
381 | if (status < 0) { | 385 | }; |
382 | dev_dbg(&twl->client->dev, | ||
383 | "can't add bci data, %d\n", | ||
384 | status); | ||
385 | goto err; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | if (status == 0) { | ||
390 | struct resource r = { | ||
391 | .start = pdata->irq_base + 8 + 1, | ||
392 | .flags = IORESOURCE_IRQ, | ||
393 | }; | ||
394 | |||
395 | status = platform_device_add_resources(pdev, &r, 1); | ||
396 | } | ||
397 | |||
398 | if (status == 0) | ||
399 | status = platform_device_add(pdev); | ||
400 | 386 | ||
387 | status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); | ||
401 | if (status < 0) { | 388 | if (status < 0) { |
402 | platform_device_put(pdev); | 389 | dev_dbg(&pdev->dev, "can't add irqs\n"); |
403 | dev_dbg(&twl->client->dev, | ||
404 | "can't create bci dev, %d\n", | ||
405 | status); | ||
406 | goto err; | 390 | goto err; |
407 | } | 391 | } |
408 | } | 392 | } |
409 | 393 | ||
410 | if (twl_has_gpio() && pdata->gpio) { | 394 | status = platform_device_add(pdev); |
411 | twl = &twl4030_modules[1]; | ||
412 | 395 | ||
413 | pdev = platform_device_alloc("twl4030_gpio", -1); | 396 | err: |
414 | if (!pdev) { | 397 | if (status < 0) { |
415 | pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME); | 398 | platform_device_put(pdev); |
416 | status = -ENOMEM; | 399 | dev_err(&twl->client->dev, "can't add %s dev\n", name); |
417 | goto err; | 400 | return ERR_PTR(status); |
418 | } | 401 | } |
419 | 402 | return &pdev->dev; | |
420 | /* more driver model init */ | 403 | } |
421 | if (status == 0) { | ||
422 | pdev->dev.parent = &twl->client->dev; | ||
423 | /* device_init_wakeup(&pdev->dev, 1); */ | ||
424 | |||
425 | status = platform_device_add_data(pdev, pdata->gpio, | ||
426 | sizeof(*pdata->gpio)); | ||
427 | if (status < 0) { | ||
428 | dev_dbg(&twl->client->dev, | ||
429 | "can't add gpio data, %d\n", | ||
430 | status); | ||
431 | goto err; | ||
432 | } | ||
433 | } | ||
434 | 404 | ||
435 | /* GPIO module IRQ */ | 405 | /* |
436 | if (status == 0) { | 406 | * NOTE: We know the first 8 IRQs after pdata->base_irq are |
437 | struct resource r = { | 407 | * for the PIH, and the next are for the PWR_INT SIH, since |
438 | .start = pdata->irq_base + 0, | 408 | * that's how twl_init_irq() sets things up. |
439 | .flags = IORESOURCE_IRQ, | 409 | */ |
440 | }; | ||
441 | 410 | ||
442 | status = platform_device_add_resources(pdev, &r, 1); | 411 | static int add_children(struct twl4030_platform_data *pdata) |
443 | } | 412 | { |
413 | struct device *child; | ||
444 | 414 | ||
445 | if (status == 0) | 415 | if (twl_has_bci() && pdata->bci) { |
446 | status = platform_device_add(pdev); | 416 | child = add_child(3, "twl4030_bci", |
417 | pdata->bci, sizeof(*pdata->bci), | ||
418 | false, | ||
419 | /* irq0 = CHG_PRES, irq1 = BCI */ | ||
420 | pdata->irq_base + 8 + 1, pdata->irq_base + 2); | ||
421 | if (IS_ERR(child)) | ||
422 | return PTR_ERR(child); | ||
423 | } | ||
447 | 424 | ||
448 | if (status < 0) { | 425 | if (twl_has_gpio() && pdata->gpio) { |
449 | platform_device_put(pdev); | 426 | child = add_child(1, "twl4030_gpio", |
450 | dev_dbg(&twl->client->dev, | 427 | pdata->gpio, sizeof(*pdata->gpio), |
451 | "can't create gpio dev, %d\n", | 428 | false, pdata->irq_base + 0, 0); |
452 | status); | 429 | if (IS_ERR(child)) |
453 | goto err; | 430 | return PTR_ERR(child); |
454 | } | ||
455 | } | 431 | } |
456 | 432 | ||
457 | if (twl_has_keypad() && pdata->keypad) { | 433 | if (twl_has_keypad() && pdata->keypad) { |
458 | pdev = platform_device_alloc("twl4030_keypad", -1); | 434 | child = add_child(2, "twl4030_keypad", |
459 | if (pdev) { | 435 | pdata->keypad, sizeof(*pdata->keypad), |
460 | twl = &twl4030_modules[2]; | 436 | true, pdata->irq_base + 1, 0); |
461 | pdev->dev.parent = &twl->client->dev; | 437 | if (IS_ERR(child)) |
462 | device_init_wakeup(&pdev->dev, 1); | 438 | return PTR_ERR(child); |
463 | status = platform_device_add_data(pdev, pdata->keypad, | ||
464 | sizeof(*pdata->keypad)); | ||
465 | if (status < 0) { | ||
466 | dev_dbg(&twl->client->dev, | ||
467 | "can't add keypad data, %d\n", | ||
468 | status); | ||
469 | platform_device_put(pdev); | ||
470 | goto err; | ||
471 | } | ||
472 | status = platform_device_add(pdev); | ||
473 | if (status < 0) { | ||
474 | platform_device_put(pdev); | ||
475 | dev_dbg(&twl->client->dev, | ||
476 | "can't create keypad dev, %d\n", | ||
477 | status); | ||
478 | goto err; | ||
479 | } | ||
480 | } else { | ||
481 | pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME); | ||
482 | status = -ENOMEM; | ||
483 | goto err; | ||
484 | } | ||
485 | } | 439 | } |
486 | 440 | ||
487 | if (twl_has_madc() && pdata->madc) { | 441 | if (twl_has_madc() && pdata->madc) { |
488 | pdev = platform_device_alloc("twl4030_madc", -1); | 442 | child = add_child(2, "twl4030_madc", |
489 | if (pdev) { | 443 | pdata->madc, sizeof(*pdata->madc), |
490 | twl = &twl4030_modules[2]; | 444 | true, pdata->irq_base + 3, 0); |
491 | pdev->dev.parent = &twl->client->dev; | 445 | if (IS_ERR(child)) |
492 | device_init_wakeup(&pdev->dev, 1); | 446 | return PTR_ERR(child); |
493 | status = platform_device_add_data(pdev, pdata->madc, | ||
494 | sizeof(*pdata->madc)); | ||
495 | if (status < 0) { | ||
496 | platform_device_put(pdev); | ||
497 | dev_dbg(&twl->client->dev, | ||
498 | "can't add madc data, %d\n", | ||
499 | status); | ||
500 | goto err; | ||
501 | } | ||
502 | status = platform_device_add(pdev); | ||
503 | if (status < 0) { | ||
504 | platform_device_put(pdev); | ||
505 | dev_dbg(&twl->client->dev, | ||
506 | "can't create madc dev, %d\n", | ||
507 | status); | ||
508 | goto err; | ||
509 | } | ||
510 | } else { | ||
511 | pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME); | ||
512 | status = -ENOMEM; | ||
513 | goto err; | ||
514 | } | ||
515 | } | 447 | } |
516 | 448 | ||
517 | if (twl_has_rtc()) { | 449 | if (twl_has_rtc()) { |
518 | twl = &twl4030_modules[3]; | ||
519 | |||
520 | pdev = platform_device_alloc("twl4030_rtc", -1); | ||
521 | if (!pdev) { | ||
522 | pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME); | ||
523 | status = -ENOMEM; | ||
524 | } else { | ||
525 | pdev->dev.parent = &twl->client->dev; | ||
526 | device_init_wakeup(&pdev->dev, 1); | ||
527 | } | ||
528 | |||
529 | /* | 450 | /* |
530 | * REVISIT platform_data here currently might use of | 451 | * REVISIT platform_data here currently might expose the |
531 | * "msecure" line ... but for now we just expect board | 452 | * "msecure" line ... but for now we just expect board |
532 | * setup to tell the chip "we are secure" at all times. | 453 | * setup to tell the chip "it's always ok to SET_TIME". |
533 | * Eventually, Linux might become more aware of such | 454 | * Eventually, Linux might become more aware of such |
534 | * HW security concerns, and "least privilege". | 455 | * HW security concerns, and "least privilege". |
535 | */ | 456 | */ |
536 | 457 | child = add_child(3, "twl4030_rtc", | |
537 | /* RTC module IRQ */ | 458 | NULL, 0, |
538 | if (status == 0) { | 459 | true, pdata->irq_base + 8 + 3, 0); |
539 | struct resource r = { | 460 | if (IS_ERR(child)) |
540 | .start = pdata->irq_base + 8 + 3, | 461 | return PTR_ERR(child); |
541 | .flags = IORESOURCE_IRQ, | ||
542 | }; | ||
543 | |||
544 | status = platform_device_add_resources(pdev, &r, 1); | ||
545 | } | ||
546 | |||
547 | if (status == 0) | ||
548 | status = platform_device_add(pdev); | ||
549 | |||
550 | if (status < 0) { | ||
551 | platform_device_put(pdev); | ||
552 | dev_dbg(&twl->client->dev, | ||
553 | "can't create rtc dev, %d\n", | ||
554 | status); | ||
555 | goto err; | ||
556 | } | ||
557 | } | 462 | } |
558 | 463 | ||
559 | if (twl_has_usb() && pdata->usb) { | 464 | if (twl_has_usb() && pdata->usb) { |
560 | twl = &twl4030_modules[0]; | 465 | child = add_child(0, "twl4030_usb", |
561 | 466 | pdata->usb, sizeof(*pdata->usb), | |
562 | pdev = platform_device_alloc("twl4030_usb", -1); | 467 | true, |
563 | if (!pdev) { | 468 | /* irq0 = USB_PRES, irq1 = USB */ |
564 | pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME); | 469 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); |
565 | status = -ENOMEM; | 470 | if (IS_ERR(child)) |
566 | goto err; | 471 | return PTR_ERR(child); |
567 | } | ||
568 | |||
569 | if (status == 0) { | ||
570 | pdev->dev.parent = &twl->client->dev; | ||
571 | device_init_wakeup(&pdev->dev, 1); | ||
572 | status = platform_device_add_data(pdev, pdata->usb, | ||
573 | sizeof(*pdata->usb)); | ||
574 | if (status < 0) { | ||
575 | platform_device_put(pdev); | ||
576 | dev_dbg(&twl->client->dev, | ||
577 | "can't add usb data, %d\n", | ||
578 | status); | ||
579 | goto err; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (status == 0) { | ||
584 | struct resource r = { | ||
585 | .start = pdata->irq_base + 8 + 2, | ||
586 | .flags = IORESOURCE_IRQ, | ||
587 | }; | ||
588 | |||
589 | status = platform_device_add_resources(pdev, &r, 1); | ||
590 | } | ||
591 | |||
592 | if (status == 0) | ||
593 | status = platform_device_add(pdev); | ||
594 | |||
595 | if (status < 0) { | ||
596 | platform_device_put(pdev); | ||
597 | dev_dbg(&twl->client->dev, | ||
598 | "can't create usb dev, %d\n", | ||
599 | status); | ||
600 | } | ||
601 | } | 472 | } |
602 | 473 | ||
603 | err: | 474 | return 0; |
604 | if (status) | ||
605 | pr_err("failed to add twl4030's children (status %d)\n", status); | ||
606 | return status; | ||
607 | } | 475 | } |
608 | 476 | ||
609 | /*----------------------------------------------------------------------*/ | 477 | /*----------------------------------------------------------------------*/ |