aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/twl4030-core.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-11-30 18:31:04 -0500
committerSamuel Ortiz <samuel@sortiz.org>2009-01-04 06:17:39 -0500
commit5725d66b9d18e630bb63e3b76bedf25fd1027265 (patch)
treee90fbe3972de8cdbc6971ea814334c42bb0c1873 /drivers/mfd/twl4030-core.c
parent4008e879e1325c29362aa2c3fa4b527273ae15a8 (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/mfd/twl4030-core.c')
-rw-r--r--drivers/mfd/twl4030-core.c300
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/* 355static 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
361static 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); 396err:
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); 411static 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
603err: 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/*----------------------------------------------------------------------*/