diff options
69 files changed, 5204 insertions, 2102 deletions
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index db9374bc528b..e508904fb67e 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
20 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/i2c/twl4030.h> | 22 | #include <linux/i2c/twl.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 4cfb7b68dfad..c90b0d0b1927 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/input/matrix_keypad.h> | 20 | #include <linux/input/matrix_keypad.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/spi/ads7846.h> | 22 | #include <linux/spi/ads7846.h> |
23 | #include <linux/i2c/twl4030.h> | 23 | #include <linux/i2c/twl.h> |
24 | #include <linux/regulator/machine.h> | 24 | #include <linux/regulator/machine.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 37431738f1c2..995d4a2b2dfd 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/spi/ads7846.h> | 25 | #include <linux/spi/ads7846.h> |
26 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
27 | #include <linux/i2c/twl4030.h> | 27 | #include <linux/i2c/twl.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/smsc911x.h> | 29 | #include <linux/smsc911x.h> |
30 | 30 | ||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 6ada8029f9a8..231cb4ec1847 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/mtd/nand.h> | 29 | #include <linux/mtd/nand.h> |
30 | 30 | ||
31 | #include <linux/regulator/machine.h> | 31 | #include <linux/regulator/machine.h> |
32 | #include <linux/i2c/twl4030.h> | 32 | #include <linux/i2c/twl.h> |
33 | 33 | ||
34 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
35 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 6f6c601eeab7..ef17cf1ab6d7 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/spi/ads7846.h> | 25 | #include <linux/spi/ads7846.h> |
26 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
27 | #include <linux/i2c/twl4030.h> | 27 | #include <linux/i2c/twl.h> |
28 | #include <linux/leds.h> | 28 | #include <linux/leds.h> |
29 | #include <linux/input.h> | 29 | #include <linux/input.h> |
30 | #include <linux/input/matrix_keypad.h> | 30 | #include <linux/input/matrix_keypad.h> |
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 5b78a87217e0..d192dd98a591 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/i2c/twl4030.h> | 29 | #include <linux/i2c/twl.h> |
30 | #include <linux/regulator/machine.h> | 30 | #include <linux/regulator/machine.h> |
31 | 31 | ||
32 | #include <linux/mtd/mtd.h> | 32 | #include <linux/mtd/mtd.h> |
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bf26ad31f9ba..17f3c91231db 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | |||
@@ -402,15 +402,9 @@ static struct twl4030_usb_data rx51_usb_data = { | |||
402 | 402 | ||
403 | static struct twl4030_ins sleep_on_seq[] __initdata = { | 403 | static struct twl4030_ins sleep_on_seq[] __initdata = { |
404 | /* | 404 | /* |
405 | * Turn off VDD1 and VDD2. | 405 | * Turn off everything |
406 | */ | 406 | */ |
407 | {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_OFF), 4}, | 407 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_SLEEP), 2}, |
408 | {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_OFF), 2}, | ||
409 | /* | ||
410 | * And also turn off the OMAP3 PLLs and the sysclk output. | ||
411 | */ | ||
412 | {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_OFF), 3}, | ||
413 | {MSG_SINGULAR(DEV_GRP_P1, 0x17, RES_STATE_OFF), 3}, | ||
414 | }; | 408 | }; |
415 | 409 | ||
416 | static struct twl4030_script sleep_on_script __initdata = { | 410 | static struct twl4030_script sleep_on_script __initdata = { |
@@ -421,14 +415,9 @@ static struct twl4030_script sleep_on_script __initdata = { | |||
421 | 415 | ||
422 | static struct twl4030_ins wakeup_seq[] __initdata = { | 416 | static struct twl4030_ins wakeup_seq[] __initdata = { |
423 | /* | 417 | /* |
424 | * Reenable the OMAP3 PLLs. | 418 | * Reenable everything |
425 | * Wakeup VDD1 and VDD2. | ||
426 | * Reenable sysclk output. | ||
427 | */ | 419 | */ |
428 | {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_ACTIVE), 0x30}, | 420 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, |
429 | {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 0x30}, | ||
430 | {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 0x37}, | ||
431 | {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 3}, | ||
432 | }; | 421 | }; |
433 | 422 | ||
434 | static struct twl4030_script wakeup_script __initdata = { | 423 | static struct twl4030_script wakeup_script __initdata = { |
@@ -439,10 +428,9 @@ static struct twl4030_script wakeup_script __initdata = { | |||
439 | 428 | ||
440 | static struct twl4030_ins wakeup_p3_seq[] __initdata = { | 429 | static struct twl4030_ins wakeup_p3_seq[] __initdata = { |
441 | /* | 430 | /* |
442 | * Wakeup VDD1 (dummy to be able to insert a delay) | 431 | * Reenable everything |
443 | * Enable CLKEN | ||
444 | */ | 432 | */ |
445 | {MSG_SINGULAR(DEV_GRP_P1, 0x17, RES_STATE_ACTIVE), 3}, | 433 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, |
446 | }; | 434 | }; |
447 | 435 | ||
448 | static struct twl4030_script wakeup_p3_script __initdata = { | 436 | static struct twl4030_script wakeup_p3_script __initdata = { |
@@ -463,12 +451,11 @@ static struct twl4030_ins wrst_seq[] __initdata = { | |||
463 | {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, | 451 | {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, |
464 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_ACTIVE), | 452 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_ACTIVE), |
465 | 0x13}, | 453 | 0x13}, |
466 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 2, RES_STATE_WRST), 0x13}, | ||
467 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x13}, | 454 | {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x13}, |
468 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x13}, | 455 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x13}, |
469 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x13}, | 456 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x13}, |
470 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x35}, | 457 | {MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x35}, |
471 | {MSG_SINGULAR(DEV_GRP_P1, RES_HFCLKOUT, RES_STATE_ACTIVE), 2}, | 458 | {MSG_SINGULAR(DEV_GRP_P3, RES_HFCLKOUT, RES_STATE_ACTIVE), 2}, |
472 | {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, | 459 | {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, |
473 | }; | 460 | }; |
474 | 461 | ||
@@ -490,22 +477,81 @@ static struct twl4030_script *twl4030_scripts[] __initdata = { | |||
490 | }; | 477 | }; |
491 | 478 | ||
492 | static struct twl4030_resconfig twl4030_rconfig[] __initdata = { | 479 | static struct twl4030_resconfig twl4030_rconfig[] __initdata = { |
493 | { .resource = RES_VINTANA1, .devgroup = -1, .type = -1, .type2 = 1 }, | 480 | { .resource = RES_VDD1, .devgroup = -1, |
494 | { .resource = RES_VINTANA2, .devgroup = -1, .type = -1, .type2 = 1 }, | 481 | .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, |
495 | { .resource = RES_VINTDIG, .devgroup = -1, .type = -1, .type2 = 1 }, | 482 | .remap_sleep = RES_STATE_OFF |
496 | { .resource = RES_VMMC1, .devgroup = -1, .type = -1, .type2 = 3}, | 483 | }, |
497 | { .resource = RES_VMMC2, .devgroup = DEV_GRP_NULL, .type = -1, | 484 | { .resource = RES_VDD2, .devgroup = -1, |
498 | .type2 = 3}, | 485 | .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, |
499 | { .resource = RES_VAUX1, .devgroup = -1, .type = -1, .type2 = 3}, | 486 | .remap_sleep = RES_STATE_OFF |
500 | { .resource = RES_VAUX2, .devgroup = -1, .type = -1, .type2 = 3}, | 487 | }, |
501 | { .resource = RES_VAUX3, .devgroup = -1, .type = -1, .type2 = 3}, | 488 | { .resource = RES_VPLL1, .devgroup = -1, |
502 | { .resource = RES_VAUX4, .devgroup = -1, .type = -1, .type2 = 3}, | 489 | .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, |
503 | { .resource = RES_VPLL2, .devgroup = -1, .type = -1, .type2 = 3}, | 490 | .remap_sleep = RES_STATE_OFF |
504 | { .resource = RES_VDAC, .devgroup = -1, .type = -1, .type2 = 3}, | 491 | }, |
505 | { .resource = RES_VSIM, .devgroup = DEV_GRP_NULL, .type = -1, | 492 | { .resource = RES_VPLL2, .devgroup = -1, |
506 | .type2 = 3}, | 493 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 |
507 | { .resource = RES_CLKEN, .devgroup = DEV_GRP_P3, .type = -1, | 494 | }, |
508 | .type2 = 1 }, | 495 | { .resource = RES_VAUX1, .devgroup = -1, |
496 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
497 | }, | ||
498 | { .resource = RES_VAUX2, .devgroup = -1, | ||
499 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
500 | }, | ||
501 | { .resource = RES_VAUX3, .devgroup = -1, | ||
502 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
503 | }, | ||
504 | { .resource = RES_VAUX4, .devgroup = -1, | ||
505 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
506 | }, | ||
507 | { .resource = RES_VMMC1, .devgroup = -1, | ||
508 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
509 | }, | ||
510 | { .resource = RES_VMMC2, .devgroup = -1, | ||
511 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
512 | }, | ||
513 | { .resource = RES_VDAC, .devgroup = -1, | ||
514 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
515 | }, | ||
516 | { .resource = RES_VSIM, .devgroup = -1, | ||
517 | .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 | ||
518 | }, | ||
519 | { .resource = RES_VINTANA1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
520 | .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
521 | }, | ||
522 | { .resource = RES_VINTANA2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
523 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
524 | }, | ||
525 | { .resource = RES_VINTDIG, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
526 | .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
527 | }, | ||
528 | { .resource = RES_VIO, .devgroup = DEV_GRP_P3, | ||
529 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
530 | }, | ||
531 | { .resource = RES_CLKEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
532 | .type = 1, .type2 = -1 , .remap_off = -1, .remap_sleep = -1 | ||
533 | }, | ||
534 | { .resource = RES_REGEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
535 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
536 | }, | ||
537 | { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
538 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
539 | }, | ||
540 | { .resource = RES_SYSEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
541 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
542 | }, | ||
543 | { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, | ||
544 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
545 | }, | ||
546 | { .resource = RES_32KCLKOUT, .devgroup = -1, | ||
547 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
548 | }, | ||
549 | { .resource = RES_RESET, .devgroup = -1, | ||
550 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
551 | }, | ||
552 | { .resource = RES_Main_Ref, .devgroup = -1, | ||
553 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
554 | }, | ||
509 | { 0, 0}, | 555 | { 0, 0}, |
510 | }; | 556 | }; |
511 | 557 | ||
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index ce5dd2d1dc21..97d6c50c3dcb 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h | |||
@@ -472,8 +472,22 @@ | |||
472 | #endif | 472 | #endif |
473 | #define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS) | 473 | #define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS) |
474 | 474 | ||
475 | #define TWL6030_IRQ_BASE (OMAP_FPGA_IRQ_END) | ||
476 | #ifdef CONFIG_TWL4030_CORE | ||
477 | #define TWL6030_BASE_NR_IRQS 20 | ||
478 | #else | ||
479 | #define TWL6030_BASE_NR_IRQS 0 | ||
480 | #endif | ||
481 | #define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) | ||
482 | |||
475 | /* Total number of interrupts depends on the enabled blocks above */ | 483 | /* Total number of interrupts depends on the enabled blocks above */ |
476 | #define NR_IRQS TWL4030_GPIO_IRQ_END | 484 | #if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) |
485 | #define TWL_IRQ_END TWL4030_GPIO_IRQ_END | ||
486 | #else | ||
487 | #define TWL_IRQ_END TWL6030_IRQ_END | ||
488 | #endif | ||
489 | |||
490 | #define NR_IRQS TWL_IRQ_END | ||
477 | 491 | ||
478 | #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) | 492 | #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) |
479 | 493 | ||
diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/adp5520-gpio.c index ad05bbc7ffd5..0f93105873cd 100644 --- a/drivers/gpio/adp5520-gpio.c +++ b/drivers/gpio/adp5520-gpio.c | |||
@@ -34,9 +34,9 @@ static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) | |||
34 | */ | 34 | */ |
35 | 35 | ||
36 | if (test_bit(off, &dev->output)) | 36 | if (test_bit(off, &dev->output)) |
37 | adp5520_read(dev->master, GPIO_OUT, ®_val); | 37 | adp5520_read(dev->master, ADP5520_GPIO_OUT, ®_val); |
38 | else | 38 | else |
39 | adp5520_read(dev->master, GPIO_IN, ®_val); | 39 | adp5520_read(dev->master, ADP5520_GPIO_IN, ®_val); |
40 | 40 | ||
41 | return !!(reg_val & dev->lut[off]); | 41 | return !!(reg_val & dev->lut[off]); |
42 | } | 42 | } |
@@ -48,9 +48,9 @@ static void adp5520_gpio_set_value(struct gpio_chip *chip, | |||
48 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); | 48 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); |
49 | 49 | ||
50 | if (val) | 50 | if (val) |
51 | adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); | 51 | adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); |
52 | else | 52 | else |
53 | adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); | 53 | adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]); |
54 | } | 54 | } |
55 | 55 | ||
56 | static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) | 56 | static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) |
@@ -60,7 +60,8 @@ static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) | |||
60 | 60 | ||
61 | clear_bit(off, &dev->output); | 61 | clear_bit(off, &dev->output); |
62 | 62 | ||
63 | return adp5520_clr_bits(dev->master, GPIO_CFG_2, dev->lut[off]); | 63 | return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2, |
64 | dev->lut[off]); | ||
64 | } | 65 | } |
65 | 66 | ||
66 | static int adp5520_gpio_direction_output(struct gpio_chip *chip, | 67 | static int adp5520_gpio_direction_output(struct gpio_chip *chip, |
@@ -73,18 +74,21 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip, | |||
73 | set_bit(off, &dev->output); | 74 | set_bit(off, &dev->output); |
74 | 75 | ||
75 | if (val) | 76 | if (val) |
76 | ret |= adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); | 77 | ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, |
78 | dev->lut[off]); | ||
77 | else | 79 | else |
78 | ret |= adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); | 80 | ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, |
81 | dev->lut[off]); | ||
79 | 82 | ||
80 | ret |= adp5520_set_bits(dev->master, GPIO_CFG_2, dev->lut[off]); | 83 | ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2, |
84 | dev->lut[off]); | ||
81 | 85 | ||
82 | return ret; | 86 | return ret; |
83 | } | 87 | } |
84 | 88 | ||
85 | static int __devinit adp5520_gpio_probe(struct platform_device *pdev) | 89 | static int __devinit adp5520_gpio_probe(struct platform_device *pdev) |
86 | { | 90 | { |
87 | struct adp5520_gpio_platfrom_data *pdata = pdev->dev.platform_data; | 91 | struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data; |
88 | struct adp5520_gpio *dev; | 92 | struct adp5520_gpio *dev; |
89 | struct gpio_chip *gc; | 93 | struct gpio_chip *gc; |
90 | int ret, i, gpios; | 94 | int ret, i, gpios; |
@@ -129,20 +133,20 @@ static int __devinit adp5520_gpio_probe(struct platform_device *pdev) | |||
129 | gc->label = pdev->name; | 133 | gc->label = pdev->name; |
130 | gc->owner = THIS_MODULE; | 134 | gc->owner = THIS_MODULE; |
131 | 135 | ||
132 | ret = adp5520_clr_bits(dev->master, GPIO_CFG_1, | 136 | ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1, |
133 | pdata->gpio_en_mask); | 137 | pdata->gpio_en_mask); |
134 | 138 | ||
135 | if (pdata->gpio_en_mask & GPIO_C3) | 139 | if (pdata->gpio_en_mask & ADP5520_GPIO_C3) |
136 | ctl_mask |= C3_MODE; | 140 | ctl_mask |= ADP5520_C3_MODE; |
137 | 141 | ||
138 | if (pdata->gpio_en_mask & GPIO_R3) | 142 | if (pdata->gpio_en_mask & ADP5520_GPIO_R3) |
139 | ctl_mask |= R3_MODE; | 143 | ctl_mask |= ADP5520_R3_MODE; |
140 | 144 | ||
141 | if (ctl_mask) | 145 | if (ctl_mask) |
142 | ret = adp5520_set_bits(dev->master, LED_CONTROL, | 146 | ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, |
143 | ctl_mask); | 147 | ctl_mask); |
144 | 148 | ||
145 | ret |= adp5520_set_bits(dev->master, GPIO_PULLUP, | 149 | ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, |
146 | pdata->gpio_pullup_mask); | 150 | pdata->gpio_pullup_mask); |
147 | 151 | ||
148 | if (ret) { | 152 | if (ret) { |
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c index 49384a7c5492..7fe881e2bdfb 100644 --- a/drivers/gpio/twl4030-gpio.c +++ b/drivers/gpio/twl4030-gpio.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | 36 | ||
37 | #include <linux/i2c/twl4030.h> | 37 | #include <linux/i2c/twl.h> |
38 | 38 | ||
39 | 39 | ||
40 | /* | 40 | /* |
@@ -80,7 +80,7 @@ static unsigned int gpio_usage_count; | |||
80 | */ | 80 | */ |
81 | static inline int gpio_twl4030_write(u8 address, u8 data) | 81 | static inline int gpio_twl4030_write(u8 address, u8 data) |
82 | { | 82 | { |
83 | return twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); | 83 | return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); |
84 | } | 84 | } |
85 | 85 | ||
86 | /*----------------------------------------------------------------------*/ | 86 | /*----------------------------------------------------------------------*/ |
@@ -117,7 +117,7 @@ static inline int gpio_twl4030_read(u8 address) | |||
117 | u8 data; | 117 | u8 data; |
118 | int ret = 0; | 118 | int ret = 0; |
119 | 119 | ||
120 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); | 120 | ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); |
121 | return (ret < 0) ? ret : data; | 121 | return (ret < 0) ? ret : data; |
122 | } | 122 | } |
123 | 123 | ||
@@ -142,7 +142,7 @@ static void twl4030_led_set_value(int led, int value) | |||
142 | cached_leden &= ~mask; | 142 | cached_leden &= ~mask; |
143 | else | 143 | else |
144 | cached_leden |= mask; | 144 | cached_leden |= mask; |
145 | status = twl4030_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, | 145 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, |
146 | TWL4030_LED_LEDEN); | 146 | TWL4030_LED_LEDEN); |
147 | mutex_unlock(&gpio_lock); | 147 | mutex_unlock(&gpio_lock); |
148 | } | 148 | } |
@@ -223,23 +223,23 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | /* initialize PWM to always-drive */ | 225 | /* initialize PWM to always-drive */ |
226 | status = twl4030_i2c_write_u8(module, 0x7f, | 226 | status = twl_i2c_write_u8(module, 0x7f, |
227 | TWL4030_PWMx_PWMxOFF); | 227 | TWL4030_PWMx_PWMxOFF); |
228 | if (status < 0) | 228 | if (status < 0) |
229 | goto done; | 229 | goto done; |
230 | status = twl4030_i2c_write_u8(module, 0x7f, | 230 | status = twl_i2c_write_u8(module, 0x7f, |
231 | TWL4030_PWMx_PWMxON); | 231 | TWL4030_PWMx_PWMxON); |
232 | if (status < 0) | 232 | if (status < 0) |
233 | goto done; | 233 | goto done; |
234 | 234 | ||
235 | /* init LED to not-driven (high) */ | 235 | /* init LED to not-driven (high) */ |
236 | module = TWL4030_MODULE_LED; | 236 | module = TWL4030_MODULE_LED; |
237 | status = twl4030_i2c_read_u8(module, &cached_leden, | 237 | status = twl_i2c_read_u8(module, &cached_leden, |
238 | TWL4030_LED_LEDEN); | 238 | TWL4030_LED_LEDEN); |
239 | if (status < 0) | 239 | if (status < 0) |
240 | goto done; | 240 | goto done; |
241 | cached_leden &= ~ledclr_mask; | 241 | cached_leden &= ~ledclr_mask; |
242 | status = twl4030_i2c_write_u8(module, cached_leden, | 242 | status = twl_i2c_write_u8(module, cached_leden, |
243 | TWL4030_LED_LEDEN); | 243 | TWL4030_LED_LEDEN); |
244 | if (status < 0) | 244 | if (status < 0) |
245 | goto done; | 245 | goto done; |
@@ -370,7 +370,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs) | |||
370 | message[i] = bit_mask; | 370 | message[i] = bit_mask; |
371 | } | 371 | } |
372 | 372 | ||
373 | return twl4030_i2c_write(TWL4030_MODULE_GPIO, message, | 373 | return twl_i2c_write(TWL4030_MODULE_GPIO, message, |
374 | REG_GPIOPUPDCTR1, 5); | 374 | REG_GPIOPUPDCTR1, 5); |
375 | } | 375 | } |
376 | 376 | ||
@@ -387,7 +387,7 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) | |||
387 | debounce >>= 8; | 387 | debounce >>= 8; |
388 | message[3] = (debounce & 0x03); | 388 | message[3] = (debounce & 0x03); |
389 | 389 | ||
390 | return twl4030_i2c_write(TWL4030_MODULE_GPIO, message, | 390 | return twl_i2c_write(TWL4030_MODULE_GPIO, message, |
391 | REG_GPIO_DEBEN1, 3); | 391 | REG_GPIO_DEBEN1, 3); |
392 | } | 392 | } |
393 | 393 | ||
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index f9c09a54ec7f..b4468b616890 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include <linux/mfd/wm831x/core.h> | 22 | #include <linux/mfd/wm831x/core.h> |
23 | #include <linux/mfd/wm831x/pdata.h> | 23 | #include <linux/mfd/wm831x/pdata.h> |
24 | #include <linux/mfd/wm831x/gpio.h> | 24 | #include <linux/mfd/wm831x/gpio.h> |
25 | 25 | #include <linux/mfd/wm831x/irq.h> | |
26 | #define WM831X_GPIO_MAX 16 | ||
27 | 26 | ||
28 | struct wm831x_gpio { | 27 | struct wm831x_gpio { |
29 | struct wm831x *wm831x; | 28 | struct wm831x *wm831x; |
@@ -80,6 +79,17 @@ static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
80 | value << offset); | 79 | value << offset); |
81 | } | 80 | } |
82 | 81 | ||
82 | static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
83 | { | ||
84 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | ||
85 | struct wm831x *wm831x = wm831x_gpio->wm831x; | ||
86 | |||
87 | if (!wm831x->irq_base) | ||
88 | return -EINVAL; | ||
89 | |||
90 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | ||
91 | } | ||
92 | |||
83 | #ifdef CONFIG_DEBUG_FS | 93 | #ifdef CONFIG_DEBUG_FS |
84 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 94 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
85 | { | 95 | { |
@@ -175,6 +185,7 @@ static struct gpio_chip template_chip = { | |||
175 | .get = wm831x_gpio_get, | 185 | .get = wm831x_gpio_get, |
176 | .direction_output = wm831x_gpio_direction_out, | 186 | .direction_output = wm831x_gpio_direction_out, |
177 | .set = wm831x_gpio_set, | 187 | .set = wm831x_gpio_set, |
188 | .to_irq = wm831x_gpio_to_irq, | ||
178 | .dbg_show = wm831x_gpio_dbg_show, | 189 | .dbg_show = wm831x_gpio_dbg_show, |
179 | .can_sleep = 1, | 190 | .can_sleep = 1, |
180 | }; | 191 | }; |
@@ -192,7 +203,7 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev) | |||
192 | 203 | ||
193 | wm831x_gpio->wm831x = wm831x; | 204 | wm831x_gpio->wm831x = wm831x; |
194 | wm831x_gpio->gpio_chip = template_chip; | 205 | wm831x_gpio->gpio_chip = template_chip; |
195 | wm831x_gpio->gpio_chip.ngpio = WM831X_GPIO_MAX; | 206 | wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; |
196 | wm831x_gpio->gpio_chip.dev = &pdev->dev; | 207 | wm831x_gpio->gpio_chip.dev = &pdev->dev; |
197 | if (pdata && pdata->gpio_base) | 208 | if (pdata && pdata->gpio_base) |
198 | wm831x_gpio->gpio_chip.base = pdata->gpio_base; | 209 | wm831x_gpio->gpio_chip.base = pdata->gpio_base; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 203b88a82b56..02c836e11813 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -24,6 +24,16 @@ config KEYBOARD_AAED2000 | |||
24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
25 | module will be called aaed2000_kbd. | 25 | module will be called aaed2000_kbd. |
26 | 26 | ||
27 | config KEYBOARD_ADP5520 | ||
28 | tristate "Keypad Support for ADP5520 PMIC" | ||
29 | depends on PMIC_ADP5520 | ||
30 | help | ||
31 | This option enables support for the keypad scan matrix | ||
32 | on Analog Devices ADP5520 PMICs. | ||
33 | |||
34 | To compile this driver as a module, choose M here: the module will | ||
35 | be called adp5520-keys. | ||
36 | |||
27 | config KEYBOARD_ADP5588 | 37 | config KEYBOARD_ADP5588 |
28 | tristate "ADP5588 I2C QWERTY Keypad and IO Expander" | 38 | tristate "ADP5588 I2C QWERTY Keypad and IO Expander" |
29 | depends on I2C | 39 | depends on I2C |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 68c017235ce9..78654ef65206 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
8 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o | ||
8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | 9 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o |
9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
10 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c new file mode 100644 index 000000000000..a7ba27fb4109 --- /dev/null +++ b/drivers/input/keyboard/adp5520-keys.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * Keypad driver for Analog Devices ADP5520 MFD PMICs | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/mfd/adp5520.h> | ||
15 | |||
16 | struct adp5520_keys { | ||
17 | struct input_dev *input; | ||
18 | struct notifier_block notifier; | ||
19 | struct device *master; | ||
20 | unsigned short keycode[ADP5520_KEYMAPSIZE]; | ||
21 | }; | ||
22 | |||
23 | static void adp5520_keys_report_event(struct adp5520_keys *dev, | ||
24 | unsigned short keymask, int value) | ||
25 | { | ||
26 | int i; | ||
27 | |||
28 | for (i = 0; i < ADP5520_MAXKEYS; i++) | ||
29 | if (keymask & (1 << i)) | ||
30 | input_report_key(dev->input, dev->keycode[i], value); | ||
31 | |||
32 | input_sync(dev->input); | ||
33 | } | ||
34 | |||
35 | static int adp5520_keys_notifier(struct notifier_block *nb, | ||
36 | unsigned long event, void *data) | ||
37 | { | ||
38 | struct adp5520_keys *dev; | ||
39 | uint8_t reg_val_lo, reg_val_hi; | ||
40 | unsigned short keymask; | ||
41 | |||
42 | dev = container_of(nb, struct adp5520_keys, notifier); | ||
43 | |||
44 | if (event & ADP5520_KP_INT) { | ||
45 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); | ||
46 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); | ||
47 | |||
48 | keymask = (reg_val_hi << 8) | reg_val_lo; | ||
49 | /* Read twice to clear */ | ||
50 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); | ||
51 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); | ||
52 | keymask |= (reg_val_hi << 8) | reg_val_lo; | ||
53 | adp5520_keys_report_event(dev, keymask, 1); | ||
54 | } | ||
55 | |||
56 | if (event & ADP5520_KR_INT) { | ||
57 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); | ||
58 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); | ||
59 | |||
60 | keymask = (reg_val_hi << 8) | reg_val_lo; | ||
61 | /* Read twice to clear */ | ||
62 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); | ||
63 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); | ||
64 | keymask |= (reg_val_hi << 8) | reg_val_lo; | ||
65 | adp5520_keys_report_event(dev, keymask, 0); | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int __devinit adp5520_keys_probe(struct platform_device *pdev) | ||
72 | { | ||
73 | struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; | ||
74 | struct input_dev *input; | ||
75 | struct adp5520_keys *dev; | ||
76 | int ret, i; | ||
77 | unsigned char en_mask, ctl_mask = 0; | ||
78 | |||
79 | if (pdev->id != ID_ADP5520) { | ||
80 | dev_err(&pdev->dev, "only ADP5520 supports Keypad\n"); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | if (pdata == NULL) { | ||
85 | dev_err(&pdev->dev, "missing platform data\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | if (!(pdata->rows_en_mask && pdata->cols_en_mask)) | ||
90 | return -EINVAL; | ||
91 | |||
92 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
93 | if (dev == NULL) { | ||
94 | dev_err(&pdev->dev, "failed to alloc memory\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
98 | input = input_allocate_device(); | ||
99 | if (!input) { | ||
100 | ret = -ENOMEM; | ||
101 | goto err; | ||
102 | } | ||
103 | |||
104 | dev->master = pdev->dev.parent; | ||
105 | dev->input = input; | ||
106 | |||
107 | input->name = pdev->name; | ||
108 | input->phys = "adp5520-keys/input0"; | ||
109 | input->dev.parent = &pdev->dev; | ||
110 | |||
111 | input_set_drvdata(input, dev); | ||
112 | |||
113 | input->id.bustype = BUS_I2C; | ||
114 | input->id.vendor = 0x0001; | ||
115 | input->id.product = 0x5520; | ||
116 | input->id.version = 0x0001; | ||
117 | |||
118 | input->keycodesize = sizeof(dev->keycode[0]); | ||
119 | input->keycodemax = pdata->keymapsize; | ||
120 | input->keycode = dev->keycode; | ||
121 | |||
122 | memcpy(dev->keycode, pdata->keymap, | ||
123 | pdata->keymapsize * input->keycodesize); | ||
124 | |||
125 | /* setup input device */ | ||
126 | __set_bit(EV_KEY, input->evbit); | ||
127 | |||
128 | if (pdata->repeat) | ||
129 | __set_bit(EV_REP, input->evbit); | ||
130 | |||
131 | for (i = 0; i < input->keycodemax; i++) | ||
132 | __set_bit(dev->keycode[i], input->keybit); | ||
133 | __clear_bit(KEY_RESERVED, input->keybit); | ||
134 | |||
135 | ret = input_register_device(input); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "unable to register input device\n"); | ||
138 | goto err; | ||
139 | } | ||
140 | |||
141 | en_mask = pdata->rows_en_mask | pdata->cols_en_mask; | ||
142 | |||
143 | ret = adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_1, en_mask); | ||
144 | |||
145 | if (en_mask & ADP5520_COL_C3) | ||
146 | ctl_mask |= ADP5520_C3_MODE; | ||
147 | |||
148 | if (en_mask & ADP5520_ROW_R3) | ||
149 | ctl_mask |= ADP5520_R3_MODE; | ||
150 | |||
151 | if (ctl_mask) | ||
152 | ret |= adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, | ||
153 | ctl_mask); | ||
154 | |||
155 | ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, | ||
156 | pdata->rows_en_mask); | ||
157 | |||
158 | if (ret) { | ||
159 | dev_err(&pdev->dev, "failed to write\n"); | ||
160 | ret = -EIO; | ||
161 | goto err1; | ||
162 | } | ||
163 | |||
164 | dev->notifier.notifier_call = adp5520_keys_notifier; | ||
165 | ret = adp5520_register_notifier(dev->master, &dev->notifier, | ||
166 | ADP5520_KP_IEN | ADP5520_KR_IEN); | ||
167 | if (ret) { | ||
168 | dev_err(&pdev->dev, "failed to register notifier\n"); | ||
169 | goto err1; | ||
170 | } | ||
171 | |||
172 | platform_set_drvdata(pdev, dev); | ||
173 | return 0; | ||
174 | |||
175 | err1: | ||
176 | input_unregister_device(input); | ||
177 | input = NULL; | ||
178 | err: | ||
179 | input_free_device(input); | ||
180 | kfree(dev); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int __devexit adp5520_keys_remove(struct platform_device *pdev) | ||
185 | { | ||
186 | struct adp5520_keys *dev = platform_get_drvdata(pdev); | ||
187 | |||
188 | adp5520_unregister_notifier(dev->master, &dev->notifier, | ||
189 | ADP5520_KP_IEN | ADP5520_KR_IEN); | ||
190 | |||
191 | input_unregister_device(dev->input); | ||
192 | kfree(dev); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static struct platform_driver adp5520_keys_driver = { | ||
197 | .driver = { | ||
198 | .name = "adp5520-keys", | ||
199 | .owner = THIS_MODULE, | ||
200 | }, | ||
201 | .probe = adp5520_keys_probe, | ||
202 | .remove = __devexit_p(adp5520_keys_remove), | ||
203 | }; | ||
204 | |||
205 | static int __init adp5520_keys_init(void) | ||
206 | { | ||
207 | return platform_driver_register(&adp5520_keys_driver); | ||
208 | } | ||
209 | module_init(adp5520_keys_init); | ||
210 | |||
211 | static void __exit adp5520_keys_exit(void) | ||
212 | { | ||
213 | platform_driver_unregister(&adp5520_keys_driver); | ||
214 | } | ||
215 | module_exit(adp5520_keys_exit); | ||
216 | |||
217 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
218 | MODULE_DESCRIPTION("Keys ADP5520 Driver"); | ||
219 | MODULE_LICENSE("GPL"); | ||
220 | MODULE_ALIAS("platform:adp5520-keys"); | ||
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 9a2977c21696..eeaa7acb9cfc 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/input.h> | 32 | #include <linux/input.h> |
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/i2c/twl4030.h> | 34 | #include <linux/i2c/twl.h> |
35 | 35 | ||
36 | 36 | ||
37 | /* | 37 | /* |
@@ -133,7 +133,7 @@ struct twl4030_keypad { | |||
133 | static int twl4030_kpread(struct twl4030_keypad *kp, | 133 | static int twl4030_kpread(struct twl4030_keypad *kp, |
134 | u8 *data, u32 reg, u8 num_bytes) | 134 | u8 *data, u32 reg, u8 num_bytes) |
135 | { | 135 | { |
136 | int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); | 136 | int ret = twl_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); |
137 | 137 | ||
138 | if (ret < 0) | 138 | if (ret < 0) |
139 | dev_warn(kp->dbg_dev, | 139 | dev_warn(kp->dbg_dev, |
@@ -145,7 +145,7 @@ static int twl4030_kpread(struct twl4030_keypad *kp, | |||
145 | 145 | ||
146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) | 146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) |
147 | { | 147 | { |
148 | int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); | 148 | int ret = twl_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); |
149 | 149 | ||
150 | if (ret < 0) | 150 | if (ret < 0) |
151 | dev_warn(kp->dbg_dev, | 151 | dev_warn(kp->dbg_dev, |
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 039dcb00ebd9..008de0c5834b 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c | |||
@@ -55,7 +55,6 @@ pcf50633_input_irq(int irq, void *data) | |||
55 | static int __devinit pcf50633_input_probe(struct platform_device *pdev) | 55 | static int __devinit pcf50633_input_probe(struct platform_device *pdev) |
56 | { | 56 | { |
57 | struct pcf50633_input *input; | 57 | struct pcf50633_input *input; |
58 | struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; | ||
59 | struct input_dev *input_dev; | 58 | struct input_dev *input_dev; |
60 | int ret; | 59 | int ret; |
61 | 60 | ||
@@ -71,7 +70,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) | |||
71 | } | 70 | } |
72 | 71 | ||
73 | platform_set_drvdata(pdev, input); | 72 | platform_set_drvdata(pdev, input); |
74 | input->pcf = pdata->pcf; | 73 | input->pcf = dev_to_pcf50633(pdev->dev.parent); |
75 | input->input_dev = input_dev; | 74 | input->input_dev = input_dev; |
76 | 75 | ||
77 | input_dev->name = "PCF50633 PMU events"; | 76 | input_dev->name = "PCF50633 PMU events"; |
@@ -85,9 +84,9 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) | |||
85 | kfree(input); | 84 | kfree(input); |
86 | return ret; | 85 | return ret; |
87 | } | 86 | } |
88 | pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR, | 87 | pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR, |
89 | pcf50633_input_irq, input); | 88 | pcf50633_input_irq, input); |
90 | pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF, | 89 | pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF, |
91 | pcf50633_input_irq, input); | 90 | pcf50633_input_irq, input); |
92 | 91 | ||
93 | return 0; | 92 | return 0; |
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index f5fc9974a111..bdde5c889035 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/i2c/twl4030.h> | 30 | #include <linux/i2c/twl.h> |
31 | 31 | ||
32 | #define PWR_PWRON_IRQ (1 << 0) | 32 | #define PWR_PWRON_IRQ (1 << 0) |
33 | 33 | ||
@@ -49,7 +49,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) | |||
49 | local_irq_enable(); | 49 | local_irq_enable(); |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, | 52 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, |
53 | STS_HW_CONDITIONS); | 53 | STS_HW_CONDITIONS); |
54 | if (!err) { | 54 | if (!err) { |
55 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); | 55 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); |
diff --git a/drivers/mfd/88pm8607.c b/drivers/mfd/88pm8607.c new file mode 100644 index 000000000000..7e3f65907993 --- /dev/null +++ b/drivers/mfd/88pm8607.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * Base driver for Marvell 88PM8607 | ||
3 | * | ||
4 | * Copyright (C) 2009 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/mfd/core.h> | ||
18 | #include <linux/mfd/88pm8607.h> | ||
19 | |||
20 | |||
21 | #define PM8607_REG_RESOURCE(_start, _end) \ | ||
22 | { \ | ||
23 | .start = PM8607_##_start, \ | ||
24 | .end = PM8607_##_end, \ | ||
25 | .flags = IORESOURCE_IO, \ | ||
26 | } | ||
27 | |||
28 | static struct resource pm8607_regulator_resources[] = { | ||
29 | PM8607_REG_RESOURCE(BUCK1, BUCK1), | ||
30 | PM8607_REG_RESOURCE(BUCK2, BUCK2), | ||
31 | PM8607_REG_RESOURCE(BUCK3, BUCK3), | ||
32 | PM8607_REG_RESOURCE(LDO1, LDO1), | ||
33 | PM8607_REG_RESOURCE(LDO2, LDO2), | ||
34 | PM8607_REG_RESOURCE(LDO3, LDO3), | ||
35 | PM8607_REG_RESOURCE(LDO4, LDO4), | ||
36 | PM8607_REG_RESOURCE(LDO5, LDO5), | ||
37 | PM8607_REG_RESOURCE(LDO6, LDO6), | ||
38 | PM8607_REG_RESOURCE(LDO7, LDO7), | ||
39 | PM8607_REG_RESOURCE(LDO8, LDO8), | ||
40 | PM8607_REG_RESOURCE(LDO9, LDO9), | ||
41 | PM8607_REG_RESOURCE(LDO10, LDO10), | ||
42 | PM8607_REG_RESOURCE(LDO12, LDO12), | ||
43 | PM8607_REG_RESOURCE(LDO14, LDO14), | ||
44 | }; | ||
45 | |||
46 | #define PM8607_REG_DEVS(_name, _id) \ | ||
47 | { \ | ||
48 | .name = "88pm8607-" #_name, \ | ||
49 | .num_resources = 1, \ | ||
50 | .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \ | ||
51 | } | ||
52 | |||
53 | static struct mfd_cell pm8607_devs[] = { | ||
54 | PM8607_REG_DEVS(buck1, BUCK1), | ||
55 | PM8607_REG_DEVS(buck2, BUCK2), | ||
56 | PM8607_REG_DEVS(buck3, BUCK3), | ||
57 | PM8607_REG_DEVS(ldo1, LDO1), | ||
58 | PM8607_REG_DEVS(ldo2, LDO2), | ||
59 | PM8607_REG_DEVS(ldo3, LDO3), | ||
60 | PM8607_REG_DEVS(ldo4, LDO4), | ||
61 | PM8607_REG_DEVS(ldo5, LDO5), | ||
62 | PM8607_REG_DEVS(ldo6, LDO6), | ||
63 | PM8607_REG_DEVS(ldo7, LDO7), | ||
64 | PM8607_REG_DEVS(ldo8, LDO8), | ||
65 | PM8607_REG_DEVS(ldo9, LDO9), | ||
66 | PM8607_REG_DEVS(ldo10, LDO10), | ||
67 | PM8607_REG_DEVS(ldo12, LDO12), | ||
68 | PM8607_REG_DEVS(ldo14, LDO14), | ||
69 | }; | ||
70 | |||
71 | static inline int pm8607_read_device(struct pm8607_chip *chip, | ||
72 | int reg, int bytes, void *dest) | ||
73 | { | ||
74 | struct i2c_client *i2c = chip->client; | ||
75 | unsigned char data; | ||
76 | int ret; | ||
77 | |||
78 | data = (unsigned char)reg; | ||
79 | ret = i2c_master_send(i2c, &data, 1); | ||
80 | if (ret < 0) | ||
81 | return ret; | ||
82 | |||
83 | ret = i2c_master_recv(i2c, dest, bytes); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int pm8607_write_device(struct pm8607_chip *chip, | ||
90 | int reg, int bytes, void *src) | ||
91 | { | ||
92 | struct i2c_client *i2c = chip->client; | ||
93 | unsigned char buf[bytes + 1]; | ||
94 | int ret; | ||
95 | |||
96 | buf[0] = (unsigned char)reg; | ||
97 | memcpy(&buf[1], src, bytes); | ||
98 | |||
99 | ret = i2c_master_send(i2c, buf, bytes + 1); | ||
100 | if (ret < 0) | ||
101 | return ret; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | int pm8607_reg_read(struct pm8607_chip *chip, int reg) | ||
106 | { | ||
107 | unsigned char data; | ||
108 | int ret; | ||
109 | |||
110 | mutex_lock(&chip->io_lock); | ||
111 | ret = chip->read(chip, reg, 1, &data); | ||
112 | mutex_unlock(&chip->io_lock); | ||
113 | |||
114 | if (ret < 0) | ||
115 | return ret; | ||
116 | else | ||
117 | return (int)data; | ||
118 | } | ||
119 | EXPORT_SYMBOL(pm8607_reg_read); | ||
120 | |||
121 | int pm8607_reg_write(struct pm8607_chip *chip, int reg, | ||
122 | unsigned char data) | ||
123 | { | ||
124 | int ret; | ||
125 | |||
126 | mutex_lock(&chip->io_lock); | ||
127 | ret = chip->write(chip, reg, 1, &data); | ||
128 | mutex_unlock(&chip->io_lock); | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | EXPORT_SYMBOL(pm8607_reg_write); | ||
133 | |||
134 | int pm8607_bulk_read(struct pm8607_chip *chip, int reg, | ||
135 | int count, unsigned char *buf) | ||
136 | { | ||
137 | int ret; | ||
138 | |||
139 | mutex_lock(&chip->io_lock); | ||
140 | ret = chip->read(chip, reg, count, buf); | ||
141 | mutex_unlock(&chip->io_lock); | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | EXPORT_SYMBOL(pm8607_bulk_read); | ||
146 | |||
147 | int pm8607_bulk_write(struct pm8607_chip *chip, int reg, | ||
148 | int count, unsigned char *buf) | ||
149 | { | ||
150 | int ret; | ||
151 | |||
152 | mutex_lock(&chip->io_lock); | ||
153 | ret = chip->write(chip, reg, count, buf); | ||
154 | mutex_unlock(&chip->io_lock); | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | EXPORT_SYMBOL(pm8607_bulk_write); | ||
159 | |||
160 | int pm8607_set_bits(struct pm8607_chip *chip, int reg, | ||
161 | unsigned char mask, unsigned char data) | ||
162 | { | ||
163 | unsigned char value; | ||
164 | int ret; | ||
165 | |||
166 | mutex_lock(&chip->io_lock); | ||
167 | ret = chip->read(chip, reg, 1, &value); | ||
168 | if (ret < 0) | ||
169 | goto out; | ||
170 | value &= ~mask; | ||
171 | value |= data; | ||
172 | ret = chip->write(chip, reg, 1, &value); | ||
173 | out: | ||
174 | mutex_unlock(&chip->io_lock); | ||
175 | return ret; | ||
176 | } | ||
177 | EXPORT_SYMBOL(pm8607_set_bits); | ||
178 | |||
179 | |||
180 | static const struct i2c_device_id pm8607_id_table[] = { | ||
181 | { "88PM8607", 0 }, | ||
182 | {} | ||
183 | }; | ||
184 | MODULE_DEVICE_TABLE(i2c, pm8607_id_table); | ||
185 | |||
186 | |||
187 | static int __devinit pm8607_probe(struct i2c_client *client, | ||
188 | const struct i2c_device_id *id) | ||
189 | { | ||
190 | struct pm8607_platform_data *pdata = client->dev.platform_data; | ||
191 | struct pm8607_chip *chip; | ||
192 | int i, count; | ||
193 | int ret; | ||
194 | |||
195 | chip = kzalloc(sizeof(struct pm8607_chip), GFP_KERNEL); | ||
196 | if (chip == NULL) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | chip->client = client; | ||
200 | chip->dev = &client->dev; | ||
201 | chip->read = pm8607_read_device; | ||
202 | chip->write = pm8607_write_device; | ||
203 | i2c_set_clientdata(client, chip); | ||
204 | |||
205 | mutex_init(&chip->io_lock); | ||
206 | dev_set_drvdata(chip->dev, chip); | ||
207 | |||
208 | ret = pm8607_reg_read(chip, PM8607_CHIP_ID); | ||
209 | if (ret < 0) { | ||
210 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); | ||
211 | goto out; | ||
212 | } | ||
213 | if ((ret & CHIP_ID_MASK) == CHIP_ID) | ||
214 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", | ||
215 | ret); | ||
216 | else { | ||
217 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " | ||
218 | "Chip ID: %02x\n", ret); | ||
219 | goto out; | ||
220 | } | ||
221 | chip->chip_id = ret; | ||
222 | |||
223 | ret = pm8607_reg_read(chip, PM8607_BUCK3); | ||
224 | if (ret < 0) { | ||
225 | dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); | ||
226 | goto out; | ||
227 | } | ||
228 | if (ret & PM8607_BUCK3_DOUBLE) | ||
229 | chip->buck3_double = 1; | ||
230 | |||
231 | ret = pm8607_reg_read(chip, PM8607_MISC1); | ||
232 | if (ret < 0) { | ||
233 | dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); | ||
234 | goto out; | ||
235 | } | ||
236 | if (pdata->i2c_port == PI2C_PORT) | ||
237 | ret |= PM8607_MISC1_PI2C; | ||
238 | else | ||
239 | ret &= ~PM8607_MISC1_PI2C; | ||
240 | ret = pm8607_reg_write(chip, PM8607_MISC1, ret); | ||
241 | if (ret < 0) { | ||
242 | dev_err(chip->dev, "Failed to write MISC1 register: %d\n", ret); | ||
243 | goto out; | ||
244 | } | ||
245 | |||
246 | |||
247 | count = ARRAY_SIZE(pm8607_devs); | ||
248 | for (i = 0; i < count; i++) { | ||
249 | ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i], | ||
250 | 1, NULL, 0); | ||
251 | if (ret != 0) { | ||
252 | dev_err(chip->dev, "Failed to add subdevs\n"); | ||
253 | goto out; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | |||
259 | out: | ||
260 | i2c_set_clientdata(client, NULL); | ||
261 | kfree(chip); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static int __devexit pm8607_remove(struct i2c_client *client) | ||
266 | { | ||
267 | struct pm8607_chip *chip = i2c_get_clientdata(client); | ||
268 | |||
269 | mfd_remove_devices(chip->dev); | ||
270 | kfree(chip); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static struct i2c_driver pm8607_driver = { | ||
275 | .driver = { | ||
276 | .name = "88PM8607", | ||
277 | .owner = THIS_MODULE, | ||
278 | }, | ||
279 | .probe = pm8607_probe, | ||
280 | .remove = __devexit_p(pm8607_remove), | ||
281 | .id_table = pm8607_id_table, | ||
282 | }; | ||
283 | |||
284 | static int __init pm8607_init(void) | ||
285 | { | ||
286 | int ret; | ||
287 | ret = i2c_add_driver(&pm8607_driver); | ||
288 | if (ret != 0) | ||
289 | pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret); | ||
290 | return ret; | ||
291 | } | ||
292 | subsys_initcall(pm8607_init); | ||
293 | |||
294 | static void __exit pm8607_exit(void) | ||
295 | { | ||
296 | i2c_del_driver(&pm8607_driver); | ||
297 | } | ||
298 | module_exit(pm8607_exit); | ||
299 | |||
300 | MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607"); | ||
301 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
302 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a296e717e86e..87829789243e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -103,10 +103,10 @@ config MENELAUS | |||
103 | cell phones and PDAs. | 103 | cell phones and PDAs. |
104 | 104 | ||
105 | config TWL4030_CORE | 105 | config TWL4030_CORE |
106 | bool "Texas Instruments TWL4030/TPS659x0 Support" | 106 | bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" |
107 | depends on I2C=y && GENERIC_HARDIRQS | 107 | depends on I2C=y && GENERIC_HARDIRQS |
108 | help | 108 | help |
109 | Say yes here if you have TWL4030 family chip on your board. | 109 | Say yes here if you have TWL4030 / TWL6030 family chip on your board. |
110 | This core driver provides register access and IRQ handling | 110 | This core driver provides register access and IRQ handling |
111 | facilities, and registers devices for the various functions | 111 | facilities, and registers devices for the various functions |
112 | so that function-specific drivers can bind to them. | 112 | so that function-specific drivers can bind to them. |
@@ -174,6 +174,16 @@ config PMIC_DA903X | |||
174 | individual components like LCD backlight, voltage regulators, | 174 | individual components like LCD backlight, voltage regulators, |
175 | LEDs and battery-charger under the corresponding menus. | 175 | LEDs and battery-charger under the corresponding menus. |
176 | 176 | ||
177 | config PMIC_ADP5520 | ||
178 | bool "Analog Devices ADP5520/01 MFD PMIC Core Support" | ||
179 | depends on I2C=y | ||
180 | help | ||
181 | Say yes here to add support for Analog Devices AD5520 and ADP5501, | ||
182 | Multifunction Power Management IC. This includes | ||
183 | the I2C driver and the core APIs _only_, you have to select | ||
184 | individual components like LCD backlight, LEDs, GPIOs and Kepad | ||
185 | under the corresponding menus. | ||
186 | |||
177 | config MFD_WM8400 | 187 | config MFD_WM8400 |
178 | tristate "Support Wolfson Microelectronics WM8400" | 188 | tristate "Support Wolfson Microelectronics WM8400" |
179 | select MFD_CORE | 189 | select MFD_CORE |
@@ -185,12 +195,12 @@ config MFD_WM8400 | |||
185 | the functionality of the device. | 195 | the functionality of the device. |
186 | 196 | ||
187 | config MFD_WM831X | 197 | config MFD_WM831X |
188 | tristate "Support Wolfson Microelectronics WM831x PMICs" | 198 | bool "Support Wolfson Microelectronics WM831x/2x PMICs" |
189 | select MFD_CORE | 199 | select MFD_CORE |
190 | depends on I2C | 200 | depends on I2C=y |
191 | help | 201 | help |
192 | Support for the Wolfson Microelecronics WM831x PMICs. This | 202 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs. |
193 | driver provides common support for accessing the device, | 203 | This driver provides common support for accessing the device, |
194 | additional drivers must be enabled in order to use the | 204 | additional drivers must be enabled in order to use the |
195 | functionality of the device. | 205 | functionality of the device. |
196 | 206 | ||
@@ -319,6 +329,25 @@ config EZX_PCAP | |||
319 | This enables the PCAP ASIC present on EZX Phones. This is | 329 | This enables the PCAP ASIC present on EZX Phones. This is |
320 | needed for MMC, TouchScreen, Sound, USB, etc.. | 330 | needed for MMC, TouchScreen, Sound, USB, etc.. |
321 | 331 | ||
332 | config MFD_88PM8607 | ||
333 | bool "Support Marvell 88PM8607" | ||
334 | depends on I2C=y | ||
335 | select MFD_CORE | ||
336 | help | ||
337 | This supports for Marvell 88PM8607 Power Management IC. This includes | ||
338 | the I2C driver and the core APIs _only_, you have to select | ||
339 | individual components like voltage regulators, RTC and | ||
340 | battery-charger under the corresponding menus. | ||
341 | |||
342 | config AB4500_CORE | ||
343 | tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" | ||
344 | depends on SPI | ||
345 | help | ||
346 | Select this option to enable access to AB4500 power management | ||
347 | chip. This connects to U8500 on the SSP/SPI bus and exports | ||
348 | read/write functions for the devices to get access to this chip. | ||
349 | This chip embeds various other multimedia funtionalities as well. | ||
350 | |||
322 | endmenu | 351 | endmenu |
323 | 352 | ||
324 | menu "Multimedia Capabilities Port drivers" | 353 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 11350c1d9301..ca2f2c4ff05e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -19,13 +19,14 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o | |||
19 | wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o | 19 | wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o |
20 | obj-$(CONFIG_MFD_WM831X) += wm831x.o | 20 | obj-$(CONFIG_MFD_WM831X) += wm831x.o |
21 | wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o | 21 | wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o |
22 | wm8350-objs += wm8350-irq.o | ||
22 | obj-$(CONFIG_MFD_WM8350) += wm8350.o | 23 | obj-$(CONFIG_MFD_WM8350) += wm8350.o |
23 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o | 24 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o |
24 | 25 | ||
25 | obj-$(CONFIG_TPS65010) += tps65010.o | 26 | obj-$(CONFIG_TPS65010) += tps65010.o |
26 | obj-$(CONFIG_MENELAUS) += menelaus.o | 27 | obj-$(CONFIG_MENELAUS) += menelaus.o |
27 | 28 | ||
28 | obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o | 29 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
29 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 30 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
30 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 31 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
31 | 32 | ||
@@ -52,3 +53,6 @@ obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o | |||
52 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o | 53 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o |
53 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | 54 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o |
54 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 55 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
56 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o | ||
57 | obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o | ||
58 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o \ No newline at end of file | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 613481028272..fd42a80e7bf9 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -900,9 +900,6 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
900 | goto exit_no_testreg_client; | 900 | goto exit_no_testreg_client; |
901 | } | 901 | } |
902 | 902 | ||
903 | strlcpy(ab3100->testreg_client->name, id->name, | ||
904 | sizeof(ab3100->testreg_client->name)); | ||
905 | |||
906 | err = ab3100_setup(ab3100); | 903 | err = ab3100_setup(ab3100); |
907 | if (err) | 904 | if (err) |
908 | goto exit_no_setup; | 905 | goto exit_no_setup; |
diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c new file mode 100644 index 000000000000..1c44c19e073a --- /dev/null +++ b/drivers/mfd/ab4500-core.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it | ||
7 | * and/or modify it under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * AB4500 is a companion power management chip used with U8500. | ||
11 | * On this platform, this is interfaced with SSP0 controller | ||
12 | * which is a ARM primecell pl022. | ||
13 | * | ||
14 | * At the moment the module just exports read/write features. | ||
15 | * Interrupt management to be added - TODO. | ||
16 | */ | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/mfd/ab4500.h> | ||
23 | |||
24 | /* just required if probe fails, we need to | ||
25 | * unregister the device | ||
26 | */ | ||
27 | static struct spi_driver ab4500_driver; | ||
28 | |||
29 | /* | ||
30 | * This funtion writes to any AB4500 registers using | ||
31 | * SPI protocol & before it writes it packs the data | ||
32 | * in the below 24 bit frame format | ||
33 | * | ||
34 | * *|------------------------------------| | ||
35 | * *| 23|22...18|17.......10|9|8|7......0| | ||
36 | * *| r/w bank adr data | | ||
37 | * * ------------------------------------ | ||
38 | * | ||
39 | * This function shouldn't be called from interrupt | ||
40 | * context | ||
41 | */ | ||
42 | int ab4500_write(struct ab4500 *ab4500, unsigned char block, | ||
43 | unsigned long addr, unsigned char data) | ||
44 | { | ||
45 | struct spi_transfer xfer; | ||
46 | struct spi_message msg; | ||
47 | int err; | ||
48 | unsigned long spi_data = | ||
49 | block << 18 | addr << 10 | data; | ||
50 | |||
51 | mutex_lock(&ab4500->lock); | ||
52 | ab4500->tx_buf[0] = spi_data; | ||
53 | ab4500->rx_buf[0] = 0; | ||
54 | |||
55 | xfer.tx_buf = ab4500->tx_buf; | ||
56 | xfer.rx_buf = NULL; | ||
57 | xfer.len = sizeof(unsigned long); | ||
58 | |||
59 | spi_message_init(&msg); | ||
60 | spi_message_add_tail(&xfer, &msg); | ||
61 | |||
62 | err = spi_sync(ab4500->spi, &msg); | ||
63 | mutex_unlock(&ab4500->lock); | ||
64 | |||
65 | return err; | ||
66 | } | ||
67 | EXPORT_SYMBOL(ab4500_write); | ||
68 | |||
69 | int ab4500_read(struct ab4500 *ab4500, unsigned char block, | ||
70 | unsigned long addr) | ||
71 | { | ||
72 | struct spi_transfer xfer; | ||
73 | struct spi_message msg; | ||
74 | unsigned long spi_data = | ||
75 | 1 << 23 | block << 18 | addr << 10; | ||
76 | |||
77 | mutex_lock(&ab4500->lock); | ||
78 | ab4500->tx_buf[0] = spi_data; | ||
79 | ab4500->rx_buf[0] = 0; | ||
80 | |||
81 | xfer.tx_buf = ab4500->tx_buf; | ||
82 | xfer.rx_buf = ab4500->rx_buf; | ||
83 | xfer.len = sizeof(unsigned long); | ||
84 | |||
85 | spi_message_init(&msg); | ||
86 | spi_message_add_tail(&xfer, &msg); | ||
87 | |||
88 | spi_sync(ab4500->spi, &msg); | ||
89 | mutex_unlock(&ab4500->lock); | ||
90 | |||
91 | return ab4500->rx_buf[0]; | ||
92 | } | ||
93 | EXPORT_SYMBOL(ab4500_read); | ||
94 | |||
95 | /* ref: ab3100 core */ | ||
96 | #define AB4500_DEVICE(devname, devid) \ | ||
97 | static struct platform_device ab4500_##devname##_device = { \ | ||
98 | .name = devid, \ | ||
99 | .id = -1, \ | ||
100 | } | ||
101 | |||
102 | /* list of childern devices of ab4500 - all are | ||
103 | * not populated here - TODO | ||
104 | */ | ||
105 | AB4500_DEVICE(charger, "ab4500-charger"); | ||
106 | AB4500_DEVICE(audio, "ab4500-audio"); | ||
107 | AB4500_DEVICE(usb, "ab4500-usb"); | ||
108 | AB4500_DEVICE(tvout, "ab4500-tvout"); | ||
109 | AB4500_DEVICE(sim, "ab4500-sim"); | ||
110 | AB4500_DEVICE(gpadc, "ab4500-gpadc"); | ||
111 | AB4500_DEVICE(clkmgt, "ab4500-clkmgt"); | ||
112 | AB4500_DEVICE(misc, "ab4500-misc"); | ||
113 | |||
114 | static struct platform_device *ab4500_platform_devs[] = { | ||
115 | &ab4500_charger_device, | ||
116 | &ab4500_audio_device, | ||
117 | &ab4500_usb_device, | ||
118 | &ab4500_tvout_device, | ||
119 | &ab4500_sim_device, | ||
120 | &ab4500_gpadc_device, | ||
121 | &ab4500_clkmgt_device, | ||
122 | &ab4500_misc_device, | ||
123 | }; | ||
124 | |||
125 | static int __init ab4500_probe(struct spi_device *spi) | ||
126 | { | ||
127 | struct ab4500 *ab4500; | ||
128 | unsigned char revision; | ||
129 | int err = 0; | ||
130 | int i; | ||
131 | |||
132 | ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL); | ||
133 | if (!ab4500) { | ||
134 | dev_err(&spi->dev, "could not allocate AB4500\n"); | ||
135 | err = -ENOMEM; | ||
136 | goto not_detect; | ||
137 | } | ||
138 | |||
139 | ab4500->spi = spi; | ||
140 | spi_set_drvdata(spi, ab4500); | ||
141 | |||
142 | mutex_init(&ab4500->lock); | ||
143 | |||
144 | /* read the revision register */ | ||
145 | revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG); | ||
146 | |||
147 | /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */ | ||
148 | if (revision == 0x0 || revision == 0x10) | ||
149 | dev_info(&spi->dev, "Detected chip: %s, revision = %x\n", | ||
150 | ab4500_driver.driver.name, revision); | ||
151 | else { | ||
152 | dev_err(&spi->dev, "unknown chip: 0x%x\n", revision); | ||
153 | goto not_detect; | ||
154 | } | ||
155 | |||
156 | for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) { | ||
157 | ab4500_platform_devs[i]->dev.parent = | ||
158 | &spi->dev; | ||
159 | platform_set_drvdata(ab4500_platform_devs[i], ab4500); | ||
160 | } | ||
161 | |||
162 | /* register the ab4500 platform devices */ | ||
163 | platform_add_devices(ab4500_platform_devs, | ||
164 | ARRAY_SIZE(ab4500_platform_devs)); | ||
165 | |||
166 | return err; | ||
167 | |||
168 | not_detect: | ||
169 | spi_unregister_driver(&ab4500_driver); | ||
170 | kfree(ab4500); | ||
171 | return err; | ||
172 | } | ||
173 | |||
174 | static int __devexit ab4500_remove(struct spi_device *spi) | ||
175 | { | ||
176 | struct ab4500 *ab4500 = | ||
177 | spi_get_drvdata(spi); | ||
178 | |||
179 | kfree(ab4500); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static struct spi_driver ab4500_driver = { | ||
185 | .driver = { | ||
186 | .name = "ab4500", | ||
187 | .owner = THIS_MODULE, | ||
188 | }, | ||
189 | .probe = ab4500_probe, | ||
190 | .remove = __devexit_p(ab4500_remove) | ||
191 | }; | ||
192 | |||
193 | static int __devinit ab4500_init(void) | ||
194 | { | ||
195 | return spi_register_driver(&ab4500_driver); | ||
196 | } | ||
197 | |||
198 | static void __exit ab4500_exit(void) | ||
199 | { | ||
200 | spi_unregister_driver(&ab4500_driver); | ||
201 | } | ||
202 | |||
203 | subsys_initcall(ab4500_init); | ||
204 | module_exit(ab4500_exit); | ||
205 | |||
206 | MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com"); | ||
207 | MODULE_DESCRIPTION("AB4500 core driver"); | ||
208 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c new file mode 100644 index 000000000000..b26644772d02 --- /dev/null +++ b/drivers/mfd/adp5520.c | |||
@@ -0,0 +1,379 @@ | |||
1 | /* | ||
2 | * Base driver for Analog Devices ADP5520/ADP5501 MFD PMICs | ||
3 | * LCD Backlight: drivers/video/backlight/adp5520_bl | ||
4 | * LEDs : drivers/led/leds-adp5520 | ||
5 | * GPIO : drivers/gpio/adp5520-gpio (ADP5520 only) | ||
6 | * Keys : drivers/input/keyboard/adp5520-keys (ADP5520 only) | ||
7 | * | ||
8 | * Copyright 2009 Analog Devices Inc. | ||
9 | * | ||
10 | * Derived from da903x: | ||
11 | * Copyright (C) 2008 Compulab, Ltd. | ||
12 | * Mike Rapoport <mike@compulab.co.il> | ||
13 | * | ||
14 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
15 | * Eric Miao <eric.miao@marvell.com> | ||
16 | * | ||
17 | * Licensed under the GPL-2 or later. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/i2c.h> | ||
28 | |||
29 | #include <linux/mfd/adp5520.h> | ||
30 | |||
31 | struct adp5520_chip { | ||
32 | struct i2c_client *client; | ||
33 | struct device *dev; | ||
34 | struct mutex lock; | ||
35 | struct blocking_notifier_head notifier_list; | ||
36 | int irq; | ||
37 | unsigned long id; | ||
38 | }; | ||
39 | |||
40 | static int __adp5520_read(struct i2c_client *client, | ||
41 | int reg, uint8_t *val) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | ret = i2c_smbus_read_byte_data(client, reg); | ||
46 | if (ret < 0) { | ||
47 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | *val = (uint8_t)ret; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int __adp5520_write(struct i2c_client *client, | ||
56 | int reg, uint8_t val) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
61 | if (ret < 0) { | ||
62 | dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", | ||
63 | val, reg); | ||
64 | return ret; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int __adp5520_ack_bits(struct i2c_client *client, int reg, | ||
70 | uint8_t bit_mask) | ||
71 | { | ||
72 | struct adp5520_chip *chip = i2c_get_clientdata(client); | ||
73 | uint8_t reg_val; | ||
74 | int ret; | ||
75 | |||
76 | mutex_lock(&chip->lock); | ||
77 | |||
78 | ret = __adp5520_read(client, reg, ®_val); | ||
79 | |||
80 | if (!ret) { | ||
81 | reg_val |= bit_mask; | ||
82 | ret = __adp5520_write(client, reg, reg_val); | ||
83 | } | ||
84 | |||
85 | mutex_unlock(&chip->lock); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | int adp5520_write(struct device *dev, int reg, uint8_t val) | ||
90 | { | ||
91 | return __adp5520_write(to_i2c_client(dev), reg, val); | ||
92 | } | ||
93 | EXPORT_SYMBOL_GPL(adp5520_write); | ||
94 | |||
95 | int adp5520_read(struct device *dev, int reg, uint8_t *val) | ||
96 | { | ||
97 | return __adp5520_read(to_i2c_client(dev), reg, val); | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(adp5520_read); | ||
100 | |||
101 | int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
102 | { | ||
103 | struct adp5520_chip *chip = dev_get_drvdata(dev); | ||
104 | uint8_t reg_val; | ||
105 | int ret; | ||
106 | |||
107 | mutex_lock(&chip->lock); | ||
108 | |||
109 | ret = __adp5520_read(chip->client, reg, ®_val); | ||
110 | |||
111 | if (!ret && ((reg_val & bit_mask) == 0)) { | ||
112 | reg_val |= bit_mask; | ||
113 | ret = __adp5520_write(chip->client, reg, reg_val); | ||
114 | } | ||
115 | |||
116 | mutex_unlock(&chip->lock); | ||
117 | return ret; | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(adp5520_set_bits); | ||
120 | |||
121 | int adp5520_clr_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
122 | { | ||
123 | struct adp5520_chip *chip = dev_get_drvdata(dev); | ||
124 | uint8_t reg_val; | ||
125 | int ret; | ||
126 | |||
127 | mutex_lock(&chip->lock); | ||
128 | |||
129 | ret = __adp5520_read(chip->client, reg, ®_val); | ||
130 | |||
131 | if (!ret && (reg_val & bit_mask)) { | ||
132 | reg_val &= ~bit_mask; | ||
133 | ret = __adp5520_write(chip->client, reg, reg_val); | ||
134 | } | ||
135 | |||
136 | mutex_unlock(&chip->lock); | ||
137 | return ret; | ||
138 | } | ||
139 | EXPORT_SYMBOL_GPL(adp5520_clr_bits); | ||
140 | |||
141 | int adp5520_register_notifier(struct device *dev, struct notifier_block *nb, | ||
142 | unsigned int events) | ||
143 | { | ||
144 | struct adp5520_chip *chip = dev_get_drvdata(dev); | ||
145 | |||
146 | if (chip->irq) { | ||
147 | adp5520_set_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, | ||
148 | events & (ADP5520_KP_IEN | ADP5520_KR_IEN | | ||
149 | ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); | ||
150 | |||
151 | return blocking_notifier_chain_register(&chip->notifier_list, | ||
152 | nb); | ||
153 | } | ||
154 | |||
155 | return -ENODEV; | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(adp5520_register_notifier); | ||
158 | |||
159 | int adp5520_unregister_notifier(struct device *dev, struct notifier_block *nb, | ||
160 | unsigned int events) | ||
161 | { | ||
162 | struct adp5520_chip *chip = dev_get_drvdata(dev); | ||
163 | |||
164 | adp5520_clr_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, | ||
165 | events & (ADP5520_KP_IEN | ADP5520_KR_IEN | | ||
166 | ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); | ||
167 | |||
168 | return blocking_notifier_chain_unregister(&chip->notifier_list, nb); | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(adp5520_unregister_notifier); | ||
171 | |||
172 | static irqreturn_t adp5520_irq_thread(int irq, void *data) | ||
173 | { | ||
174 | struct adp5520_chip *chip = data; | ||
175 | unsigned int events; | ||
176 | uint8_t reg_val; | ||
177 | int ret; | ||
178 | |||
179 | ret = __adp5520_read(chip->client, ADP5520_MODE_STATUS, ®_val); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | events = reg_val & (ADP5520_OVP_INT | ADP5520_CMPR_INT | | ||
184 | ADP5520_GPI_INT | ADP5520_KR_INT | ADP5520_KP_INT); | ||
185 | |||
186 | blocking_notifier_call_chain(&chip->notifier_list, events, NULL); | ||
187 | /* ACK, Sticky bits are W1C */ | ||
188 | __adp5520_ack_bits(chip->client, ADP5520_MODE_STATUS, events); | ||
189 | |||
190 | out: | ||
191 | return IRQ_HANDLED; | ||
192 | } | ||
193 | |||
194 | static int __remove_subdev(struct device *dev, void *unused) | ||
195 | { | ||
196 | platform_device_unregister(to_platform_device(dev)); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static int adp5520_remove_subdevs(struct adp5520_chip *chip) | ||
201 | { | ||
202 | return device_for_each_child(chip->dev, NULL, __remove_subdev); | ||
203 | } | ||
204 | |||
205 | static int __devinit adp5520_probe(struct i2c_client *client, | ||
206 | const struct i2c_device_id *id) | ||
207 | { | ||
208 | struct adp5520_platform_data *pdata = client->dev.platform_data; | ||
209 | struct platform_device *pdev; | ||
210 | struct adp5520_chip *chip; | ||
211 | int ret; | ||
212 | |||
213 | if (!i2c_check_functionality(client->adapter, | ||
214 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
215 | dev_err(&client->dev, "SMBUS Word Data not Supported\n"); | ||
216 | return -EIO; | ||
217 | } | ||
218 | |||
219 | if (pdata == NULL) { | ||
220 | dev_err(&client->dev, "missing platform data\n"); | ||
221 | return -ENODEV; | ||
222 | } | ||
223 | |||
224 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
225 | if (!chip) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | i2c_set_clientdata(client, chip); | ||
229 | chip->client = client; | ||
230 | |||
231 | chip->dev = &client->dev; | ||
232 | chip->irq = client->irq; | ||
233 | chip->id = id->driver_data; | ||
234 | mutex_init(&chip->lock); | ||
235 | |||
236 | if (chip->irq) { | ||
237 | BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list); | ||
238 | |||
239 | ret = request_threaded_irq(chip->irq, NULL, adp5520_irq_thread, | ||
240 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
241 | "adp5520", chip); | ||
242 | if (ret) { | ||
243 | dev_err(&client->dev, "failed to request irq %d\n", | ||
244 | chip->irq); | ||
245 | goto out_free_chip; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | ret = adp5520_write(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); | ||
250 | if (ret) { | ||
251 | dev_err(&client->dev, "failed to write\n"); | ||
252 | goto out_free_irq; | ||
253 | } | ||
254 | |||
255 | if (pdata->keys) { | ||
256 | pdev = platform_device_register_data(chip->dev, "adp5520-keys", | ||
257 | chip->id, pdata->keys, sizeof(*pdata->keys)); | ||
258 | if (IS_ERR(pdev)) { | ||
259 | ret = PTR_ERR(pdev); | ||
260 | goto out_remove_subdevs; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | if (pdata->gpio) { | ||
265 | pdev = platform_device_register_data(chip->dev, "adp5520-gpio", | ||
266 | chip->id, pdata->gpio, sizeof(*pdata->gpio)); | ||
267 | if (IS_ERR(pdev)) { | ||
268 | ret = PTR_ERR(pdev); | ||
269 | goto out_remove_subdevs; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | if (pdata->leds) { | ||
274 | pdev = platform_device_register_data(chip->dev, "adp5520-led", | ||
275 | chip->id, pdata->leds, sizeof(*pdata->leds)); | ||
276 | if (IS_ERR(pdev)) { | ||
277 | ret = PTR_ERR(pdev); | ||
278 | goto out_remove_subdevs; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | if (pdata->backlight) { | ||
283 | pdev = platform_device_register_data(chip->dev, | ||
284 | "adp5520-backlight", | ||
285 | chip->id, | ||
286 | pdata->backlight, | ||
287 | sizeof(*pdata->backlight)); | ||
288 | if (IS_ERR(pdev)) { | ||
289 | ret = PTR_ERR(pdev); | ||
290 | goto out_remove_subdevs; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | |||
296 | out_remove_subdevs: | ||
297 | adp5520_remove_subdevs(chip); | ||
298 | |||
299 | out_free_irq: | ||
300 | if (chip->irq) | ||
301 | free_irq(chip->irq, chip); | ||
302 | |||
303 | out_free_chip: | ||
304 | i2c_set_clientdata(client, NULL); | ||
305 | kfree(chip); | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | static int __devexit adp5520_remove(struct i2c_client *client) | ||
311 | { | ||
312 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); | ||
313 | |||
314 | if (chip->irq) | ||
315 | free_irq(chip->irq, chip); | ||
316 | |||
317 | adp5520_remove_subdevs(chip); | ||
318 | adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); | ||
319 | i2c_set_clientdata(client, NULL); | ||
320 | kfree(chip); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | #ifdef CONFIG_PM | ||
325 | static int adp5520_suspend(struct i2c_client *client, | ||
326 | pm_message_t state) | ||
327 | { | ||
328 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); | ||
329 | |||
330 | adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int adp5520_resume(struct i2c_client *client) | ||
335 | { | ||
336 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); | ||
337 | |||
338 | adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); | ||
339 | return 0; | ||
340 | } | ||
341 | #else | ||
342 | #define adp5520_suspend NULL | ||
343 | #define adp5520_resume NULL | ||
344 | #endif | ||
345 | |||
346 | static const struct i2c_device_id adp5520_id[] = { | ||
347 | { "pmic-adp5520", ID_ADP5520 }, | ||
348 | { "pmic-adp5501", ID_ADP5501 }, | ||
349 | { } | ||
350 | }; | ||
351 | MODULE_DEVICE_TABLE(i2c, adp5520_id); | ||
352 | |||
353 | static struct i2c_driver adp5520_driver = { | ||
354 | .driver = { | ||
355 | .name = "adp5520", | ||
356 | .owner = THIS_MODULE, | ||
357 | }, | ||
358 | .probe = adp5520_probe, | ||
359 | .remove = __devexit_p(adp5520_remove), | ||
360 | .suspend = adp5520_suspend, | ||
361 | .resume = adp5520_resume, | ||
362 | .id_table = adp5520_id, | ||
363 | }; | ||
364 | |||
365 | static int __init adp5520_init(void) | ||
366 | { | ||
367 | return i2c_add_driver(&adp5520_driver); | ||
368 | } | ||
369 | module_init(adp5520_init); | ||
370 | |||
371 | static void __exit adp5520_exit(void) | ||
372 | { | ||
373 | i2c_del_driver(&adp5520_driver); | ||
374 | } | ||
375 | module_exit(adp5520_exit); | ||
376 | |||
377 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
378 | MODULE_DESCRIPTION("ADP5520(01) PMIC-MFD Driver"); | ||
379 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 63a2a6632106..e22128c3e9a8 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -908,7 +908,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
908 | return ret; | 908 | return ret; |
909 | } | 909 | } |
910 | 910 | ||
911 | static int asic3_remove(struct platform_device *pdev) | 911 | static int __devexit asic3_remove(struct platform_device *pdev) |
912 | { | 912 | { |
913 | int ret; | 913 | int ret; |
914 | struct asic3 *asic = platform_get_drvdata(pdev); | 914 | struct asic3 *asic = platform_get_drvdata(pdev); |
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 876288917976..df405af968fa 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c | |||
@@ -387,7 +387,6 @@ static int __devinit pcap_add_subdev(struct pcap_chip *pcap, | |||
387 | pdev = platform_device_alloc(subdev->name, subdev->id); | 387 | pdev = platform_device_alloc(subdev->name, subdev->id); |
388 | pdev->dev.parent = &pcap->spi->dev; | 388 | pdev->dev.parent = &pcap->spi->dev; |
389 | pdev->dev.platform_data = subdev->platform_data; | 389 | pdev->dev.platform_data = subdev->platform_data; |
390 | platform_set_drvdata(pdev, pcap); | ||
391 | 390 | ||
392 | return platform_device_add(pdev); | 391 | return platform_device_add(pdev); |
393 | } | 392 | } |
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index e354d2912ef1..a1ade2324ea9 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -1,286 +1,549 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | 2 | * Copyright 2009 Pengutronix |
3 | * | 3 | * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> |
4 | * This code is in parts based on wm8350-core.c and pcf50633-core.c | ||
5 | * | ||
6 | * Initial development of this code was funded by | ||
7 | * Phytec Messtechnik GmbH, http://www.phytec.de | ||
8 | * | 4 | * |
9 | * This program is free software; you can redistribute it and/or modify | 5 | * loosely based on an earlier driver that has |
10 | * it under the terms of the GNU General Public License as published by | 6 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> |
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | 7 | * |
19 | * You should have received a copy of the GNU General Public License | 8 | * This program is free software; you can redistribute it and/or modify it under |
20 | * along with this program; if not, write to the Free Software | 9 | * the terms of the GNU General Public License version 2 as published by the |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 10 | * Free Software Foundation. |
22 | */ | 11 | */ |
23 | |||
24 | #include <linux/mfd/mc13783-private.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/mfd/mc13783.h> | ||
27 | #include <linux/completion.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/spi/spi.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | 12 | #include <linux/module.h> |
34 | #include <linux/init.h> | 13 | #include <linux/spi/spi.h> |
35 | #include <linux/slab.h> | 14 | #include <linux/mfd/core.h> |
36 | #include <linux/irq.h> | 15 | #include <linux/mfd/mc13783-private.h> |
16 | |||
17 | #define MC13783_IRQSTAT0 0 | ||
18 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | ||
19 | #define MC13783_IRQSTAT0_ADCBISDONEI (1 << 1) | ||
20 | #define MC13783_IRQSTAT0_TSI (1 << 2) | ||
21 | #define MC13783_IRQSTAT0_WHIGHI (1 << 3) | ||
22 | #define MC13783_IRQSTAT0_WLOWI (1 << 4) | ||
23 | #define MC13783_IRQSTAT0_CHGDETI (1 << 6) | ||
24 | #define MC13783_IRQSTAT0_CHGOVI (1 << 7) | ||
25 | #define MC13783_IRQSTAT0_CHGREVI (1 << 8) | ||
26 | #define MC13783_IRQSTAT0_CHGSHORTI (1 << 9) | ||
27 | #define MC13783_IRQSTAT0_CCCVI (1 << 10) | ||
28 | #define MC13783_IRQSTAT0_CHGCURRI (1 << 11) | ||
29 | #define MC13783_IRQSTAT0_BPONI (1 << 12) | ||
30 | #define MC13783_IRQSTAT0_LOBATLI (1 << 13) | ||
31 | #define MC13783_IRQSTAT0_LOBATHI (1 << 14) | ||
32 | #define MC13783_IRQSTAT0_UDPI (1 << 15) | ||
33 | #define MC13783_IRQSTAT0_USBI (1 << 16) | ||
34 | #define MC13783_IRQSTAT0_IDI (1 << 19) | ||
35 | #define MC13783_IRQSTAT0_SE1I (1 << 21) | ||
36 | #define MC13783_IRQSTAT0_CKDETI (1 << 22) | ||
37 | #define MC13783_IRQSTAT0_UDMI (1 << 23) | ||
38 | |||
39 | #define MC13783_IRQMASK0 1 | ||
40 | #define MC13783_IRQMASK0_ADCDONEM MC13783_IRQSTAT0_ADCDONEI | ||
41 | #define MC13783_IRQMASK0_ADCBISDONEM MC13783_IRQSTAT0_ADCBISDONEI | ||
42 | #define MC13783_IRQMASK0_TSM MC13783_IRQSTAT0_TSI | ||
43 | #define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI | ||
44 | #define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI | ||
45 | #define MC13783_IRQMASK0_CHGDETM MC13783_IRQSTAT0_CHGDETI | ||
46 | #define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI | ||
47 | #define MC13783_IRQMASK0_CHGREVM MC13783_IRQSTAT0_CHGREVI | ||
48 | #define MC13783_IRQMASK0_CHGSHORTM MC13783_IRQSTAT0_CHGSHORTI | ||
49 | #define MC13783_IRQMASK0_CCCVM MC13783_IRQSTAT0_CCCVI | ||
50 | #define MC13783_IRQMASK0_CHGCURRM MC13783_IRQSTAT0_CHGCURRI | ||
51 | #define MC13783_IRQMASK0_BPONM MC13783_IRQSTAT0_BPONI | ||
52 | #define MC13783_IRQMASK0_LOBATLM MC13783_IRQSTAT0_LOBATLI | ||
53 | #define MC13783_IRQMASK0_LOBATHM MC13783_IRQSTAT0_LOBATHI | ||
54 | #define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI | ||
55 | #define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI | ||
56 | #define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI | ||
57 | #define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I | ||
58 | #define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI | ||
59 | #define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI | ||
60 | |||
61 | #define MC13783_IRQSTAT1 3 | ||
62 | #define MC13783_IRQSTAT1_1HZI (1 << 0) | ||
63 | #define MC13783_IRQSTAT1_TODAI (1 << 1) | ||
64 | #define MC13783_IRQSTAT1_ONOFD1I (1 << 3) | ||
65 | #define MC13783_IRQSTAT1_ONOFD2I (1 << 4) | ||
66 | #define MC13783_IRQSTAT1_ONOFD3I (1 << 5) | ||
67 | #define MC13783_IRQSTAT1_SYSRSTI (1 << 6) | ||
68 | #define MC13783_IRQSTAT1_RTCRSTI (1 << 7) | ||
69 | #define MC13783_IRQSTAT1_PCI (1 << 8) | ||
70 | #define MC13783_IRQSTAT1_WARMI (1 << 9) | ||
71 | #define MC13783_IRQSTAT1_MEMHLDI (1 << 10) | ||
72 | #define MC13783_IRQSTAT1_PWRRDYI (1 << 11) | ||
73 | #define MC13783_IRQSTAT1_THWARNLI (1 << 12) | ||
74 | #define MC13783_IRQSTAT1_THWARNHI (1 << 13) | ||
75 | #define MC13783_IRQSTAT1_CLKI (1 << 14) | ||
76 | #define MC13783_IRQSTAT1_SEMAFI (1 << 15) | ||
77 | #define MC13783_IRQSTAT1_MC2BI (1 << 17) | ||
78 | #define MC13783_IRQSTAT1_HSDETI (1 << 18) | ||
79 | #define MC13783_IRQSTAT1_HSLI (1 << 19) | ||
80 | #define MC13783_IRQSTAT1_ALSPTHI (1 << 20) | ||
81 | #define MC13783_IRQSTAT1_AHSSHORTI (1 << 21) | ||
82 | |||
83 | #define MC13783_IRQMASK1 4 | ||
84 | #define MC13783_IRQMASK1_1HZM MC13783_IRQSTAT1_1HZI | ||
85 | #define MC13783_IRQMASK1_TODAM MC13783_IRQSTAT1_TODAI | ||
86 | #define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I | ||
87 | #define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I | ||
88 | #define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I | ||
89 | #define MC13783_IRQMASK1_SYSRSTM MC13783_IRQSTAT1_SYSRSTI | ||
90 | #define MC13783_IRQMASK1_RTCRSTM MC13783_IRQSTAT1_RTCRSTI | ||
91 | #define MC13783_IRQMASK1_PCM MC13783_IRQSTAT1_PCI | ||
92 | #define MC13783_IRQMASK1_WARMM MC13783_IRQSTAT1_WARMI | ||
93 | #define MC13783_IRQMASK1_MEMHLDM MC13783_IRQSTAT1_MEMHLDI | ||
94 | #define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI | ||
95 | #define MC13783_IRQMASK1_THWARNLM MC13783_IRQSTAT1_THWARNLI | ||
96 | #define MC13783_IRQMASK1_THWARNHM MC13783_IRQSTAT1_THWARNHI | ||
97 | #define MC13783_IRQMASK1_CLKM MC13783_IRQSTAT1_CLKI | ||
98 | #define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI | ||
99 | #define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI | ||
100 | #define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI | ||
101 | #define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI | ||
102 | #define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI | ||
103 | #define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI | ||
104 | |||
105 | #define MC13783_ADC1 44 | ||
106 | #define MC13783_ADC1_ADEN (1 << 0) | ||
107 | #define MC13783_ADC1_RAND (1 << 1) | ||
108 | #define MC13783_ADC1_ADSEL (1 << 3) | ||
109 | #define MC13783_ADC1_ASC (1 << 20) | ||
110 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | ||
111 | |||
112 | #define MC13783_NUMREGS 0x3f | ||
113 | |||
114 | void mc13783_lock(struct mc13783 *mc13783) | ||
115 | { | ||
116 | if (!mutex_trylock(&mc13783->lock)) { | ||
117 | dev_dbg(&mc13783->spidev->dev, "wait for %s from %pf\n", | ||
118 | __func__, __builtin_return_address(0)); | ||
119 | |||
120 | mutex_lock(&mc13783->lock); | ||
121 | } | ||
122 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", | ||
123 | __func__, __builtin_return_address(0)); | ||
124 | } | ||
125 | EXPORT_SYMBOL(mc13783_lock); | ||
37 | 126 | ||
38 | #define MC13783_MAX_REG_NUM 0x3f | 127 | void mc13783_unlock(struct mc13783 *mc13783) |
39 | #define MC13783_FRAME_MASK 0x00ffffff | 128 | { |
40 | #define MC13783_MAX_REG_NUM 0x3f | 129 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", |
41 | #define MC13783_REG_NUM_SHIFT 0x19 | 130 | __func__, __builtin_return_address(0)); |
42 | #define MC13783_WRITE_BIT_SHIFT 31 | 131 | mutex_unlock(&mc13783->lock); |
132 | } | ||
133 | EXPORT_SYMBOL(mc13783_unlock); | ||
43 | 134 | ||
44 | static inline int spi_rw(struct spi_device *spi, u8 * buf, size_t len) | 135 | #define MC13783_REGOFFSET_SHIFT 25 |
136 | int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val) | ||
45 | { | 137 | { |
46 | struct spi_transfer t = { | 138 | struct spi_transfer t; |
47 | .tx_buf = (const void *)buf, | ||
48 | .rx_buf = buf, | ||
49 | .len = len, | ||
50 | .cs_change = 0, | ||
51 | .delay_usecs = 0, | ||
52 | }; | ||
53 | struct spi_message m; | 139 | struct spi_message m; |
140 | int ret; | ||
141 | |||
142 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
143 | |||
144 | if (offset > MC13783_NUMREGS) | ||
145 | return -EINVAL; | ||
146 | |||
147 | *val = offset << MC13783_REGOFFSET_SHIFT; | ||
148 | |||
149 | memset(&t, 0, sizeof(t)); | ||
150 | |||
151 | t.tx_buf = val; | ||
152 | t.rx_buf = val; | ||
153 | t.len = sizeof(u32); | ||
54 | 154 | ||
55 | spi_message_init(&m); | 155 | spi_message_init(&m); |
56 | spi_message_add_tail(&t, &m); | 156 | spi_message_add_tail(&t, &m); |
57 | if (spi_sync(spi, &m) != 0 || m.status != 0) | ||
58 | return -EINVAL; | ||
59 | return len - m.actual_length; | ||
60 | } | ||
61 | 157 | ||
62 | static int mc13783_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) | 158 | ret = spi_sync(mc13783->spidev, &m); |
63 | { | ||
64 | unsigned int frame = 0; | ||
65 | int ret = 0; | ||
66 | 159 | ||
67 | if (reg_num > MC13783_MAX_REG_NUM) | 160 | /* error in message.status implies error return from spi_sync */ |
68 | return -EINVAL; | 161 | BUG_ON(!ret && m.status); |
69 | 162 | ||
70 | frame |= reg_num << MC13783_REG_NUM_SHIFT; | 163 | if (ret) |
164 | return ret; | ||
71 | 165 | ||
72 | ret = spi_rw(mc13783->spi_device, (u8 *)&frame, 4); | 166 | *val &= 0xffffff; |
73 | 167 | ||
74 | *reg_val = frame & MC13783_FRAME_MASK; | 168 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); |
75 | 169 | ||
76 | return ret; | 170 | return 0; |
77 | } | 171 | } |
172 | EXPORT_SYMBOL(mc13783_reg_read); | ||
78 | 173 | ||
79 | static int mc13783_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) | 174 | int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val) |
80 | { | 175 | { |
81 | unsigned int frame = 0; | 176 | u32 buf; |
177 | struct spi_transfer t; | ||
178 | struct spi_message m; | ||
179 | int ret; | ||
180 | |||
181 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
82 | 182 | ||
83 | if (reg_num > MC13783_MAX_REG_NUM) | 183 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] <- 0x%06x\n", offset, val); |
184 | |||
185 | if (offset > MC13783_NUMREGS || val > 0xffffff) | ||
84 | return -EINVAL; | 186 | return -EINVAL; |
85 | 187 | ||
86 | frame |= (1 << MC13783_WRITE_BIT_SHIFT); | 188 | buf = 1 << 31 | offset << MC13783_REGOFFSET_SHIFT | val; |
87 | frame |= reg_num << MC13783_REG_NUM_SHIFT; | 189 | |
88 | frame |= reg_val & MC13783_FRAME_MASK; | 190 | memset(&t, 0, sizeof(t)); |
89 | 191 | ||
90 | return spi_rw(mc13783->spi_device, (u8 *)&frame, 4); | 192 | t.tx_buf = &buf; |
193 | t.rx_buf = &buf; | ||
194 | t.len = sizeof(u32); | ||
195 | |||
196 | spi_message_init(&m); | ||
197 | spi_message_add_tail(&t, &m); | ||
198 | |||
199 | ret = spi_sync(mc13783->spidev, &m); | ||
200 | |||
201 | BUG_ON(!ret && m.status); | ||
202 | |||
203 | if (ret) | ||
204 | return ret; | ||
205 | |||
206 | return 0; | ||
91 | } | 207 | } |
208 | EXPORT_SYMBOL(mc13783_reg_write); | ||
92 | 209 | ||
93 | int mc13783_reg_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) | 210 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, |
211 | u32 mask, u32 val) | ||
94 | { | 212 | { |
95 | int ret; | 213 | int ret; |
214 | u32 valread; | ||
96 | 215 | ||
97 | mutex_lock(&mc13783->io_lock); | 216 | BUG_ON(val & ~mask); |
98 | ret = mc13783_read(mc13783, reg_num, reg_val); | ||
99 | mutex_unlock(&mc13783->io_lock); | ||
100 | 217 | ||
101 | return ret; | 218 | ret = mc13783_reg_read(mc13783, offset, &valread); |
219 | if (ret) | ||
220 | return ret; | ||
221 | |||
222 | valread = (valread & ~mask) | val; | ||
223 | |||
224 | return mc13783_reg_write(mc13783, offset, valread); | ||
102 | } | 225 | } |
103 | EXPORT_SYMBOL_GPL(mc13783_reg_read); | 226 | EXPORT_SYMBOL(mc13783_reg_rmw); |
104 | 227 | ||
105 | int mc13783_reg_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) | 228 | int mc13783_mask(struct mc13783 *mc13783, int irq) |
106 | { | 229 | { |
107 | int ret; | 230 | int ret; |
231 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
232 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
233 | u32 mask; | ||
108 | 234 | ||
109 | mutex_lock(&mc13783->io_lock); | 235 | if (irq < 0 || irq >= MC13783_NUM_IRQ) |
110 | ret = mc13783_write(mc13783, reg_num, reg_val); | 236 | return -EINVAL; |
111 | mutex_unlock(&mc13783->io_lock); | ||
112 | 237 | ||
113 | return ret; | 238 | ret = mc13783_reg_read(mc13783, offmask, &mask); |
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | if (mask & irqbit) | ||
243 | /* already masked */ | ||
244 | return 0; | ||
245 | |||
246 | return mc13783_reg_write(mc13783, offmask, mask | irqbit); | ||
114 | } | 247 | } |
115 | EXPORT_SYMBOL_GPL(mc13783_reg_write); | 248 | EXPORT_SYMBOL(mc13783_mask); |
116 | 249 | ||
117 | /** | 250 | int mc13783_unmask(struct mc13783 *mc13783, int irq) |
118 | * mc13783_set_bits - Bitmask write | ||
119 | * | ||
120 | * @mc13783: Pointer to mc13783 control structure | ||
121 | * @reg: Register to access | ||
122 | * @mask: Mask of bits to change | ||
123 | * @val: Value to set for masked bits | ||
124 | */ | ||
125 | int mc13783_set_bits(struct mc13783 *mc13783, int reg, u32 mask, u32 val) | ||
126 | { | 251 | { |
127 | u32 tmp; | ||
128 | int ret; | 252 | int ret; |
253 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
254 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
255 | u32 mask; | ||
129 | 256 | ||
130 | mutex_lock(&mc13783->io_lock); | 257 | if (irq < 0 || irq >= MC13783_NUM_IRQ) |
258 | return -EINVAL; | ||
131 | 259 | ||
132 | ret = mc13783_read(mc13783, reg, &tmp); | 260 | ret = mc13783_reg_read(mc13783, offmask, &mask); |
133 | tmp = (tmp & ~mask) | val; | 261 | if (ret) |
134 | if (ret == 0) | 262 | return ret; |
135 | ret = mc13783_write(mc13783, reg, tmp); | ||
136 | 263 | ||
137 | mutex_unlock(&mc13783->io_lock); | 264 | if (!(mask & irqbit)) |
265 | /* already unmasked */ | ||
266 | return 0; | ||
138 | 267 | ||
139 | return ret; | 268 | return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); |
140 | } | 269 | } |
141 | EXPORT_SYMBOL_GPL(mc13783_set_bits); | 270 | EXPORT_SYMBOL(mc13783_unmask); |
142 | 271 | ||
143 | int mc13783_register_irq(struct mc13783 *mc13783, int irq, | 272 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, |
144 | void (*handler) (int, void *), void *data) | 273 | irq_handler_t handler, const char *name, void *dev) |
145 | { | 274 | { |
146 | if (irq < 0 || irq > MC13783_NUM_IRQ || !handler) | 275 | BUG_ON(!mutex_is_locked(&mc13783->lock)); |
276 | BUG_ON(!handler); | ||
277 | |||
278 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
147 | return -EINVAL; | 279 | return -EINVAL; |
148 | 280 | ||
149 | if (WARN_ON(mc13783->irq_handler[irq].handler)) | 281 | if (mc13783->irqhandler[irq]) |
150 | return -EBUSY; | 282 | return -EBUSY; |
151 | 283 | ||
152 | mutex_lock(&mc13783->io_lock); | 284 | mc13783->irqhandler[irq] = handler; |
153 | mc13783->irq_handler[irq].handler = handler; | 285 | mc13783->irqdata[irq] = dev; |
154 | mc13783->irq_handler[irq].data = data; | ||
155 | mutex_unlock(&mc13783->io_lock); | ||
156 | 286 | ||
157 | return 0; | 287 | return 0; |
158 | } | 288 | } |
159 | EXPORT_SYMBOL_GPL(mc13783_register_irq); | 289 | EXPORT_SYMBOL(mc13783_irq_request_nounmask); |
160 | 290 | ||
161 | int mc13783_free_irq(struct mc13783 *mc13783, int irq) | 291 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, |
292 | irq_handler_t handler, const char *name, void *dev) | ||
162 | { | 293 | { |
163 | if (irq < 0 || irq > MC13783_NUM_IRQ) | 294 | int ret; |
295 | |||
296 | ret = mc13783_irq_request_nounmask(mc13783, irq, handler, name, dev); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | ret = mc13783_unmask(mc13783, irq); | ||
301 | if (ret) { | ||
302 | mc13783->irqhandler[irq] = NULL; | ||
303 | mc13783->irqdata[irq] = NULL; | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | EXPORT_SYMBOL(mc13783_irq_request); | ||
310 | |||
311 | int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev) | ||
312 | { | ||
313 | int ret; | ||
314 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
315 | |||
316 | if (irq < 0 || irq >= MC13783_NUM_IRQ || !mc13783->irqhandler[irq] || | ||
317 | mc13783->irqdata[irq] != dev) | ||
164 | return -EINVAL; | 318 | return -EINVAL; |
165 | 319 | ||
166 | mutex_lock(&mc13783->io_lock); | 320 | ret = mc13783_mask(mc13783, irq); |
167 | mc13783->irq_handler[irq].handler = NULL; | 321 | if (ret) |
168 | mutex_unlock(&mc13783->io_lock); | 322 | return ret; |
323 | |||
324 | mc13783->irqhandler[irq] = NULL; | ||
325 | mc13783->irqdata[irq] = NULL; | ||
169 | 326 | ||
170 | return 0; | 327 | return 0; |
171 | } | 328 | } |
172 | EXPORT_SYMBOL_GPL(mc13783_free_irq); | 329 | EXPORT_SYMBOL(mc13783_irq_free); |
173 | 330 | ||
174 | static void mc13783_irq_work(struct work_struct *work) | 331 | static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq) |
175 | { | 332 | { |
176 | struct mc13783 *mc13783 = container_of(work, struct mc13783, work); | 333 | return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); |
177 | int i; | ||
178 | unsigned int adc_sts; | ||
179 | |||
180 | /* check if the adc has finished any completion */ | ||
181 | mc13783_reg_read(mc13783, MC13783_REG_INTERRUPT_STATUS_0, &adc_sts); | ||
182 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, | ||
183 | adc_sts & MC13783_INT_STAT_ADCDONEI); | ||
184 | |||
185 | if (adc_sts & MC13783_INT_STAT_ADCDONEI) | ||
186 | complete_all(&mc13783->adc_done); | ||
187 | |||
188 | for (i = 0; i < MC13783_NUM_IRQ; i++) | ||
189 | if (mc13783->irq_handler[i].handler) | ||
190 | mc13783->irq_handler[i].handler(i, | ||
191 | mc13783->irq_handler[i].data); | ||
192 | enable_irq(mc13783->irq); | ||
193 | } | 334 | } |
194 | 335 | ||
195 | static irqreturn_t mc13783_interrupt(int irq, void *dev_id) | 336 | int mc13783_ackirq(struct mc13783 *mc13783, int irq) |
196 | { | 337 | { |
197 | struct mc13783 *mc13783 = dev_id; | 338 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; |
339 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
198 | 340 | ||
199 | disable_irq_nosync(irq); | 341 | BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); |
200 | 342 | ||
201 | schedule_work(&mc13783->work); | 343 | return mc13783_reg_write(mc13783, offstat, val); |
202 | return IRQ_HANDLED; | ||
203 | } | 344 | } |
345 | EXPORT_SYMBOL(mc13783_ackirq); | ||
204 | 346 | ||
205 | /* set adc to ts interrupt mode, which generates touchscreen wakeup interrupt */ | 347 | /* |
206 | static inline void mc13783_adc_set_ts_irq_mode(struct mc13783 *mc13783) | 348 | * returns: number of handled irqs or negative error |
349 | * locking: holds mc13783->lock | ||
350 | */ | ||
351 | static int mc13783_irq_handle(struct mc13783 *mc13783, | ||
352 | unsigned int offstat, unsigned int offmask, int baseirq) | ||
207 | { | 353 | { |
208 | unsigned int reg_adc0, reg_adc1; | 354 | u32 stat, mask; |
355 | int ret = mc13783_reg_read(mc13783, offstat, &stat); | ||
356 | int num_handled = 0; | ||
357 | |||
358 | if (ret) | ||
359 | return ret; | ||
360 | |||
361 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
362 | if (ret) | ||
363 | return ret; | ||
364 | |||
365 | while (stat & ~mask) { | ||
366 | int irq = __ffs(stat & ~mask); | ||
367 | |||
368 | stat &= ~(1 << irq); | ||
369 | |||
370 | if (likely(mc13783->irqhandler[baseirq + irq])) { | ||
371 | irqreturn_t handled; | ||
209 | 372 | ||
210 | reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE | 373 | handled = mc13783_irqhandler(mc13783, baseirq + irq); |
211 | | MC13783_ADC0_TSMOD0; | 374 | if (handled == IRQ_HANDLED) |
212 | reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN; | 375 | num_handled++; |
376 | } else { | ||
377 | dev_err(&mc13783->spidev->dev, | ||
378 | "BUG: irq %u but no handler\n", | ||
379 | baseirq + irq); | ||
213 | 380 | ||
214 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); | 381 | mask |= 1 << irq; |
215 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); | 382 | |
383 | ret = mc13783_reg_write(mc13783, offmask, mask); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | return num_handled; | ||
216 | } | 388 | } |
217 | 389 | ||
390 | static irqreturn_t mc13783_irq_thread(int irq, void *data) | ||
391 | { | ||
392 | struct mc13783 *mc13783 = data; | ||
393 | irqreturn_t ret; | ||
394 | int handled = 0; | ||
395 | |||
396 | mc13783_lock(mc13783); | ||
397 | |||
398 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT0, | ||
399 | MC13783_IRQMASK0, MC13783_IRQ_ADCDONE); | ||
400 | if (ret > 0) | ||
401 | handled = 1; | ||
402 | |||
403 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT1, | ||
404 | MC13783_IRQMASK1, MC13783_IRQ_1HZ); | ||
405 | if (ret > 0) | ||
406 | handled = 1; | ||
407 | |||
408 | mc13783_unlock(mc13783); | ||
409 | |||
410 | return IRQ_RETVAL(handled); | ||
411 | } | ||
412 | |||
413 | #define MC13783_ADC1_CHAN0_SHIFT 5 | ||
414 | #define MC13783_ADC1_CHAN1_SHIFT 8 | ||
415 | |||
416 | struct mc13783_adcdone_data { | ||
417 | struct mc13783 *mc13783; | ||
418 | struct completion done; | ||
419 | }; | ||
420 | |||
421 | static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | ||
422 | { | ||
423 | struct mc13783_adcdone_data *adcdone_data = data; | ||
424 | |||
425 | mc13783_ackirq(adcdone_data->mc13783, irq); | ||
426 | |||
427 | complete_all(&adcdone_data->done); | ||
428 | |||
429 | return IRQ_HANDLED; | ||
430 | } | ||
431 | |||
432 | #define MC13783_ADC_WORKING (1 << 16) | ||
433 | |||
218 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | 434 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, |
219 | unsigned int channel, unsigned int *sample) | 435 | unsigned int channel, unsigned int *sample) |
220 | { | 436 | { |
221 | unsigned int reg_adc0, reg_adc1; | 437 | u32 adc0, adc1, old_adc0; |
222 | int i; | 438 | int i, ret; |
439 | struct mc13783_adcdone_data adcdone_data = { | ||
440 | .mc13783 = mc13783, | ||
441 | }; | ||
442 | init_completion(&adcdone_data.done); | ||
443 | |||
444 | dev_dbg(&mc13783->spidev->dev, "%s\n", __func__); | ||
445 | |||
446 | mc13783_lock(mc13783); | ||
447 | |||
448 | if (mc13783->flags & MC13783_ADC_WORKING) { | ||
449 | ret = -EBUSY; | ||
450 | goto out; | ||
451 | } | ||
452 | |||
453 | mc13783->flags |= MC13783_ADC_WORKING; | ||
223 | 454 | ||
224 | mutex_lock(&mc13783->adc_conv_lock); | 455 | mc13783_reg_read(mc13783, MC13783_ADC0, &old_adc0); |
225 | 456 | ||
226 | /* set up auto incrementing anyway to make quick read */ | 457 | adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; |
227 | reg_adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; | 458 | adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; |
228 | /* enable the adc, ignore external triggering and set ASC to trigger | ||
229 | * conversion */ | ||
230 | reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | ||
231 | | MC13783_ADC1_ASC; | ||
232 | 459 | ||
233 | /* setup channel number */ | ||
234 | if (channel > 7) | 460 | if (channel > 7) |
235 | reg_adc1 |= MC13783_ADC1_ADSEL; | 461 | adc1 |= MC13783_ADC1_ADSEL; |
236 | 462 | ||
237 | switch (mode) { | 463 | switch (mode) { |
238 | case MC13783_ADC_MODE_TS: | 464 | case MC13783_ADC_MODE_TS: |
239 | /* enables touch screen reference mode and set touchscreen mode | 465 | adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 | |
240 | * to position mode */ | 466 | MC13783_ADC0_TSMOD1; |
241 | reg_adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE | 467 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; |
242 | | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1; | ||
243 | reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
244 | break; | 468 | break; |
469 | |||
245 | case MC13783_ADC_MODE_SINGLE_CHAN: | 470 | case MC13783_ADC_MODE_SINGLE_CHAN: |
246 | reg_adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; | 471 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; |
247 | reg_adc1 |= MC13783_ADC1_RAND; | 472 | adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; |
473 | adc1 |= MC13783_ADC1_RAND; | ||
248 | break; | 474 | break; |
475 | |||
249 | case MC13783_ADC_MODE_MULT_CHAN: | 476 | case MC13783_ADC_MODE_MULT_CHAN: |
250 | reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | 477 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; |
478 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
251 | break; | 479 | break; |
480 | |||
252 | default: | 481 | default: |
482 | mc13783_unlock(mc13783); | ||
253 | return -EINVAL; | 483 | return -EINVAL; |
254 | } | 484 | } |
255 | 485 | ||
256 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); | 486 | dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); |
257 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); | 487 | mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, |
488 | mc13783_handler_adcdone, __func__, &adcdone_data); | ||
489 | mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE); | ||
258 | 490 | ||
259 | wait_for_completion_interruptible(&mc13783->adc_done); | 491 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); |
492 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); | ||
260 | 493 | ||
261 | for (i = 0; i < 4; i++) | 494 | mc13783_unlock(mc13783); |
262 | mc13783_reg_read(mc13783, MC13783_REG_ADC_2, &sample[i]); | ||
263 | 495 | ||
264 | if (mc13783->ts_active) | 496 | ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); |
265 | mc13783_adc_set_ts_irq_mode(mc13783); | ||
266 | 497 | ||
267 | mutex_unlock(&mc13783->adc_conv_lock); | 498 | if (!ret) |
499 | ret = -ETIMEDOUT; | ||
268 | 500 | ||
269 | return 0; | 501 | mc13783_lock(mc13783); |
502 | |||
503 | mc13783_irq_free(mc13783, MC13783_IRQ_ADCDONE, &adcdone_data); | ||
504 | |||
505 | if (ret > 0) | ||
506 | for (i = 0; i < 4; ++i) { | ||
507 | ret = mc13783_reg_read(mc13783, | ||
508 | MC13783_REG_ADC_2, &sample[i]); | ||
509 | if (ret) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (mode == MC13783_ADC_MODE_TS) | ||
514 | /* restore TSMOD */ | ||
515 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, old_adc0); | ||
516 | |||
517 | mc13783->flags &= ~MC13783_ADC_WORKING; | ||
518 | out: | ||
519 | mc13783_unlock(mc13783); | ||
520 | |||
521 | return ret; | ||
270 | } | 522 | } |
271 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | 523 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); |
272 | 524 | ||
273 | void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status) | 525 | static int mc13783_add_subdevice_pdata(struct mc13783 *mc13783, |
526 | const char *name, void *pdata, size_t pdata_size) | ||
274 | { | 527 | { |
275 | mc13783->ts_active = status; | 528 | struct mfd_cell cell = { |
529 | .name = name, | ||
530 | .platform_data = pdata, | ||
531 | .data_size = pdata_size, | ||
532 | }; | ||
533 | |||
534 | return mfd_add_devices(&mc13783->spidev->dev, -1, &cell, 1, NULL, 0); | ||
535 | } | ||
536 | |||
537 | static int mc13783_add_subdevice(struct mc13783 *mc13783, const char *name) | ||
538 | { | ||
539 | return mc13783_add_subdevice_pdata(mc13783, name, NULL, 0); | ||
276 | } | 540 | } |
277 | EXPORT_SYMBOL_GPL(mc13783_adc_set_ts_status); | ||
278 | 541 | ||
279 | static int mc13783_check_revision(struct mc13783 *mc13783) | 542 | static int mc13783_check_revision(struct mc13783 *mc13783) |
280 | { | 543 | { |
281 | u32 rev_id, rev1, rev2, finid, icid; | 544 | u32 rev_id, rev1, rev2, finid, icid; |
282 | 545 | ||
283 | mc13783_read(mc13783, MC13783_REG_REVISION, &rev_id); | 546 | mc13783_reg_read(mc13783, MC13783_REG_REVISION, &rev_id); |
284 | 547 | ||
285 | rev1 = (rev_id & 0x018) >> 3; | 548 | rev1 = (rev_id & 0x018) >> 3; |
286 | rev2 = (rev_id & 0x007); | 549 | rev2 = (rev_id & 0x007); |
@@ -292,38 +555,24 @@ static int mc13783_check_revision(struct mc13783 *mc13783) | |||
292 | rev1 = 3; | 555 | rev1 = 3; |
293 | 556 | ||
294 | if (rev1 == 0 || icid != 2) { | 557 | if (rev1 == 0 || icid != 2) { |
295 | dev_err(mc13783->dev, "No MC13783 detected.\n"); | 558 | dev_err(&mc13783->spidev->dev, "No MC13783 detected.\n"); |
296 | return -ENODEV; | 559 | return -ENODEV; |
297 | } | 560 | } |
298 | 561 | ||
299 | mc13783->revision = ((rev1 * 10) + rev2); | 562 | dev_info(&mc13783->spidev->dev, |
300 | dev_info(mc13783->dev, "MC13783 Rev %d.%d FinVer %x detected\n", rev1, | 563 | "MC13783 Rev %d.%d FinVer %x detected\n", |
301 | rev2, finid); | 564 | rev1, rev2, finid); |
302 | 565 | ||
303 | return 0; | 566 | return 0; |
304 | } | 567 | } |
305 | 568 | ||
306 | /* | 569 | static int mc13783_probe(struct spi_device *spi) |
307 | * Register a client device. This is non-fatal since there is no need to | ||
308 | * fail the entire device init due to a single platform device failing. | ||
309 | */ | ||
310 | static void mc13783_client_dev_register(struct mc13783 *mc13783, | ||
311 | const char *name) | ||
312 | { | ||
313 | struct mfd_cell cell = {}; | ||
314 | |||
315 | cell.name = name; | ||
316 | |||
317 | mfd_add_devices(mc13783->dev, -1, &cell, 1, NULL, 0); | ||
318 | } | ||
319 | |||
320 | static int __devinit mc13783_probe(struct spi_device *spi) | ||
321 | { | 570 | { |
322 | struct mc13783 *mc13783; | 571 | struct mc13783 *mc13783; |
323 | struct mc13783_platform_data *pdata = spi->dev.platform_data; | 572 | struct mc13783_platform_data *pdata = dev_get_platdata(&spi->dev); |
324 | int ret; | 573 | int ret; |
325 | 574 | ||
326 | mc13783 = kzalloc(sizeof(struct mc13783), GFP_KERNEL); | 575 | mc13783 = kzalloc(sizeof(*mc13783), GFP_KERNEL); |
327 | if (!mc13783) | 576 | if (!mc13783) |
328 | return -ENOMEM; | 577 | return -ENOMEM; |
329 | 578 | ||
@@ -332,96 +581,104 @@ static int __devinit mc13783_probe(struct spi_device *spi) | |||
332 | spi->bits_per_word = 32; | 581 | spi->bits_per_word = 32; |
333 | spi_setup(spi); | 582 | spi_setup(spi); |
334 | 583 | ||
335 | mc13783->spi_device = spi; | 584 | mc13783->spidev = spi; |
336 | mc13783->dev = &spi->dev; | 585 | |
337 | mc13783->irq = spi->irq; | 586 | mutex_init(&mc13783->lock); |
587 | mc13783_lock(mc13783); | ||
588 | |||
589 | ret = mc13783_check_revision(mc13783); | ||
590 | if (ret) | ||
591 | goto err_revision; | ||
592 | |||
593 | /* mask all irqs */ | ||
594 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK0, 0x00ffffff); | ||
595 | if (ret) | ||
596 | goto err_mask; | ||
338 | 597 | ||
339 | INIT_WORK(&mc13783->work, mc13783_irq_work); | 598 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK1, 0x00ffffff); |
340 | mutex_init(&mc13783->io_lock); | 599 | if (ret) |
341 | mutex_init(&mc13783->adc_conv_lock); | 600 | goto err_mask; |
342 | init_completion(&mc13783->adc_done); | 601 | |
602 | ret = request_threaded_irq(spi->irq, NULL, mc13783_irq_thread, | ||
603 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13783", mc13783); | ||
604 | |||
605 | if (ret) { | ||
606 | err_mask: | ||
607 | err_revision: | ||
608 | mutex_unlock(&mc13783->lock); | ||
609 | dev_set_drvdata(&spi->dev, NULL); | ||
610 | kfree(mc13783); | ||
611 | return ret; | ||
612 | } | ||
343 | 613 | ||
614 | /* This should go away (BEGIN) */ | ||
344 | if (pdata) { | 615 | if (pdata) { |
345 | mc13783->flags = pdata->flags; | 616 | mc13783->flags = pdata->flags; |
346 | mc13783->regulators = pdata->regulators; | 617 | mc13783->regulators = pdata->regulators; |
347 | mc13783->num_regulators = pdata->num_regulators; | 618 | mc13783->num_regulators = pdata->num_regulators; |
348 | } | 619 | } |
620 | /* This should go away (END) */ | ||
349 | 621 | ||
350 | if (mc13783_check_revision(mc13783)) { | 622 | if (pdata->flags & MC13783_USE_ADC) |
351 | ret = -ENODEV; | 623 | mc13783_add_subdevice(mc13783, "mc13783-adc"); |
352 | goto err_out; | 624 | |
625 | if (pdata->flags & MC13783_USE_CODEC) | ||
626 | mc13783_add_subdevice(mc13783, "mc13783-codec"); | ||
627 | |||
628 | if (pdata->flags & MC13783_USE_REGULATOR) { | ||
629 | struct mc13783_regulator_platform_data regulator_pdata = { | ||
630 | .num_regulators = pdata->num_regulators, | ||
631 | .regulators = pdata->regulators, | ||
632 | }; | ||
633 | |||
634 | mc13783_add_subdevice_pdata(mc13783, "mc13783-regulator", | ||
635 | ®ulator_pdata, sizeof(regulator_pdata)); | ||
353 | } | 636 | } |
354 | 637 | ||
355 | /* clear and mask all interrupts */ | 638 | if (pdata->flags & MC13783_USE_RTC) |
356 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, 0x00ffffff); | 639 | mc13783_add_subdevice(mc13783, "mc13783-rtc"); |
357 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_0, 0x00ffffff); | ||
358 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_1, 0x00ffffff); | ||
359 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_1, 0x00ffffff); | ||
360 | 640 | ||
361 | /* unmask adcdone interrupts */ | 641 | if (pdata->flags & MC13783_USE_TOUCHSCREEN) |
362 | mc13783_set_bits(mc13783, MC13783_REG_INTERRUPT_MASK_0, | 642 | mc13783_add_subdevice(mc13783, "mc13783-ts"); |
363 | MC13783_INT_MASK_ADCDONEM, 0); | ||
364 | 643 | ||
365 | ret = request_irq(mc13783->irq, mc13783_interrupt, | 644 | mc13783_unlock(mc13783); |
366 | IRQF_DISABLED | IRQF_TRIGGER_HIGH, "mc13783", | ||
367 | mc13783); | ||
368 | if (ret) | ||
369 | goto err_out; | ||
370 | |||
371 | if (mc13783->flags & MC13783_USE_CODEC) | ||
372 | mc13783_client_dev_register(mc13783, "mc13783-codec"); | ||
373 | if (mc13783->flags & MC13783_USE_ADC) | ||
374 | mc13783_client_dev_register(mc13783, "mc13783-adc"); | ||
375 | if (mc13783->flags & MC13783_USE_RTC) | ||
376 | mc13783_client_dev_register(mc13783, "mc13783-rtc"); | ||
377 | if (mc13783->flags & MC13783_USE_REGULATOR) | ||
378 | mc13783_client_dev_register(mc13783, "mc13783-regulator"); | ||
379 | if (mc13783->flags & MC13783_USE_TOUCHSCREEN) | ||
380 | mc13783_client_dev_register(mc13783, "mc13783-ts"); | ||
381 | 645 | ||
382 | return 0; | 646 | return 0; |
383 | |||
384 | err_out: | ||
385 | kfree(mc13783); | ||
386 | return ret; | ||
387 | } | 647 | } |
388 | 648 | ||
389 | static int __devexit mc13783_remove(struct spi_device *spi) | 649 | static int __devexit mc13783_remove(struct spi_device *spi) |
390 | { | 650 | { |
391 | struct mc13783 *mc13783; | 651 | struct mc13783 *mc13783 = dev_get_drvdata(&spi->dev); |
392 | 652 | ||
393 | mc13783 = dev_get_drvdata(&spi->dev); | 653 | free_irq(mc13783->spidev->irq, mc13783); |
394 | |||
395 | free_irq(mc13783->irq, mc13783); | ||
396 | 654 | ||
397 | mfd_remove_devices(&spi->dev); | 655 | mfd_remove_devices(&spi->dev); |
398 | 656 | ||
399 | return 0; | 657 | return 0; |
400 | } | 658 | } |
401 | 659 | ||
402 | static struct spi_driver pmic_driver = { | 660 | static struct spi_driver mc13783_driver = { |
403 | .driver = { | 661 | .driver = { |
404 | .name = "mc13783", | 662 | .name = "mc13783", |
405 | .bus = &spi_bus_type, | 663 | .bus = &spi_bus_type, |
406 | .owner = THIS_MODULE, | 664 | .owner = THIS_MODULE, |
407 | }, | 665 | }, |
408 | .probe = mc13783_probe, | 666 | .probe = mc13783_probe, |
409 | .remove = __devexit_p(mc13783_remove), | 667 | .remove = __devexit_p(mc13783_remove), |
410 | }; | 668 | }; |
411 | 669 | ||
412 | static int __init pmic_init(void) | 670 | static int __init mc13783_init(void) |
413 | { | 671 | { |
414 | return spi_register_driver(&pmic_driver); | 672 | return spi_register_driver(&mc13783_driver); |
415 | } | 673 | } |
416 | subsys_initcall(pmic_init); | 674 | subsys_initcall(mc13783_init); |
417 | 675 | ||
418 | static void __exit pmic_exit(void) | 676 | static void __exit mc13783_exit(void) |
419 | { | 677 | { |
420 | spi_unregister_driver(&pmic_driver); | 678 | spi_unregister_driver(&mc13783_driver); |
421 | } | 679 | } |
422 | module_exit(pmic_exit); | 680 | module_exit(mc13783_exit); |
423 | |||
424 | MODULE_DESCRIPTION("Core/Protocol driver for Freescale MC13783 PMIC"); | ||
425 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
426 | MODULE_LICENSE("GPL"); | ||
427 | 681 | ||
682 | MODULE_DESCRIPTION("Core driver for Freescale MC13783 PMIC"); | ||
683 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
684 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c index 3d31e97d6a45..6d2e8466df1d 100644 --- a/drivers/mfd/pcf50633-adc.c +++ b/drivers/mfd/pcf50633-adc.c | |||
@@ -209,17 +209,16 @@ static void pcf50633_adc_irq(int irq, void *data) | |||
209 | 209 | ||
210 | static int __devinit pcf50633_adc_probe(struct platform_device *pdev) | 210 | static int __devinit pcf50633_adc_probe(struct platform_device *pdev) |
211 | { | 211 | { |
212 | struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; | ||
213 | struct pcf50633_adc *adc; | 212 | struct pcf50633_adc *adc; |
214 | 213 | ||
215 | adc = kzalloc(sizeof(*adc), GFP_KERNEL); | 214 | adc = kzalloc(sizeof(*adc), GFP_KERNEL); |
216 | if (!adc) | 215 | if (!adc) |
217 | return -ENOMEM; | 216 | return -ENOMEM; |
218 | 217 | ||
219 | adc->pcf = pdata->pcf; | 218 | adc->pcf = dev_to_pcf50633(pdev->dev.parent); |
220 | platform_set_drvdata(pdev, adc); | 219 | platform_set_drvdata(pdev, adc); |
221 | 220 | ||
222 | pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ADCRDY, | 221 | pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY, |
223 | pcf50633_adc_irq, adc); | 222 | pcf50633_adc_irq, adc); |
224 | 223 | ||
225 | mutex_init(&adc->queue_mutex); | 224 | mutex_init(&adc->queue_mutex); |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index d26d7747175e..03dcc9200707 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -290,7 +290,7 @@ out: | |||
290 | 290 | ||
291 | int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) | 291 | int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) |
292 | { | 292 | { |
293 | dev_info(pcf->dev, "Masking IRQ %d\n", irq); | 293 | dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); |
294 | 294 | ||
295 | return __pcf50633_irq_mask_set(pcf, irq, 1); | 295 | return __pcf50633_irq_mask_set(pcf, irq, 1); |
296 | } | 296 | } |
@@ -298,7 +298,7 @@ EXPORT_SYMBOL_GPL(pcf50633_irq_mask); | |||
298 | 298 | ||
299 | int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) | 299 | int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) |
300 | { | 300 | { |
301 | dev_info(pcf->dev, "Unmasking IRQ %d\n", irq); | 301 | dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); |
302 | 302 | ||
303 | return __pcf50633_irq_mask_set(pcf, irq, 0); | 303 | return __pcf50633_irq_mask_set(pcf, irq, 0); |
304 | } | 304 | } |
@@ -345,6 +345,9 @@ static void pcf50633_irq_worker(struct work_struct *work) | |||
345 | goto out; | 345 | goto out; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* defeat 8s death from lowsys on A5 */ | ||
349 | pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04); | ||
350 | |||
348 | /* We immediately read the usb and adapter status. We thus make sure | 351 | /* We immediately read the usb and adapter status. We thus make sure |
349 | * only of USBINS/USBREM IRQ handlers are called */ | 352 | * only of USBINS/USBREM IRQ handlers are called */ |
350 | if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { | 353 | if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { |
@@ -453,7 +456,6 @@ static void | |||
453 | pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | 456 | pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, |
454 | struct platform_device **pdev) | 457 | struct platform_device **pdev) |
455 | { | 458 | { |
456 | struct pcf50633_subdev_pdata *subdev_pdata; | ||
457 | int ret; | 459 | int ret; |
458 | 460 | ||
459 | *pdev = platform_device_alloc(name, -1); | 461 | *pdev = platform_device_alloc(name, -1); |
@@ -462,15 +464,6 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | |||
462 | return; | 464 | return; |
463 | } | 465 | } |
464 | 466 | ||
465 | subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL); | ||
466 | if (!subdev_pdata) { | ||
467 | dev_err(pcf->dev, "Error allocating subdev pdata\n"); | ||
468 | platform_device_put(*pdev); | ||
469 | } | ||
470 | |||
471 | subdev_pdata->pcf = pcf; | ||
472 | platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata)); | ||
473 | |||
474 | (*pdev)->dev.parent = pcf->dev; | 467 | (*pdev)->dev.parent = pcf->dev; |
475 | 468 | ||
476 | ret = platform_device_add(*pdev); | 469 | ret = platform_device_add(*pdev); |
@@ -482,13 +475,13 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | |||
482 | } | 475 | } |
483 | 476 | ||
484 | #ifdef CONFIG_PM | 477 | #ifdef CONFIG_PM |
485 | static int pcf50633_suspend(struct device *dev, pm_message_t state) | 478 | static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) |
486 | { | 479 | { |
487 | struct pcf50633 *pcf; | 480 | struct pcf50633 *pcf; |
488 | int ret = 0, i; | 481 | int ret = 0, i; |
489 | u8 res[5]; | 482 | u8 res[5]; |
490 | 483 | ||
491 | pcf = dev_get_drvdata(dev); | 484 | pcf = i2c_get_clientdata(client); |
492 | 485 | ||
493 | /* Make sure our interrupt handlers are not called | 486 | /* Make sure our interrupt handlers are not called |
494 | * henceforth */ | 487 | * henceforth */ |
@@ -523,12 +516,12 @@ out: | |||
523 | return ret; | 516 | return ret; |
524 | } | 517 | } |
525 | 518 | ||
526 | static int pcf50633_resume(struct device *dev) | 519 | static int pcf50633_resume(struct i2c_client *client) |
527 | { | 520 | { |
528 | struct pcf50633 *pcf; | 521 | struct pcf50633 *pcf; |
529 | int ret; | 522 | int ret; |
530 | 523 | ||
531 | pcf = dev_get_drvdata(dev); | 524 | pcf = i2c_get_clientdata(client); |
532 | 525 | ||
533 | /* Write the saved mask registers */ | 526 | /* Write the saved mask registers */ |
534 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, | 527 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, |
@@ -560,9 +553,14 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
560 | { | 553 | { |
561 | struct pcf50633 *pcf; | 554 | struct pcf50633 *pcf; |
562 | struct pcf50633_platform_data *pdata = client->dev.platform_data; | 555 | struct pcf50633_platform_data *pdata = client->dev.platform_data; |
563 | int i, ret = 0; | 556 | int i, ret; |
564 | int version, variant; | 557 | int version, variant; |
565 | 558 | ||
559 | if (!client->irq) { | ||
560 | dev_err(&client->dev, "Missing IRQ\n"); | ||
561 | return -ENOENT; | ||
562 | } | ||
563 | |||
566 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); | 564 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); |
567 | if (!pcf) | 565 | if (!pcf) |
568 | return -ENOMEM; | 566 | return -ENOMEM; |
@@ -577,6 +575,12 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
577 | pcf->irq = client->irq; | 575 | pcf->irq = client->irq; |
578 | pcf->work_queue = create_singlethread_workqueue("pcf50633"); | 576 | pcf->work_queue = create_singlethread_workqueue("pcf50633"); |
579 | 577 | ||
578 | if (!pcf->work_queue) { | ||
579 | dev_err(&client->dev, "Failed to alloc workqueue\n"); | ||
580 | ret = -ENOMEM; | ||
581 | goto err_free; | ||
582 | } | ||
583 | |||
580 | INIT_WORK(&pcf->irq_work, pcf50633_irq_worker); | 584 | INIT_WORK(&pcf->irq_work, pcf50633_irq_worker); |
581 | 585 | ||
582 | version = pcf50633_reg_read(pcf, 0); | 586 | version = pcf50633_reg_read(pcf, 0); |
@@ -584,7 +588,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
584 | if (version < 0 || variant < 0) { | 588 | if (version < 0 || variant < 0) { |
585 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); | 589 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); |
586 | ret = -ENODEV; | 590 | ret = -ENODEV; |
587 | goto err; | 591 | goto err_destroy_workqueue; |
588 | } | 592 | } |
589 | 593 | ||
590 | dev_info(pcf->dev, "Probed device version %d variant %d\n", | 594 | dev_info(pcf->dev, "Probed device version %d variant %d\n", |
@@ -598,6 +602,14 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
598 | pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); | 602 | pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); |
599 | pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); | 603 | pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); |
600 | 604 | ||
605 | ret = request_irq(client->irq, pcf50633_irq, | ||
606 | IRQF_TRIGGER_LOW, "pcf50633", pcf); | ||
607 | |||
608 | if (ret) { | ||
609 | dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); | ||
610 | goto err_destroy_workqueue; | ||
611 | } | ||
612 | |||
601 | /* Create sub devices */ | 613 | /* Create sub devices */ |
602 | pcf50633_client_dev_register(pcf, "pcf50633-input", | 614 | pcf50633_client_dev_register(pcf, "pcf50633-input", |
603 | &pcf->input_pdev); | 615 | &pcf->input_pdev); |
@@ -613,31 +625,18 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
613 | 625 | ||
614 | pdev = platform_device_alloc("pcf50633-regltr", i); | 626 | pdev = platform_device_alloc("pcf50633-regltr", i); |
615 | if (!pdev) { | 627 | if (!pdev) { |
616 | dev_err(pcf->dev, "Cannot create regulator\n"); | 628 | dev_err(pcf->dev, "Cannot create regulator %d\n", i); |
617 | continue; | 629 | continue; |
618 | } | 630 | } |
619 | 631 | ||
620 | pdev->dev.parent = pcf->dev; | 632 | pdev->dev.parent = pcf->dev; |
621 | pdev->dev.platform_data = &pdata->reg_init_data[i]; | 633 | platform_device_add_data(pdev, &pdata->reg_init_data[i], |
622 | dev_set_drvdata(&pdev->dev, pcf); | 634 | sizeof(pdata->reg_init_data[i])); |
623 | pcf->regulator_pdev[i] = pdev; | 635 | pcf->regulator_pdev[i] = pdev; |
624 | 636 | ||
625 | platform_device_add(pdev); | 637 | platform_device_add(pdev); |
626 | } | 638 | } |
627 | 639 | ||
628 | if (client->irq) { | ||
629 | ret = request_irq(client->irq, pcf50633_irq, | ||
630 | IRQF_TRIGGER_LOW, "pcf50633", pcf); | ||
631 | |||
632 | if (ret) { | ||
633 | dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); | ||
634 | goto err; | ||
635 | } | ||
636 | } else { | ||
637 | dev_err(pcf->dev, "No IRQ configured\n"); | ||
638 | goto err; | ||
639 | } | ||
640 | |||
641 | if (enable_irq_wake(client->irq) < 0) | 640 | if (enable_irq_wake(client->irq) < 0) |
642 | dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source" | 641 | dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source" |
643 | "in this hardware revision", client->irq); | 642 | "in this hardware revision", client->irq); |
@@ -651,9 +650,12 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
651 | 650 | ||
652 | return 0; | 651 | return 0; |
653 | 652 | ||
654 | err: | 653 | err_destroy_workqueue: |
655 | destroy_workqueue(pcf->work_queue); | 654 | destroy_workqueue(pcf->work_queue); |
655 | err_free: | ||
656 | i2c_set_clientdata(client, NULL); | ||
656 | kfree(pcf); | 657 | kfree(pcf); |
658 | |||
657 | return ret; | 659 | return ret; |
658 | } | 660 | } |
659 | 661 | ||
@@ -686,12 +688,12 @@ static struct i2c_device_id pcf50633_id_table[] = { | |||
686 | static struct i2c_driver pcf50633_driver = { | 688 | static struct i2c_driver pcf50633_driver = { |
687 | .driver = { | 689 | .driver = { |
688 | .name = "pcf50633", | 690 | .name = "pcf50633", |
689 | .suspend = pcf50633_suspend, | ||
690 | .resume = pcf50633_resume, | ||
691 | }, | 691 | }, |
692 | .id_table = pcf50633_id_table, | 692 | .id_table = pcf50633_id_table, |
693 | .probe = pcf50633_probe, | 693 | .probe = pcf50633_probe, |
694 | .remove = __devexit_p(pcf50633_remove), | 694 | .remove = __devexit_p(pcf50633_remove), |
695 | .suspend = pcf50633_suspend, | ||
696 | .resume = pcf50633_resume, | ||
695 | }; | 697 | }; |
696 | 698 | ||
697 | static int __init pcf50633_init(void) | 699 | static int __init pcf50633_init(void) |
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index acf8b9d5f575..e5955306c2fa 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c | |||
@@ -637,7 +637,7 @@ static int tps65010_probe(struct i2c_client *client, | |||
637 | tps, DEBUG_FOPS); | 637 | tps, DEBUG_FOPS); |
638 | 638 | ||
639 | /* optionally register GPIOs */ | 639 | /* optionally register GPIOs */ |
640 | if (board && board->base > 0) { | 640 | if (board && board->base != 0) { |
641 | tps->outmask = board->outmask; | 641 | tps->outmask = board->outmask; |
642 | 642 | ||
643 | tps->chip.label = client->name; | 643 | tps->chip.label = client->name; |
@@ -964,6 +964,34 @@ int tps65010_config_vregs1(unsigned value) | |||
964 | } | 964 | } |
965 | EXPORT_SYMBOL(tps65010_config_vregs1); | 965 | EXPORT_SYMBOL(tps65010_config_vregs1); |
966 | 966 | ||
967 | int tps65010_config_vdcdc2(unsigned value) | ||
968 | { | ||
969 | struct i2c_client *c; | ||
970 | int status; | ||
971 | |||
972 | if (!the_tps) | ||
973 | return -ENODEV; | ||
974 | |||
975 | c = the_tps->client; | ||
976 | mutex_lock(&the_tps->lock); | ||
977 | |||
978 | pr_debug("%s: vdcdc2 0x%02x\n", DRIVER_NAME, | ||
979 | i2c_smbus_read_byte_data(c, TPS_VDCDC2)); | ||
980 | |||
981 | status = i2c_smbus_write_byte_data(c, TPS_VDCDC2, value); | ||
982 | |||
983 | if (status != 0) | ||
984 | printk(KERN_ERR "%s: Failed to write vdcdc2 register\n", | ||
985 | DRIVER_NAME); | ||
986 | else | ||
987 | pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, | ||
988 | i2c_smbus_read_byte_data(c, TPS_VDCDC2)); | ||
989 | |||
990 | mutex_unlock(&the_tps->lock); | ||
991 | return status; | ||
992 | } | ||
993 | EXPORT_SYMBOL(tps65010_config_vdcdc2); | ||
994 | |||
967 | /*-------------------------------------------------------------------------*/ | 995 | /*-------------------------------------------------------------------------*/ |
968 | /* tps65013_set_low_pwr parameter: | 996 | /* tps65013_set_low_pwr parameter: |
969 | * mode: ON or OFF | 997 | * mode: ON or OFF |
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl-core.c index 40449cdf09db..2a7606534196 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices | 2 | * twl_core.c - driver for TWL4030/TWL5030/TWL60X0/TPS659x0 PM |
3 | * and audio CODEC devices | ||
3 | * | 4 | * |
4 | * Copyright (C) 2005-2006 Texas Instruments, Inc. | 5 | * Copyright (C) 2005-2006 Texas Instruments, Inc. |
5 | * | 6 | * |
@@ -36,7 +37,7 @@ | |||
36 | #include <linux/regulator/machine.h> | 37 | #include <linux/regulator/machine.h> |
37 | 38 | ||
38 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
39 | #include <linux/i2c/twl4030.h> | 40 | #include <linux/i2c/twl.h> |
40 | 41 | ||
41 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 42 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
42 | #include <plat/cpu.h> | 43 | #include <plat/cpu.h> |
@@ -55,7 +56,7 @@ | |||
55 | * (and associated registers). | 56 | * (and associated registers). |
56 | */ | 57 | */ |
57 | 58 | ||
58 | #define DRIVER_NAME "twl4030" | 59 | #define DRIVER_NAME "twl" |
59 | 60 | ||
60 | #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ | 61 | #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ |
61 | defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) | 62 | defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) |
@@ -125,7 +126,7 @@ | |||
125 | /* Last - for index max*/ | 126 | /* Last - for index max*/ |
126 | #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG | 127 | #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG |
127 | 128 | ||
128 | #define TWL4030_NUM_SLAVES 4 | 129 | #define TWL_NUM_SLAVES 4 |
129 | 130 | ||
130 | #if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \ | 131 | #if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \ |
131 | || defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE) | 132 | || defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE) |
@@ -134,6 +135,13 @@ | |||
134 | #define twl_has_pwrbutton() false | 135 | #define twl_has_pwrbutton() false |
135 | #endif | 136 | #endif |
136 | 137 | ||
138 | #define SUB_CHIP_ID0 0 | ||
139 | #define SUB_CHIP_ID1 1 | ||
140 | #define SUB_CHIP_ID2 2 | ||
141 | #define SUB_CHIP_ID3 3 | ||
142 | |||
143 | #define TWL_MODULE_LAST TWL4030_MODULE_LAST | ||
144 | |||
137 | /* Base Address defns for twl4030_map[] */ | 145 | /* Base Address defns for twl4030_map[] */ |
138 | 146 | ||
139 | /* subchip/slave 0 - USB ID */ | 147 | /* subchip/slave 0 - USB ID */ |
@@ -158,6 +166,10 @@ | |||
158 | #define TWL4030_BASEADD_PWMB 0x00F1 | 166 | #define TWL4030_BASEADD_PWMB 0x00F1 |
159 | #define TWL4030_BASEADD_KEYPAD 0x00D2 | 167 | #define TWL4030_BASEADD_KEYPAD 0x00D2 |
160 | 168 | ||
169 | #define TWL5031_BASEADD_ACCESSORY 0x0074 /* Replaces Main Charge */ | ||
170 | #define TWL5031_BASEADD_INTERRUPTS 0x00B9 /* Different than TWL4030's | ||
171 | one */ | ||
172 | |||
161 | /* subchip/slave 3 - POWER ID */ | 173 | /* subchip/slave 3 - POWER ID */ |
162 | #define TWL4030_BASEADD_BACKUP 0x0014 | 174 | #define TWL4030_BASEADD_BACKUP 0x0014 |
163 | #define TWL4030_BASEADD_INT 0x002E | 175 | #define TWL4030_BASEADD_INT 0x002E |
@@ -169,6 +181,30 @@ | |||
169 | /* Triton Core internal information (END) */ | 181 | /* Triton Core internal information (END) */ |
170 | 182 | ||
171 | 183 | ||
184 | /* subchip/slave 0 0x48 - POWER */ | ||
185 | #define TWL6030_BASEADD_RTC 0x0000 | ||
186 | #define TWL6030_BASEADD_MEM 0x0017 | ||
187 | #define TWL6030_BASEADD_PM_MASTER 0x001F | ||
188 | #define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */ | ||
189 | #define TWL6030_BASEADD_PM_MISC 0x00E2 | ||
190 | #define TWL6030_BASEADD_PM_PUPD 0x00F0 | ||
191 | |||
192 | /* subchip/slave 1 0x49 - FEATURE */ | ||
193 | #define TWL6030_BASEADD_USB 0x0000 | ||
194 | #define TWL6030_BASEADD_GPADC_CTRL 0x002E | ||
195 | #define TWL6030_BASEADD_AUX 0x0090 | ||
196 | #define TWL6030_BASEADD_PWM 0x00BA | ||
197 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 | ||
198 | #define TWL6030_BASEADD_PIH 0x00D0 | ||
199 | #define TWL6030_BASEADD_CHARGER 0x00E0 | ||
200 | |||
201 | /* subchip/slave 2 0x4A - DFT */ | ||
202 | #define TWL6030_BASEADD_DIEID 0x00C0 | ||
203 | |||
204 | /* subchip/slave 3 0x4B - AUDIO */ | ||
205 | #define TWL6030_BASEADD_AUDIO 0x0000 | ||
206 | #define TWL6030_BASEADD_RSV 0x0000 | ||
207 | |||
172 | /* Few power values */ | 208 | /* Few power values */ |
173 | #define R_CFG_BOOT 0x05 | 209 | #define R_CFG_BOOT 0x05 |
174 | #define R_PROTECT_KEY 0x0E | 210 | #define R_PROTECT_KEY 0x0E |
@@ -183,19 +219,29 @@ | |||
183 | #define HFCLK_FREQ_26_MHZ (2 << 0) | 219 | #define HFCLK_FREQ_26_MHZ (2 << 0) |
184 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) | 220 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) |
185 | #define HIGH_PERF_SQ (1 << 3) | 221 | #define HIGH_PERF_SQ (1 << 3) |
222 | #define CK32K_LOWPWR_EN (1 << 7) | ||
186 | 223 | ||
187 | 224 | ||
188 | /* chip-specific feature flags, for i2c_device_id.driver_data */ | 225 | /* chip-specific feature flags, for i2c_device_id.driver_data */ |
189 | #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ | 226 | #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ |
190 | #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ | 227 | #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ |
228 | #define TWL5031 BIT(2) /* twl5031 has different registers */ | ||
229 | #define TWL6030_CLASS BIT(3) /* TWL6030 class */ | ||
191 | 230 | ||
192 | /*----------------------------------------------------------------------*/ | 231 | /*----------------------------------------------------------------------*/ |
193 | 232 | ||
194 | /* is driver active, bound to a chip? */ | 233 | /* is driver active, bound to a chip? */ |
195 | static bool inuse; | 234 | static bool inuse; |
196 | 235 | ||
197 | /* Structure for each TWL4030 Slave */ | 236 | static unsigned int twl_id; |
198 | struct twl4030_client { | 237 | unsigned int twl_rev(void) |
238 | { | ||
239 | return twl_id; | ||
240 | } | ||
241 | EXPORT_SYMBOL(twl_rev); | ||
242 | |||
243 | /* Structure for each TWL4030/TWL6030 Slave */ | ||
244 | struct twl_client { | ||
199 | struct i2c_client *client; | 245 | struct i2c_client *client; |
200 | u8 address; | 246 | u8 address; |
201 | 247 | ||
@@ -206,19 +252,20 @@ struct twl4030_client { | |||
206 | struct mutex xfer_lock; | 252 | struct mutex xfer_lock; |
207 | }; | 253 | }; |
208 | 254 | ||
209 | static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES]; | 255 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; |
210 | 256 | ||
211 | 257 | ||
212 | /* mapping the module id to slave id and base address */ | 258 | /* mapping the module id to slave id and base address */ |
213 | struct twl4030mapping { | 259 | struct twl_mapping { |
214 | unsigned char sid; /* Slave ID */ | 260 | unsigned char sid; /* Slave ID */ |
215 | unsigned char base; /* base address */ | 261 | unsigned char base; /* base address */ |
216 | }; | 262 | }; |
263 | struct twl_mapping *twl_map; | ||
217 | 264 | ||
218 | static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | 265 | static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { |
219 | /* | 266 | /* |
220 | * NOTE: don't change this table without updating the | 267 | * NOTE: don't change this table without updating the |
221 | * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_* | 268 | * <linux/i2c/twl.h> defines for TWL4030_MODULE_* |
222 | * so they continue to match the order in this table. | 269 | * so they continue to match the order in this table. |
223 | */ | 270 | */ |
224 | 271 | ||
@@ -240,6 +287,8 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | |||
240 | { 2, TWL4030_BASEADD_PWM1 }, | 287 | { 2, TWL4030_BASEADD_PWM1 }, |
241 | { 2, TWL4030_BASEADD_PWMA }, | 288 | { 2, TWL4030_BASEADD_PWMA }, |
242 | { 2, TWL4030_BASEADD_PWMB }, | 289 | { 2, TWL4030_BASEADD_PWMB }, |
290 | { 2, TWL5031_BASEADD_ACCESSORY }, | ||
291 | { 2, TWL5031_BASEADD_INTERRUPTS }, | ||
243 | 292 | ||
244 | { 3, TWL4030_BASEADD_BACKUP }, | 293 | { 3, TWL4030_BASEADD_BACKUP }, |
245 | { 3, TWL4030_BASEADD_INT }, | 294 | { 3, TWL4030_BASEADD_INT }, |
@@ -249,12 +298,46 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | |||
249 | { 3, TWL4030_BASEADD_SECURED_REG }, | 298 | { 3, TWL4030_BASEADD_SECURED_REG }, |
250 | }; | 299 | }; |
251 | 300 | ||
301 | static struct twl_mapping twl6030_map[] = { | ||
302 | /* | ||
303 | * NOTE: don't change this table without updating the | ||
304 | * <linux/i2c/twl.h> defines for TWL4030_MODULE_* | ||
305 | * so they continue to match the order in this table. | ||
306 | */ | ||
307 | { SUB_CHIP_ID1, TWL6030_BASEADD_USB }, | ||
308 | { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO }, | ||
309 | { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID }, | ||
310 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
311 | { SUB_CHIP_ID1, TWL6030_BASEADD_PIH }, | ||
312 | |||
313 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
314 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
315 | { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL }, | ||
316 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
317 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
318 | |||
319 | { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER }, | ||
320 | { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE }, | ||
321 | { SUB_CHIP_ID1, TWL6030_BASEADD_PWM }, | ||
322 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
323 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
324 | |||
325 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
326 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
327 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
328 | { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER }, | ||
329 | { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC }, | ||
330 | |||
331 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, | ||
332 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, | ||
333 | }; | ||
334 | |||
252 | /*----------------------------------------------------------------------*/ | 335 | /*----------------------------------------------------------------------*/ |
253 | 336 | ||
254 | /* Exported Functions */ | 337 | /* Exported Functions */ |
255 | 338 | ||
256 | /** | 339 | /** |
257 | * twl4030_i2c_write - Writes a n bit register in TWL4030 | 340 | * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 |
258 | * @mod_no: module number | 341 | * @mod_no: module number |
259 | * @value: an array of num_bytes+1 containing data to write | 342 | * @value: an array of num_bytes+1 containing data to write |
260 | * @reg: register address (just offset will do) | 343 | * @reg: register address (just offset will do) |
@@ -265,19 +348,19 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | |||
265 | * | 348 | * |
266 | * Returns the result of operation - 0 is success | 349 | * Returns the result of operation - 0 is success |
267 | */ | 350 | */ |
268 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 351 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
269 | { | 352 | { |
270 | int ret; | 353 | int ret; |
271 | int sid; | 354 | int sid; |
272 | struct twl4030_client *twl; | 355 | struct twl_client *twl; |
273 | struct i2c_msg *msg; | 356 | struct i2c_msg *msg; |
274 | 357 | ||
275 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | 358 | if (unlikely(mod_no > TWL_MODULE_LAST)) { |
276 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 359 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
277 | return -EPERM; | 360 | return -EPERM; |
278 | } | 361 | } |
279 | sid = twl4030_map[mod_no].sid; | 362 | sid = twl_map[mod_no].sid; |
280 | twl = &twl4030_modules[sid]; | 363 | twl = &twl_modules[sid]; |
281 | 364 | ||
282 | if (unlikely(!inuse)) { | 365 | if (unlikely(!inuse)) { |
283 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | 366 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); |
@@ -294,19 +377,26 @@ int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
294 | msg->flags = 0; | 377 | msg->flags = 0; |
295 | msg->buf = value; | 378 | msg->buf = value; |
296 | /* over write the first byte of buffer with the register address */ | 379 | /* over write the first byte of buffer with the register address */ |
297 | *value = twl4030_map[mod_no].base + reg; | 380 | *value = twl_map[mod_no].base + reg; |
298 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); | 381 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); |
299 | mutex_unlock(&twl->xfer_lock); | 382 | mutex_unlock(&twl->xfer_lock); |
300 | 383 | ||
301 | /* i2cTransfer returns num messages.translate it pls.. */ | 384 | /* i2c_transfer returns number of messages transferred */ |
302 | if (ret >= 0) | 385 | if (ret != 1) { |
303 | ret = 0; | 386 | pr_err("%s: i2c_write failed to transfer all messages\n", |
304 | return ret; | 387 | DRIVER_NAME); |
388 | if (ret < 0) | ||
389 | return ret; | ||
390 | else | ||
391 | return -EIO; | ||
392 | } else { | ||
393 | return 0; | ||
394 | } | ||
305 | } | 395 | } |
306 | EXPORT_SYMBOL(twl4030_i2c_write); | 396 | EXPORT_SYMBOL(twl_i2c_write); |
307 | 397 | ||
308 | /** | 398 | /** |
309 | * twl4030_i2c_read - Reads a n bit register in TWL4030 | 399 | * twl_i2c_read - Reads a n bit register in TWL4030/TWL5030/TWL60X0 |
310 | * @mod_no: module number | 400 | * @mod_no: module number |
311 | * @value: an array of num_bytes containing data to be read | 401 | * @value: an array of num_bytes containing data to be read |
312 | * @reg: register address (just offset will do) | 402 | * @reg: register address (just offset will do) |
@@ -314,20 +404,20 @@ EXPORT_SYMBOL(twl4030_i2c_write); | |||
314 | * | 404 | * |
315 | * Returns result of operation - num_bytes is success else failure. | 405 | * Returns result of operation - num_bytes is success else failure. |
316 | */ | 406 | */ |
317 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 407 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
318 | { | 408 | { |
319 | int ret; | 409 | int ret; |
320 | u8 val; | 410 | u8 val; |
321 | int sid; | 411 | int sid; |
322 | struct twl4030_client *twl; | 412 | struct twl_client *twl; |
323 | struct i2c_msg *msg; | 413 | struct i2c_msg *msg; |
324 | 414 | ||
325 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | 415 | if (unlikely(mod_no > TWL_MODULE_LAST)) { |
326 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 416 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
327 | return -EPERM; | 417 | return -EPERM; |
328 | } | 418 | } |
329 | sid = twl4030_map[mod_no].sid; | 419 | sid = twl_map[mod_no].sid; |
330 | twl = &twl4030_modules[sid]; | 420 | twl = &twl_modules[sid]; |
331 | 421 | ||
332 | if (unlikely(!inuse)) { | 422 | if (unlikely(!inuse)) { |
333 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | 423 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); |
@@ -339,7 +429,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
339 | msg->addr = twl->address; | 429 | msg->addr = twl->address; |
340 | msg->len = 1; | 430 | msg->len = 1; |
341 | msg->flags = 0; /* Read the register value */ | 431 | msg->flags = 0; /* Read the register value */ |
342 | val = twl4030_map[mod_no].base + reg; | 432 | val = twl_map[mod_no].base + reg; |
343 | msg->buf = &val; | 433 | msg->buf = &val; |
344 | /* [MSG2] fill the data rx buffer */ | 434 | /* [MSG2] fill the data rx buffer */ |
345 | msg = &twl->xfer_msg[1]; | 435 | msg = &twl->xfer_msg[1]; |
@@ -350,45 +440,52 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
350 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); | 440 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); |
351 | mutex_unlock(&twl->xfer_lock); | 441 | mutex_unlock(&twl->xfer_lock); |
352 | 442 | ||
353 | /* i2cTransfer returns num messages.translate it pls.. */ | 443 | /* i2c_transfer returns number of messages transferred */ |
354 | if (ret >= 0) | 444 | if (ret != 2) { |
355 | ret = 0; | 445 | pr_err("%s: i2c_read failed to transfer all messages\n", |
356 | return ret; | 446 | DRIVER_NAME); |
447 | if (ret < 0) | ||
448 | return ret; | ||
449 | else | ||
450 | return -EIO; | ||
451 | } else { | ||
452 | return 0; | ||
453 | } | ||
357 | } | 454 | } |
358 | EXPORT_SYMBOL(twl4030_i2c_read); | 455 | EXPORT_SYMBOL(twl_i2c_read); |
359 | 456 | ||
360 | /** | 457 | /** |
361 | * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030 | 458 | * twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL5030/TWL60X0 |
362 | * @mod_no: module number | 459 | * @mod_no: module number |
363 | * @value: the value to be written 8 bit | 460 | * @value: the value to be written 8 bit |
364 | * @reg: register address (just offset will do) | 461 | * @reg: register address (just offset will do) |
365 | * | 462 | * |
366 | * Returns result of operation - 0 is success | 463 | * Returns result of operation - 0 is success |
367 | */ | 464 | */ |
368 | int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg) | 465 | int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg) |
369 | { | 466 | { |
370 | 467 | ||
371 | /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ | 468 | /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ |
372 | u8 temp_buffer[2] = { 0 }; | 469 | u8 temp_buffer[2] = { 0 }; |
373 | /* offset 1 contains the data */ | 470 | /* offset 1 contains the data */ |
374 | temp_buffer[1] = value; | 471 | temp_buffer[1] = value; |
375 | return twl4030_i2c_write(mod_no, temp_buffer, reg, 1); | 472 | return twl_i2c_write(mod_no, temp_buffer, reg, 1); |
376 | } | 473 | } |
377 | EXPORT_SYMBOL(twl4030_i2c_write_u8); | 474 | EXPORT_SYMBOL(twl_i2c_write_u8); |
378 | 475 | ||
379 | /** | 476 | /** |
380 | * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030 | 477 | * twl_i2c_read_u8 - Reads a 8 bit register from TWL4030/TWL5030/TWL60X0 |
381 | * @mod_no: module number | 478 | * @mod_no: module number |
382 | * @value: the value read 8 bit | 479 | * @value: the value read 8 bit |
383 | * @reg: register address (just offset will do) | 480 | * @reg: register address (just offset will do) |
384 | * | 481 | * |
385 | * Returns result of operation - 0 is success | 482 | * Returns result of operation - 0 is success |
386 | */ | 483 | */ |
387 | int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) | 484 | int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) |
388 | { | 485 | { |
389 | return twl4030_i2c_read(mod_no, value, reg, 1); | 486 | return twl_i2c_read(mod_no, value, reg, 1); |
390 | } | 487 | } |
391 | EXPORT_SYMBOL(twl4030_i2c_read_u8); | 488 | EXPORT_SYMBOL(twl_i2c_read_u8); |
392 | 489 | ||
393 | /*----------------------------------------------------------------------*/ | 490 | /*----------------------------------------------------------------------*/ |
394 | 491 | ||
@@ -398,7 +495,7 @@ add_numbered_child(unsigned chip, const char *name, int num, | |||
398 | bool can_wakeup, int irq0, int irq1) | 495 | bool can_wakeup, int irq0, int irq1) |
399 | { | 496 | { |
400 | struct platform_device *pdev; | 497 | struct platform_device *pdev; |
401 | struct twl4030_client *twl = &twl4030_modules[chip]; | 498 | struct twl_client *twl = &twl_modules[chip]; |
402 | int status; | 499 | int status; |
403 | 500 | ||
404 | pdev = platform_device_alloc(name, num); | 501 | pdev = platform_device_alloc(name, num); |
@@ -456,6 +553,7 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
456 | struct regulator_consumer_supply *consumers, | 553 | struct regulator_consumer_supply *consumers, |
457 | unsigned num_consumers) | 554 | unsigned num_consumers) |
458 | { | 555 | { |
556 | unsigned sub_chip_id; | ||
459 | /* regulator framework demands init_data ... */ | 557 | /* regulator framework demands init_data ... */ |
460 | if (!pdata) | 558 | if (!pdata) |
461 | return NULL; | 559 | return NULL; |
@@ -466,7 +564,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
466 | } | 564 | } |
467 | 565 | ||
468 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ | 566 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
469 | return add_numbered_child(3, "twl4030_reg", num, | 567 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; |
568 | return add_numbered_child(sub_chip_id, "twl_reg", num, | ||
470 | pdata, sizeof(*pdata), false, 0, 0); | 569 | pdata, sizeof(*pdata), false, 0, 0); |
471 | } | 570 | } |
472 | 571 | ||
@@ -486,29 +585,32 @@ static int | |||
486 | add_children(struct twl4030_platform_data *pdata, unsigned long features) | 585 | add_children(struct twl4030_platform_data *pdata, unsigned long features) |
487 | { | 586 | { |
488 | struct device *child; | 587 | struct device *child; |
588 | unsigned sub_chip_id; | ||
489 | 589 | ||
490 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { | 590 | if (twl_has_bci() && pdata->bci && |
591 | !(features & (TPS_SUBSET | TWL5031))) { | ||
491 | child = add_child(3, "twl4030_bci", | 592 | child = add_child(3, "twl4030_bci", |
492 | pdata->bci, sizeof(*pdata->bci), | 593 | pdata->bci, sizeof(*pdata->bci), |
493 | false, | 594 | false, |
494 | /* irq0 = CHG_PRES, irq1 = BCI */ | 595 | /* irq0 = CHG_PRES, irq1 = BCI */ |
495 | pdata->irq_base + 8 + 1, pdata->irq_base + 2); | 596 | pdata->irq_base + BCI_PRES_INTR_OFFSET, |
597 | pdata->irq_base + BCI_INTR_OFFSET); | ||
496 | if (IS_ERR(child)) | 598 | if (IS_ERR(child)) |
497 | return PTR_ERR(child); | 599 | return PTR_ERR(child); |
498 | } | 600 | } |
499 | 601 | ||
500 | if (twl_has_gpio() && pdata->gpio) { | 602 | if (twl_has_gpio() && pdata->gpio) { |
501 | child = add_child(1, "twl4030_gpio", | 603 | child = add_child(SUB_CHIP_ID1, "twl4030_gpio", |
502 | pdata->gpio, sizeof(*pdata->gpio), | 604 | pdata->gpio, sizeof(*pdata->gpio), |
503 | false, pdata->irq_base + 0, 0); | 605 | false, pdata->irq_base + GPIO_INTR_OFFSET, 0); |
504 | if (IS_ERR(child)) | 606 | if (IS_ERR(child)) |
505 | return PTR_ERR(child); | 607 | return PTR_ERR(child); |
506 | } | 608 | } |
507 | 609 | ||
508 | if (twl_has_keypad() && pdata->keypad) { | 610 | if (twl_has_keypad() && pdata->keypad) { |
509 | child = add_child(2, "twl4030_keypad", | 611 | child = add_child(SUB_CHIP_ID2, "twl4030_keypad", |
510 | pdata->keypad, sizeof(*pdata->keypad), | 612 | pdata->keypad, sizeof(*pdata->keypad), |
511 | true, pdata->irq_base + 1, 0); | 613 | true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0); |
512 | if (IS_ERR(child)) | 614 | if (IS_ERR(child)) |
513 | return PTR_ERR(child); | 615 | return PTR_ERR(child); |
514 | } | 616 | } |
@@ -516,7 +618,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
516 | if (twl_has_madc() && pdata->madc) { | 618 | if (twl_has_madc() && pdata->madc) { |
517 | child = add_child(2, "twl4030_madc", | 619 | child = add_child(2, "twl4030_madc", |
518 | pdata->madc, sizeof(*pdata->madc), | 620 | pdata->madc, sizeof(*pdata->madc), |
519 | true, pdata->irq_base + 3, 0); | 621 | true, pdata->irq_base + MADC_INTR_OFFSET, 0); |
520 | if (IS_ERR(child)) | 622 | if (IS_ERR(child)) |
521 | return PTR_ERR(child); | 623 | return PTR_ERR(child); |
522 | } | 624 | } |
@@ -529,14 +631,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
529 | * Eventually, Linux might become more aware of such | 631 | * Eventually, Linux might become more aware of such |
530 | * HW security concerns, and "least privilege". | 632 | * HW security concerns, and "least privilege". |
531 | */ | 633 | */ |
532 | child = add_child(3, "twl4030_rtc", | 634 | sub_chip_id = twl_map[TWL_MODULE_RTC].sid; |
635 | child = add_child(sub_chip_id, "twl_rtc", | ||
533 | NULL, 0, | 636 | NULL, 0, |
534 | true, pdata->irq_base + 8 + 3, 0); | 637 | true, pdata->irq_base + RTC_INTR_OFFSET, 0); |
535 | if (IS_ERR(child)) | 638 | if (IS_ERR(child)) |
536 | return PTR_ERR(child); | 639 | return PTR_ERR(child); |
537 | } | 640 | } |
538 | 641 | ||
539 | if (twl_has_usb() && pdata->usb) { | 642 | if (twl_has_usb() && pdata->usb && twl_class_is_4030()) { |
540 | 643 | ||
541 | static struct regulator_consumer_supply usb1v5 = { | 644 | static struct regulator_consumer_supply usb1v5 = { |
542 | .supply = "usb1v5", | 645 | .supply = "usb1v5", |
@@ -581,7 +684,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
581 | pdata->usb, sizeof(*pdata->usb), | 684 | pdata->usb, sizeof(*pdata->usb), |
582 | true, | 685 | true, |
583 | /* irq0 = USB_PRES, irq1 = USB */ | 686 | /* irq0 = USB_PRES, irq1 = USB */ |
584 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); | 687 | pdata->irq_base + USB_PRES_INTR_OFFSET, |
688 | pdata->irq_base + USB_INTR_OFFSET); | ||
585 | 689 | ||
586 | if (IS_ERR(child)) | 690 | if (IS_ERR(child)) |
587 | return PTR_ERR(child); | 691 | return PTR_ERR(child); |
@@ -615,12 +719,23 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
615 | return PTR_ERR(child); | 719 | return PTR_ERR(child); |
616 | } | 720 | } |
617 | 721 | ||
618 | if (twl_has_regulator()) { | 722 | /* twl4030 regulators */ |
619 | /* | 723 | if (twl_has_regulator() && twl_class_is_4030()) { |
620 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); | 724 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); |
621 | if (IS_ERR(child)) | 725 | if (IS_ERR(child)) |
622 | return PTR_ERR(child); | 726 | return PTR_ERR(child); |
623 | */ | 727 | |
728 | child = add_regulator(TWL4030_REG_VIO, pdata->vio); | ||
729 | if (IS_ERR(child)) | ||
730 | return PTR_ERR(child); | ||
731 | |||
732 | child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); | ||
733 | if (IS_ERR(child)) | ||
734 | return PTR_ERR(child); | ||
735 | |||
736 | child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); | ||
737 | if (IS_ERR(child)) | ||
738 | return PTR_ERR(child); | ||
624 | 739 | ||
625 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); | 740 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); |
626 | if (IS_ERR(child)) | 741 | if (IS_ERR(child)) |
@@ -636,10 +751,23 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
636 | pdata->vaux2); | 751 | pdata->vaux2); |
637 | if (IS_ERR(child)) | 752 | if (IS_ERR(child)) |
638 | return PTR_ERR(child); | 753 | return PTR_ERR(child); |
754 | |||
755 | child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); | ||
756 | if (IS_ERR(child)) | ||
757 | return PTR_ERR(child); | ||
758 | |||
759 | child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); | ||
760 | if (IS_ERR(child)) | ||
761 | return PTR_ERR(child); | ||
762 | |||
763 | child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); | ||
764 | if (IS_ERR(child)) | ||
765 | return PTR_ERR(child); | ||
639 | } | 766 | } |
640 | 767 | ||
641 | /* maybe add LDOs that are omitted on cost-reduced parts */ | 768 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
642 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { | 769 | if (twl_has_regulator() && !(features & TPS_SUBSET) |
770 | && twl_class_is_4030()) { | ||
643 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); | 771 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); |
644 | if (IS_ERR(child)) | 772 | if (IS_ERR(child)) |
645 | return PTR_ERR(child); | 773 | return PTR_ERR(child); |
@@ -665,6 +793,49 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
665 | return PTR_ERR(child); | 793 | return PTR_ERR(child); |
666 | } | 794 | } |
667 | 795 | ||
796 | /* twl6030 regulators */ | ||
797 | if (twl_has_regulator() && twl_class_is_6030()) { | ||
798 | child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); | ||
799 | if (IS_ERR(child)) | ||
800 | return PTR_ERR(child); | ||
801 | |||
802 | child = add_regulator(TWL6030_REG_VPP, pdata->vpp); | ||
803 | if (IS_ERR(child)) | ||
804 | return PTR_ERR(child); | ||
805 | |||
806 | child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); | ||
807 | if (IS_ERR(child)) | ||
808 | return PTR_ERR(child); | ||
809 | |||
810 | child = add_regulator(TWL6030_REG_VANA, pdata->vana); | ||
811 | if (IS_ERR(child)) | ||
812 | return PTR_ERR(child); | ||
813 | |||
814 | child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); | ||
815 | if (IS_ERR(child)) | ||
816 | return PTR_ERR(child); | ||
817 | |||
818 | child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); | ||
819 | if (IS_ERR(child)) | ||
820 | return PTR_ERR(child); | ||
821 | |||
822 | child = add_regulator(TWL6030_REG_VUSB, pdata->vusb); | ||
823 | if (IS_ERR(child)) | ||
824 | return PTR_ERR(child); | ||
825 | |||
826 | child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); | ||
827 | if (IS_ERR(child)) | ||
828 | return PTR_ERR(child); | ||
829 | |||
830 | child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); | ||
831 | if (IS_ERR(child)) | ||
832 | return PTR_ERR(child); | ||
833 | |||
834 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); | ||
835 | if (IS_ERR(child)) | ||
836 | return PTR_ERR(child); | ||
837 | } | ||
838 | |||
668 | return 0; | 839 | return 0; |
669 | } | 840 | } |
670 | 841 | ||
@@ -679,7 +850,7 @@ static inline int __init protect_pm_master(void) | |||
679 | { | 850 | { |
680 | int e = 0; | 851 | int e = 0; |
681 | 852 | ||
682 | e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK, | 853 | e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_LOCK, |
683 | R_PROTECT_KEY); | 854 | R_PROTECT_KEY); |
684 | return e; | 855 | return e; |
685 | } | 856 | } |
@@ -688,14 +859,15 @@ static inline int __init unprotect_pm_master(void) | |||
688 | { | 859 | { |
689 | int e = 0; | 860 | int e = 0; |
690 | 861 | ||
691 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1, | 862 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK1, |
692 | R_PROTECT_KEY); | 863 | R_PROTECT_KEY); |
693 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2, | 864 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK2, |
694 | R_PROTECT_KEY); | 865 | R_PROTECT_KEY); |
695 | return e; | 866 | return e; |
696 | } | 867 | } |
697 | 868 | ||
698 | static void clocks_init(struct device *dev) | 869 | static void clocks_init(struct device *dev, |
870 | struct twl4030_clock_init_data *clock) | ||
699 | { | 871 | { |
700 | int e = 0; | 872 | int e = 0; |
701 | struct clk *osc; | 873 | struct clk *osc; |
@@ -709,7 +881,7 @@ static void clocks_init(struct device *dev) | |||
709 | osc = clk_get(dev, "osc_sys_ck"); | 881 | osc = clk_get(dev, "osc_sys_ck"); |
710 | 882 | ||
711 | if (IS_ERR(osc)) { | 883 | if (IS_ERR(osc)) { |
712 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | 884 | printk(KERN_WARNING "Skipping twl internal clock init and " |
713 | "using bootloader value (unknown osc rate)\n"); | 885 | "using bootloader value (unknown osc rate)\n"); |
714 | return; | 886 | return; |
715 | } | 887 | } |
@@ -723,7 +895,7 @@ static void clocks_init(struct device *dev) | |||
723 | */ | 895 | */ |
724 | osc = ERR_PTR(-EIO); | 896 | osc = ERR_PTR(-EIO); |
725 | 897 | ||
726 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | 898 | printk(KERN_WARNING "Skipping twl internal clock init and " |
727 | "using bootloader value (unknown osc rate)\n"); | 899 | "using bootloader value (unknown osc rate)\n"); |
728 | 900 | ||
729 | return; | 901 | return; |
@@ -742,9 +914,12 @@ static void clocks_init(struct device *dev) | |||
742 | } | 914 | } |
743 | 915 | ||
744 | ctrl |= HIGH_PERF_SQ; | 916 | ctrl |= HIGH_PERF_SQ; |
917 | if (clock && clock->ck32k_lowpwr_enable) | ||
918 | ctrl |= CK32K_LOWPWR_EN; | ||
919 | |||
745 | e |= unprotect_pm_master(); | 920 | e |= unprotect_pm_master(); |
746 | /* effect->MADC+USB ck en */ | 921 | /* effect->MADC+USB ck en */ |
747 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); | 922 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); |
748 | e |= protect_pm_master(); | 923 | e |= protect_pm_master(); |
749 | 924 | ||
750 | if (e < 0) | 925 | if (e < 0) |
@@ -753,24 +928,31 @@ static void clocks_init(struct device *dev) | |||
753 | 928 | ||
754 | /*----------------------------------------------------------------------*/ | 929 | /*----------------------------------------------------------------------*/ |
755 | 930 | ||
756 | int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | 931 | int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); |
757 | int twl_exit_irq(void); | 932 | int twl4030_exit_irq(void); |
933 | int twl4030_init_chip_irq(const char *chip); | ||
934 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
935 | int twl6030_exit_irq(void); | ||
758 | 936 | ||
759 | static int twl4030_remove(struct i2c_client *client) | 937 | static int twl_remove(struct i2c_client *client) |
760 | { | 938 | { |
761 | unsigned i; | 939 | unsigned i; |
762 | int status; | 940 | int status; |
763 | 941 | ||
764 | status = twl_exit_irq(); | 942 | if (twl_class_is_4030()) |
943 | status = twl4030_exit_irq(); | ||
944 | else | ||
945 | status = twl6030_exit_irq(); | ||
946 | |||
765 | if (status < 0) | 947 | if (status < 0) |
766 | return status; | 948 | return status; |
767 | 949 | ||
768 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | 950 | for (i = 0; i < TWL_NUM_SLAVES; i++) { |
769 | struct twl4030_client *twl = &twl4030_modules[i]; | 951 | struct twl_client *twl = &twl_modules[i]; |
770 | 952 | ||
771 | if (twl->client && twl->client != client) | 953 | if (twl->client && twl->client != client) |
772 | i2c_unregister_device(twl->client); | 954 | i2c_unregister_device(twl->client); |
773 | twl4030_modules[i].client = NULL; | 955 | twl_modules[i].client = NULL; |
774 | } | 956 | } |
775 | inuse = false; | 957 | inuse = false; |
776 | return 0; | 958 | return 0; |
@@ -778,7 +960,7 @@ static int twl4030_remove(struct i2c_client *client) | |||
778 | 960 | ||
779 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ | 961 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ |
780 | static int __init | 962 | static int __init |
781 | twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | 963 | twl_probe(struct i2c_client *client, const struct i2c_device_id *id) |
782 | { | 964 | { |
783 | int status; | 965 | int status; |
784 | unsigned i; | 966 | unsigned i; |
@@ -799,8 +981,8 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
799 | return -EBUSY; | 981 | return -EBUSY; |
800 | } | 982 | } |
801 | 983 | ||
802 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | 984 | for (i = 0; i < TWL_NUM_SLAVES; i++) { |
803 | struct twl4030_client *twl = &twl4030_modules[i]; | 985 | struct twl_client *twl = &twl_modules[i]; |
804 | 986 | ||
805 | twl->address = client->addr + i; | 987 | twl->address = client->addr + i; |
806 | if (i == 0) | 988 | if (i == 0) |
@@ -814,15 +996,20 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
814 | status = -ENOMEM; | 996 | status = -ENOMEM; |
815 | goto fail; | 997 | goto fail; |
816 | } | 998 | } |
817 | strlcpy(twl->client->name, id->name, | ||
818 | sizeof(twl->client->name)); | ||
819 | } | 999 | } |
820 | mutex_init(&twl->xfer_lock); | 1000 | mutex_init(&twl->xfer_lock); |
821 | } | 1001 | } |
822 | inuse = true; | 1002 | inuse = true; |
1003 | if ((id->driver_data) & TWL6030_CLASS) { | ||
1004 | twl_id = TWL6030_CLASS_ID; | ||
1005 | twl_map = &twl6030_map[0]; | ||
1006 | } else { | ||
1007 | twl_id = TWL4030_CLASS_ID; | ||
1008 | twl_map = &twl4030_map[0]; | ||
1009 | } | ||
823 | 1010 | ||
824 | /* setup clock framework */ | 1011 | /* setup clock framework */ |
825 | clocks_init(&client->dev); | 1012 | clocks_init(&client->dev, pdata->clock); |
826 | 1013 | ||
827 | /* load power event scripts */ | 1014 | /* load power event scripts */ |
828 | if (twl_has_power() && pdata->power) | 1015 | if (twl_has_power() && pdata->power) |
@@ -832,7 +1019,15 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
832 | if (client->irq | 1019 | if (client->irq |
833 | && pdata->irq_base | 1020 | && pdata->irq_base |
834 | && pdata->irq_end > pdata->irq_base) { | 1021 | && pdata->irq_end > pdata->irq_base) { |
835 | status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); | 1022 | if (twl_class_is_4030()) { |
1023 | twl4030_init_chip_irq(id->name); | ||
1024 | status = twl4030_init_irq(client->irq, pdata->irq_base, | ||
1025 | pdata->irq_end); | ||
1026 | } else { | ||
1027 | status = twl6030_init_irq(client->irq, pdata->irq_base, | ||
1028 | pdata->irq_end); | ||
1029 | } | ||
1030 | |||
836 | if (status < 0) | 1031 | if (status < 0) |
837 | goto fail; | 1032 | goto fail; |
838 | } | 1033 | } |
@@ -840,40 +1035,42 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
840 | status = add_children(pdata, id->driver_data); | 1035 | status = add_children(pdata, id->driver_data); |
841 | fail: | 1036 | fail: |
842 | if (status < 0) | 1037 | if (status < 0) |
843 | twl4030_remove(client); | 1038 | twl_remove(client); |
844 | return status; | 1039 | return status; |
845 | } | 1040 | } |
846 | 1041 | ||
847 | static const struct i2c_device_id twl4030_ids[] = { | 1042 | static const struct i2c_device_id twl_ids[] = { |
848 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ | 1043 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ |
849 | { "twl5030", 0 }, /* T2 updated */ | 1044 | { "twl5030", 0 }, /* T2 updated */ |
1045 | { "twl5031", TWL5031 }, /* TWL5030 updated */ | ||
850 | { "tps65950", 0 }, /* catalog version of twl5030 */ | 1046 | { "tps65950", 0 }, /* catalog version of twl5030 */ |
851 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ | 1047 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ |
852 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ | 1048 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ |
1049 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ | ||
853 | { /* end of list */ }, | 1050 | { /* end of list */ }, |
854 | }; | 1051 | }; |
855 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); | 1052 | MODULE_DEVICE_TABLE(i2c, twl_ids); |
856 | 1053 | ||
857 | /* One Client Driver , 4 Clients */ | 1054 | /* One Client Driver , 4 Clients */ |
858 | static struct i2c_driver twl4030_driver = { | 1055 | static struct i2c_driver twl_driver = { |
859 | .driver.name = DRIVER_NAME, | 1056 | .driver.name = DRIVER_NAME, |
860 | .id_table = twl4030_ids, | 1057 | .id_table = twl_ids, |
861 | .probe = twl4030_probe, | 1058 | .probe = twl_probe, |
862 | .remove = twl4030_remove, | 1059 | .remove = twl_remove, |
863 | }; | 1060 | }; |
864 | 1061 | ||
865 | static int __init twl4030_init(void) | 1062 | static int __init twl_init(void) |
866 | { | 1063 | { |
867 | return i2c_add_driver(&twl4030_driver); | 1064 | return i2c_add_driver(&twl_driver); |
868 | } | 1065 | } |
869 | subsys_initcall(twl4030_init); | 1066 | subsys_initcall(twl_init); |
870 | 1067 | ||
871 | static void __exit twl4030_exit(void) | 1068 | static void __exit twl_exit(void) |
872 | { | 1069 | { |
873 | i2c_del_driver(&twl4030_driver); | 1070 | i2c_del_driver(&twl_driver); |
874 | } | 1071 | } |
875 | module_exit(twl4030_exit); | 1072 | module_exit(twl_exit); |
876 | 1073 | ||
877 | MODULE_AUTHOR("Texas Instruments, Inc."); | 1074 | MODULE_AUTHOR("Texas Instruments, Inc."); |
878 | MODULE_DESCRIPTION("I2C Core interface for TWL4030"); | 1075 | MODULE_DESCRIPTION("I2C Core interface for TWL"); |
879 | MODULE_LICENSE("GPL"); | 1076 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index fb194fe244c1..20d29bafc9f5 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
33 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
34 | 34 | ||
35 | #include <linux/i2c/twl4030.h> | 35 | #include <linux/i2c/twl.h> |
36 | 36 | ||
37 | 37 | ||
38 | /* | 38 | /* |
@@ -74,6 +74,8 @@ struct sih { | |||
74 | u8 edr_offset; | 74 | u8 edr_offset; |
75 | u8 bytes_edr; /* bytelen of EDR */ | 75 | u8 bytes_edr; /* bytelen of EDR */ |
76 | 76 | ||
77 | u8 irq_lines; /* number of supported irq lines */ | ||
78 | |||
77 | /* SIR ignored -- set interrupt, for testing only */ | 79 | /* SIR ignored -- set interrupt, for testing only */ |
78 | struct irq_data { | 80 | struct irq_data { |
79 | u8 isr_offset; | 81 | u8 isr_offset; |
@@ -82,6 +84,9 @@ struct sih { | |||
82 | /* + 2 bytes padding */ | 84 | /* + 2 bytes padding */ |
83 | }; | 85 | }; |
84 | 86 | ||
87 | static const struct sih *sih_modules; | ||
88 | static int nr_sih_modules; | ||
89 | |||
85 | #define SIH_INITIALIZER(modname, nbits) \ | 90 | #define SIH_INITIALIZER(modname, nbits) \ |
86 | .module = TWL4030_MODULE_ ## modname, \ | 91 | .module = TWL4030_MODULE_ ## modname, \ |
87 | .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \ | 92 | .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \ |
@@ -89,6 +94,7 @@ struct sih { | |||
89 | .bytes_ixr = DIV_ROUND_UP(nbits, 8), \ | 94 | .bytes_ixr = DIV_ROUND_UP(nbits, 8), \ |
90 | .edr_offset = TWL4030_ ## modname ## _EDR, \ | 95 | .edr_offset = TWL4030_ ## modname ## _EDR, \ |
91 | .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \ | 96 | .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \ |
97 | .irq_lines = 2, \ | ||
92 | .mask = { { \ | 98 | .mask = { { \ |
93 | .isr_offset = TWL4030_ ## modname ## _ISR1, \ | 99 | .isr_offset = TWL4030_ ## modname ## _ISR1, \ |
94 | .imr_offset = TWL4030_ ## modname ## _IMR1, \ | 100 | .imr_offset = TWL4030_ ## modname ## _IMR1, \ |
@@ -107,7 +113,8 @@ struct sih { | |||
107 | /* Order in this table matches order in PIH_ISR. That is, | 113 | /* Order in this table matches order in PIH_ISR. That is, |
108 | * BIT(n) in PIH_ISR is sih_modules[n]. | 114 | * BIT(n) in PIH_ISR is sih_modules[n]. |
109 | */ | 115 | */ |
110 | static const struct sih sih_modules[6] = { | 116 | /* sih_modules_twl4030 is used both in twl4030 and twl5030 */ |
117 | static const struct sih sih_modules_twl4030[6] = { | ||
111 | [0] = { | 118 | [0] = { |
112 | .name = "gpio", | 119 | .name = "gpio", |
113 | .module = TWL4030_MODULE_GPIO, | 120 | .module = TWL4030_MODULE_GPIO, |
@@ -118,6 +125,7 @@ static const struct sih sih_modules[6] = { | |||
118 | /* Note: *all* of these IRQs default to no-trigger */ | 125 | /* Note: *all* of these IRQs default to no-trigger */ |
119 | .edr_offset = REG_GPIO_EDR1, | 126 | .edr_offset = REG_GPIO_EDR1, |
120 | .bytes_edr = 5, | 127 | .bytes_edr = 5, |
128 | .irq_lines = 2, | ||
121 | .mask = { { | 129 | .mask = { { |
122 | .isr_offset = REG_GPIO_ISR1A, | 130 | .isr_offset = REG_GPIO_ISR1A, |
123 | .imr_offset = REG_GPIO_IMR1A, | 131 | .imr_offset = REG_GPIO_IMR1A, |
@@ -140,6 +148,7 @@ static const struct sih sih_modules[6] = { | |||
140 | .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, | 148 | .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, |
141 | /* Note: most of these IRQs default to no-trigger */ | 149 | /* Note: most of these IRQs default to no-trigger */ |
142 | .bytes_edr = 3, | 150 | .bytes_edr = 3, |
151 | .irq_lines = 2, | ||
143 | .mask = { { | 152 | .mask = { { |
144 | .isr_offset = TWL4030_INTERRUPTS_BCIISR1A, | 153 | .isr_offset = TWL4030_INTERRUPTS_BCIISR1A, |
145 | .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A, | 154 | .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A, |
@@ -164,6 +173,99 @@ static const struct sih sih_modules[6] = { | |||
164 | /* there are no SIH modules #6 or #7 ... */ | 173 | /* there are no SIH modules #6 or #7 ... */ |
165 | }; | 174 | }; |
166 | 175 | ||
176 | static const struct sih sih_modules_twl5031[8] = { | ||
177 | [0] = { | ||
178 | .name = "gpio", | ||
179 | .module = TWL4030_MODULE_GPIO, | ||
180 | .control_offset = REG_GPIO_SIH_CTRL, | ||
181 | .set_cor = true, | ||
182 | .bits = TWL4030_GPIO_MAX, | ||
183 | .bytes_ixr = 3, | ||
184 | /* Note: *all* of these IRQs default to no-trigger */ | ||
185 | .edr_offset = REG_GPIO_EDR1, | ||
186 | .bytes_edr = 5, | ||
187 | .irq_lines = 2, | ||
188 | .mask = { { | ||
189 | .isr_offset = REG_GPIO_ISR1A, | ||
190 | .imr_offset = REG_GPIO_IMR1A, | ||
191 | }, { | ||
192 | .isr_offset = REG_GPIO_ISR1B, | ||
193 | .imr_offset = REG_GPIO_IMR1B, | ||
194 | }, }, | ||
195 | }, | ||
196 | [1] = { | ||
197 | .name = "keypad", | ||
198 | .set_cor = true, | ||
199 | SIH_INITIALIZER(KEYPAD_KEYP, 4) | ||
200 | }, | ||
201 | [2] = { | ||
202 | .name = "bci", | ||
203 | .module = TWL5031_MODULE_INTERRUPTS, | ||
204 | .control_offset = TWL5031_INTERRUPTS_BCISIHCTRL, | ||
205 | .bits = 7, | ||
206 | .bytes_ixr = 1, | ||
207 | .edr_offset = TWL5031_INTERRUPTS_BCIEDR1, | ||
208 | /* Note: most of these IRQs default to no-trigger */ | ||
209 | .bytes_edr = 2, | ||
210 | .irq_lines = 2, | ||
211 | .mask = { { | ||
212 | .isr_offset = TWL5031_INTERRUPTS_BCIISR1, | ||
213 | .imr_offset = TWL5031_INTERRUPTS_BCIIMR1, | ||
214 | }, { | ||
215 | .isr_offset = TWL5031_INTERRUPTS_BCIISR2, | ||
216 | .imr_offset = TWL5031_INTERRUPTS_BCIIMR2, | ||
217 | }, }, | ||
218 | }, | ||
219 | [3] = { | ||
220 | .name = "madc", | ||
221 | SIH_INITIALIZER(MADC, 4) | ||
222 | }, | ||
223 | [4] = { | ||
224 | /* USB doesn't use the same SIH organization */ | ||
225 | .name = "usb", | ||
226 | }, | ||
227 | [5] = { | ||
228 | .name = "power", | ||
229 | .set_cor = true, | ||
230 | SIH_INITIALIZER(INT_PWR, 8) | ||
231 | }, | ||
232 | [6] = { | ||
233 | /* | ||
234 | * ACI doesn't use the same SIH organization. | ||
235 | * For example, it supports only one interrupt line | ||
236 | */ | ||
237 | .name = "aci", | ||
238 | .module = TWL5031_MODULE_ACCESSORY, | ||
239 | .bits = 9, | ||
240 | .bytes_ixr = 2, | ||
241 | .irq_lines = 1, | ||
242 | .mask = { { | ||
243 | .isr_offset = TWL5031_ACIIDR_LSB, | ||
244 | .imr_offset = TWL5031_ACIIMR_LSB, | ||
245 | }, }, | ||
246 | |||
247 | }, | ||
248 | [7] = { | ||
249 | /* Accessory */ | ||
250 | .name = "acc", | ||
251 | .module = TWL5031_MODULE_ACCESSORY, | ||
252 | .control_offset = TWL5031_ACCSIHCTRL, | ||
253 | .bits = 2, | ||
254 | .bytes_ixr = 1, | ||
255 | .edr_offset = TWL5031_ACCEDR1, | ||
256 | /* Note: most of these IRQs default to no-trigger */ | ||
257 | .bytes_edr = 1, | ||
258 | .irq_lines = 2, | ||
259 | .mask = { { | ||
260 | .isr_offset = TWL5031_ACCISR1, | ||
261 | .imr_offset = TWL5031_ACCIMR1, | ||
262 | }, { | ||
263 | .isr_offset = TWL5031_ACCISR2, | ||
264 | .imr_offset = TWL5031_ACCIMR2, | ||
265 | }, }, | ||
266 | }, | ||
267 | }; | ||
268 | |||
167 | #undef TWL4030_MODULE_KEYPAD_KEYP | 269 | #undef TWL4030_MODULE_KEYPAD_KEYP |
168 | #undef TWL4030_MODULE_INT_PWR | 270 | #undef TWL4030_MODULE_INT_PWR |
169 | #undef TWL4030_INT_PWR_EDR | 271 | #undef TWL4030_INT_PWR_EDR |
@@ -194,7 +296,7 @@ static int twl4030_irq_thread(void *data) | |||
194 | /* Wait for IRQ, then read PIH irq status (also blocking) */ | 296 | /* Wait for IRQ, then read PIH irq status (also blocking) */ |
195 | wait_for_completion_interruptible(&irq_event); | 297 | wait_for_completion_interruptible(&irq_event); |
196 | 298 | ||
197 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, | 299 | ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, |
198 | REG_PIH_ISR_P1); | 300 | REG_PIH_ISR_P1); |
199 | if (ret) { | 301 | if (ret) { |
200 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", | 302 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", |
@@ -284,13 +386,17 @@ static int twl4030_init_sih_modules(unsigned line) | |||
284 | /* disable all interrupts on our line */ | 386 | /* disable all interrupts on our line */ |
285 | memset(buf, 0xff, sizeof buf); | 387 | memset(buf, 0xff, sizeof buf); |
286 | sih = sih_modules; | 388 | sih = sih_modules; |
287 | for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { | 389 | for (i = 0; i < nr_sih_modules; i++, sih++) { |
288 | 390 | ||
289 | /* skip USB -- it's funky */ | 391 | /* skip USB -- it's funky */ |
290 | if (!sih->bytes_ixr) | 392 | if (!sih->bytes_ixr) |
291 | continue; | 393 | continue; |
292 | 394 | ||
293 | status = twl4030_i2c_write(sih->module, buf, | 395 | /* Not all the SIH modules support multiple interrupt lines */ |
396 | if (sih->irq_lines <= line) | ||
397 | continue; | ||
398 | |||
399 | status = twl_i2c_write(sih->module, buf, | ||
294 | sih->mask[line].imr_offset, sih->bytes_ixr); | 400 | sih->mask[line].imr_offset, sih->bytes_ixr); |
295 | if (status < 0) | 401 | if (status < 0) |
296 | pr_err("twl4030: err %d initializing %s %s\n", | 402 | pr_err("twl4030: err %d initializing %s %s\n", |
@@ -304,7 +410,7 @@ static int twl4030_init_sih_modules(unsigned line) | |||
304 | * And for PWR_INT it's not documented... | 410 | * And for PWR_INT it's not documented... |
305 | */ | 411 | */ |
306 | if (sih->set_cor) { | 412 | if (sih->set_cor) { |
307 | status = twl4030_i2c_write_u8(sih->module, | 413 | status = twl_i2c_write_u8(sih->module, |
308 | TWL4030_SIH_CTRL_COR_MASK, | 414 | TWL4030_SIH_CTRL_COR_MASK, |
309 | sih->control_offset); | 415 | sih->control_offset); |
310 | if (status < 0) | 416 | if (status < 0) |
@@ -314,7 +420,7 @@ static int twl4030_init_sih_modules(unsigned line) | |||
314 | } | 420 | } |
315 | 421 | ||
316 | sih = sih_modules; | 422 | sih = sih_modules; |
317 | for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { | 423 | for (i = 0; i < nr_sih_modules; i++, sih++) { |
318 | u8 rxbuf[4]; | 424 | u8 rxbuf[4]; |
319 | int j; | 425 | int j; |
320 | 426 | ||
@@ -322,20 +428,24 @@ static int twl4030_init_sih_modules(unsigned line) | |||
322 | if (!sih->bytes_ixr) | 428 | if (!sih->bytes_ixr) |
323 | continue; | 429 | continue; |
324 | 430 | ||
431 | /* Not all the SIH modules support multiple interrupt lines */ | ||
432 | if (sih->irq_lines <= line) | ||
433 | continue; | ||
434 | |||
325 | /* Clear pending interrupt status. Either the read was | 435 | /* Clear pending interrupt status. Either the read was |
326 | * enough, or we need to write those bits. Repeat, in | 436 | * enough, or we need to write those bits. Repeat, in |
327 | * case an IRQ is pending (PENDDIS=0) ... that's not | 437 | * case an IRQ is pending (PENDDIS=0) ... that's not |
328 | * uncommon with PWR_INT.PWRON. | 438 | * uncommon with PWR_INT.PWRON. |
329 | */ | 439 | */ |
330 | for (j = 0; j < 2; j++) { | 440 | for (j = 0; j < 2; j++) { |
331 | status = twl4030_i2c_read(sih->module, rxbuf, | 441 | status = twl_i2c_read(sih->module, rxbuf, |
332 | sih->mask[line].isr_offset, sih->bytes_ixr); | 442 | sih->mask[line].isr_offset, sih->bytes_ixr); |
333 | if (status < 0) | 443 | if (status < 0) |
334 | pr_err("twl4030: err %d initializing %s %s\n", | 444 | pr_err("twl4030: err %d initializing %s %s\n", |
335 | status, sih->name, "ISR"); | 445 | status, sih->name, "ISR"); |
336 | 446 | ||
337 | if (!sih->set_cor) | 447 | if (!sih->set_cor) |
338 | status = twl4030_i2c_write(sih->module, buf, | 448 | status = twl_i2c_write(sih->module, buf, |
339 | sih->mask[line].isr_offset, | 449 | sih->mask[line].isr_offset, |
340 | sih->bytes_ixr); | 450 | sih->bytes_ixr); |
341 | /* else COR=1 means read sufficed. | 451 | /* else COR=1 means read sufficed. |
@@ -404,7 +514,7 @@ static void twl4030_sih_do_mask(struct work_struct *work) | |||
404 | return; | 514 | return; |
405 | 515 | ||
406 | /* write the whole mask ... simpler than subsetting it */ | 516 | /* write the whole mask ... simpler than subsetting it */ |
407 | status = twl4030_i2c_write(sih->module, imr.bytes, | 517 | status = twl_i2c_write(sih->module, imr.bytes, |
408 | sih->mask[irq_line].imr_offset, sih->bytes_ixr); | 518 | sih->mask[irq_line].imr_offset, sih->bytes_ixr); |
409 | if (status) | 519 | if (status) |
410 | pr_err("twl4030: %s, %s --> %d\n", __func__, | 520 | pr_err("twl4030: %s, %s --> %d\n", __func__, |
@@ -435,7 +545,7 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
435 | * any processor on the other IRQ line, EDR registers are | 545 | * any processor on the other IRQ line, EDR registers are |
436 | * shared. | 546 | * shared. |
437 | */ | 547 | */ |
438 | status = twl4030_i2c_read(sih->module, bytes + 1, | 548 | status = twl_i2c_read(sih->module, bytes + 1, |
439 | sih->edr_offset, sih->bytes_edr); | 549 | sih->edr_offset, sih->bytes_edr); |
440 | if (status) { | 550 | if (status) { |
441 | pr_err("twl4030: %s, %s --> %d\n", __func__, | 551 | pr_err("twl4030: %s, %s --> %d\n", __func__, |
@@ -469,7 +579,7 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
469 | } | 579 | } |
470 | 580 | ||
471 | /* Write */ | 581 | /* Write */ |
472 | status = twl4030_i2c_write(sih->module, bytes, | 582 | status = twl_i2c_write(sih->module, bytes, |
473 | sih->edr_offset, sih->bytes_edr); | 583 | sih->edr_offset, sih->bytes_edr); |
474 | if (status) | 584 | if (status) |
475 | pr_err("twl4030: %s, %s --> %d\n", __func__, | 585 | pr_err("twl4030: %s, %s --> %d\n", __func__, |
@@ -554,7 +664,7 @@ static inline int sih_read_isr(const struct sih *sih) | |||
554 | /* FIXME need retry-on-error ... */ | 664 | /* FIXME need retry-on-error ... */ |
555 | 665 | ||
556 | isr.word = 0; | 666 | isr.word = 0; |
557 | status = twl4030_i2c_read(sih->module, isr.bytes, | 667 | status = twl_i2c_read(sih->module, isr.bytes, |
558 | sih->mask[irq_line].isr_offset, sih->bytes_ixr); | 668 | sih->mask[irq_line].isr_offset, sih->bytes_ixr); |
559 | 669 | ||
560 | return (status < 0) ? status : le32_to_cpu(isr.word); | 670 | return (status < 0) ? status : le32_to_cpu(isr.word); |
@@ -611,7 +721,7 @@ int twl4030_sih_setup(int module) | |||
611 | 721 | ||
612 | /* only support modules with standard clear-on-read for now */ | 722 | /* only support modules with standard clear-on-read for now */ |
613 | for (sih_mod = 0, sih = sih_modules; | 723 | for (sih_mod = 0, sih = sih_modules; |
614 | sih_mod < ARRAY_SIZE(sih_modules); | 724 | sih_mod < nr_sih_modules; |
615 | sih_mod++, sih++) { | 725 | sih_mod++, sih++) { |
616 | if (sih->module == module && sih->set_cor) { | 726 | if (sih->module == module && sih->set_cor) { |
617 | if (!WARN((irq_base + sih->bits) > NR_IRQS, | 727 | if (!WARN((irq_base + sih->bits) > NR_IRQS, |
@@ -668,7 +778,7 @@ int twl4030_sih_setup(int module) | |||
668 | /* FIXME pass in which interrupt line we'll use ... */ | 778 | /* FIXME pass in which interrupt line we'll use ... */ |
669 | #define twl_irq_line 0 | 779 | #define twl_irq_line 0 |
670 | 780 | ||
671 | int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | 781 | int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) |
672 | { | 782 | { |
673 | static struct irq_chip twl4030_irq_chip; | 783 | static struct irq_chip twl4030_irq_chip; |
674 | 784 | ||
@@ -728,7 +838,8 @@ int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
728 | goto fail_rqirq; | 838 | goto fail_rqirq; |
729 | } | 839 | } |
730 | 840 | ||
731 | task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq"); | 841 | task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num, |
842 | "twl4030-irq"); | ||
732 | if (IS_ERR(task)) { | 843 | if (IS_ERR(task)) { |
733 | pr_err("twl4030: could not create irq %d thread!\n", irq_num); | 844 | pr_err("twl4030: could not create irq %d thread!\n", irq_num); |
734 | status = PTR_ERR(task); | 845 | status = PTR_ERR(task); |
@@ -747,7 +858,7 @@ fail: | |||
747 | return status; | 858 | return status; |
748 | } | 859 | } |
749 | 860 | ||
750 | int twl_exit_irq(void) | 861 | int twl4030_exit_irq(void) |
751 | { | 862 | { |
752 | /* FIXME undo twl_init_irq() */ | 863 | /* FIXME undo twl_init_irq() */ |
753 | if (twl4030_irq_base) { | 864 | if (twl4030_irq_base) { |
@@ -756,3 +867,16 @@ int twl_exit_irq(void) | |||
756 | } | 867 | } |
757 | return 0; | 868 | return 0; |
758 | } | 869 | } |
870 | |||
871 | int twl4030_init_chip_irq(const char *chip) | ||
872 | { | ||
873 | if (!strcmp(chip, "twl5031")) { | ||
874 | sih_modules = sih_modules_twl5031; | ||
875 | nr_sih_modules = ARRAY_SIZE(sih_modules_twl5031); | ||
876 | } else { | ||
877 | sih_modules = sih_modules_twl4030; | ||
878 | nr_sih_modules = ARRAY_SIZE(sih_modules_twl4030); | ||
879 | } | ||
880 | |||
881 | return 0; | ||
882 | } | ||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index d423e0c4176b..0815292fdafc 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
29 | #include <linux/i2c/twl4030.h> | 29 | #include <linux/i2c/twl.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | 31 | ||
32 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
@@ -67,19 +67,35 @@ static u8 twl4030_start_script_address = 0x2b; | |||
67 | #define R_KEY_1 0xC0 | 67 | #define R_KEY_1 0xC0 |
68 | #define R_KEY_2 0x0C | 68 | #define R_KEY_2 0x0C |
69 | 69 | ||
70 | /* resource configuration registers */ | 70 | /* resource configuration registers |
71 | 71 | <RESOURCE>_DEV_GRP at address 'n+0' | |
72 | #define DEVGROUP_OFFSET 0 | 72 | <RESOURCE>_TYPE at address 'n+1' |
73 | <RESOURCE>_REMAP at address 'n+2' | ||
74 | <RESOURCE>_DEDICATED at address 'n+3' | ||
75 | */ | ||
76 | #define DEV_GRP_OFFSET 0 | ||
73 | #define TYPE_OFFSET 1 | 77 | #define TYPE_OFFSET 1 |
78 | #define REMAP_OFFSET 2 | ||
79 | #define DEDICATED_OFFSET 3 | ||
80 | |||
81 | /* Bit positions in the registers */ | ||
82 | |||
83 | /* <RESOURCE>_DEV_GRP */ | ||
84 | #define DEV_GRP_SHIFT 5 | ||
85 | #define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) | ||
74 | 86 | ||
75 | /* Bit positions */ | 87 | /* <RESOURCE>_TYPE */ |
76 | #define DEVGROUP_SHIFT 5 | ||
77 | #define DEVGROUP_MASK (7 << DEVGROUP_SHIFT) | ||
78 | #define TYPE_SHIFT 0 | 88 | #define TYPE_SHIFT 0 |
79 | #define TYPE_MASK (7 << TYPE_SHIFT) | 89 | #define TYPE_MASK (7 << TYPE_SHIFT) |
80 | #define TYPE2_SHIFT 3 | 90 | #define TYPE2_SHIFT 3 |
81 | #define TYPE2_MASK (3 << TYPE2_SHIFT) | 91 | #define TYPE2_MASK (3 << TYPE2_SHIFT) |
82 | 92 | ||
93 | /* <RESOURCE>_REMAP */ | ||
94 | #define SLEEP_STATE_SHIFT 0 | ||
95 | #define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT) | ||
96 | #define OFF_STATE_SHIFT 4 | ||
97 | #define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT) | ||
98 | |||
83 | static u8 res_config_addrs[] = { | 99 | static u8 res_config_addrs[] = { |
84 | [RES_VAUX1] = 0x17, | 100 | [RES_VAUX1] = 0x17, |
85 | [RES_VAUX2] = 0x1b, | 101 | [RES_VAUX2] = 0x1b, |
@@ -115,11 +131,11 @@ static int __init twl4030_write_script_byte(u8 address, u8 byte) | |||
115 | { | 131 | { |
116 | int err; | 132 | int err; |
117 | 133 | ||
118 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, | 134 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, |
119 | R_MEMORY_ADDRESS); | 135 | R_MEMORY_ADDRESS); |
120 | if (err) | 136 | if (err) |
121 | goto out; | 137 | goto out; |
122 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, | 138 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, |
123 | R_MEMORY_DATA); | 139 | R_MEMORY_DATA); |
124 | out: | 140 | out: |
125 | return err; | 141 | return err; |
@@ -176,18 +192,18 @@ static int __init twl4030_config_wakeup3_sequence(u8 address) | |||
176 | u8 data; | 192 | u8 data; |
177 | 193 | ||
178 | /* Set SLEEP to ACTIVE SEQ address for P3 */ | 194 | /* Set SLEEP to ACTIVE SEQ address for P3 */ |
179 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, | 195 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, |
180 | R_SEQ_ADD_S2A3); | 196 | R_SEQ_ADD_S2A3); |
181 | if (err) | 197 | if (err) |
182 | goto out; | 198 | goto out; |
183 | 199 | ||
184 | /* P3 LVL_WAKEUP should be on LEVEL */ | 200 | /* P3 LVL_WAKEUP should be on LEVEL */ |
185 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, | 201 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, |
186 | R_P3_SW_EVENTS); | 202 | R_P3_SW_EVENTS); |
187 | if (err) | 203 | if (err) |
188 | goto out; | 204 | goto out; |
189 | data |= LVL_WAKEUP; | 205 | data |= LVL_WAKEUP; |
190 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, | 206 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, |
191 | R_P3_SW_EVENTS); | 207 | R_P3_SW_EVENTS); |
192 | out: | 208 | out: |
193 | if (err) | 209 | if (err) |
@@ -201,42 +217,42 @@ static int __init twl4030_config_wakeup12_sequence(u8 address) | |||
201 | u8 data; | 217 | u8 data; |
202 | 218 | ||
203 | /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ | 219 | /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ |
204 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, | 220 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, |
205 | R_SEQ_ADD_S2A12); | 221 | R_SEQ_ADD_S2A12); |
206 | if (err) | 222 | if (err) |
207 | goto out; | 223 | goto out; |
208 | 224 | ||
209 | /* P1/P2 LVL_WAKEUP should be on LEVEL */ | 225 | /* P1/P2 LVL_WAKEUP should be on LEVEL */ |
210 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, | 226 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, |
211 | R_P1_SW_EVENTS); | 227 | R_P1_SW_EVENTS); |
212 | if (err) | 228 | if (err) |
213 | goto out; | 229 | goto out; |
214 | 230 | ||
215 | data |= LVL_WAKEUP; | 231 | data |= LVL_WAKEUP; |
216 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, | 232 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, |
217 | R_P1_SW_EVENTS); | 233 | R_P1_SW_EVENTS); |
218 | if (err) | 234 | if (err) |
219 | goto out; | 235 | goto out; |
220 | 236 | ||
221 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, | 237 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, |
222 | R_P2_SW_EVENTS); | 238 | R_P2_SW_EVENTS); |
223 | if (err) | 239 | if (err) |
224 | goto out; | 240 | goto out; |
225 | 241 | ||
226 | data |= LVL_WAKEUP; | 242 | data |= LVL_WAKEUP; |
227 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, | 243 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, |
228 | R_P2_SW_EVENTS); | 244 | R_P2_SW_EVENTS); |
229 | if (err) | 245 | if (err) |
230 | goto out; | 246 | goto out; |
231 | 247 | ||
232 | if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) { | 248 | if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) { |
233 | /* Disabling AC charger effect on sleep-active transitions */ | 249 | /* Disabling AC charger effect on sleep-active transitions */ |
234 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, | 250 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, |
235 | R_CFG_P1_TRANSITION); | 251 | R_CFG_P1_TRANSITION); |
236 | if (err) | 252 | if (err) |
237 | goto out; | 253 | goto out; |
238 | data &= ~(1<<1); | 254 | data &= ~(1<<1); |
239 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , | 255 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , |
240 | R_CFG_P1_TRANSITION); | 256 | R_CFG_P1_TRANSITION); |
241 | if (err) | 257 | if (err) |
242 | goto out; | 258 | goto out; |
@@ -254,7 +270,7 @@ static int __init twl4030_config_sleep_sequence(u8 address) | |||
254 | int err; | 270 | int err; |
255 | 271 | ||
256 | /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ | 272 | /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ |
257 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, | 273 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, |
258 | R_SEQ_ADD_A2S); | 274 | R_SEQ_ADD_A2S); |
259 | 275 | ||
260 | if (err) | 276 | if (err) |
@@ -269,41 +285,41 @@ static int __init twl4030_config_warmreset_sequence(u8 address) | |||
269 | u8 rd_data; | 285 | u8 rd_data; |
270 | 286 | ||
271 | /* Set WARM RESET SEQ address for P1 */ | 287 | /* Set WARM RESET SEQ address for P1 */ |
272 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, | 288 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, |
273 | R_SEQ_ADD_WARM); | 289 | R_SEQ_ADD_WARM); |
274 | if (err) | 290 | if (err) |
275 | goto out; | 291 | goto out; |
276 | 292 | ||
277 | /* P1/P2/P3 enable WARMRESET */ | 293 | /* P1/P2/P3 enable WARMRESET */ |
278 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, | 294 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, |
279 | R_P1_SW_EVENTS); | 295 | R_P1_SW_EVENTS); |
280 | if (err) | 296 | if (err) |
281 | goto out; | 297 | goto out; |
282 | 298 | ||
283 | rd_data |= ENABLE_WARMRESET; | 299 | rd_data |= ENABLE_WARMRESET; |
284 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, | 300 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, |
285 | R_P1_SW_EVENTS); | 301 | R_P1_SW_EVENTS); |
286 | if (err) | 302 | if (err) |
287 | goto out; | 303 | goto out; |
288 | 304 | ||
289 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, | 305 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, |
290 | R_P2_SW_EVENTS); | 306 | R_P2_SW_EVENTS); |
291 | if (err) | 307 | if (err) |
292 | goto out; | 308 | goto out; |
293 | 309 | ||
294 | rd_data |= ENABLE_WARMRESET; | 310 | rd_data |= ENABLE_WARMRESET; |
295 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, | 311 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, |
296 | R_P2_SW_EVENTS); | 312 | R_P2_SW_EVENTS); |
297 | if (err) | 313 | if (err) |
298 | goto out; | 314 | goto out; |
299 | 315 | ||
300 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, | 316 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, |
301 | R_P3_SW_EVENTS); | 317 | R_P3_SW_EVENTS); |
302 | if (err) | 318 | if (err) |
303 | goto out; | 319 | goto out; |
304 | 320 | ||
305 | rd_data |= ENABLE_WARMRESET; | 321 | rd_data |= ENABLE_WARMRESET; |
306 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, | 322 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, |
307 | R_P3_SW_EVENTS); | 323 | R_P3_SW_EVENTS); |
308 | out: | 324 | out: |
309 | if (err) | 325 | if (err) |
@@ -317,6 +333,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | |||
317 | int err; | 333 | int err; |
318 | u8 type; | 334 | u8 type; |
319 | u8 grp; | 335 | u8 grp; |
336 | u8 remap; | ||
320 | 337 | ||
321 | if (rconfig->resource > TOTAL_RESOURCES) { | 338 | if (rconfig->resource > TOTAL_RESOURCES) { |
322 | pr_err("TWL4030 Resource %d does not exist\n", | 339 | pr_err("TWL4030 Resource %d does not exist\n", |
@@ -327,19 +344,19 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | |||
327 | rconfig_addr = res_config_addrs[rconfig->resource]; | 344 | rconfig_addr = res_config_addrs[rconfig->resource]; |
328 | 345 | ||
329 | /* Set resource group */ | 346 | /* Set resource group */ |
330 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, | 347 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, |
331 | rconfig_addr + DEVGROUP_OFFSET); | 348 | rconfig_addr + DEV_GRP_OFFSET); |
332 | if (err) { | 349 | if (err) { |
333 | pr_err("TWL4030 Resource %d group could not be read\n", | 350 | pr_err("TWL4030 Resource %d group could not be read\n", |
334 | rconfig->resource); | 351 | rconfig->resource); |
335 | return err; | 352 | return err; |
336 | } | 353 | } |
337 | 354 | ||
338 | if (rconfig->devgroup >= 0) { | 355 | if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { |
339 | grp &= ~DEVGROUP_MASK; | 356 | grp &= ~DEV_GRP_MASK; |
340 | grp |= rconfig->devgroup << DEVGROUP_SHIFT; | 357 | grp |= rconfig->devgroup << DEV_GRP_SHIFT; |
341 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | 358 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, |
342 | grp, rconfig_addr + DEVGROUP_OFFSET); | 359 | grp, rconfig_addr + DEV_GRP_OFFSET); |
343 | if (err < 0) { | 360 | if (err < 0) { |
344 | pr_err("TWL4030 failed to program devgroup\n"); | 361 | pr_err("TWL4030 failed to program devgroup\n"); |
345 | return err; | 362 | return err; |
@@ -347,7 +364,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | |||
347 | } | 364 | } |
348 | 365 | ||
349 | /* Set resource types */ | 366 | /* Set resource types */ |
350 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, | 367 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, |
351 | rconfig_addr + TYPE_OFFSET); | 368 | rconfig_addr + TYPE_OFFSET); |
352 | if (err < 0) { | 369 | if (err < 0) { |
353 | pr_err("TWL4030 Resource %d type could not be read\n", | 370 | pr_err("TWL4030 Resource %d type could not be read\n", |
@@ -355,23 +372,50 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | |||
355 | return err; | 372 | return err; |
356 | } | 373 | } |
357 | 374 | ||
358 | if (rconfig->type >= 0) { | 375 | if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { |
359 | type &= ~TYPE_MASK; | 376 | type &= ~TYPE_MASK; |
360 | type |= rconfig->type << TYPE_SHIFT; | 377 | type |= rconfig->type << TYPE_SHIFT; |
361 | } | 378 | } |
362 | 379 | ||
363 | if (rconfig->type2 >= 0) { | 380 | if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { |
364 | type &= ~TYPE2_MASK; | 381 | type &= ~TYPE2_MASK; |
365 | type |= rconfig->type2 << TYPE2_SHIFT; | 382 | type |= rconfig->type2 << TYPE2_SHIFT; |
366 | } | 383 | } |
367 | 384 | ||
368 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | 385 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, |
369 | type, rconfig_addr + TYPE_OFFSET); | 386 | type, rconfig_addr + TYPE_OFFSET); |
370 | if (err < 0) { | 387 | if (err < 0) { |
371 | pr_err("TWL4030 failed to program resource type\n"); | 388 | pr_err("TWL4030 failed to program resource type\n"); |
372 | return err; | 389 | return err; |
373 | } | 390 | } |
374 | 391 | ||
392 | /* Set remap states */ | ||
393 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, | ||
394 | rconfig_addr + REMAP_OFFSET); | ||
395 | if (err < 0) { | ||
396 | pr_err("TWL4030 Resource %d remap could not be read\n", | ||
397 | rconfig->resource); | ||
398 | return err; | ||
399 | } | ||
400 | |||
401 | if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { | ||
402 | remap &= ~OFF_STATE_MASK; | ||
403 | remap |= rconfig->remap_off << OFF_STATE_SHIFT; | ||
404 | } | ||
405 | |||
406 | if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { | ||
407 | remap &= ~SLEEP_STATE_MASK; | ||
408 | remap |= rconfig->remap_off << SLEEP_STATE_SHIFT; | ||
409 | } | ||
410 | |||
411 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
412 | remap, | ||
413 | rconfig_addr + REMAP_OFFSET); | ||
414 | if (err < 0) { | ||
415 | pr_err("TWL4030 failed to program remap\n"); | ||
416 | return err; | ||
417 | } | ||
418 | |||
375 | return 0; | 419 | return 0; |
376 | } | 420 | } |
377 | 421 | ||
@@ -424,12 +468,12 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | |||
424 | struct twl4030_resconfig *resconfig; | 468 | struct twl4030_resconfig *resconfig; |
425 | u8 address = twl4030_start_script_address; | 469 | u8 address = twl4030_start_script_address; |
426 | 470 | ||
427 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, | 471 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, |
428 | R_PROTECT_KEY); | 472 | R_PROTECT_KEY); |
429 | if (err) | 473 | if (err) |
430 | goto unlock; | 474 | goto unlock; |
431 | 475 | ||
432 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, | 476 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, |
433 | R_PROTECT_KEY); | 477 | R_PROTECT_KEY); |
434 | if (err) | 478 | if (err) |
435 | goto unlock; | 479 | goto unlock; |
@@ -452,7 +496,7 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | |||
452 | } | 496 | } |
453 | } | 497 | } |
454 | 498 | ||
455 | err = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); | 499 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); |
456 | if (err) | 500 | if (err) |
457 | pr_err("TWL4030 Unable to relock registers\n"); | 501 | pr_err("TWL4030 Unable to relock registers\n"); |
458 | return; | 502 | return; |
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c new file mode 100644 index 000000000000..10bf228ad626 --- /dev/null +++ b/drivers/mfd/twl6030-irq.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * twl6030-irq.c - TWL6030 irq support | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Modifications to defer interrupt handling to a kernel thread: | ||
7 | * Copyright (C) 2006 MontaVista Software, Inc. | ||
8 | * | ||
9 | * Based on tlv320aic23.c: | ||
10 | * Copyright (c) by Kai Svahn <kai.svahn@nokia.com> | ||
11 | * | ||
12 | * Code cleanup and modifications to IRQ handler. | ||
13 | * by syed khasim <x0khasim@ti.com> | ||
14 | * | ||
15 | * TWL6030 specific code and IRQ handling changes by | ||
16 | * Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com> | ||
17 | * Balaji T K <balajitk@ti.com> | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/irq.h> | ||
37 | #include <linux/kthread.h> | ||
38 | #include <linux/i2c/twl.h> | ||
39 | |||
40 | /* | ||
41 | * TWL6030 (unlike its predecessors, which had two level interrupt handling) | ||
42 | * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C. | ||
43 | * It exposes status bits saying who has raised an interrupt. There are | ||
44 | * three mask registers that corresponds to these status registers, that | ||
45 | * enables/disables these interrupts. | ||
46 | * | ||
47 | * We set up IRQs starting at a platform-specified base. An interrupt map table, | ||
48 | * specifies mapping between interrupt number and the associated module. | ||
49 | * | ||
50 | */ | ||
51 | |||
52 | static int twl6030_interrupt_mapping[24] = { | ||
53 | PWR_INTR_OFFSET, /* Bit 0 PWRON */ | ||
54 | PWR_INTR_OFFSET, /* Bit 1 RPWRON */ | ||
55 | PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */ | ||
56 | RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */ | ||
57 | RTC_INTR_OFFSET, /* Bit 4 RTC_PERIOD */ | ||
58 | HOTDIE_INTR_OFFSET, /* Bit 5 HOT_DIE */ | ||
59 | SMPSLDO_INTR_OFFSET, /* Bit 6 VXXX_SHORT */ | ||
60 | SMPSLDO_INTR_OFFSET, /* Bit 7 VMMC_SHORT */ | ||
61 | |||
62 | SMPSLDO_INTR_OFFSET, /* Bit 8 VUSIM_SHORT */ | ||
63 | BATDETECT_INTR_OFFSET, /* Bit 9 BAT */ | ||
64 | SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */ | ||
65 | MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */ | ||
66 | RSV_INTR_OFFSET, /* Bit 12 Reserved */ | ||
67 | MADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */ | ||
68 | MADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */ | ||
69 | GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */ | ||
70 | |||
71 | USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */ | ||
72 | USBOTG_INTR_OFFSET, /* Bit 17 VBUS_WKUP */ | ||
73 | USBOTG_INTR_OFFSET, /* Bit 18 ID */ | ||
74 | USBOTG_INTR_OFFSET, /* Bit 19 VBUS */ | ||
75 | CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */ | ||
76 | CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */ | ||
77 | CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */ | ||
78 | RSV_INTR_OFFSET, /* Bit 23 Reserved */ | ||
79 | }; | ||
80 | /*----------------------------------------------------------------------*/ | ||
81 | |||
82 | static unsigned twl6030_irq_base; | ||
83 | |||
84 | static struct completion irq_event; | ||
85 | |||
86 | /* | ||
87 | * This thread processes interrupts reported by the Primary Interrupt Handler. | ||
88 | */ | ||
89 | static int twl6030_irq_thread(void *data) | ||
90 | { | ||
91 | long irq = (long)data; | ||
92 | static unsigned i2c_errors; | ||
93 | static const unsigned max_i2c_errors = 100; | ||
94 | int ret; | ||
95 | |||
96 | current->flags |= PF_NOFREEZE; | ||
97 | |||
98 | while (!kthread_should_stop()) { | ||
99 | int i; | ||
100 | union { | ||
101 | u8 bytes[4]; | ||
102 | u32 int_sts; | ||
103 | } sts; | ||
104 | |||
105 | /* Wait for IRQ, then read PIH irq status (also blocking) */ | ||
106 | wait_for_completion_interruptible(&irq_event); | ||
107 | |||
108 | /* read INT_STS_A, B and C in one shot using a burst read */ | ||
109 | ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes, | ||
110 | REG_INT_STS_A, 3); | ||
111 | if (ret) { | ||
112 | pr_warning("twl6030: I2C error %d reading PIH ISR\n", | ||
113 | ret); | ||
114 | if (++i2c_errors >= max_i2c_errors) { | ||
115 | printk(KERN_ERR "Maximum I2C error count" | ||
116 | " exceeded. Terminating %s.\n", | ||
117 | __func__); | ||
118 | break; | ||
119 | } | ||
120 | complete(&irq_event); | ||
121 | continue; | ||
122 | } | ||
123 | |||
124 | |||
125 | |||
126 | sts.bytes[3] = 0; /* Only 24 bits are valid*/ | ||
127 | |||
128 | for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) { | ||
129 | local_irq_disable(); | ||
130 | if (sts.int_sts & 0x1) { | ||
131 | int module_irq = twl6030_irq_base + | ||
132 | twl6030_interrupt_mapping[i]; | ||
133 | struct irq_desc *d = irq_to_desc(module_irq); | ||
134 | |||
135 | if (!d) { | ||
136 | pr_err("twl6030: Invalid SIH IRQ: %d\n", | ||
137 | module_irq); | ||
138 | return -EINVAL; | ||
139 | } | ||
140 | |||
141 | /* These can't be masked ... always warn | ||
142 | * if we get any surprises. | ||
143 | */ | ||
144 | if (d->status & IRQ_DISABLED) | ||
145 | note_interrupt(module_irq, d, | ||
146 | IRQ_NONE); | ||
147 | else | ||
148 | d->handle_irq(module_irq, d); | ||
149 | |||
150 | } | ||
151 | local_irq_enable(); | ||
152 | } | ||
153 | ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes, | ||
154 | REG_INT_STS_A, 3); /* clear INT_STS_A */ | ||
155 | if (ret) | ||
156 | pr_warning("twl6030: I2C error in clearing PIH ISR\n"); | ||
157 | |||
158 | enable_irq(irq); | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * handle_twl6030_int() is the desc->handle method for the twl6030 interrupt. | ||
166 | * This is a chained interrupt, so there is no desc->action method for it. | ||
167 | * Now we need to query the interrupt controller in the twl6030 to determine | ||
168 | * which module is generating the interrupt request. However, we can't do i2c | ||
169 | * transactions in interrupt context, so we must defer that work to a kernel | ||
170 | * thread. All we do here is acknowledge and mask the interrupt and wakeup | ||
171 | * the kernel thread. | ||
172 | */ | ||
173 | static irqreturn_t handle_twl6030_pih(int irq, void *devid) | ||
174 | { | ||
175 | disable_irq_nosync(irq); | ||
176 | complete(devid); | ||
177 | return IRQ_HANDLED; | ||
178 | } | ||
179 | |||
180 | /*----------------------------------------------------------------------*/ | ||
181 | |||
182 | static inline void activate_irq(int irq) | ||
183 | { | ||
184 | #ifdef CONFIG_ARM | ||
185 | /* ARM requires an extra step to clear IRQ_NOREQUEST, which it | ||
186 | * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. | ||
187 | */ | ||
188 | set_irq_flags(irq, IRQF_VALID); | ||
189 | #else | ||
190 | /* same effect on other architectures */ | ||
191 | set_irq_noprobe(irq); | ||
192 | #endif | ||
193 | } | ||
194 | |||
195 | /*----------------------------------------------------------------------*/ | ||
196 | |||
197 | static unsigned twl6030_irq_next; | ||
198 | |||
199 | /*----------------------------------------------------------------------*/ | ||
200 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset) | ||
201 | { | ||
202 | int ret; | ||
203 | u8 unmask_value; | ||
204 | ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value, | ||
205 | REG_INT_STS_A + offset); | ||
206 | unmask_value &= (~(bit_mask)); | ||
207 | ret |= twl_i2c_write_u8(TWL_MODULE_PIH, unmask_value, | ||
208 | REG_INT_STS_A + offset); /* unmask INT_MSK_A/B/C */ | ||
209 | return ret; | ||
210 | } | ||
211 | EXPORT_SYMBOL(twl6030_interrupt_unmask); | ||
212 | |||
213 | int twl6030_interrupt_mask(u8 bit_mask, u8 offset) | ||
214 | { | ||
215 | int ret; | ||
216 | u8 mask_value; | ||
217 | ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value, | ||
218 | REG_INT_STS_A + offset); | ||
219 | mask_value |= (bit_mask); | ||
220 | ret |= twl_i2c_write_u8(TWL_MODULE_PIH, mask_value, | ||
221 | REG_INT_STS_A + offset); /* mask INT_MSK_A/B/C */ | ||
222 | return ret; | ||
223 | } | ||
224 | EXPORT_SYMBOL(twl6030_interrupt_mask); | ||
225 | |||
226 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | ||
227 | { | ||
228 | |||
229 | int status = 0; | ||
230 | int i; | ||
231 | struct task_struct *task; | ||
232 | int ret; | ||
233 | u8 mask[4]; | ||
234 | |||
235 | static struct irq_chip twl6030_irq_chip; | ||
236 | mask[1] = 0xFF; | ||
237 | mask[2] = 0xFF; | ||
238 | mask[3] = 0xFF; | ||
239 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | ||
240 | REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ | ||
241 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | ||
242 | REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ | ||
243 | ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], | ||
244 | REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ | ||
245 | |||
246 | twl6030_irq_base = irq_base; | ||
247 | |||
248 | /* install an irq handler for each of the modules; | ||
249 | * clone dummy irq_chip since PIH can't *do* anything | ||
250 | */ | ||
251 | twl6030_irq_chip = dummy_irq_chip; | ||
252 | twl6030_irq_chip.name = "twl6030"; | ||
253 | twl6030_irq_chip.set_type = NULL; | ||
254 | |||
255 | for (i = irq_base; i < irq_end; i++) { | ||
256 | set_irq_chip_and_handler(i, &twl6030_irq_chip, | ||
257 | handle_simple_irq); | ||
258 | activate_irq(i); | ||
259 | } | ||
260 | |||
261 | twl6030_irq_next = i; | ||
262 | pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", | ||
263 | irq_num, irq_base, twl6030_irq_next - 1); | ||
264 | |||
265 | /* install an irq handler to demultiplex the TWL6030 interrupt */ | ||
266 | init_completion(&irq_event); | ||
267 | task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); | ||
268 | if (IS_ERR(task)) { | ||
269 | pr_err("twl6030: could not create irq %d thread!\n", irq_num); | ||
270 | status = PTR_ERR(task); | ||
271 | goto fail_kthread; | ||
272 | } | ||
273 | |||
274 | status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED, | ||
275 | "TWL6030-PIH", &irq_event); | ||
276 | if (status < 0) { | ||
277 | pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); | ||
278 | goto fail_irq; | ||
279 | } | ||
280 | return status; | ||
281 | fail_irq: | ||
282 | free_irq(irq_num, &irq_event); | ||
283 | |||
284 | fail_kthread: | ||
285 | for (i = irq_base; i < irq_end; i++) | ||
286 | set_irq_chip_and_handler(i, NULL, NULL); | ||
287 | return status; | ||
288 | } | ||
289 | |||
290 | int twl6030_exit_irq(void) | ||
291 | { | ||
292 | |||
293 | if (twl6030_irq_base) { | ||
294 | pr_err("twl6030: can't yet clean up IRQs?\n"); | ||
295 | return -ENOSYS; | ||
296 | } | ||
297 | return 0; | ||
298 | } | ||
299 | |||
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 7f27576ca046..223a90c7492f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -90,9 +90,10 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = { | |||
90 | EXPORT_SYMBOL_GPL(wm831x_isinkv_values); | 90 | EXPORT_SYMBOL_GPL(wm831x_isinkv_values); |
91 | 91 | ||
92 | enum wm831x_parent { | 92 | enum wm831x_parent { |
93 | WM8310 = 0, | 93 | WM8310 = 0x8310, |
94 | WM8311 = 1, | 94 | WM8311 = 0x8311, |
95 | WM8312 = 2, | 95 | WM8312 = 0x8312, |
96 | WM8320 = 0x8320, | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 99 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
@@ -478,6 +479,20 @@ static struct resource wm831x_dcdc4_resources[] = { | |||
478 | }, | 479 | }, |
479 | }; | 480 | }; |
480 | 481 | ||
482 | static struct resource wm8320_dcdc4_buck_resources[] = { | ||
483 | { | ||
484 | .start = WM831X_DC4_CONTROL, | ||
485 | .end = WM832X_DC4_SLEEP_CONTROL, | ||
486 | .flags = IORESOURCE_IO, | ||
487 | }, | ||
488 | { | ||
489 | .name = "UV", | ||
490 | .start = WM831X_IRQ_UV_DC4, | ||
491 | .end = WM831X_IRQ_UV_DC4, | ||
492 | .flags = IORESOURCE_IRQ, | ||
493 | }, | ||
494 | }; | ||
495 | |||
481 | static struct resource wm831x_gpio_resources[] = { | 496 | static struct resource wm831x_gpio_resources[] = { |
482 | { | 497 | { |
483 | .start = WM831X_IRQ_GPIO_1, | 498 | .start = WM831X_IRQ_GPIO_1, |
@@ -1237,6 +1252,137 @@ static struct mfd_cell wm8312_devs[] = { | |||
1237 | }, | 1252 | }, |
1238 | }; | 1253 | }; |
1239 | 1254 | ||
1255 | static struct mfd_cell wm8320_devs[] = { | ||
1256 | { | ||
1257 | .name = "wm831x-backup", | ||
1258 | }, | ||
1259 | { | ||
1260 | .name = "wm831x-buckv", | ||
1261 | .id = 1, | ||
1262 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), | ||
1263 | .resources = wm831x_dcdc1_resources, | ||
1264 | }, | ||
1265 | { | ||
1266 | .name = "wm831x-buckv", | ||
1267 | .id = 2, | ||
1268 | .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources), | ||
1269 | .resources = wm831x_dcdc2_resources, | ||
1270 | }, | ||
1271 | { | ||
1272 | .name = "wm831x-buckp", | ||
1273 | .id = 3, | ||
1274 | .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources), | ||
1275 | .resources = wm831x_dcdc3_resources, | ||
1276 | }, | ||
1277 | { | ||
1278 | .name = "wm831x-buckp", | ||
1279 | .id = 4, | ||
1280 | .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources), | ||
1281 | .resources = wm8320_dcdc4_buck_resources, | ||
1282 | }, | ||
1283 | { | ||
1284 | .name = "wm831x-gpio", | ||
1285 | .num_resources = ARRAY_SIZE(wm831x_gpio_resources), | ||
1286 | .resources = wm831x_gpio_resources, | ||
1287 | }, | ||
1288 | { | ||
1289 | .name = "wm831x-hwmon", | ||
1290 | }, | ||
1291 | { | ||
1292 | .name = "wm831x-ldo", | ||
1293 | .id = 1, | ||
1294 | .num_resources = ARRAY_SIZE(wm831x_ldo1_resources), | ||
1295 | .resources = wm831x_ldo1_resources, | ||
1296 | }, | ||
1297 | { | ||
1298 | .name = "wm831x-ldo", | ||
1299 | .id = 2, | ||
1300 | .num_resources = ARRAY_SIZE(wm831x_ldo2_resources), | ||
1301 | .resources = wm831x_ldo2_resources, | ||
1302 | }, | ||
1303 | { | ||
1304 | .name = "wm831x-ldo", | ||
1305 | .id = 3, | ||
1306 | .num_resources = ARRAY_SIZE(wm831x_ldo3_resources), | ||
1307 | .resources = wm831x_ldo3_resources, | ||
1308 | }, | ||
1309 | { | ||
1310 | .name = "wm831x-ldo", | ||
1311 | .id = 4, | ||
1312 | .num_resources = ARRAY_SIZE(wm831x_ldo4_resources), | ||
1313 | .resources = wm831x_ldo4_resources, | ||
1314 | }, | ||
1315 | { | ||
1316 | .name = "wm831x-ldo", | ||
1317 | .id = 5, | ||
1318 | .num_resources = ARRAY_SIZE(wm831x_ldo5_resources), | ||
1319 | .resources = wm831x_ldo5_resources, | ||
1320 | }, | ||
1321 | { | ||
1322 | .name = "wm831x-ldo", | ||
1323 | .id = 6, | ||
1324 | .num_resources = ARRAY_SIZE(wm831x_ldo6_resources), | ||
1325 | .resources = wm831x_ldo6_resources, | ||
1326 | }, | ||
1327 | { | ||
1328 | .name = "wm831x-aldo", | ||
1329 | .id = 7, | ||
1330 | .num_resources = ARRAY_SIZE(wm831x_ldo7_resources), | ||
1331 | .resources = wm831x_ldo7_resources, | ||
1332 | }, | ||
1333 | { | ||
1334 | .name = "wm831x-aldo", | ||
1335 | .id = 8, | ||
1336 | .num_resources = ARRAY_SIZE(wm831x_ldo8_resources), | ||
1337 | .resources = wm831x_ldo8_resources, | ||
1338 | }, | ||
1339 | { | ||
1340 | .name = "wm831x-aldo", | ||
1341 | .id = 9, | ||
1342 | .num_resources = ARRAY_SIZE(wm831x_ldo9_resources), | ||
1343 | .resources = wm831x_ldo9_resources, | ||
1344 | }, | ||
1345 | { | ||
1346 | .name = "wm831x-aldo", | ||
1347 | .id = 10, | ||
1348 | .num_resources = ARRAY_SIZE(wm831x_ldo10_resources), | ||
1349 | .resources = wm831x_ldo10_resources, | ||
1350 | }, | ||
1351 | { | ||
1352 | .name = "wm831x-alive-ldo", | ||
1353 | .id = 11, | ||
1354 | .num_resources = ARRAY_SIZE(wm831x_ldo11_resources), | ||
1355 | .resources = wm831x_ldo11_resources, | ||
1356 | }, | ||
1357 | { | ||
1358 | .name = "wm831x-on", | ||
1359 | .num_resources = ARRAY_SIZE(wm831x_on_resources), | ||
1360 | .resources = wm831x_on_resources, | ||
1361 | }, | ||
1362 | { | ||
1363 | .name = "wm831x-rtc", | ||
1364 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
1365 | .resources = wm831x_rtc_resources, | ||
1366 | }, | ||
1367 | { | ||
1368 | .name = "wm831x-status", | ||
1369 | .id = 1, | ||
1370 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), | ||
1371 | .resources = wm831x_status1_resources, | ||
1372 | }, | ||
1373 | { | ||
1374 | .name = "wm831x-status", | ||
1375 | .id = 2, | ||
1376 | .num_resources = ARRAY_SIZE(wm831x_status2_resources), | ||
1377 | .resources = wm831x_status2_resources, | ||
1378 | }, | ||
1379 | { | ||
1380 | .name = "wm831x-watchdog", | ||
1381 | .num_resources = ARRAY_SIZE(wm831x_wdt_resources), | ||
1382 | .resources = wm831x_wdt_resources, | ||
1383 | }, | ||
1384 | }; | ||
1385 | |||
1240 | static struct mfd_cell backlight_devs[] = { | 1386 | static struct mfd_cell backlight_devs[] = { |
1241 | { | 1387 | { |
1242 | .name = "wm831x-backlight", | 1388 | .name = "wm831x-backlight", |
@@ -1282,50 +1428,37 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1282 | goto err; | 1428 | goto err; |
1283 | } | 1429 | } |
1284 | 1430 | ||
1431 | /* Some engineering samples do not have the ID set, rely on | ||
1432 | * the device being registered correctly. | ||
1433 | */ | ||
1434 | if (ret == 0) { | ||
1435 | dev_info(wm831x->dev, "Device is an engineering sample\n"); | ||
1436 | ret = id; | ||
1437 | } | ||
1438 | |||
1285 | switch (ret) { | 1439 | switch (ret) { |
1286 | case 0x8310: | 1440 | case WM8310: |
1287 | parent = WM8310; | 1441 | parent = WM8310; |
1288 | switch (rev) { | 1442 | wm831x->num_gpio = 16; |
1289 | case 0: | 1443 | dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); |
1290 | dev_info(wm831x->dev, "WM8310 revision %c\n", | ||
1291 | 'A' + rev); | ||
1292 | break; | ||
1293 | } | ||
1294 | break; | 1444 | break; |
1295 | 1445 | ||
1296 | case 0x8311: | 1446 | case WM8311: |
1297 | parent = WM8311; | 1447 | parent = WM8311; |
1298 | switch (rev) { | 1448 | wm831x->num_gpio = 16; |
1299 | case 0: | 1449 | dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); |
1300 | dev_info(wm831x->dev, "WM8311 revision %c\n", | ||
1301 | 'A' + rev); | ||
1302 | break; | ||
1303 | } | ||
1304 | break; | 1450 | break; |
1305 | 1451 | ||
1306 | case 0x8312: | 1452 | case WM8312: |
1307 | parent = WM8312; | 1453 | parent = WM8312; |
1308 | switch (rev) { | 1454 | wm831x->num_gpio = 16; |
1309 | case 0: | 1455 | dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); |
1310 | dev_info(wm831x->dev, "WM8312 revision %c\n", | ||
1311 | 'A' + rev); | ||
1312 | break; | ||
1313 | } | ||
1314 | break; | 1456 | break; |
1315 | 1457 | ||
1316 | case 0: | 1458 | case WM8320: |
1317 | /* Some engineering samples do not have the ID set, | 1459 | parent = WM8320; |
1318 | * rely on the device being registered correctly. | 1460 | wm831x->num_gpio = 12; |
1319 | * This will need revisiting for future devices with | 1461 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); |
1320 | * multiple dies. | ||
1321 | */ | ||
1322 | parent = id; | ||
1323 | switch (rev) { | ||
1324 | case 0: | ||
1325 | dev_info(wm831x->dev, "WM831%d ES revision %c\n", | ||
1326 | parent, 'A' + rev); | ||
1327 | break; | ||
1328 | } | ||
1329 | break; | 1462 | break; |
1330 | 1463 | ||
1331 | default: | 1464 | default: |
@@ -1338,7 +1471,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1338 | * current parts. | 1471 | * current parts. |
1339 | */ | 1472 | */ |
1340 | if (parent != id) | 1473 | if (parent != id) |
1341 | dev_warn(wm831x->dev, "Device was registered as a WM831%lu\n", | 1474 | dev_warn(wm831x->dev, "Device was registered as a WM%lx\n", |
1342 | id); | 1475 | id); |
1343 | 1476 | ||
1344 | /* Bootstrap the user key */ | 1477 | /* Bootstrap the user key */ |
@@ -1371,18 +1504,24 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1371 | case WM8310: | 1504 | case WM8310: |
1372 | ret = mfd_add_devices(wm831x->dev, -1, | 1505 | ret = mfd_add_devices(wm831x->dev, -1, |
1373 | wm8310_devs, ARRAY_SIZE(wm8310_devs), | 1506 | wm8310_devs, ARRAY_SIZE(wm8310_devs), |
1374 | NULL, 0); | 1507 | NULL, wm831x->irq_base); |
1375 | break; | 1508 | break; |
1376 | 1509 | ||
1377 | case WM8311: | 1510 | case WM8311: |
1378 | ret = mfd_add_devices(wm831x->dev, -1, | 1511 | ret = mfd_add_devices(wm831x->dev, -1, |
1379 | wm8311_devs, ARRAY_SIZE(wm8311_devs), | 1512 | wm8311_devs, ARRAY_SIZE(wm8311_devs), |
1380 | NULL, 0); | 1513 | NULL, wm831x->irq_base); |
1381 | break; | 1514 | break; |
1382 | 1515 | ||
1383 | case WM8312: | 1516 | case WM8312: |
1384 | ret = mfd_add_devices(wm831x->dev, -1, | 1517 | ret = mfd_add_devices(wm831x->dev, -1, |
1385 | wm8312_devs, ARRAY_SIZE(wm8312_devs), | 1518 | wm8312_devs, ARRAY_SIZE(wm8312_devs), |
1519 | NULL, wm831x->irq_base); | ||
1520 | break; | ||
1521 | |||
1522 | case WM8320: | ||
1523 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1524 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1386 | NULL, 0); | 1525 | NULL, 0); |
1387 | break; | 1526 | break; |
1388 | 1527 | ||
@@ -1399,7 +1538,8 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1399 | if (pdata && pdata->backlight) { | 1538 | if (pdata && pdata->backlight) { |
1400 | /* Treat errors as non-critical */ | 1539 | /* Treat errors as non-critical */ |
1401 | ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, | 1540 | ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, |
1402 | ARRAY_SIZE(backlight_devs), NULL, 0); | 1541 | ARRAY_SIZE(backlight_devs), NULL, |
1542 | wm831x->irq_base); | ||
1403 | if (ret < 0) | 1543 | if (ret < 0) |
1404 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", | 1544 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", |
1405 | ret); | 1545 | ret); |
@@ -1511,6 +1651,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { | |||
1511 | { "wm8310", WM8310 }, | 1651 | { "wm8310", WM8310 }, |
1512 | { "wm8311", WM8311 }, | 1652 | { "wm8311", WM8311 }, |
1513 | { "wm8312", WM8312 }, | 1653 | { "wm8312", WM8312 }, |
1654 | { "wm8320", WM8320 }, | ||
1514 | { } | 1655 | { } |
1515 | }; | 1656 | }; |
1516 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | 1657 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index ac056ea6b66e..301327697117 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/irq.h> | ||
18 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | 21 | ||
@@ -339,110 +340,71 @@ static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data) | |||
339 | return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; | 340 | return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; |
340 | } | 341 | } |
341 | 342 | ||
342 | static void __wm831x_enable_irq(struct wm831x *wm831x, int irq) | 343 | static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, |
344 | int irq) | ||
343 | { | 345 | { |
344 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | 346 | return &wm831x_irqs[irq - wm831x->irq_base]; |
345 | |||
346 | wm831x->irq_masks[irq_data->reg - 1] &= ~irq_data->mask; | ||
347 | wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), | ||
348 | wm831x->irq_masks[irq_data->reg - 1]); | ||
349 | } | 347 | } |
350 | 348 | ||
351 | void wm831x_enable_irq(struct wm831x *wm831x, int irq) | 349 | static void wm831x_irq_lock(unsigned int irq) |
352 | { | 350 | { |
353 | mutex_lock(&wm831x->irq_lock); | 351 | struct wm831x *wm831x = get_irq_chip_data(irq); |
354 | __wm831x_enable_irq(wm831x, irq); | ||
355 | mutex_unlock(&wm831x->irq_lock); | ||
356 | } | ||
357 | EXPORT_SYMBOL_GPL(wm831x_enable_irq); | ||
358 | 352 | ||
359 | static void __wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
360 | { | ||
361 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | ||
362 | |||
363 | wm831x->irq_masks[irq_data->reg - 1] |= irq_data->mask; | ||
364 | wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data), | ||
365 | wm831x->irq_masks[irq_data->reg - 1]); | ||
366 | } | ||
367 | |||
368 | void wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
369 | { | ||
370 | mutex_lock(&wm831x->irq_lock); | 353 | mutex_lock(&wm831x->irq_lock); |
371 | __wm831x_disable_irq(wm831x, irq); | ||
372 | mutex_unlock(&wm831x->irq_lock); | ||
373 | } | 354 | } |
374 | EXPORT_SYMBOL_GPL(wm831x_disable_irq); | ||
375 | 355 | ||
376 | int wm831x_request_irq(struct wm831x *wm831x, | 356 | static void wm831x_irq_sync_unlock(unsigned int irq) |
377 | unsigned int irq, irq_handler_t handler, | ||
378 | unsigned long flags, const char *name, | ||
379 | void *dev) | ||
380 | { | 357 | { |
381 | int ret = 0; | 358 | struct wm831x *wm831x = get_irq_chip_data(irq); |
382 | 359 | int i; | |
383 | if (irq < 0 || irq >= WM831X_NUM_IRQS) | 360 | |
384 | return -EINVAL; | 361 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { |
385 | 362 | /* If there's been a change in the mask write it back | |
386 | mutex_lock(&wm831x->irq_lock); | 363 | * to the hardware. */ |
387 | 364 | if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) { | |
388 | if (wm831x_irqs[irq].handler) { | 365 | wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i]; |
389 | dev_err(wm831x->dev, "Already have handler for IRQ %d\n", irq); | 366 | wm831x_reg_write(wm831x, |
390 | ret = -EINVAL; | 367 | WM831X_INTERRUPT_STATUS_1_MASK + i, |
391 | goto out; | 368 | wm831x->irq_masks_cur[i]); |
369 | } | ||
392 | } | 370 | } |
393 | 371 | ||
394 | wm831x_irqs[irq].handler = handler; | ||
395 | wm831x_irqs[irq].handler_data = dev; | ||
396 | |||
397 | __wm831x_enable_irq(wm831x, irq); | ||
398 | |||
399 | out: | ||
400 | mutex_unlock(&wm831x->irq_lock); | 372 | mutex_unlock(&wm831x->irq_lock); |
401 | |||
402 | return ret; | ||
403 | } | 373 | } |
404 | EXPORT_SYMBOL_GPL(wm831x_request_irq); | ||
405 | 374 | ||
406 | void wm831x_free_irq(struct wm831x *wm831x, unsigned int irq, void *data) | 375 | static void wm831x_irq_unmask(unsigned int irq) |
407 | { | 376 | { |
408 | if (irq < 0 || irq >= WM831X_NUM_IRQS) | 377 | struct wm831x *wm831x = get_irq_chip_data(irq); |
409 | return; | 378 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); |
410 | |||
411 | mutex_lock(&wm831x->irq_lock); | ||
412 | 379 | ||
413 | wm831x_irqs[irq].handler = NULL; | 380 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; |
414 | wm831x_irqs[irq].handler_data = NULL; | ||
415 | |||
416 | __wm831x_disable_irq(wm831x, irq); | ||
417 | |||
418 | mutex_unlock(&wm831x->irq_lock); | ||
419 | } | 381 | } |
420 | EXPORT_SYMBOL_GPL(wm831x_free_irq); | ||
421 | 382 | ||
422 | 383 | static void wm831x_irq_mask(unsigned int irq) | |
423 | static void wm831x_handle_irq(struct wm831x *wm831x, int irq, int status) | ||
424 | { | 384 | { |
425 | struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; | 385 | struct wm831x *wm831x = get_irq_chip_data(irq); |
426 | 386 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); | |
427 | if (irq_data->handler) { | 387 | |
428 | irq_data->handler(irq, irq_data->handler_data); | 388 | wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; |
429 | wm831x_reg_write(wm831x, irq_data_to_status_reg(irq_data), | ||
430 | irq_data->mask); | ||
431 | } else { | ||
432 | dev_err(wm831x->dev, "Unhandled IRQ %d, masking\n", irq); | ||
433 | __wm831x_disable_irq(wm831x, irq); | ||
434 | } | ||
435 | } | 389 | } |
436 | 390 | ||
437 | /* Main interrupt handling occurs in a workqueue since we need | 391 | static struct irq_chip wm831x_irq_chip = { |
438 | * interrupts enabled to interact with the chip. */ | 392 | .name = "wm831x", |
439 | static void wm831x_irq_worker(struct work_struct *work) | 393 | .bus_lock = wm831x_irq_lock, |
394 | .bus_sync_unlock = wm831x_irq_sync_unlock, | ||
395 | .mask = wm831x_irq_mask, | ||
396 | .unmask = wm831x_irq_unmask, | ||
397 | }; | ||
398 | |||
399 | /* The processing of the primary interrupt occurs in a thread so that | ||
400 | * we can interact with the device over I2C or SPI. */ | ||
401 | static irqreturn_t wm831x_irq_thread(int irq, void *data) | ||
440 | { | 402 | { |
441 | struct wm831x *wm831x = container_of(work, struct wm831x, irq_work); | 403 | struct wm831x *wm831x = data; |
442 | unsigned int i; | 404 | unsigned int i; |
443 | int primary; | 405 | int primary; |
444 | int status_regs[5]; | 406 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; |
445 | int read[5] = { 0 }; | 407 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; |
446 | int *status; | 408 | int *status; |
447 | 409 | ||
448 | primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); | 410 | primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); |
@@ -452,8 +414,6 @@ static void wm831x_irq_worker(struct work_struct *work) | |||
452 | goto out; | 414 | goto out; |
453 | } | 415 | } |
454 | 416 | ||
455 | mutex_lock(&wm831x->irq_lock); | ||
456 | |||
457 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { | 417 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { |
458 | int offset = wm831x_irqs[i].reg - 1; | 418 | int offset = wm831x_irqs[i].reg - 1; |
459 | 419 | ||
@@ -471,41 +431,34 @@ static void wm831x_irq_worker(struct work_struct *work) | |||
471 | dev_err(wm831x->dev, | 431 | dev_err(wm831x->dev, |
472 | "Failed to read IRQ status: %d\n", | 432 | "Failed to read IRQ status: %d\n", |
473 | *status); | 433 | *status); |
474 | goto out_lock; | 434 | goto out; |
475 | } | 435 | } |
476 | 436 | ||
477 | /* Mask out the disabled IRQs */ | ||
478 | *status &= ~wm831x->irq_masks[offset]; | ||
479 | read[offset] = 1; | 437 | read[offset] = 1; |
480 | } | 438 | } |
481 | 439 | ||
482 | if (*status & wm831x_irqs[i].mask) | 440 | /* Report it if it isn't masked, or forget the status. */ |
483 | wm831x_handle_irq(wm831x, i, *status); | 441 | if ((*status & ~wm831x->irq_masks_cur[offset]) |
442 | & wm831x_irqs[i].mask) | ||
443 | handle_nested_irq(wm831x->irq_base + i); | ||
444 | else | ||
445 | *status &= ~wm831x_irqs[i].mask; | ||
484 | } | 446 | } |
485 | 447 | ||
486 | out_lock: | ||
487 | mutex_unlock(&wm831x->irq_lock); | ||
488 | out: | 448 | out: |
489 | enable_irq(wm831x->irq); | 449 | for (i = 0; i < ARRAY_SIZE(status_regs); i++) { |
490 | } | 450 | if (status_regs[i]) |
491 | 451 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i, | |
492 | 452 | status_regs[i]); | |
493 | static irqreturn_t wm831x_cpu_irq(int irq, void *data) | 453 | } |
494 | { | ||
495 | struct wm831x *wm831x = data; | ||
496 | |||
497 | /* Shut the interrupt to the CPU up and schedule the actual | ||
498 | * handler; we can't check that the IRQ is asserted. */ | ||
499 | disable_irq_nosync(irq); | ||
500 | |||
501 | queue_work(wm831x->irq_wq, &wm831x->irq_work); | ||
502 | 454 | ||
503 | return IRQ_HANDLED; | 455 | return IRQ_HANDLED; |
504 | } | 456 | } |
505 | 457 | ||
506 | int wm831x_irq_init(struct wm831x *wm831x, int irq) | 458 | int wm831x_irq_init(struct wm831x *wm831x, int irq) |
507 | { | 459 | { |
508 | int i, ret; | 460 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
461 | int i, cur_irq, ret; | ||
509 | 462 | ||
510 | mutex_init(&wm831x->irq_lock); | 463 | mutex_init(&wm831x->irq_lock); |
511 | 464 | ||
@@ -515,41 +468,53 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
515 | return 0; | 468 | return 0; |
516 | } | 469 | } |
517 | 470 | ||
518 | 471 | if (!pdata || !pdata->irq_base) { | |
519 | wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq"); | 472 | dev_err(wm831x->dev, |
520 | if (!wm831x->irq_wq) { | 473 | "No interrupt base specified, no interrupts\n"); |
521 | dev_err(wm831x->dev, "Failed to allocate IRQ worker\n"); | 474 | return 0; |
522 | return -ESRCH; | ||
523 | } | 475 | } |
524 | 476 | ||
525 | wm831x->irq = irq; | 477 | wm831x->irq = irq; |
526 | INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); | 478 | wm831x->irq_base = pdata->irq_base; |
527 | 479 | ||
528 | /* Mask the individual interrupt sources */ | 480 | /* Mask the individual interrupt sources */ |
529 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks); i++) { | 481 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { |
530 | wm831x->irq_masks[i] = 0xffff; | 482 | wm831x->irq_masks_cur[i] = 0xffff; |
483 | wm831x->irq_masks_cache[i] = 0xffff; | ||
531 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, | 484 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, |
532 | 0xffff); | 485 | 0xffff); |
533 | } | 486 | } |
534 | 487 | ||
535 | /* Enable top level interrupts, we mask at secondary level */ | 488 | /* Register them with genirq */ |
536 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | 489 | for (cur_irq = wm831x->irq_base; |
490 | cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; | ||
491 | cur_irq++) { | ||
492 | set_irq_chip_data(cur_irq, wm831x); | ||
493 | set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip, | ||
494 | handle_edge_irq); | ||
495 | set_irq_nested_thread(cur_irq, 1); | ||
496 | |||
497 | /* ARM needs us to explicitly flag the IRQ as valid | ||
498 | * and will set them noprobe when we do so. */ | ||
499 | #ifdef CONFIG_ARM | ||
500 | set_irq_flags(cur_irq, IRQF_VALID); | ||
501 | #else | ||
502 | set_irq_noprobe(cur_irq); | ||
503 | #endif | ||
504 | } | ||
537 | 505 | ||
538 | /* We're good to go. We set IRQF_SHARED since there's a | 506 | ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, |
539 | * chance the driver will interoperate with another driver but | 507 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
540 | * the need to disable the IRQ while handing via I2C/SPI means | 508 | "wm831x", wm831x); |
541 | * that this may break and performance will be impacted. If | ||
542 | * this does happen it's a hardware design issue and the only | ||
543 | * other alternative would be polling. | ||
544 | */ | ||
545 | ret = request_irq(irq, wm831x_cpu_irq, IRQF_TRIGGER_LOW | IRQF_SHARED, | ||
546 | "wm831x", wm831x); | ||
547 | if (ret != 0) { | 509 | if (ret != 0) { |
548 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", | 510 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", |
549 | irq, ret); | 511 | irq, ret); |
550 | return ret; | 512 | return ret; |
551 | } | 513 | } |
552 | 514 | ||
515 | /* Enable top level interrupts, we mask at secondary level */ | ||
516 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | ||
517 | |||
553 | return 0; | 518 | return 0; |
554 | } | 519 | } |
555 | 520 | ||
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index ba27c9dc1ad3..8485a7018060 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -337,733 +337,6 @@ int wm8350_reg_unlock(struct wm8350 *wm8350) | |||
337 | } | 337 | } |
338 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); | 338 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); |
339 | 339 | ||
340 | static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) | ||
341 | { | ||
342 | mutex_lock(&wm8350->irq_mutex); | ||
343 | |||
344 | if (wm8350->irq[irq].handler) | ||
345 | wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data); | ||
346 | else { | ||
347 | dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", | ||
348 | irq); | ||
349 | wm8350_mask_irq(wm8350, irq); | ||
350 | } | ||
351 | |||
352 | mutex_unlock(&wm8350->irq_mutex); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * This is a threaded IRQ handler so can access I2C/SPI. Since all | ||
357 | * interrupts are clear on read the IRQ line will be reasserted and | ||
358 | * the physical IRQ will be handled again if another interrupt is | ||
359 | * asserted while we run - in the normal course of events this is a | ||
360 | * rare occurrence so we save I2C/SPI reads. | ||
361 | */ | ||
362 | static irqreturn_t wm8350_irq(int irq, void *data) | ||
363 | { | ||
364 | struct wm8350 *wm8350 = data; | ||
365 | u16 level_one, status1, status2, comp; | ||
366 | |||
367 | /* TODO: Use block reads to improve performance? */ | ||
368 | level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) | ||
369 | & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); | ||
370 | status1 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1) | ||
371 | & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_1_MASK); | ||
372 | status2 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_2) | ||
373 | & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_2_MASK); | ||
374 | comp = wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS) | ||
375 | & ~wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK); | ||
376 | |||
377 | /* over current */ | ||
378 | if (level_one & WM8350_OC_INT) { | ||
379 | u16 oc; | ||
380 | |||
381 | oc = wm8350_reg_read(wm8350, WM8350_OVER_CURRENT_INT_STATUS); | ||
382 | oc &= ~wm8350_reg_read(wm8350, | ||
383 | WM8350_OVER_CURRENT_INT_STATUS_MASK); | ||
384 | |||
385 | if (oc & WM8350_OC_LS_EINT) /* limit switch */ | ||
386 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_OC_LS); | ||
387 | } | ||
388 | |||
389 | /* under voltage */ | ||
390 | if (level_one & WM8350_UV_INT) { | ||
391 | u16 uv; | ||
392 | |||
393 | uv = wm8350_reg_read(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS); | ||
394 | uv &= ~wm8350_reg_read(wm8350, | ||
395 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK); | ||
396 | |||
397 | if (uv & WM8350_UV_DC1_EINT) | ||
398 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC1); | ||
399 | if (uv & WM8350_UV_DC2_EINT) | ||
400 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC2); | ||
401 | if (uv & WM8350_UV_DC3_EINT) | ||
402 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC3); | ||
403 | if (uv & WM8350_UV_DC4_EINT) | ||
404 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC4); | ||
405 | if (uv & WM8350_UV_DC5_EINT) | ||
406 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC5); | ||
407 | if (uv & WM8350_UV_DC6_EINT) | ||
408 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC6); | ||
409 | if (uv & WM8350_UV_LDO1_EINT) | ||
410 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO1); | ||
411 | if (uv & WM8350_UV_LDO2_EINT) | ||
412 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO2); | ||
413 | if (uv & WM8350_UV_LDO3_EINT) | ||
414 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO3); | ||
415 | if (uv & WM8350_UV_LDO4_EINT) | ||
416 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO4); | ||
417 | } | ||
418 | |||
419 | /* charger, RTC */ | ||
420 | if (status1) { | ||
421 | if (status1 & WM8350_CHG_BAT_HOT_EINT) | ||
422 | wm8350_irq_call_handler(wm8350, | ||
423 | WM8350_IRQ_CHG_BAT_HOT); | ||
424 | if (status1 & WM8350_CHG_BAT_COLD_EINT) | ||
425 | wm8350_irq_call_handler(wm8350, | ||
426 | WM8350_IRQ_CHG_BAT_COLD); | ||
427 | if (status1 & WM8350_CHG_BAT_FAIL_EINT) | ||
428 | wm8350_irq_call_handler(wm8350, | ||
429 | WM8350_IRQ_CHG_BAT_FAIL); | ||
430 | if (status1 & WM8350_CHG_TO_EINT) | ||
431 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_TO); | ||
432 | if (status1 & WM8350_CHG_END_EINT) | ||
433 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_END); | ||
434 | if (status1 & WM8350_CHG_START_EINT) | ||
435 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_START); | ||
436 | if (status1 & WM8350_CHG_FAST_RDY_EINT) | ||
437 | wm8350_irq_call_handler(wm8350, | ||
438 | WM8350_IRQ_CHG_FAST_RDY); | ||
439 | if (status1 & WM8350_CHG_VBATT_LT_3P9_EINT) | ||
440 | wm8350_irq_call_handler(wm8350, | ||
441 | WM8350_IRQ_CHG_VBATT_LT_3P9); | ||
442 | if (status1 & WM8350_CHG_VBATT_LT_3P1_EINT) | ||
443 | wm8350_irq_call_handler(wm8350, | ||
444 | WM8350_IRQ_CHG_VBATT_LT_3P1); | ||
445 | if (status1 & WM8350_CHG_VBATT_LT_2P85_EINT) | ||
446 | wm8350_irq_call_handler(wm8350, | ||
447 | WM8350_IRQ_CHG_VBATT_LT_2P85); | ||
448 | if (status1 & WM8350_RTC_ALM_EINT) | ||
449 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_ALM); | ||
450 | if (status1 & WM8350_RTC_SEC_EINT) | ||
451 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_SEC); | ||
452 | if (status1 & WM8350_RTC_PER_EINT) | ||
453 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_PER); | ||
454 | } | ||
455 | |||
456 | /* current sink, system, aux adc */ | ||
457 | if (status2) { | ||
458 | if (status2 & WM8350_CS1_EINT) | ||
459 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS1); | ||
460 | if (status2 & WM8350_CS2_EINT) | ||
461 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS2); | ||
462 | |||
463 | if (status2 & WM8350_SYS_HYST_COMP_FAIL_EINT) | ||
464 | wm8350_irq_call_handler(wm8350, | ||
465 | WM8350_IRQ_SYS_HYST_COMP_FAIL); | ||
466 | if (status2 & WM8350_SYS_CHIP_GT115_EINT) | ||
467 | wm8350_irq_call_handler(wm8350, | ||
468 | WM8350_IRQ_SYS_CHIP_GT115); | ||
469 | if (status2 & WM8350_SYS_CHIP_GT140_EINT) | ||
470 | wm8350_irq_call_handler(wm8350, | ||
471 | WM8350_IRQ_SYS_CHIP_GT140); | ||
472 | if (status2 & WM8350_SYS_WDOG_TO_EINT) | ||
473 | wm8350_irq_call_handler(wm8350, | ||
474 | WM8350_IRQ_SYS_WDOG_TO); | ||
475 | |||
476 | if (status2 & WM8350_AUXADC_DATARDY_EINT) | ||
477 | wm8350_irq_call_handler(wm8350, | ||
478 | WM8350_IRQ_AUXADC_DATARDY); | ||
479 | if (status2 & WM8350_AUXADC_DCOMP4_EINT) | ||
480 | wm8350_irq_call_handler(wm8350, | ||
481 | WM8350_IRQ_AUXADC_DCOMP4); | ||
482 | if (status2 & WM8350_AUXADC_DCOMP3_EINT) | ||
483 | wm8350_irq_call_handler(wm8350, | ||
484 | WM8350_IRQ_AUXADC_DCOMP3); | ||
485 | if (status2 & WM8350_AUXADC_DCOMP2_EINT) | ||
486 | wm8350_irq_call_handler(wm8350, | ||
487 | WM8350_IRQ_AUXADC_DCOMP2); | ||
488 | if (status2 & WM8350_AUXADC_DCOMP1_EINT) | ||
489 | wm8350_irq_call_handler(wm8350, | ||
490 | WM8350_IRQ_AUXADC_DCOMP1); | ||
491 | |||
492 | if (status2 & WM8350_USB_LIMIT_EINT) | ||
493 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_USB_LIMIT); | ||
494 | } | ||
495 | |||
496 | /* wake, codec, ext */ | ||
497 | if (comp) { | ||
498 | if (comp & WM8350_WKUP_OFF_STATE_EINT) | ||
499 | wm8350_irq_call_handler(wm8350, | ||
500 | WM8350_IRQ_WKUP_OFF_STATE); | ||
501 | if (comp & WM8350_WKUP_HIB_STATE_EINT) | ||
502 | wm8350_irq_call_handler(wm8350, | ||
503 | WM8350_IRQ_WKUP_HIB_STATE); | ||
504 | if (comp & WM8350_WKUP_CONV_FAULT_EINT) | ||
505 | wm8350_irq_call_handler(wm8350, | ||
506 | WM8350_IRQ_WKUP_CONV_FAULT); | ||
507 | if (comp & WM8350_WKUP_WDOG_RST_EINT) | ||
508 | wm8350_irq_call_handler(wm8350, | ||
509 | WM8350_IRQ_WKUP_WDOG_RST); | ||
510 | if (comp & WM8350_WKUP_GP_PWR_ON_EINT) | ||
511 | wm8350_irq_call_handler(wm8350, | ||
512 | WM8350_IRQ_WKUP_GP_PWR_ON); | ||
513 | if (comp & WM8350_WKUP_ONKEY_EINT) | ||
514 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_WKUP_ONKEY); | ||
515 | if (comp & WM8350_WKUP_GP_WAKEUP_EINT) | ||
516 | wm8350_irq_call_handler(wm8350, | ||
517 | WM8350_IRQ_WKUP_GP_WAKEUP); | ||
518 | |||
519 | if (comp & WM8350_CODEC_JCK_DET_L_EINT) | ||
520 | wm8350_irq_call_handler(wm8350, | ||
521 | WM8350_IRQ_CODEC_JCK_DET_L); | ||
522 | if (comp & WM8350_CODEC_JCK_DET_R_EINT) | ||
523 | wm8350_irq_call_handler(wm8350, | ||
524 | WM8350_IRQ_CODEC_JCK_DET_R); | ||
525 | if (comp & WM8350_CODEC_MICSCD_EINT) | ||
526 | wm8350_irq_call_handler(wm8350, | ||
527 | WM8350_IRQ_CODEC_MICSCD); | ||
528 | if (comp & WM8350_CODEC_MICD_EINT) | ||
529 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_CODEC_MICD); | ||
530 | |||
531 | if (comp & WM8350_EXT_USB_FB_EINT) | ||
532 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
533 | if (comp & WM8350_EXT_WALL_FB_EINT) | ||
534 | wm8350_irq_call_handler(wm8350, | ||
535 | WM8350_IRQ_EXT_WALL_FB); | ||
536 | if (comp & WM8350_EXT_BAT_FB_EINT) | ||
537 | wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
538 | } | ||
539 | |||
540 | if (level_one & WM8350_GP_INT) { | ||
541 | int i; | ||
542 | u16 gpio; | ||
543 | |||
544 | gpio = wm8350_reg_read(wm8350, WM8350_GPIO_INT_STATUS); | ||
545 | gpio &= ~wm8350_reg_read(wm8350, | ||
546 | WM8350_GPIO_INT_STATUS_MASK); | ||
547 | |||
548 | for (i = 0; i < 12; i++) { | ||
549 | if (gpio & (1 << i)) | ||
550 | wm8350_irq_call_handler(wm8350, | ||
551 | WM8350_IRQ_GPIO(i)); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | return IRQ_HANDLED; | ||
556 | } | ||
557 | |||
558 | int wm8350_register_irq(struct wm8350 *wm8350, int irq, | ||
559 | void (*handler) (struct wm8350 *, int, void *), | ||
560 | void *data) | ||
561 | { | ||
562 | if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) | ||
563 | return -EINVAL; | ||
564 | |||
565 | if (wm8350->irq[irq].handler) | ||
566 | return -EBUSY; | ||
567 | |||
568 | mutex_lock(&wm8350->irq_mutex); | ||
569 | wm8350->irq[irq].handler = handler; | ||
570 | wm8350->irq[irq].data = data; | ||
571 | mutex_unlock(&wm8350->irq_mutex); | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | EXPORT_SYMBOL_GPL(wm8350_register_irq); | ||
576 | |||
577 | int wm8350_free_irq(struct wm8350 *wm8350, int irq) | ||
578 | { | ||
579 | if (irq < 0 || irq > WM8350_NUM_IRQ) | ||
580 | return -EINVAL; | ||
581 | |||
582 | mutex_lock(&wm8350->irq_mutex); | ||
583 | wm8350->irq[irq].handler = NULL; | ||
584 | mutex_unlock(&wm8350->irq_mutex); | ||
585 | return 0; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(wm8350_free_irq); | ||
588 | |||
589 | int wm8350_mask_irq(struct wm8350 *wm8350, int irq) | ||
590 | { | ||
591 | switch (irq) { | ||
592 | case WM8350_IRQ_CHG_BAT_HOT: | ||
593 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
594 | WM8350_IM_CHG_BAT_HOT_EINT); | ||
595 | case WM8350_IRQ_CHG_BAT_COLD: | ||
596 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
597 | WM8350_IM_CHG_BAT_COLD_EINT); | ||
598 | case WM8350_IRQ_CHG_BAT_FAIL: | ||
599 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
600 | WM8350_IM_CHG_BAT_FAIL_EINT); | ||
601 | case WM8350_IRQ_CHG_TO: | ||
602 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
603 | WM8350_IM_CHG_TO_EINT); | ||
604 | case WM8350_IRQ_CHG_END: | ||
605 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
606 | WM8350_IM_CHG_END_EINT); | ||
607 | case WM8350_IRQ_CHG_START: | ||
608 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
609 | WM8350_IM_CHG_START_EINT); | ||
610 | case WM8350_IRQ_CHG_FAST_RDY: | ||
611 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
612 | WM8350_IM_CHG_FAST_RDY_EINT); | ||
613 | case WM8350_IRQ_RTC_PER: | ||
614 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
615 | WM8350_IM_RTC_PER_EINT); | ||
616 | case WM8350_IRQ_RTC_SEC: | ||
617 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
618 | WM8350_IM_RTC_SEC_EINT); | ||
619 | case WM8350_IRQ_RTC_ALM: | ||
620 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
621 | WM8350_IM_RTC_ALM_EINT); | ||
622 | case WM8350_IRQ_CHG_VBATT_LT_3P9: | ||
623 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
624 | WM8350_IM_CHG_VBATT_LT_3P9_EINT); | ||
625 | case WM8350_IRQ_CHG_VBATT_LT_3P1: | ||
626 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
627 | WM8350_IM_CHG_VBATT_LT_3P1_EINT); | ||
628 | case WM8350_IRQ_CHG_VBATT_LT_2P85: | ||
629 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
630 | WM8350_IM_CHG_VBATT_LT_2P85_EINT); | ||
631 | case WM8350_IRQ_CS1: | ||
632 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
633 | WM8350_IM_CS1_EINT); | ||
634 | case WM8350_IRQ_CS2: | ||
635 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
636 | WM8350_IM_CS2_EINT); | ||
637 | case WM8350_IRQ_USB_LIMIT: | ||
638 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
639 | WM8350_IM_USB_LIMIT_EINT); | ||
640 | case WM8350_IRQ_AUXADC_DATARDY: | ||
641 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
642 | WM8350_IM_AUXADC_DATARDY_EINT); | ||
643 | case WM8350_IRQ_AUXADC_DCOMP4: | ||
644 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
645 | WM8350_IM_AUXADC_DCOMP4_EINT); | ||
646 | case WM8350_IRQ_AUXADC_DCOMP3: | ||
647 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
648 | WM8350_IM_AUXADC_DCOMP3_EINT); | ||
649 | case WM8350_IRQ_AUXADC_DCOMP2: | ||
650 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
651 | WM8350_IM_AUXADC_DCOMP2_EINT); | ||
652 | case WM8350_IRQ_AUXADC_DCOMP1: | ||
653 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
654 | WM8350_IM_AUXADC_DCOMP1_EINT); | ||
655 | case WM8350_IRQ_SYS_HYST_COMP_FAIL: | ||
656 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
657 | WM8350_IM_SYS_HYST_COMP_FAIL_EINT); | ||
658 | case WM8350_IRQ_SYS_CHIP_GT115: | ||
659 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
660 | WM8350_IM_SYS_CHIP_GT115_EINT); | ||
661 | case WM8350_IRQ_SYS_CHIP_GT140: | ||
662 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
663 | WM8350_IM_SYS_CHIP_GT140_EINT); | ||
664 | case WM8350_IRQ_SYS_WDOG_TO: | ||
665 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
666 | WM8350_IM_SYS_WDOG_TO_EINT); | ||
667 | case WM8350_IRQ_UV_LDO4: | ||
668 | return wm8350_set_bits(wm8350, | ||
669 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
670 | WM8350_IM_UV_LDO4_EINT); | ||
671 | case WM8350_IRQ_UV_LDO3: | ||
672 | return wm8350_set_bits(wm8350, | ||
673 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
674 | WM8350_IM_UV_LDO3_EINT); | ||
675 | case WM8350_IRQ_UV_LDO2: | ||
676 | return wm8350_set_bits(wm8350, | ||
677 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
678 | WM8350_IM_UV_LDO2_EINT); | ||
679 | case WM8350_IRQ_UV_LDO1: | ||
680 | return wm8350_set_bits(wm8350, | ||
681 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
682 | WM8350_IM_UV_LDO1_EINT); | ||
683 | case WM8350_IRQ_UV_DC6: | ||
684 | return wm8350_set_bits(wm8350, | ||
685 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
686 | WM8350_IM_UV_DC6_EINT); | ||
687 | case WM8350_IRQ_UV_DC5: | ||
688 | return wm8350_set_bits(wm8350, | ||
689 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
690 | WM8350_IM_UV_DC5_EINT); | ||
691 | case WM8350_IRQ_UV_DC4: | ||
692 | return wm8350_set_bits(wm8350, | ||
693 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
694 | WM8350_IM_UV_DC4_EINT); | ||
695 | case WM8350_IRQ_UV_DC3: | ||
696 | return wm8350_set_bits(wm8350, | ||
697 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
698 | WM8350_IM_UV_DC3_EINT); | ||
699 | case WM8350_IRQ_UV_DC2: | ||
700 | return wm8350_set_bits(wm8350, | ||
701 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
702 | WM8350_IM_UV_DC2_EINT); | ||
703 | case WM8350_IRQ_UV_DC1: | ||
704 | return wm8350_set_bits(wm8350, | ||
705 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
706 | WM8350_IM_UV_DC1_EINT); | ||
707 | case WM8350_IRQ_OC_LS: | ||
708 | return wm8350_set_bits(wm8350, | ||
709 | WM8350_OVER_CURRENT_INT_STATUS_MASK, | ||
710 | WM8350_IM_OC_LS_EINT); | ||
711 | case WM8350_IRQ_EXT_USB_FB: | ||
712 | return wm8350_set_bits(wm8350, | ||
713 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
714 | WM8350_IM_EXT_USB_FB_EINT); | ||
715 | case WM8350_IRQ_EXT_WALL_FB: | ||
716 | return wm8350_set_bits(wm8350, | ||
717 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
718 | WM8350_IM_EXT_WALL_FB_EINT); | ||
719 | case WM8350_IRQ_EXT_BAT_FB: | ||
720 | return wm8350_set_bits(wm8350, | ||
721 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
722 | WM8350_IM_EXT_BAT_FB_EINT); | ||
723 | case WM8350_IRQ_CODEC_JCK_DET_L: | ||
724 | return wm8350_set_bits(wm8350, | ||
725 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
726 | WM8350_IM_CODEC_JCK_DET_L_EINT); | ||
727 | case WM8350_IRQ_CODEC_JCK_DET_R: | ||
728 | return wm8350_set_bits(wm8350, | ||
729 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
730 | WM8350_IM_CODEC_JCK_DET_R_EINT); | ||
731 | case WM8350_IRQ_CODEC_MICSCD: | ||
732 | return wm8350_set_bits(wm8350, | ||
733 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
734 | WM8350_IM_CODEC_MICSCD_EINT); | ||
735 | case WM8350_IRQ_CODEC_MICD: | ||
736 | return wm8350_set_bits(wm8350, | ||
737 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
738 | WM8350_IM_CODEC_MICD_EINT); | ||
739 | case WM8350_IRQ_WKUP_OFF_STATE: | ||
740 | return wm8350_set_bits(wm8350, | ||
741 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
742 | WM8350_IM_WKUP_OFF_STATE_EINT); | ||
743 | case WM8350_IRQ_WKUP_HIB_STATE: | ||
744 | return wm8350_set_bits(wm8350, | ||
745 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
746 | WM8350_IM_WKUP_HIB_STATE_EINT); | ||
747 | case WM8350_IRQ_WKUP_CONV_FAULT: | ||
748 | return wm8350_set_bits(wm8350, | ||
749 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
750 | WM8350_IM_WKUP_CONV_FAULT_EINT); | ||
751 | case WM8350_IRQ_WKUP_WDOG_RST: | ||
752 | return wm8350_set_bits(wm8350, | ||
753 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
754 | WM8350_IM_WKUP_OFF_STATE_EINT); | ||
755 | case WM8350_IRQ_WKUP_GP_PWR_ON: | ||
756 | return wm8350_set_bits(wm8350, | ||
757 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
758 | WM8350_IM_WKUP_GP_PWR_ON_EINT); | ||
759 | case WM8350_IRQ_WKUP_ONKEY: | ||
760 | return wm8350_set_bits(wm8350, | ||
761 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
762 | WM8350_IM_WKUP_ONKEY_EINT); | ||
763 | case WM8350_IRQ_WKUP_GP_WAKEUP: | ||
764 | return wm8350_set_bits(wm8350, | ||
765 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
766 | WM8350_IM_WKUP_GP_WAKEUP_EINT); | ||
767 | case WM8350_IRQ_GPIO(0): | ||
768 | return wm8350_set_bits(wm8350, | ||
769 | WM8350_GPIO_INT_STATUS_MASK, | ||
770 | WM8350_IM_GP0_EINT); | ||
771 | case WM8350_IRQ_GPIO(1): | ||
772 | return wm8350_set_bits(wm8350, | ||
773 | WM8350_GPIO_INT_STATUS_MASK, | ||
774 | WM8350_IM_GP1_EINT); | ||
775 | case WM8350_IRQ_GPIO(2): | ||
776 | return wm8350_set_bits(wm8350, | ||
777 | WM8350_GPIO_INT_STATUS_MASK, | ||
778 | WM8350_IM_GP2_EINT); | ||
779 | case WM8350_IRQ_GPIO(3): | ||
780 | return wm8350_set_bits(wm8350, | ||
781 | WM8350_GPIO_INT_STATUS_MASK, | ||
782 | WM8350_IM_GP3_EINT); | ||
783 | case WM8350_IRQ_GPIO(4): | ||
784 | return wm8350_set_bits(wm8350, | ||
785 | WM8350_GPIO_INT_STATUS_MASK, | ||
786 | WM8350_IM_GP4_EINT); | ||
787 | case WM8350_IRQ_GPIO(5): | ||
788 | return wm8350_set_bits(wm8350, | ||
789 | WM8350_GPIO_INT_STATUS_MASK, | ||
790 | WM8350_IM_GP5_EINT); | ||
791 | case WM8350_IRQ_GPIO(6): | ||
792 | return wm8350_set_bits(wm8350, | ||
793 | WM8350_GPIO_INT_STATUS_MASK, | ||
794 | WM8350_IM_GP6_EINT); | ||
795 | case WM8350_IRQ_GPIO(7): | ||
796 | return wm8350_set_bits(wm8350, | ||
797 | WM8350_GPIO_INT_STATUS_MASK, | ||
798 | WM8350_IM_GP7_EINT); | ||
799 | case WM8350_IRQ_GPIO(8): | ||
800 | return wm8350_set_bits(wm8350, | ||
801 | WM8350_GPIO_INT_STATUS_MASK, | ||
802 | WM8350_IM_GP8_EINT); | ||
803 | case WM8350_IRQ_GPIO(9): | ||
804 | return wm8350_set_bits(wm8350, | ||
805 | WM8350_GPIO_INT_STATUS_MASK, | ||
806 | WM8350_IM_GP9_EINT); | ||
807 | case WM8350_IRQ_GPIO(10): | ||
808 | return wm8350_set_bits(wm8350, | ||
809 | WM8350_GPIO_INT_STATUS_MASK, | ||
810 | WM8350_IM_GP10_EINT); | ||
811 | case WM8350_IRQ_GPIO(11): | ||
812 | return wm8350_set_bits(wm8350, | ||
813 | WM8350_GPIO_INT_STATUS_MASK, | ||
814 | WM8350_IM_GP11_EINT); | ||
815 | case WM8350_IRQ_GPIO(12): | ||
816 | return wm8350_set_bits(wm8350, | ||
817 | WM8350_GPIO_INT_STATUS_MASK, | ||
818 | WM8350_IM_GP12_EINT); | ||
819 | default: | ||
820 | dev_warn(wm8350->dev, "Attempting to mask unknown IRQ %d\n", | ||
821 | irq); | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | return 0; | ||
825 | } | ||
826 | EXPORT_SYMBOL_GPL(wm8350_mask_irq); | ||
827 | |||
828 | int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) | ||
829 | { | ||
830 | switch (irq) { | ||
831 | case WM8350_IRQ_CHG_BAT_HOT: | ||
832 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
833 | WM8350_IM_CHG_BAT_HOT_EINT); | ||
834 | case WM8350_IRQ_CHG_BAT_COLD: | ||
835 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
836 | WM8350_IM_CHG_BAT_COLD_EINT); | ||
837 | case WM8350_IRQ_CHG_BAT_FAIL: | ||
838 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
839 | WM8350_IM_CHG_BAT_FAIL_EINT); | ||
840 | case WM8350_IRQ_CHG_TO: | ||
841 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
842 | WM8350_IM_CHG_TO_EINT); | ||
843 | case WM8350_IRQ_CHG_END: | ||
844 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
845 | WM8350_IM_CHG_END_EINT); | ||
846 | case WM8350_IRQ_CHG_START: | ||
847 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
848 | WM8350_IM_CHG_START_EINT); | ||
849 | case WM8350_IRQ_CHG_FAST_RDY: | ||
850 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
851 | WM8350_IM_CHG_FAST_RDY_EINT); | ||
852 | case WM8350_IRQ_RTC_PER: | ||
853 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
854 | WM8350_IM_RTC_PER_EINT); | ||
855 | case WM8350_IRQ_RTC_SEC: | ||
856 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
857 | WM8350_IM_RTC_SEC_EINT); | ||
858 | case WM8350_IRQ_RTC_ALM: | ||
859 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
860 | WM8350_IM_RTC_ALM_EINT); | ||
861 | case WM8350_IRQ_CHG_VBATT_LT_3P9: | ||
862 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
863 | WM8350_IM_CHG_VBATT_LT_3P9_EINT); | ||
864 | case WM8350_IRQ_CHG_VBATT_LT_3P1: | ||
865 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
866 | WM8350_IM_CHG_VBATT_LT_3P1_EINT); | ||
867 | case WM8350_IRQ_CHG_VBATT_LT_2P85: | ||
868 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK, | ||
869 | WM8350_IM_CHG_VBATT_LT_2P85_EINT); | ||
870 | case WM8350_IRQ_CS1: | ||
871 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
872 | WM8350_IM_CS1_EINT); | ||
873 | case WM8350_IRQ_CS2: | ||
874 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
875 | WM8350_IM_CS2_EINT); | ||
876 | case WM8350_IRQ_USB_LIMIT: | ||
877 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
878 | WM8350_IM_USB_LIMIT_EINT); | ||
879 | case WM8350_IRQ_AUXADC_DATARDY: | ||
880 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
881 | WM8350_IM_AUXADC_DATARDY_EINT); | ||
882 | case WM8350_IRQ_AUXADC_DCOMP4: | ||
883 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
884 | WM8350_IM_AUXADC_DCOMP4_EINT); | ||
885 | case WM8350_IRQ_AUXADC_DCOMP3: | ||
886 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
887 | WM8350_IM_AUXADC_DCOMP3_EINT); | ||
888 | case WM8350_IRQ_AUXADC_DCOMP2: | ||
889 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
890 | WM8350_IM_AUXADC_DCOMP2_EINT); | ||
891 | case WM8350_IRQ_AUXADC_DCOMP1: | ||
892 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
893 | WM8350_IM_AUXADC_DCOMP1_EINT); | ||
894 | case WM8350_IRQ_SYS_HYST_COMP_FAIL: | ||
895 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
896 | WM8350_IM_SYS_HYST_COMP_FAIL_EINT); | ||
897 | case WM8350_IRQ_SYS_CHIP_GT115: | ||
898 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
899 | WM8350_IM_SYS_CHIP_GT115_EINT); | ||
900 | case WM8350_IRQ_SYS_CHIP_GT140: | ||
901 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
902 | WM8350_IM_SYS_CHIP_GT140_EINT); | ||
903 | case WM8350_IRQ_SYS_WDOG_TO: | ||
904 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK, | ||
905 | WM8350_IM_SYS_WDOG_TO_EINT); | ||
906 | case WM8350_IRQ_UV_LDO4: | ||
907 | return wm8350_clear_bits(wm8350, | ||
908 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
909 | WM8350_IM_UV_LDO4_EINT); | ||
910 | case WM8350_IRQ_UV_LDO3: | ||
911 | return wm8350_clear_bits(wm8350, | ||
912 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
913 | WM8350_IM_UV_LDO3_EINT); | ||
914 | case WM8350_IRQ_UV_LDO2: | ||
915 | return wm8350_clear_bits(wm8350, | ||
916 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
917 | WM8350_IM_UV_LDO2_EINT); | ||
918 | case WM8350_IRQ_UV_LDO1: | ||
919 | return wm8350_clear_bits(wm8350, | ||
920 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
921 | WM8350_IM_UV_LDO1_EINT); | ||
922 | case WM8350_IRQ_UV_DC6: | ||
923 | return wm8350_clear_bits(wm8350, | ||
924 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
925 | WM8350_IM_UV_DC6_EINT); | ||
926 | case WM8350_IRQ_UV_DC5: | ||
927 | return wm8350_clear_bits(wm8350, | ||
928 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
929 | WM8350_IM_UV_DC5_EINT); | ||
930 | case WM8350_IRQ_UV_DC4: | ||
931 | return wm8350_clear_bits(wm8350, | ||
932 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
933 | WM8350_IM_UV_DC4_EINT); | ||
934 | case WM8350_IRQ_UV_DC3: | ||
935 | return wm8350_clear_bits(wm8350, | ||
936 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
937 | WM8350_IM_UV_DC3_EINT); | ||
938 | case WM8350_IRQ_UV_DC2: | ||
939 | return wm8350_clear_bits(wm8350, | ||
940 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
941 | WM8350_IM_UV_DC2_EINT); | ||
942 | case WM8350_IRQ_UV_DC1: | ||
943 | return wm8350_clear_bits(wm8350, | ||
944 | WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, | ||
945 | WM8350_IM_UV_DC1_EINT); | ||
946 | case WM8350_IRQ_OC_LS: | ||
947 | return wm8350_clear_bits(wm8350, | ||
948 | WM8350_OVER_CURRENT_INT_STATUS_MASK, | ||
949 | WM8350_IM_OC_LS_EINT); | ||
950 | case WM8350_IRQ_EXT_USB_FB: | ||
951 | return wm8350_clear_bits(wm8350, | ||
952 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
953 | WM8350_IM_EXT_USB_FB_EINT); | ||
954 | case WM8350_IRQ_EXT_WALL_FB: | ||
955 | return wm8350_clear_bits(wm8350, | ||
956 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
957 | WM8350_IM_EXT_WALL_FB_EINT); | ||
958 | case WM8350_IRQ_EXT_BAT_FB: | ||
959 | return wm8350_clear_bits(wm8350, | ||
960 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
961 | WM8350_IM_EXT_BAT_FB_EINT); | ||
962 | case WM8350_IRQ_CODEC_JCK_DET_L: | ||
963 | return wm8350_clear_bits(wm8350, | ||
964 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
965 | WM8350_IM_CODEC_JCK_DET_L_EINT); | ||
966 | case WM8350_IRQ_CODEC_JCK_DET_R: | ||
967 | return wm8350_clear_bits(wm8350, | ||
968 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
969 | WM8350_IM_CODEC_JCK_DET_R_EINT); | ||
970 | case WM8350_IRQ_CODEC_MICSCD: | ||
971 | return wm8350_clear_bits(wm8350, | ||
972 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
973 | WM8350_IM_CODEC_MICSCD_EINT); | ||
974 | case WM8350_IRQ_CODEC_MICD: | ||
975 | return wm8350_clear_bits(wm8350, | ||
976 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
977 | WM8350_IM_CODEC_MICD_EINT); | ||
978 | case WM8350_IRQ_WKUP_OFF_STATE: | ||
979 | return wm8350_clear_bits(wm8350, | ||
980 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
981 | WM8350_IM_WKUP_OFF_STATE_EINT); | ||
982 | case WM8350_IRQ_WKUP_HIB_STATE: | ||
983 | return wm8350_clear_bits(wm8350, | ||
984 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
985 | WM8350_IM_WKUP_HIB_STATE_EINT); | ||
986 | case WM8350_IRQ_WKUP_CONV_FAULT: | ||
987 | return wm8350_clear_bits(wm8350, | ||
988 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
989 | WM8350_IM_WKUP_CONV_FAULT_EINT); | ||
990 | case WM8350_IRQ_WKUP_WDOG_RST: | ||
991 | return wm8350_clear_bits(wm8350, | ||
992 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
993 | WM8350_IM_WKUP_OFF_STATE_EINT); | ||
994 | case WM8350_IRQ_WKUP_GP_PWR_ON: | ||
995 | return wm8350_clear_bits(wm8350, | ||
996 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
997 | WM8350_IM_WKUP_GP_PWR_ON_EINT); | ||
998 | case WM8350_IRQ_WKUP_ONKEY: | ||
999 | return wm8350_clear_bits(wm8350, | ||
1000 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
1001 | WM8350_IM_WKUP_ONKEY_EINT); | ||
1002 | case WM8350_IRQ_WKUP_GP_WAKEUP: | ||
1003 | return wm8350_clear_bits(wm8350, | ||
1004 | WM8350_COMPARATOR_INT_STATUS_MASK, | ||
1005 | WM8350_IM_WKUP_GP_WAKEUP_EINT); | ||
1006 | case WM8350_IRQ_GPIO(0): | ||
1007 | return wm8350_clear_bits(wm8350, | ||
1008 | WM8350_GPIO_INT_STATUS_MASK, | ||
1009 | WM8350_IM_GP0_EINT); | ||
1010 | case WM8350_IRQ_GPIO(1): | ||
1011 | return wm8350_clear_bits(wm8350, | ||
1012 | WM8350_GPIO_INT_STATUS_MASK, | ||
1013 | WM8350_IM_GP1_EINT); | ||
1014 | case WM8350_IRQ_GPIO(2): | ||
1015 | return wm8350_clear_bits(wm8350, | ||
1016 | WM8350_GPIO_INT_STATUS_MASK, | ||
1017 | WM8350_IM_GP2_EINT); | ||
1018 | case WM8350_IRQ_GPIO(3): | ||
1019 | return wm8350_clear_bits(wm8350, | ||
1020 | WM8350_GPIO_INT_STATUS_MASK, | ||
1021 | WM8350_IM_GP3_EINT); | ||
1022 | case WM8350_IRQ_GPIO(4): | ||
1023 | return wm8350_clear_bits(wm8350, | ||
1024 | WM8350_GPIO_INT_STATUS_MASK, | ||
1025 | WM8350_IM_GP4_EINT); | ||
1026 | case WM8350_IRQ_GPIO(5): | ||
1027 | return wm8350_clear_bits(wm8350, | ||
1028 | WM8350_GPIO_INT_STATUS_MASK, | ||
1029 | WM8350_IM_GP5_EINT); | ||
1030 | case WM8350_IRQ_GPIO(6): | ||
1031 | return wm8350_clear_bits(wm8350, | ||
1032 | WM8350_GPIO_INT_STATUS_MASK, | ||
1033 | WM8350_IM_GP6_EINT); | ||
1034 | case WM8350_IRQ_GPIO(7): | ||
1035 | return wm8350_clear_bits(wm8350, | ||
1036 | WM8350_GPIO_INT_STATUS_MASK, | ||
1037 | WM8350_IM_GP7_EINT); | ||
1038 | case WM8350_IRQ_GPIO(8): | ||
1039 | return wm8350_clear_bits(wm8350, | ||
1040 | WM8350_GPIO_INT_STATUS_MASK, | ||
1041 | WM8350_IM_GP8_EINT); | ||
1042 | case WM8350_IRQ_GPIO(9): | ||
1043 | return wm8350_clear_bits(wm8350, | ||
1044 | WM8350_GPIO_INT_STATUS_MASK, | ||
1045 | WM8350_IM_GP9_EINT); | ||
1046 | case WM8350_IRQ_GPIO(10): | ||
1047 | return wm8350_clear_bits(wm8350, | ||
1048 | WM8350_GPIO_INT_STATUS_MASK, | ||
1049 | WM8350_IM_GP10_EINT); | ||
1050 | case WM8350_IRQ_GPIO(11): | ||
1051 | return wm8350_clear_bits(wm8350, | ||
1052 | WM8350_GPIO_INT_STATUS_MASK, | ||
1053 | WM8350_IM_GP11_EINT); | ||
1054 | case WM8350_IRQ_GPIO(12): | ||
1055 | return wm8350_clear_bits(wm8350, | ||
1056 | WM8350_GPIO_INT_STATUS_MASK, | ||
1057 | WM8350_IM_GP12_EINT); | ||
1058 | default: | ||
1059 | dev_warn(wm8350->dev, "Attempting to unmask unknown IRQ %d\n", | ||
1060 | irq); | ||
1061 | return -EINVAL; | ||
1062 | } | ||
1063 | return 0; | ||
1064 | } | ||
1065 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); | ||
1066 | |||
1067 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | 340 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) |
1068 | { | 341 | { |
1069 | u16 reg, result = 0; | 342 | u16 reg, result = 0; |
@@ -1264,7 +537,7 @@ static void wm8350_client_dev_register(struct wm8350 *wm8350, | |||
1264 | int ret; | 537 | int ret; |
1265 | 538 | ||
1266 | *pdev = platform_device_alloc(name, -1); | 539 | *pdev = platform_device_alloc(name, -1); |
1267 | if (pdev == NULL) { | 540 | if (*pdev == NULL) { |
1268 | dev_err(wm8350->dev, "Failed to allocate %s\n", name); | 541 | dev_err(wm8350->dev, "Failed to allocate %s\n", name); |
1269 | return; | 542 | return; |
1270 | } | 543 | } |
@@ -1409,49 +682,18 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
1409 | return ret; | 682 | return ret; |
1410 | } | 683 | } |
1411 | 684 | ||
1412 | wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); | ||
1413 | wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF); | ||
1414 | wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF); | ||
1415 | wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF); | ||
1416 | wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF); | ||
1417 | wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF); | ||
1418 | |||
1419 | mutex_init(&wm8350->auxadc_mutex); | 685 | mutex_init(&wm8350->auxadc_mutex); |
1420 | mutex_init(&wm8350->irq_mutex); | ||
1421 | if (irq) { | ||
1422 | int flags = IRQF_ONESHOT; | ||
1423 | |||
1424 | if (pdata && pdata->irq_high) { | ||
1425 | flags |= IRQF_TRIGGER_HIGH; | ||
1426 | |||
1427 | wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, | ||
1428 | WM8350_IRQ_POL); | ||
1429 | } else { | ||
1430 | flags |= IRQF_TRIGGER_LOW; | ||
1431 | |||
1432 | wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1, | ||
1433 | WM8350_IRQ_POL); | ||
1434 | } | ||
1435 | 686 | ||
1436 | ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, | 687 | ret = wm8350_irq_init(wm8350, irq, pdata); |
1437 | "wm8350", wm8350); | 688 | if (ret < 0) |
1438 | if (ret != 0) { | ||
1439 | dev_err(wm8350->dev, "Failed to request IRQ: %d\n", | ||
1440 | ret); | ||
1441 | goto err; | ||
1442 | } | ||
1443 | } else { | ||
1444 | dev_err(wm8350->dev, "No IRQ configured\n"); | ||
1445 | goto err; | 689 | goto err; |
1446 | } | ||
1447 | wm8350->chip_irq = irq; | ||
1448 | 690 | ||
1449 | if (pdata && pdata->init) { | 691 | if (pdata && pdata->init) { |
1450 | ret = pdata->init(wm8350); | 692 | ret = pdata->init(wm8350); |
1451 | if (ret != 0) { | 693 | if (ret != 0) { |
1452 | dev_err(wm8350->dev, "Platform init() failed: %d\n", | 694 | dev_err(wm8350->dev, "Platform init() failed: %d\n", |
1453 | ret); | 695 | ret); |
1454 | goto err; | 696 | goto err_irq; |
1455 | } | 697 | } |
1456 | } | 698 | } |
1457 | 699 | ||
@@ -1470,6 +712,8 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
1470 | 712 | ||
1471 | return 0; | 713 | return 0; |
1472 | 714 | ||
715 | err_irq: | ||
716 | wm8350_irq_exit(wm8350); | ||
1473 | err: | 717 | err: |
1474 | kfree(wm8350->reg_cache); | 718 | kfree(wm8350->reg_cache); |
1475 | return ret; | 719 | return ret; |
@@ -1493,7 +737,8 @@ void wm8350_device_exit(struct wm8350 *wm8350) | |||
1493 | platform_device_unregister(wm8350->gpio.pdev); | 737 | platform_device_unregister(wm8350->gpio.pdev); |
1494 | platform_device_unregister(wm8350->codec.pdev); | 738 | platform_device_unregister(wm8350->codec.pdev); |
1495 | 739 | ||
1496 | free_irq(wm8350->chip_irq, wm8350); | 740 | wm8350_irq_exit(wm8350); |
741 | |||
1497 | kfree(wm8350->reg_cache); | 742 | kfree(wm8350->reg_cache); |
1498 | } | 743 | } |
1499 | EXPORT_SYMBOL_GPL(wm8350_device_exit); | 744 | EXPORT_SYMBOL_GPL(wm8350_device_exit); |
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c new file mode 100644 index 000000000000..c8df547c4747 --- /dev/null +++ b/drivers/mfd/wm8350-irq.c | |||
@@ -0,0 +1,529 @@ | |||
1 | /* | ||
2 | * wm8350-irq.c -- IRQ support for Wolfson WM8350 | ||
3 | * | ||
4 | * Copyright 2007, 2008, 2009 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Liam Girdwood, Mark Brown | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/bug.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | |||
23 | #include <linux/mfd/wm8350/core.h> | ||
24 | #include <linux/mfd/wm8350/audio.h> | ||
25 | #include <linux/mfd/wm8350/comparator.h> | ||
26 | #include <linux/mfd/wm8350/gpio.h> | ||
27 | #include <linux/mfd/wm8350/pmic.h> | ||
28 | #include <linux/mfd/wm8350/rtc.h> | ||
29 | #include <linux/mfd/wm8350/supply.h> | ||
30 | #include <linux/mfd/wm8350/wdt.h> | ||
31 | |||
32 | #define WM8350_NUM_IRQ_REGS 7 | ||
33 | |||
34 | #define WM8350_INT_OFFSET_1 0 | ||
35 | #define WM8350_INT_OFFSET_2 1 | ||
36 | #define WM8350_POWER_UP_INT_OFFSET 2 | ||
37 | #define WM8350_UNDER_VOLTAGE_INT_OFFSET 3 | ||
38 | #define WM8350_OVER_CURRENT_INT_OFFSET 4 | ||
39 | #define WM8350_GPIO_INT_OFFSET 5 | ||
40 | #define WM8350_COMPARATOR_INT_OFFSET 6 | ||
41 | |||
42 | struct wm8350_irq_data { | ||
43 | int primary; | ||
44 | int reg; | ||
45 | int mask; | ||
46 | int primary_only; | ||
47 | }; | ||
48 | |||
49 | static struct wm8350_irq_data wm8350_irqs[] = { | ||
50 | [WM8350_IRQ_OC_LS] = { | ||
51 | .primary = WM8350_OC_INT, | ||
52 | .reg = WM8350_OVER_CURRENT_INT_OFFSET, | ||
53 | .mask = WM8350_OC_LS_EINT, | ||
54 | .primary_only = 1, | ||
55 | }, | ||
56 | [WM8350_IRQ_UV_DC1] = { | ||
57 | .primary = WM8350_UV_INT, | ||
58 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
59 | .mask = WM8350_UV_DC1_EINT, | ||
60 | }, | ||
61 | [WM8350_IRQ_UV_DC2] = { | ||
62 | .primary = WM8350_UV_INT, | ||
63 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
64 | .mask = WM8350_UV_DC2_EINT, | ||
65 | }, | ||
66 | [WM8350_IRQ_UV_DC3] = { | ||
67 | .primary = WM8350_UV_INT, | ||
68 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
69 | .mask = WM8350_UV_DC3_EINT, | ||
70 | }, | ||
71 | [WM8350_IRQ_UV_DC4] = { | ||
72 | .primary = WM8350_UV_INT, | ||
73 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
74 | .mask = WM8350_UV_DC4_EINT, | ||
75 | }, | ||
76 | [WM8350_IRQ_UV_DC5] = { | ||
77 | .primary = WM8350_UV_INT, | ||
78 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
79 | .mask = WM8350_UV_DC5_EINT, | ||
80 | }, | ||
81 | [WM8350_IRQ_UV_DC6] = { | ||
82 | .primary = WM8350_UV_INT, | ||
83 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
84 | .mask = WM8350_UV_DC6_EINT, | ||
85 | }, | ||
86 | [WM8350_IRQ_UV_LDO1] = { | ||
87 | .primary = WM8350_UV_INT, | ||
88 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
89 | .mask = WM8350_UV_LDO1_EINT, | ||
90 | }, | ||
91 | [WM8350_IRQ_UV_LDO2] = { | ||
92 | .primary = WM8350_UV_INT, | ||
93 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
94 | .mask = WM8350_UV_LDO2_EINT, | ||
95 | }, | ||
96 | [WM8350_IRQ_UV_LDO3] = { | ||
97 | .primary = WM8350_UV_INT, | ||
98 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
99 | .mask = WM8350_UV_LDO3_EINT, | ||
100 | }, | ||
101 | [WM8350_IRQ_UV_LDO4] = { | ||
102 | .primary = WM8350_UV_INT, | ||
103 | .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET, | ||
104 | .mask = WM8350_UV_LDO4_EINT, | ||
105 | }, | ||
106 | [WM8350_IRQ_CHG_BAT_HOT] = { | ||
107 | .primary = WM8350_CHG_INT, | ||
108 | .reg = WM8350_INT_OFFSET_1, | ||
109 | .mask = WM8350_CHG_BAT_HOT_EINT, | ||
110 | }, | ||
111 | [WM8350_IRQ_CHG_BAT_COLD] = { | ||
112 | .primary = WM8350_CHG_INT, | ||
113 | .reg = WM8350_INT_OFFSET_1, | ||
114 | .mask = WM8350_CHG_BAT_COLD_EINT, | ||
115 | }, | ||
116 | [WM8350_IRQ_CHG_BAT_FAIL] = { | ||
117 | .primary = WM8350_CHG_INT, | ||
118 | .reg = WM8350_INT_OFFSET_1, | ||
119 | .mask = WM8350_CHG_BAT_FAIL_EINT, | ||
120 | }, | ||
121 | [WM8350_IRQ_CHG_TO] = { | ||
122 | .primary = WM8350_CHG_INT, | ||
123 | .reg = WM8350_INT_OFFSET_1, | ||
124 | .mask = WM8350_CHG_TO_EINT, | ||
125 | }, | ||
126 | [WM8350_IRQ_CHG_END] = { | ||
127 | .primary = WM8350_CHG_INT, | ||
128 | .reg = WM8350_INT_OFFSET_1, | ||
129 | .mask = WM8350_CHG_END_EINT, | ||
130 | }, | ||
131 | [WM8350_IRQ_CHG_START] = { | ||
132 | .primary = WM8350_CHG_INT, | ||
133 | .reg = WM8350_INT_OFFSET_1, | ||
134 | .mask = WM8350_CHG_START_EINT, | ||
135 | }, | ||
136 | [WM8350_IRQ_CHG_FAST_RDY] = { | ||
137 | .primary = WM8350_CHG_INT, | ||
138 | .reg = WM8350_INT_OFFSET_1, | ||
139 | .mask = WM8350_CHG_FAST_RDY_EINT, | ||
140 | }, | ||
141 | [WM8350_IRQ_CHG_VBATT_LT_3P9] = { | ||
142 | .primary = WM8350_CHG_INT, | ||
143 | .reg = WM8350_INT_OFFSET_1, | ||
144 | .mask = WM8350_CHG_VBATT_LT_3P9_EINT, | ||
145 | }, | ||
146 | [WM8350_IRQ_CHG_VBATT_LT_3P1] = { | ||
147 | .primary = WM8350_CHG_INT, | ||
148 | .reg = WM8350_INT_OFFSET_1, | ||
149 | .mask = WM8350_CHG_VBATT_LT_3P1_EINT, | ||
150 | }, | ||
151 | [WM8350_IRQ_CHG_VBATT_LT_2P85] = { | ||
152 | .primary = WM8350_CHG_INT, | ||
153 | .reg = WM8350_INT_OFFSET_1, | ||
154 | .mask = WM8350_CHG_VBATT_LT_2P85_EINT, | ||
155 | }, | ||
156 | [WM8350_IRQ_RTC_ALM] = { | ||
157 | .primary = WM8350_RTC_INT, | ||
158 | .reg = WM8350_INT_OFFSET_1, | ||
159 | .mask = WM8350_RTC_ALM_EINT, | ||
160 | }, | ||
161 | [WM8350_IRQ_RTC_SEC] = { | ||
162 | .primary = WM8350_RTC_INT, | ||
163 | .reg = WM8350_INT_OFFSET_1, | ||
164 | .mask = WM8350_RTC_SEC_EINT, | ||
165 | }, | ||
166 | [WM8350_IRQ_RTC_PER] = { | ||
167 | .primary = WM8350_RTC_INT, | ||
168 | .reg = WM8350_INT_OFFSET_1, | ||
169 | .mask = WM8350_RTC_PER_EINT, | ||
170 | }, | ||
171 | [WM8350_IRQ_CS1] = { | ||
172 | .primary = WM8350_CS_INT, | ||
173 | .reg = WM8350_INT_OFFSET_2, | ||
174 | .mask = WM8350_CS1_EINT, | ||
175 | }, | ||
176 | [WM8350_IRQ_CS2] = { | ||
177 | .primary = WM8350_CS_INT, | ||
178 | .reg = WM8350_INT_OFFSET_2, | ||
179 | .mask = WM8350_CS2_EINT, | ||
180 | }, | ||
181 | [WM8350_IRQ_SYS_HYST_COMP_FAIL] = { | ||
182 | .primary = WM8350_SYS_INT, | ||
183 | .reg = WM8350_INT_OFFSET_2, | ||
184 | .mask = WM8350_SYS_HYST_COMP_FAIL_EINT, | ||
185 | }, | ||
186 | [WM8350_IRQ_SYS_CHIP_GT115] = { | ||
187 | .primary = WM8350_SYS_INT, | ||
188 | .reg = WM8350_INT_OFFSET_2, | ||
189 | .mask = WM8350_SYS_CHIP_GT115_EINT, | ||
190 | }, | ||
191 | [WM8350_IRQ_SYS_CHIP_GT140] = { | ||
192 | .primary = WM8350_SYS_INT, | ||
193 | .reg = WM8350_INT_OFFSET_2, | ||
194 | .mask = WM8350_SYS_CHIP_GT140_EINT, | ||
195 | }, | ||
196 | [WM8350_IRQ_SYS_WDOG_TO] = { | ||
197 | .primary = WM8350_SYS_INT, | ||
198 | .reg = WM8350_INT_OFFSET_2, | ||
199 | .mask = WM8350_SYS_WDOG_TO_EINT, | ||
200 | }, | ||
201 | [WM8350_IRQ_AUXADC_DATARDY] = { | ||
202 | .primary = WM8350_AUXADC_INT, | ||
203 | .reg = WM8350_INT_OFFSET_2, | ||
204 | .mask = WM8350_AUXADC_DATARDY_EINT, | ||
205 | }, | ||
206 | [WM8350_IRQ_AUXADC_DCOMP4] = { | ||
207 | .primary = WM8350_AUXADC_INT, | ||
208 | .reg = WM8350_INT_OFFSET_2, | ||
209 | .mask = WM8350_AUXADC_DCOMP4_EINT, | ||
210 | }, | ||
211 | [WM8350_IRQ_AUXADC_DCOMP3] = { | ||
212 | .primary = WM8350_AUXADC_INT, | ||
213 | .reg = WM8350_INT_OFFSET_2, | ||
214 | .mask = WM8350_AUXADC_DCOMP3_EINT, | ||
215 | }, | ||
216 | [WM8350_IRQ_AUXADC_DCOMP2] = { | ||
217 | .primary = WM8350_AUXADC_INT, | ||
218 | .reg = WM8350_INT_OFFSET_2, | ||
219 | .mask = WM8350_AUXADC_DCOMP2_EINT, | ||
220 | }, | ||
221 | [WM8350_IRQ_AUXADC_DCOMP1] = { | ||
222 | .primary = WM8350_AUXADC_INT, | ||
223 | .reg = WM8350_INT_OFFSET_2, | ||
224 | .mask = WM8350_AUXADC_DCOMP1_EINT, | ||
225 | }, | ||
226 | [WM8350_IRQ_USB_LIMIT] = { | ||
227 | .primary = WM8350_USB_INT, | ||
228 | .reg = WM8350_INT_OFFSET_2, | ||
229 | .mask = WM8350_USB_LIMIT_EINT, | ||
230 | .primary_only = 1, | ||
231 | }, | ||
232 | [WM8350_IRQ_WKUP_OFF_STATE] = { | ||
233 | .primary = WM8350_WKUP_INT, | ||
234 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
235 | .mask = WM8350_WKUP_OFF_STATE_EINT, | ||
236 | }, | ||
237 | [WM8350_IRQ_WKUP_HIB_STATE] = { | ||
238 | .primary = WM8350_WKUP_INT, | ||
239 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
240 | .mask = WM8350_WKUP_HIB_STATE_EINT, | ||
241 | }, | ||
242 | [WM8350_IRQ_WKUP_CONV_FAULT] = { | ||
243 | .primary = WM8350_WKUP_INT, | ||
244 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
245 | .mask = WM8350_WKUP_CONV_FAULT_EINT, | ||
246 | }, | ||
247 | [WM8350_IRQ_WKUP_WDOG_RST] = { | ||
248 | .primary = WM8350_WKUP_INT, | ||
249 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
250 | .mask = WM8350_WKUP_WDOG_RST_EINT, | ||
251 | }, | ||
252 | [WM8350_IRQ_WKUP_GP_PWR_ON] = { | ||
253 | .primary = WM8350_WKUP_INT, | ||
254 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
255 | .mask = WM8350_WKUP_GP_PWR_ON_EINT, | ||
256 | }, | ||
257 | [WM8350_IRQ_WKUP_ONKEY] = { | ||
258 | .primary = WM8350_WKUP_INT, | ||
259 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
260 | .mask = WM8350_WKUP_ONKEY_EINT, | ||
261 | }, | ||
262 | [WM8350_IRQ_WKUP_GP_WAKEUP] = { | ||
263 | .primary = WM8350_WKUP_INT, | ||
264 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
265 | .mask = WM8350_WKUP_GP_WAKEUP_EINT, | ||
266 | }, | ||
267 | [WM8350_IRQ_CODEC_JCK_DET_L] = { | ||
268 | .primary = WM8350_CODEC_INT, | ||
269 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
270 | .mask = WM8350_CODEC_JCK_DET_L_EINT, | ||
271 | }, | ||
272 | [WM8350_IRQ_CODEC_JCK_DET_R] = { | ||
273 | .primary = WM8350_CODEC_INT, | ||
274 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
275 | .mask = WM8350_CODEC_JCK_DET_R_EINT, | ||
276 | }, | ||
277 | [WM8350_IRQ_CODEC_MICSCD] = { | ||
278 | .primary = WM8350_CODEC_INT, | ||
279 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
280 | .mask = WM8350_CODEC_MICSCD_EINT, | ||
281 | }, | ||
282 | [WM8350_IRQ_CODEC_MICD] = { | ||
283 | .primary = WM8350_CODEC_INT, | ||
284 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
285 | .mask = WM8350_CODEC_MICD_EINT, | ||
286 | }, | ||
287 | [WM8350_IRQ_EXT_USB_FB] = { | ||
288 | .primary = WM8350_EXT_INT, | ||
289 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
290 | .mask = WM8350_EXT_USB_FB_EINT, | ||
291 | }, | ||
292 | [WM8350_IRQ_EXT_WALL_FB] = { | ||
293 | .primary = WM8350_EXT_INT, | ||
294 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
295 | .mask = WM8350_EXT_WALL_FB_EINT, | ||
296 | }, | ||
297 | [WM8350_IRQ_EXT_BAT_FB] = { | ||
298 | .primary = WM8350_EXT_INT, | ||
299 | .reg = WM8350_COMPARATOR_INT_OFFSET, | ||
300 | .mask = WM8350_EXT_BAT_FB_EINT, | ||
301 | }, | ||
302 | [WM8350_IRQ_GPIO(0)] = { | ||
303 | .primary = WM8350_GP_INT, | ||
304 | .reg = WM8350_GPIO_INT_OFFSET, | ||
305 | .mask = WM8350_GP0_EINT, | ||
306 | }, | ||
307 | [WM8350_IRQ_GPIO(1)] = { | ||
308 | .primary = WM8350_GP_INT, | ||
309 | .reg = WM8350_GPIO_INT_OFFSET, | ||
310 | .mask = WM8350_GP1_EINT, | ||
311 | }, | ||
312 | [WM8350_IRQ_GPIO(2)] = { | ||
313 | .primary = WM8350_GP_INT, | ||
314 | .reg = WM8350_GPIO_INT_OFFSET, | ||
315 | .mask = WM8350_GP2_EINT, | ||
316 | }, | ||
317 | [WM8350_IRQ_GPIO(3)] = { | ||
318 | .primary = WM8350_GP_INT, | ||
319 | .reg = WM8350_GPIO_INT_OFFSET, | ||
320 | .mask = WM8350_GP3_EINT, | ||
321 | }, | ||
322 | [WM8350_IRQ_GPIO(4)] = { | ||
323 | .primary = WM8350_GP_INT, | ||
324 | .reg = WM8350_GPIO_INT_OFFSET, | ||
325 | .mask = WM8350_GP4_EINT, | ||
326 | }, | ||
327 | [WM8350_IRQ_GPIO(5)] = { | ||
328 | .primary = WM8350_GP_INT, | ||
329 | .reg = WM8350_GPIO_INT_OFFSET, | ||
330 | .mask = WM8350_GP5_EINT, | ||
331 | }, | ||
332 | [WM8350_IRQ_GPIO(6)] = { | ||
333 | .primary = WM8350_GP_INT, | ||
334 | .reg = WM8350_GPIO_INT_OFFSET, | ||
335 | .mask = WM8350_GP6_EINT, | ||
336 | }, | ||
337 | [WM8350_IRQ_GPIO(7)] = { | ||
338 | .primary = WM8350_GP_INT, | ||
339 | .reg = WM8350_GPIO_INT_OFFSET, | ||
340 | .mask = WM8350_GP7_EINT, | ||
341 | }, | ||
342 | [WM8350_IRQ_GPIO(8)] = { | ||
343 | .primary = WM8350_GP_INT, | ||
344 | .reg = WM8350_GPIO_INT_OFFSET, | ||
345 | .mask = WM8350_GP8_EINT, | ||
346 | }, | ||
347 | [WM8350_IRQ_GPIO(9)] = { | ||
348 | .primary = WM8350_GP_INT, | ||
349 | .reg = WM8350_GPIO_INT_OFFSET, | ||
350 | .mask = WM8350_GP9_EINT, | ||
351 | }, | ||
352 | [WM8350_IRQ_GPIO(10)] = { | ||
353 | .primary = WM8350_GP_INT, | ||
354 | .reg = WM8350_GPIO_INT_OFFSET, | ||
355 | .mask = WM8350_GP10_EINT, | ||
356 | }, | ||
357 | [WM8350_IRQ_GPIO(11)] = { | ||
358 | .primary = WM8350_GP_INT, | ||
359 | .reg = WM8350_GPIO_INT_OFFSET, | ||
360 | .mask = WM8350_GP11_EINT, | ||
361 | }, | ||
362 | [WM8350_IRQ_GPIO(12)] = { | ||
363 | .primary = WM8350_GP_INT, | ||
364 | .reg = WM8350_GPIO_INT_OFFSET, | ||
365 | .mask = WM8350_GP12_EINT, | ||
366 | }, | ||
367 | }; | ||
368 | |||
369 | static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) | ||
370 | { | ||
371 | mutex_lock(&wm8350->irq_mutex); | ||
372 | |||
373 | if (wm8350->irq[irq].handler) | ||
374 | wm8350->irq[irq].handler(irq, wm8350->irq[irq].data); | ||
375 | else { | ||
376 | dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", | ||
377 | irq); | ||
378 | wm8350_mask_irq(wm8350, irq); | ||
379 | } | ||
380 | |||
381 | mutex_unlock(&wm8350->irq_mutex); | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * This is a threaded IRQ handler so can access I2C/SPI. Since all | ||
386 | * interrupts are clear on read the IRQ line will be reasserted and | ||
387 | * the physical IRQ will be handled again if another interrupt is | ||
388 | * asserted while we run - in the normal course of events this is a | ||
389 | * rare occurrence so we save I2C/SPI reads. | ||
390 | */ | ||
391 | static irqreturn_t wm8350_irq(int irq, void *irq_data) | ||
392 | { | ||
393 | struct wm8350 *wm8350 = irq_data; | ||
394 | u16 level_one; | ||
395 | u16 sub_reg[WM8350_NUM_IRQ_REGS]; | ||
396 | int read_done[WM8350_NUM_IRQ_REGS]; | ||
397 | struct wm8350_irq_data *data; | ||
398 | int i; | ||
399 | |||
400 | /* TODO: Use block reads to improve performance? */ | ||
401 | level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) | ||
402 | & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); | ||
403 | |||
404 | if (!level_one) | ||
405 | return IRQ_NONE; | ||
406 | |||
407 | memset(&read_done, 0, sizeof(read_done)); | ||
408 | |||
409 | for (i = 0; i < ARRAY_SIZE(wm8350_irqs); i++) { | ||
410 | data = &wm8350_irqs[i]; | ||
411 | |||
412 | if (!(level_one & data->primary)) | ||
413 | continue; | ||
414 | |||
415 | if (!read_done[data->reg]) { | ||
416 | sub_reg[data->reg] = | ||
417 | wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 + | ||
418 | data->reg); | ||
419 | sub_reg[data->reg] &= | ||
420 | ~wm8350_reg_read(wm8350, | ||
421 | WM8350_INT_STATUS_1_MASK + | ||
422 | data->reg); | ||
423 | read_done[data->reg] = 1; | ||
424 | } | ||
425 | |||
426 | if (sub_reg[data->reg] & data->mask) | ||
427 | wm8350_irq_call_handler(wm8350, i); | ||
428 | } | ||
429 | |||
430 | return IRQ_HANDLED; | ||
431 | } | ||
432 | |||
433 | int wm8350_register_irq(struct wm8350 *wm8350, int irq, | ||
434 | irq_handler_t handler, unsigned long flags, | ||
435 | const char *name, void *data) | ||
436 | { | ||
437 | if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) | ||
438 | return -EINVAL; | ||
439 | |||
440 | if (wm8350->irq[irq].handler) | ||
441 | return -EBUSY; | ||
442 | |||
443 | mutex_lock(&wm8350->irq_mutex); | ||
444 | wm8350->irq[irq].handler = handler; | ||
445 | wm8350->irq[irq].data = data; | ||
446 | mutex_unlock(&wm8350->irq_mutex); | ||
447 | |||
448 | wm8350_unmask_irq(wm8350, irq); | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | EXPORT_SYMBOL_GPL(wm8350_register_irq); | ||
453 | |||
454 | int wm8350_free_irq(struct wm8350 *wm8350, int irq) | ||
455 | { | ||
456 | if (irq < 0 || irq > WM8350_NUM_IRQ) | ||
457 | return -EINVAL; | ||
458 | |||
459 | wm8350_mask_irq(wm8350, irq); | ||
460 | |||
461 | mutex_lock(&wm8350->irq_mutex); | ||
462 | wm8350->irq[irq].handler = NULL; | ||
463 | mutex_unlock(&wm8350->irq_mutex); | ||
464 | return 0; | ||
465 | } | ||
466 | EXPORT_SYMBOL_GPL(wm8350_free_irq); | ||
467 | |||
468 | int wm8350_mask_irq(struct wm8350 *wm8350, int irq) | ||
469 | { | ||
470 | return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK + | ||
471 | wm8350_irqs[irq].reg, | ||
472 | wm8350_irqs[irq].mask); | ||
473 | } | ||
474 | EXPORT_SYMBOL_GPL(wm8350_mask_irq); | ||
475 | |||
476 | int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) | ||
477 | { | ||
478 | return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK + | ||
479 | wm8350_irqs[irq].reg, | ||
480 | wm8350_irqs[irq].mask); | ||
481 | } | ||
482 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); | ||
483 | |||
484 | int wm8350_irq_init(struct wm8350 *wm8350, int irq, | ||
485 | struct wm8350_platform_data *pdata) | ||
486 | { | ||
487 | int ret; | ||
488 | int flags = IRQF_ONESHOT; | ||
489 | |||
490 | if (!irq) { | ||
491 | dev_err(wm8350->dev, "No IRQ configured\n"); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); | ||
496 | wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF); | ||
497 | wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF); | ||
498 | wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF); | ||
499 | wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF); | ||
500 | wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF); | ||
501 | |||
502 | mutex_init(&wm8350->irq_mutex); | ||
503 | wm8350->chip_irq = irq; | ||
504 | |||
505 | if (pdata && pdata->irq_high) { | ||
506 | flags |= IRQF_TRIGGER_HIGH; | ||
507 | |||
508 | wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, | ||
509 | WM8350_IRQ_POL); | ||
510 | } else { | ||
511 | flags |= IRQF_TRIGGER_LOW; | ||
512 | |||
513 | wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1, | ||
514 | WM8350_IRQ_POL); | ||
515 | } | ||
516 | |||
517 | ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, | ||
518 | "wm8350", wm8350); | ||
519 | if (ret != 0) | ||
520 | dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret); | ||
521 | |||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | int wm8350_irq_exit(struct wm8350 *wm8350) | ||
526 | { | ||
527 | free_irq(wm8350->chip_irq, wm8350); | ||
528 | return 0; | ||
529 | } | ||
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index 7ccc1eab98ab..e965139e5cd5 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c | |||
@@ -3170,14 +3170,6 @@ const u16 wm8352_mode3_defaults[] = { | |||
3170 | }; | 3170 | }; |
3171 | #endif | 3171 | #endif |
3172 | 3172 | ||
3173 | /* The register defaults for the config mode used must be compiled in but | ||
3174 | * due to the impact on kernel size it is possible to disable | ||
3175 | */ | ||
3176 | #ifndef WM8350_HAVE_CONFIG_MODE | ||
3177 | #warning No WM8350 config modes supported - select at least one of the | ||
3178 | #warning MFD_WM8350_CONFIG_MODE_n options from the board driver. | ||
3179 | #endif | ||
3180 | |||
3181 | /* | 3173 | /* |
3182 | * Access masks. | 3174 | * Access masks. |
3183 | */ | 3175 | */ |
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index e8b278f71781..6a84a8eb8d7a 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c | |||
@@ -303,7 +303,6 @@ static const u8 mbc_irq_handlers[] = { | |||
303 | static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | 303 | static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) |
304 | { | 304 | { |
305 | struct pcf50633_mbc *mbc; | 305 | struct pcf50633_mbc *mbc; |
306 | struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; | ||
307 | int ret; | 306 | int ret; |
308 | int i; | 307 | int i; |
309 | u8 mbcs1; | 308 | u8 mbcs1; |
@@ -313,7 +312,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | |||
313 | return -ENOMEM; | 312 | return -ENOMEM; |
314 | 313 | ||
315 | platform_set_drvdata(pdev, mbc); | 314 | platform_set_drvdata(pdev, mbc); |
316 | mbc->pcf = pdata->pcf; | 315 | mbc->pcf = dev_to_pcf50633(pdev->dev.parent); |
317 | 316 | ||
318 | /* Set up IRQ handlers */ | 317 | /* Set up IRQ handlers */ |
319 | for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++) | 318 | for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++) |
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c index 28b0299c0043..ad4f071e1287 100644 --- a/drivers/power/wm8350_power.c +++ b/drivers/power/wm8350_power.c | |||
@@ -184,8 +184,9 @@ static ssize_t charger_state_show(struct device *dev, | |||
184 | 184 | ||
185 | static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL); | 185 | static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL); |
186 | 186 | ||
187 | static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) | 187 | static irqreturn_t wm8350_charger_handler(int irq, void *data) |
188 | { | 188 | { |
189 | struct wm8350 *wm8350 = data; | ||
189 | struct wm8350_power *power = &wm8350->power; | 190 | struct wm8350_power *power = &wm8350->power; |
190 | struct wm8350_charger_policy *policy = power->policy; | 191 | struct wm8350_charger_policy *policy = power->policy; |
191 | 192 | ||
@@ -238,6 +239,8 @@ static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) | |||
238 | default: | 239 | default: |
239 | dev_err(wm8350->dev, "Unknown interrupt %d\n", irq); | 240 | dev_err(wm8350->dev, "Unknown interrupt %d\n", irq); |
240 | } | 241 | } |
242 | |||
243 | return IRQ_HANDLED; | ||
241 | } | 244 | } |
242 | 245 | ||
243 | /********************************************************************* | 246 | /********************************************************************* |
@@ -387,73 +390,55 @@ static void wm8350_init_charger(struct wm8350 *wm8350) | |||
387 | { | 390 | { |
388 | /* register our interest in charger events */ | 391 | /* register our interest in charger events */ |
389 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, | 392 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, |
390 | wm8350_charger_handler, NULL); | 393 | wm8350_charger_handler, 0, "Battery hot", wm8350); |
391 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | ||
392 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, | 394 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, |
393 | wm8350_charger_handler, NULL); | 395 | wm8350_charger_handler, 0, "Battery cold", wm8350); |
394 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | ||
395 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, | 396 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, |
396 | wm8350_charger_handler, NULL); | 397 | wm8350_charger_handler, 0, "Battery fail", wm8350); |
397 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | ||
398 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, | 398 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, |
399 | wm8350_charger_handler, NULL); | 399 | wm8350_charger_handler, 0, |
400 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO); | 400 | "Charger timeout", wm8350); |
401 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, | 401 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, |
402 | wm8350_charger_handler, NULL); | 402 | wm8350_charger_handler, 0, |
403 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END); | 403 | "Charge end", wm8350); |
404 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, | 404 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, |
405 | wm8350_charger_handler, NULL); | 405 | wm8350_charger_handler, 0, |
406 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START); | 406 | "Charge start", wm8350); |
407 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, | 407 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, |
408 | wm8350_charger_handler, NULL); | 408 | wm8350_charger_handler, 0, |
409 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY); | 409 | "Fast charge ready", wm8350); |
410 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, | 410 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, |
411 | wm8350_charger_handler, NULL); | 411 | wm8350_charger_handler, 0, |
412 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | 412 | "Battery <3.9V", wm8350); |
413 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, | 413 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, |
414 | wm8350_charger_handler, NULL); | 414 | wm8350_charger_handler, 0, |
415 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | 415 | "Battery <3.1V", wm8350); |
416 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, | 416 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, |
417 | wm8350_charger_handler, NULL); | 417 | wm8350_charger_handler, 0, |
418 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | 418 | "Battery <2.85V", wm8350); |
419 | 419 | ||
420 | /* and supply change events */ | 420 | /* and supply change events */ |
421 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, | 421 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, |
422 | wm8350_charger_handler, NULL); | 422 | wm8350_charger_handler, 0, "USB", wm8350); |
423 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
424 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, | 423 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, |
425 | wm8350_charger_handler, NULL); | 424 | wm8350_charger_handler, 0, "Wall", wm8350); |
426 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | ||
427 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, | 425 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, |
428 | wm8350_charger_handler, NULL); | 426 | wm8350_charger_handler, 0, "Battery", wm8350); |
429 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
430 | } | 427 | } |
431 | 428 | ||
432 | static void free_charger_irq(struct wm8350 *wm8350) | 429 | static void free_charger_irq(struct wm8350 *wm8350) |
433 | { | 430 | { |
434 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | ||
435 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | 431 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); |
436 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | ||
437 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | 432 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); |
438 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | ||
439 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | 433 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); |
440 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO); | ||
441 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); | 434 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); |
442 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END); | ||
443 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); | 435 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); |
444 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START); | ||
445 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); | 436 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); |
446 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | ||
447 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | 437 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); |
448 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | ||
449 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | 438 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); |
450 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | ||
451 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | 439 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); |
452 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
453 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | 440 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); |
454 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | ||
455 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | 441 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); |
456 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
457 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | 442 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); |
458 | } | 443 | } |
459 | 444 | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bcbb161bde0b..7cfdd65bebb4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -70,7 +70,7 @@ config REGULATOR_MAX1586 | |||
70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. | 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. |
71 | 71 | ||
72 | config REGULATOR_TWL4030 | 72 | config REGULATOR_TWL4030 |
73 | bool "TI TWL4030/TWL5030/TPS695x0 PMIC" | 73 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
74 | depends on TWL4030_CORE | 74 | depends on TWL4030_CORE |
75 | help | 75 | help |
76 | This driver supports the voltage regulators provided by | 76 | This driver supports the voltage regulators provided by |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 4257a8683778..9ae3cc44e668 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o | |||
11 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | 11 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o |
12 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 12 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
13 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o | 13 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o |
14 | obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o | 14 | obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o |
15 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 15 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
16 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o | 16 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o |
17 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o | 17 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o |
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 0803ffe6236d..c8f41dc05b76 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c | |||
@@ -314,13 +314,15 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) | |||
314 | struct pcf50633 *pcf; | 314 | struct pcf50633 *pcf; |
315 | 315 | ||
316 | /* Already set by core driver */ | 316 | /* Already set by core driver */ |
317 | pcf = platform_get_drvdata(pdev); | 317 | pcf = dev_to_pcf50633(pdev->dev.parent); |
318 | 318 | ||
319 | rdev = regulator_register(®ulators[pdev->id], &pdev->dev, | 319 | rdev = regulator_register(®ulators[pdev->id], &pdev->dev, |
320 | pdev->dev.platform_data, pcf); | 320 | pdev->dev.platform_data, pcf); |
321 | if (IS_ERR(rdev)) | 321 | if (IS_ERR(rdev)) |
322 | return PTR_ERR(rdev); | 322 | return PTR_ERR(rdev); |
323 | 323 | ||
324 | platform_set_drvdata(pdev, rdev); | ||
325 | |||
324 | if (pcf->pdata->regulator_registered) | 326 | if (pcf->pdata->regulator_registered) |
325 | pcf->pdata->regulator_registered(pcf, pdev->id); | 327 | pcf->pdata->regulator_registered(pcf, pdev->id); |
326 | 328 | ||
@@ -331,6 +333,7 @@ static int __devexit pcf50633_regulator_remove(struct platform_device *pdev) | |||
331 | { | 333 | { |
332 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | 334 | struct regulator_dev *rdev = platform_get_drvdata(pdev); |
333 | 335 | ||
336 | platform_set_drvdata(pdev, NULL); | ||
334 | regulator_unregister(rdev); | 337 | regulator_unregister(rdev); |
335 | 338 | ||
336 | return 0; | 339 | return 0; |
diff --git a/drivers/regulator/twl4030-regulator.c b/drivers/regulator/twl-regulator.c index e2032fb60b55..7ea1c3a31081 100644 --- a/drivers/regulator/twl4030-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * twl4030-regulator.c -- support regulators in twl4030 family chips | 2 | * twl-regulator.c -- support regulators in twl4030/twl6030 family chips |
3 | * | 3 | * |
4 | * Copyright (C) 2008 David Brownell | 4 | * Copyright (C) 2008 David Brownell |
5 | * | 5 | * |
@@ -15,11 +15,11 @@ | |||
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/regulator/driver.h> | 16 | #include <linux/regulator/driver.h> |
17 | #include <linux/regulator/machine.h> | 17 | #include <linux/regulator/machine.h> |
18 | #include <linux/i2c/twl4030.h> | 18 | #include <linux/i2c/twl.h> |
19 | 19 | ||
20 | 20 | ||
21 | /* | 21 | /* |
22 | * The TWL4030/TW5030/TPS659x0 family chips include power management, a | 22 | * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a |
23 | * USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions | 23 | * USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions |
24 | * include an audio codec, battery charger, and more voltage regulators. | 24 | * include an audio codec, battery charger, and more voltage regulators. |
25 | * These chips are often used in OMAP-based systems. | 25 | * These chips are often used in OMAP-based systems. |
@@ -33,7 +33,7 @@ struct twlreg_info { | |||
33 | /* start of regulator's PM_RECEIVER control register bank */ | 33 | /* start of regulator's PM_RECEIVER control register bank */ |
34 | u8 base; | 34 | u8 base; |
35 | 35 | ||
36 | /* twl4030 resource ID, for resource control state machine */ | 36 | /* twl resource ID, for resource control state machine */ |
37 | u8 id; | 37 | u8 id; |
38 | 38 | ||
39 | /* voltage in mV = table[VSEL]; table_len must be a power-of-two */ | 39 | /* voltage in mV = table[VSEL]; table_len must be a power-of-two */ |
@@ -52,27 +52,38 @@ struct twlreg_info { | |||
52 | * The first three registers of all power resource banks help hardware to | 52 | * The first three registers of all power resource banks help hardware to |
53 | * manage the various resource groups. | 53 | * manage the various resource groups. |
54 | */ | 54 | */ |
55 | /* Common offset in TWL4030/6030 */ | ||
55 | #define VREG_GRP 0 | 56 | #define VREG_GRP 0 |
57 | /* TWL4030 register offsets */ | ||
56 | #define VREG_TYPE 1 | 58 | #define VREG_TYPE 1 |
57 | #define VREG_REMAP 2 | 59 | #define VREG_REMAP 2 |
58 | #define VREG_DEDICATED 3 /* LDO control */ | 60 | #define VREG_DEDICATED 3 /* LDO control */ |
59 | 61 | /* TWL6030 register offsets */ | |
62 | #define VREG_TRANS 1 | ||
63 | #define VREG_STATE 2 | ||
64 | #define VREG_VOLTAGE 3 | ||
65 | /* TWL6030 Misc register offsets */ | ||
66 | #define VREG_BC_ALL 1 | ||
67 | #define VREG_BC_REF 2 | ||
68 | #define VREG_BC_PROC 3 | ||
69 | #define VREG_BC_CLK_RST 4 | ||
60 | 70 | ||
61 | static inline int | 71 | static inline int |
62 | twl4030reg_read(struct twlreg_info *info, unsigned offset) | 72 | twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) |
63 | { | 73 | { |
64 | u8 value; | 74 | u8 value; |
65 | int status; | 75 | int status; |
66 | 76 | ||
67 | status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, | 77 | status = twl_i2c_read_u8(slave_subgp, |
68 | &value, info->base + offset); | 78 | &value, info->base + offset); |
69 | return (status < 0) ? status : value; | 79 | return (status < 0) ? status : value; |
70 | } | 80 | } |
71 | 81 | ||
72 | static inline int | 82 | static inline int |
73 | twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value) | 83 | twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, |
84 | u8 value) | ||
74 | { | 85 | { |
75 | return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | 86 | return twl_i2c_write_u8(slave_subgp, |
76 | value, info->base + offset); | 87 | value, info->base + offset); |
77 | } | 88 | } |
78 | 89 | ||
@@ -80,59 +91,79 @@ twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value) | |||
80 | 91 | ||
81 | /* generic power resource operations, which work on all regulators */ | 92 | /* generic power resource operations, which work on all regulators */ |
82 | 93 | ||
83 | static int twl4030reg_grp(struct regulator_dev *rdev) | 94 | static int twlreg_grp(struct regulator_dev *rdev) |
84 | { | 95 | { |
85 | return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP); | 96 | return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER, |
97 | VREG_GRP); | ||
86 | } | 98 | } |
87 | 99 | ||
88 | /* | 100 | /* |
89 | * Enable/disable regulators by joining/leaving the P1 (processor) group. | 101 | * Enable/disable regulators by joining/leaving the P1 (processor) group. |
90 | * We assume nobody else is updating the DEV_GRP registers. | 102 | * We assume nobody else is updating the DEV_GRP registers. |
91 | */ | 103 | */ |
92 | 104 | /* definition for 4030 family */ | |
93 | #define P3_GRP BIT(7) /* "peripherals" */ | 105 | #define P3_GRP_4030 BIT(7) /* "peripherals" */ |
94 | #define P2_GRP BIT(6) /* secondary processor, modem, etc */ | 106 | #define P2_GRP_4030 BIT(6) /* secondary processor, modem, etc */ |
95 | #define P1_GRP BIT(5) /* CPU/Linux */ | 107 | #define P1_GRP_4030 BIT(5) /* CPU/Linux */ |
96 | 108 | /* definition for 6030 family */ | |
97 | static int twl4030reg_is_enabled(struct regulator_dev *rdev) | 109 | #define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ |
110 | #define P2_GRP_6030 BIT(1) /* "peripherals" */ | ||
111 | #define P1_GRP_6030 BIT(0) /* CPU/Linux */ | ||
112 | |||
113 | static int twlreg_is_enabled(struct regulator_dev *rdev) | ||
98 | { | 114 | { |
99 | int state = twl4030reg_grp(rdev); | 115 | int state = twlreg_grp(rdev); |
100 | 116 | ||
101 | if (state < 0) | 117 | if (state < 0) |
102 | return state; | 118 | return state; |
103 | 119 | ||
104 | return (state & P1_GRP) != 0; | 120 | if (twl_class_is_4030()) |
121 | state &= P1_GRP_4030; | ||
122 | else | ||
123 | state &= P1_GRP_6030; | ||
124 | return state; | ||
105 | } | 125 | } |
106 | 126 | ||
107 | static int twl4030reg_enable(struct regulator_dev *rdev) | 127 | static int twlreg_enable(struct regulator_dev *rdev) |
108 | { | 128 | { |
109 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 129 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
110 | int grp; | 130 | int grp; |
111 | 131 | ||
112 | grp = twl4030reg_read(info, VREG_GRP); | 132 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
113 | if (grp < 0) | 133 | if (grp < 0) |
114 | return grp; | 134 | return grp; |
115 | 135 | ||
116 | grp |= P1_GRP; | 136 | if (twl_class_is_4030()) |
117 | return twl4030reg_write(info, VREG_GRP, grp); | 137 | grp |= P1_GRP_4030; |
138 | else | ||
139 | grp |= P1_GRP_6030; | ||
140 | |||
141 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
118 | } | 142 | } |
119 | 143 | ||
120 | static int twl4030reg_disable(struct regulator_dev *rdev) | 144 | static int twlreg_disable(struct regulator_dev *rdev) |
121 | { | 145 | { |
122 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 146 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
123 | int grp; | 147 | int grp; |
124 | 148 | ||
125 | grp = twl4030reg_read(info, VREG_GRP); | 149 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
126 | if (grp < 0) | 150 | if (grp < 0) |
127 | return grp; | 151 | return grp; |
128 | 152 | ||
129 | grp &= ~P1_GRP; | 153 | if (twl_class_is_4030()) |
130 | return twl4030reg_write(info, VREG_GRP, grp); | 154 | grp &= ~P1_GRP_4030; |
155 | else | ||
156 | grp &= ~P1_GRP_6030; | ||
157 | |||
158 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
131 | } | 159 | } |
132 | 160 | ||
133 | static int twl4030reg_get_status(struct regulator_dev *rdev) | 161 | static int twlreg_get_status(struct regulator_dev *rdev) |
134 | { | 162 | { |
135 | int state = twl4030reg_grp(rdev); | 163 | int state = twlreg_grp(rdev); |
164 | |||
165 | if (twl_class_is_6030()) | ||
166 | return 0; /* FIXME return for 6030 regulator */ | ||
136 | 167 | ||
137 | if (state < 0) | 168 | if (state < 0) |
138 | return state; | 169 | return state; |
@@ -146,12 +177,15 @@ static int twl4030reg_get_status(struct regulator_dev *rdev) | |||
146 | : REGULATOR_STATUS_STANDBY; | 177 | : REGULATOR_STATUS_STANDBY; |
147 | } | 178 | } |
148 | 179 | ||
149 | static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) | 180 | static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) |
150 | { | 181 | { |
151 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 182 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
152 | unsigned message; | 183 | unsigned message; |
153 | int status; | 184 | int status; |
154 | 185 | ||
186 | if (twl_class_is_6030()) | ||
187 | return 0; /* FIXME return for 6030 regulator */ | ||
188 | |||
155 | /* We can only set the mode through state machine commands... */ | 189 | /* We can only set the mode through state machine commands... */ |
156 | switch (mode) { | 190 | switch (mode) { |
157 | case REGULATOR_MODE_NORMAL: | 191 | case REGULATOR_MODE_NORMAL: |
@@ -165,18 +199,18 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
165 | } | 199 | } |
166 | 200 | ||
167 | /* Ensure the resource is associated with some group */ | 201 | /* Ensure the resource is associated with some group */ |
168 | status = twl4030reg_grp(rdev); | 202 | status = twlreg_grp(rdev); |
169 | if (status < 0) | 203 | if (status < 0) |
170 | return status; | 204 | return status; |
171 | if (!(status & (P3_GRP | P2_GRP | P1_GRP))) | 205 | if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) |
172 | return -EACCES; | 206 | return -EACCES; |
173 | 207 | ||
174 | status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, | 208 | status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, |
175 | message >> 8, 0x15 /* PB_WORD_MSB */ ); | 209 | message >> 8, 0x15 /* PB_WORD_MSB */ ); |
176 | if (status >= 0) | 210 | if (status >= 0) |
177 | return status; | 211 | return status; |
178 | 212 | ||
179 | return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, | 213 | return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, |
180 | message, 0x16 /* PB_WORD_LSB */ ); | 214 | message, 0x16 /* PB_WORD_LSB */ ); |
181 | } | 215 | } |
182 | 216 | ||
@@ -260,9 +294,31 @@ static const u16 VSIM_VSEL_table[] = { | |||
260 | static const u16 VDAC_VSEL_table[] = { | 294 | static const u16 VDAC_VSEL_table[] = { |
261 | 1200, 1300, 1800, 1800, | 295 | 1200, 1300, 1800, 1800, |
262 | }; | 296 | }; |
297 | static const u16 VAUX1_6030_VSEL_table[] = { | ||
298 | 1000, 1300, 1800, 2500, | ||
299 | 2800, 2900, 3000, 3000, | ||
300 | }; | ||
301 | static const u16 VAUX2_6030_VSEL_table[] = { | ||
302 | 1200, 1800, 2500, 2750, | ||
303 | 2800, 2800, 2800, 2800, | ||
304 | }; | ||
305 | static const u16 VAUX3_6030_VSEL_table[] = { | ||
306 | 1000, 1200, 1300, 1800, | ||
307 | 2500, 2800, 3000, 3000, | ||
308 | }; | ||
309 | static const u16 VMMC_VSEL_table[] = { | ||
310 | 1200, 1800, 2800, 2900, | ||
311 | 3000, 3000, 3000, 3000, | ||
312 | }; | ||
313 | static const u16 VPP_VSEL_table[] = { | ||
314 | 1800, 1900, 2000, 2100, | ||
315 | 2200, 2300, 2400, 2500, | ||
316 | }; | ||
317 | static const u16 VUSIM_VSEL_table[] = { | ||
318 | 1200, 1800, 2500, 2900, | ||
319 | }; | ||
263 | 320 | ||
264 | 321 | static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) | |
265 | static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) | ||
266 | { | 322 | { |
267 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 323 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
268 | int mV = info->table[index]; | 324 | int mV = info->table[index]; |
@@ -271,7 +327,7 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
271 | } | 327 | } |
272 | 328 | ||
273 | static int | 329 | static int |
274 | twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | 330 | twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) |
275 | { | 331 | { |
276 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 332 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
277 | int vsel; | 333 | int vsel; |
@@ -288,16 +344,18 @@ twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
288 | 344 | ||
289 | /* use the first in-range value */ | 345 | /* use the first in-range value */ |
290 | if (min_uV <= uV && uV <= max_uV) | 346 | if (min_uV <= uV && uV <= max_uV) |
291 | return twl4030reg_write(info, VREG_DEDICATED, vsel); | 347 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, |
348 | VREG_VOLTAGE, vsel); | ||
292 | } | 349 | } |
293 | 350 | ||
294 | return -EDOM; | 351 | return -EDOM; |
295 | } | 352 | } |
296 | 353 | ||
297 | static int twl4030ldo_get_voltage(struct regulator_dev *rdev) | 354 | static int twlldo_get_voltage(struct regulator_dev *rdev) |
298 | { | 355 | { |
299 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 356 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
300 | int vsel = twl4030reg_read(info, VREG_DEDICATED); | 357 | int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, |
358 | VREG_VOLTAGE); | ||
301 | 359 | ||
302 | if (vsel < 0) | 360 | if (vsel < 0) |
303 | return vsel; | 361 | return vsel; |
@@ -306,19 +364,19 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev) | |||
306 | return LDO_MV(info->table[vsel]) * 1000; | 364 | return LDO_MV(info->table[vsel]) * 1000; |
307 | } | 365 | } |
308 | 366 | ||
309 | static struct regulator_ops twl4030ldo_ops = { | 367 | static struct regulator_ops twlldo_ops = { |
310 | .list_voltage = twl4030ldo_list_voltage, | 368 | .list_voltage = twlldo_list_voltage, |
311 | 369 | ||
312 | .set_voltage = twl4030ldo_set_voltage, | 370 | .set_voltage = twlldo_set_voltage, |
313 | .get_voltage = twl4030ldo_get_voltage, | 371 | .get_voltage = twlldo_get_voltage, |
314 | 372 | ||
315 | .enable = twl4030reg_enable, | 373 | .enable = twlreg_enable, |
316 | .disable = twl4030reg_disable, | 374 | .disable = twlreg_disable, |
317 | .is_enabled = twl4030reg_is_enabled, | 375 | .is_enabled = twlreg_is_enabled, |
318 | 376 | ||
319 | .set_mode = twl4030reg_set_mode, | 377 | .set_mode = twlreg_set_mode, |
320 | 378 | ||
321 | .get_status = twl4030reg_get_status, | 379 | .get_status = twlreg_get_status, |
322 | }; | 380 | }; |
323 | 381 | ||
324 | /*----------------------------------------------------------------------*/ | 382 | /*----------------------------------------------------------------------*/ |
@@ -326,60 +384,69 @@ static struct regulator_ops twl4030ldo_ops = { | |||
326 | /* | 384 | /* |
327 | * Fixed voltage LDOs don't have a VSEL field to update. | 385 | * Fixed voltage LDOs don't have a VSEL field to update. |
328 | */ | 386 | */ |
329 | static int twl4030fixed_list_voltage(struct regulator_dev *rdev, unsigned index) | 387 | static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index) |
330 | { | 388 | { |
331 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 389 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
332 | 390 | ||
333 | return info->min_mV * 1000; | 391 | return info->min_mV * 1000; |
334 | } | 392 | } |
335 | 393 | ||
336 | static int twl4030fixed_get_voltage(struct regulator_dev *rdev) | 394 | static int twlfixed_get_voltage(struct regulator_dev *rdev) |
337 | { | 395 | { |
338 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 396 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
339 | 397 | ||
340 | return info->min_mV * 1000; | 398 | return info->min_mV * 1000; |
341 | } | 399 | } |
342 | 400 | ||
343 | static struct regulator_ops twl4030fixed_ops = { | 401 | static struct regulator_ops twlfixed_ops = { |
344 | .list_voltage = twl4030fixed_list_voltage, | 402 | .list_voltage = twlfixed_list_voltage, |
345 | 403 | ||
346 | .get_voltage = twl4030fixed_get_voltage, | 404 | .get_voltage = twlfixed_get_voltage, |
347 | 405 | ||
348 | .enable = twl4030reg_enable, | 406 | .enable = twlreg_enable, |
349 | .disable = twl4030reg_disable, | 407 | .disable = twlreg_disable, |
350 | .is_enabled = twl4030reg_is_enabled, | 408 | .is_enabled = twlreg_is_enabled, |
351 | 409 | ||
352 | .set_mode = twl4030reg_set_mode, | 410 | .set_mode = twlreg_set_mode, |
353 | 411 | ||
354 | .get_status = twl4030reg_get_status, | 412 | .get_status = twlreg_get_status, |
355 | }; | 413 | }; |
356 | 414 | ||
357 | /*----------------------------------------------------------------------*/ | 415 | /*----------------------------------------------------------------------*/ |
358 | 416 | ||
359 | #define TWL_ADJUSTABLE_LDO(label, offset, num) { \ | 417 | #define TWL4030_ADJUSTABLE_LDO(label, offset, num) \ |
418 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) | ||
419 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ | ||
420 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) | ||
421 | #define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ | ||
422 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) | ||
423 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ | ||
424 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) | ||
425 | |||
426 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ | ||
360 | .base = offset, \ | 427 | .base = offset, \ |
361 | .id = num, \ | 428 | .id = num, \ |
362 | .table_len = ARRAY_SIZE(label##_VSEL_table), \ | 429 | .table_len = ARRAY_SIZE(label##_VSEL_table), \ |
363 | .table = label##_VSEL_table, \ | 430 | .table = label##_VSEL_table, \ |
364 | .desc = { \ | 431 | .desc = { \ |
365 | .name = #label, \ | 432 | .name = #label, \ |
366 | .id = TWL4030_REG_##label, \ | 433 | .id = family##_REG_##label, \ |
367 | .n_voltages = ARRAY_SIZE(label##_VSEL_table), \ | 434 | .n_voltages = ARRAY_SIZE(label##_VSEL_table), \ |
368 | .ops = &twl4030ldo_ops, \ | 435 | .ops = &twlldo_ops, \ |
369 | .type = REGULATOR_VOLTAGE, \ | 436 | .type = REGULATOR_VOLTAGE, \ |
370 | .owner = THIS_MODULE, \ | 437 | .owner = THIS_MODULE, \ |
371 | }, \ | 438 | }, \ |
372 | } | 439 | } |
373 | 440 | ||
374 | #define TWL_FIXED_LDO(label, offset, mVolts, num) { \ | 441 | #define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \ |
375 | .base = offset, \ | 442 | .base = offset, \ |
376 | .id = num, \ | 443 | .id = num, \ |
377 | .min_mV = mVolts, \ | 444 | .min_mV = mVolts, \ |
378 | .desc = { \ | 445 | .desc = { \ |
379 | .name = #label, \ | 446 | .name = #label, \ |
380 | .id = TWL4030_REG_##label, \ | 447 | .id = family##_REG_##label, \ |
381 | .n_voltages = 1, \ | 448 | .n_voltages = 1, \ |
382 | .ops = &twl4030fixed_ops, \ | 449 | .ops = &twlfixed_ops, \ |
383 | .type = REGULATOR_VOLTAGE, \ | 450 | .type = REGULATOR_VOLTAGE, \ |
384 | .owner = THIS_MODULE, \ | 451 | .owner = THIS_MODULE, \ |
385 | }, \ | 452 | }, \ |
@@ -389,35 +456,47 @@ static struct regulator_ops twl4030fixed_ops = { | |||
389 | * We list regulators here if systems need some level of | 456 | * We list regulators here if systems need some level of |
390 | * software control over them after boot. | 457 | * software control over them after boot. |
391 | */ | 458 | */ |
392 | static struct twlreg_info twl4030_regs[] = { | 459 | static struct twlreg_info twl_regs[] = { |
393 | TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1), | 460 | TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1), |
394 | TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), | 461 | TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), |
395 | TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), | 462 | TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), |
396 | TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), | 463 | TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), |
397 | TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4), | 464 | TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4), |
398 | TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5), | 465 | TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5), |
399 | TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), | 466 | TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), |
400 | /* | 467 | /* |
401 | TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), | 468 | TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), |
402 | */ | 469 | */ |
403 | TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8), | 470 | TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8), |
404 | TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9), | 471 | TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9), |
405 | TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10), | 472 | TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10), |
406 | /* | 473 | /* |
407 | TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), | 474 | TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), |
408 | TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), | 475 | TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), |
409 | TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), | 476 | TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), |
410 | TWL_SMPS(VIO, 0x4b, 14), | 477 | TWL4030_SMPS(VIO, 0x4b, 14), |
411 | TWL_SMPS(VDD1, 0x55, 15), | 478 | TWL4030_SMPS(VDD1, 0x55, 15), |
412 | TWL_SMPS(VDD2, 0x63, 16), | 479 | TWL4030_SMPS(VDD2, 0x63, 16), |
413 | */ | 480 | */ |
414 | TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), | 481 | TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), |
415 | TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), | 482 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), |
416 | TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), | 483 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), |
417 | /* VUSBCP is managed *only* by the USB subchip */ | 484 | /* VUSBCP is managed *only* by the USB subchip */ |
485 | |||
486 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ | ||
487 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), | ||
488 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), | ||
489 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), | ||
490 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), | ||
491 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), | ||
492 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), | ||
493 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), | ||
494 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), | ||
495 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), | ||
496 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) | ||
418 | }; | 497 | }; |
419 | 498 | ||
420 | static int twl4030reg_probe(struct platform_device *pdev) | 499 | static int twlreg_probe(struct platform_device *pdev) |
421 | { | 500 | { |
422 | int i; | 501 | int i; |
423 | struct twlreg_info *info; | 502 | struct twlreg_info *info; |
@@ -425,10 +504,10 @@ static int twl4030reg_probe(struct platform_device *pdev) | |||
425 | struct regulation_constraints *c; | 504 | struct regulation_constraints *c; |
426 | struct regulator_dev *rdev; | 505 | struct regulator_dev *rdev; |
427 | 506 | ||
428 | for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) { | 507 | for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { |
429 | if (twl4030_regs[i].desc.id != pdev->id) | 508 | if (twl_regs[i].desc.id != pdev->id) |
430 | continue; | 509 | continue; |
431 | info = twl4030_regs + i; | 510 | info = twl_regs + i; |
432 | break; | 511 | break; |
433 | } | 512 | } |
434 | if (!info) | 513 | if (!info) |
@@ -466,35 +545,35 @@ static int twl4030reg_probe(struct platform_device *pdev) | |||
466 | return 0; | 545 | return 0; |
467 | } | 546 | } |
468 | 547 | ||
469 | static int __devexit twl4030reg_remove(struct platform_device *pdev) | 548 | static int __devexit twlreg_remove(struct platform_device *pdev) |
470 | { | 549 | { |
471 | regulator_unregister(platform_get_drvdata(pdev)); | 550 | regulator_unregister(platform_get_drvdata(pdev)); |
472 | return 0; | 551 | return 0; |
473 | } | 552 | } |
474 | 553 | ||
475 | MODULE_ALIAS("platform:twl4030_reg"); | 554 | MODULE_ALIAS("platform:twl_reg"); |
476 | 555 | ||
477 | static struct platform_driver twl4030reg_driver = { | 556 | static struct platform_driver twlreg_driver = { |
478 | .probe = twl4030reg_probe, | 557 | .probe = twlreg_probe, |
479 | .remove = __devexit_p(twl4030reg_remove), | 558 | .remove = __devexit_p(twlreg_remove), |
480 | /* NOTE: short name, to work around driver model truncation of | 559 | /* NOTE: short name, to work around driver model truncation of |
481 | * "twl4030_regulator.12" (and friends) to "twl4030_regulator.1". | 560 | * "twl_regulator.12" (and friends) to "twl_regulator.1". |
482 | */ | 561 | */ |
483 | .driver.name = "twl4030_reg", | 562 | .driver.name = "twl_reg", |
484 | .driver.owner = THIS_MODULE, | 563 | .driver.owner = THIS_MODULE, |
485 | }; | 564 | }; |
486 | 565 | ||
487 | static int __init twl4030reg_init(void) | 566 | static int __init twlreg_init(void) |
488 | { | 567 | { |
489 | return platform_driver_register(&twl4030reg_driver); | 568 | return platform_driver_register(&twlreg_driver); |
490 | } | 569 | } |
491 | subsys_initcall(twl4030reg_init); | 570 | subsys_initcall(twlreg_init); |
492 | 571 | ||
493 | static void __exit twl4030reg_exit(void) | 572 | static void __exit twlreg_exit(void) |
494 | { | 573 | { |
495 | platform_driver_unregister(&twl4030reg_driver); | 574 | platform_driver_unregister(&twlreg_driver); |
496 | } | 575 | } |
497 | module_exit(twl4030reg_exit) | 576 | module_exit(twlreg_exit) |
498 | 577 | ||
499 | MODULE_DESCRIPTION("TWL4030 regulator driver"); | 578 | MODULE_DESCRIPTION("TWL regulator driver"); |
500 | MODULE_LICENSE("GPL"); | 579 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 768bd0e5b48b..1bbff099a546 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
@@ -1330,9 +1330,10 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { | |||
1330 | }, | 1330 | }, |
1331 | }; | 1331 | }; |
1332 | 1332 | ||
1333 | static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data) | 1333 | static irqreturn_t pmic_uv_handler(int irq, void *data) |
1334 | { | 1334 | { |
1335 | struct regulator_dev *rdev = (struct regulator_dev *)data; | 1335 | struct regulator_dev *rdev = (struct regulator_dev *)data; |
1336 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | ||
1336 | 1337 | ||
1337 | mutex_lock(&rdev->mutex); | 1338 | mutex_lock(&rdev->mutex); |
1338 | if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) | 1339 | if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) |
@@ -1344,6 +1345,8 @@ static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data) | |||
1344 | REGULATOR_EVENT_UNDER_VOLTAGE, | 1345 | REGULATOR_EVENT_UNDER_VOLTAGE, |
1345 | wm8350); | 1346 | wm8350); |
1346 | mutex_unlock(&rdev->mutex); | 1347 | mutex_unlock(&rdev->mutex); |
1348 | |||
1349 | return IRQ_HANDLED; | ||
1347 | } | 1350 | } |
1348 | 1351 | ||
1349 | static int wm8350_regulator_probe(struct platform_device *pdev) | 1352 | static int wm8350_regulator_probe(struct platform_device *pdev) |
@@ -1388,7 +1391,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) | |||
1388 | 1391 | ||
1389 | /* register regulator IRQ */ | 1392 | /* register regulator IRQ */ |
1390 | ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq, | 1393 | ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq, |
1391 | pmic_uv_handler, rdev); | 1394 | pmic_uv_handler, 0, "UV", rdev); |
1392 | if (ret < 0) { | 1395 | if (ret < 0) { |
1393 | regulator_unregister(rdev); | 1396 | regulator_unregister(rdev); |
1394 | dev_err(&pdev->dev, "failed to register regulator %s IRQ\n", | 1397 | dev_err(&pdev->dev, "failed to register regulator %s IRQ\n", |
@@ -1396,8 +1399,6 @@ static int wm8350_regulator_probe(struct platform_device *pdev) | |||
1396 | return ret; | 1399 | return ret; |
1397 | } | 1400 | } |
1398 | 1401 | ||
1399 | wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq); | ||
1400 | |||
1401 | return 0; | 1402 | return 0; |
1402 | } | 1403 | } |
1403 | 1404 | ||
@@ -1406,7 +1407,6 @@ static int wm8350_regulator_remove(struct platform_device *pdev) | |||
1406 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | 1407 | struct regulator_dev *rdev = platform_get_drvdata(pdev); |
1407 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | 1408 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
1408 | 1409 | ||
1409 | wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq); | ||
1410 | wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); | 1410 | wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); |
1411 | 1411 | ||
1412 | regulator_unregister(rdev); | 1412 | regulator_unregister(rdev); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f2e1004d12c7..71fbd6e8edf7 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -258,14 +258,14 @@ config RTC_DRV_TWL92330 | |||
258 | the Menelaus driver; it's not separate module. | 258 | the Menelaus driver; it's not separate module. |
259 | 259 | ||
260 | config RTC_DRV_TWL4030 | 260 | config RTC_DRV_TWL4030 |
261 | tristate "TI TWL4030/TWL5030/TPS659x0" | 261 | tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" |
262 | depends on RTC_CLASS && TWL4030_CORE | 262 | depends on RTC_CLASS && TWL4030_CORE |
263 | help | 263 | help |
264 | If you say yes here you get support for the RTC on the | 264 | If you say yes here you get support for the RTC on the |
265 | TWL4030 family chips, used mostly with OMAP3 platforms. | 265 | TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. |
266 | 266 | ||
267 | This driver can also be built as a module. If so, the module | 267 | This driver can also be built as a module. If so, the module |
268 | will be called rtc-twl4030. | 268 | will be called rtc-twl. |
269 | 269 | ||
270 | config RTC_DRV_S35390A | 270 | config RTC_DRV_S35390A |
271 | tristate "Seiko Instruments S-35390A" | 271 | tristate "Seiko Instruments S-35390A" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index af1ba7ae2857..7da6efb3e953 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -80,7 +80,7 @@ obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | |||
80 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | 80 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o |
81 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | 81 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o |
82 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 82 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
83 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | 83 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
84 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 84 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
85 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 85 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
86 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 86 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 4c5d5d0c4cfc..9b74e9c9151c 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -277,16 +277,13 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
277 | 277 | ||
278 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | 278 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) |
279 | { | 279 | { |
280 | struct pcf50633_subdev_pdata *pdata; | ||
281 | struct pcf50633_rtc *rtc; | 280 | struct pcf50633_rtc *rtc; |
282 | 281 | ||
283 | |||
284 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 282 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
285 | if (!rtc) | 283 | if (!rtc) |
286 | return -ENOMEM; | 284 | return -ENOMEM; |
287 | 285 | ||
288 | pdata = pdev->dev.platform_data; | 286 | rtc->pcf = dev_to_pcf50633(pdev->dev.parent); |
289 | rtc->pcf = pdata->pcf; | ||
290 | platform_set_drvdata(pdev, rtc); | 287 | platform_set_drvdata(pdev, rtc); |
291 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, | 288 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, |
292 | &pcf50633_rtc_ops, THIS_MODULE); | 289 | &pcf50633_rtc_ops, THIS_MODULE); |
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl.c index 9c8c70c497dc..c6a83a2a722c 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * rtc-twl4030.c -- TWL4030 Real Time Clock interface | 2 | * rtc-twl.c -- TWL Real Time Clock interface |
3 | * | 3 | * |
4 | * Copyright (C) 2007 MontaVista Software, Inc | 4 | * Copyright (C) 2007 MontaVista Software, Inc |
5 | * Author: Alexandre Rusev <source@mvista.com> | 5 | * Author: Alexandre Rusev <source@mvista.com> |
@@ -28,33 +28,81 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | 30 | ||
31 | #include <linux/i2c/twl4030.h> | 31 | #include <linux/i2c/twl.h> |
32 | 32 | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * RTC block register offsets (use TWL_MODULE_RTC) | 35 | * RTC block register offsets (use TWL_MODULE_RTC) |
36 | */ | 36 | */ |
37 | #define REG_SECONDS_REG 0x00 | 37 | enum { |
38 | #define REG_MINUTES_REG 0x01 | 38 | REG_SECONDS_REG = 0, |
39 | #define REG_HOURS_REG 0x02 | 39 | REG_MINUTES_REG, |
40 | #define REG_DAYS_REG 0x03 | 40 | REG_HOURS_REG, |
41 | #define REG_MONTHS_REG 0x04 | 41 | REG_DAYS_REG, |
42 | #define REG_YEARS_REG 0x05 | 42 | REG_MONTHS_REG, |
43 | #define REG_WEEKS_REG 0x06 | 43 | REG_YEARS_REG, |
44 | 44 | REG_WEEKS_REG, | |
45 | #define REG_ALARM_SECONDS_REG 0x07 | 45 | |
46 | #define REG_ALARM_MINUTES_REG 0x08 | 46 | REG_ALARM_SECONDS_REG, |
47 | #define REG_ALARM_HOURS_REG 0x09 | 47 | REG_ALARM_MINUTES_REG, |
48 | #define REG_ALARM_DAYS_REG 0x0A | 48 | REG_ALARM_HOURS_REG, |
49 | #define REG_ALARM_MONTHS_REG 0x0B | 49 | REG_ALARM_DAYS_REG, |
50 | #define REG_ALARM_YEARS_REG 0x0C | 50 | REG_ALARM_MONTHS_REG, |
51 | 51 | REG_ALARM_YEARS_REG, | |
52 | #define REG_RTC_CTRL_REG 0x0D | 52 | |
53 | #define REG_RTC_STATUS_REG 0x0E | 53 | REG_RTC_CTRL_REG, |
54 | #define REG_RTC_INTERRUPTS_REG 0x0F | 54 | REG_RTC_STATUS_REG, |
55 | 55 | REG_RTC_INTERRUPTS_REG, | |
56 | #define REG_RTC_COMP_LSB_REG 0x10 | 56 | |
57 | #define REG_RTC_COMP_MSB_REG 0x11 | 57 | REG_RTC_COMP_LSB_REG, |
58 | REG_RTC_COMP_MSB_REG, | ||
59 | }; | ||
60 | const static u8 twl4030_rtc_reg_map[] = { | ||
61 | [REG_SECONDS_REG] = 0x00, | ||
62 | [REG_MINUTES_REG] = 0x01, | ||
63 | [REG_HOURS_REG] = 0x02, | ||
64 | [REG_DAYS_REG] = 0x03, | ||
65 | [REG_MONTHS_REG] = 0x04, | ||
66 | [REG_YEARS_REG] = 0x05, | ||
67 | [REG_WEEKS_REG] = 0x06, | ||
68 | |||
69 | [REG_ALARM_SECONDS_REG] = 0x07, | ||
70 | [REG_ALARM_MINUTES_REG] = 0x08, | ||
71 | [REG_ALARM_HOURS_REG] = 0x09, | ||
72 | [REG_ALARM_DAYS_REG] = 0x0A, | ||
73 | [REG_ALARM_MONTHS_REG] = 0x0B, | ||
74 | [REG_ALARM_YEARS_REG] = 0x0C, | ||
75 | |||
76 | [REG_RTC_CTRL_REG] = 0x0D, | ||
77 | [REG_RTC_STATUS_REG] = 0x0E, | ||
78 | [REG_RTC_INTERRUPTS_REG] = 0x0F, | ||
79 | |||
80 | [REG_RTC_COMP_LSB_REG] = 0x10, | ||
81 | [REG_RTC_COMP_MSB_REG] = 0x11, | ||
82 | }; | ||
83 | const static u8 twl6030_rtc_reg_map[] = { | ||
84 | [REG_SECONDS_REG] = 0x00, | ||
85 | [REG_MINUTES_REG] = 0x01, | ||
86 | [REG_HOURS_REG] = 0x02, | ||
87 | [REG_DAYS_REG] = 0x03, | ||
88 | [REG_MONTHS_REG] = 0x04, | ||
89 | [REG_YEARS_REG] = 0x05, | ||
90 | [REG_WEEKS_REG] = 0x06, | ||
91 | |||
92 | [REG_ALARM_SECONDS_REG] = 0x08, | ||
93 | [REG_ALARM_MINUTES_REG] = 0x09, | ||
94 | [REG_ALARM_HOURS_REG] = 0x0A, | ||
95 | [REG_ALARM_DAYS_REG] = 0x0B, | ||
96 | [REG_ALARM_MONTHS_REG] = 0x0C, | ||
97 | [REG_ALARM_YEARS_REG] = 0x0D, | ||
98 | |||
99 | [REG_RTC_CTRL_REG] = 0x10, | ||
100 | [REG_RTC_STATUS_REG] = 0x11, | ||
101 | [REG_RTC_INTERRUPTS_REG] = 0x12, | ||
102 | |||
103 | [REG_RTC_COMP_LSB_REG] = 0x13, | ||
104 | [REG_RTC_COMP_MSB_REG] = 0x14, | ||
105 | }; | ||
58 | 106 | ||
59 | /* RTC_CTRL_REG bitfields */ | 107 | /* RTC_CTRL_REG bitfields */ |
60 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 | 108 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 |
@@ -84,31 +132,32 @@ | |||
84 | #define ALL_TIME_REGS 6 | 132 | #define ALL_TIME_REGS 6 |
85 | 133 | ||
86 | /*----------------------------------------------------------------------*/ | 134 | /*----------------------------------------------------------------------*/ |
135 | static u8 *rtc_reg_map; | ||
87 | 136 | ||
88 | /* | 137 | /* |
89 | * Supports 1 byte read from TWL4030 RTC register. | 138 | * Supports 1 byte read from TWL RTC register. |
90 | */ | 139 | */ |
91 | static int twl4030_rtc_read_u8(u8 *data, u8 reg) | 140 | static int twl_rtc_read_u8(u8 *data, u8 reg) |
92 | { | 141 | { |
93 | int ret; | 142 | int ret; |
94 | 143 | ||
95 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); | 144 | ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
96 | if (ret < 0) | 145 | if (ret < 0) |
97 | pr_err("twl4030_rtc: Could not read TWL4030" | 146 | pr_err("twl_rtc: Could not read TWL" |
98 | "register %X - error %d\n", reg, ret); | 147 | "register %X - error %d\n", reg, ret); |
99 | return ret; | 148 | return ret; |
100 | } | 149 | } |
101 | 150 | ||
102 | /* | 151 | /* |
103 | * Supports 1 byte write to TWL4030 RTC registers. | 152 | * Supports 1 byte write to TWL RTC registers. |
104 | */ | 153 | */ |
105 | static int twl4030_rtc_write_u8(u8 data, u8 reg) | 154 | static int twl_rtc_write_u8(u8 data, u8 reg) |
106 | { | 155 | { |
107 | int ret; | 156 | int ret; |
108 | 157 | ||
109 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); | 158 | ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
110 | if (ret < 0) | 159 | if (ret < 0) |
111 | pr_err("twl4030_rtc: Could not write TWL4030" | 160 | pr_err("twl_rtc: Could not write TWL" |
112 | "register %X - error %d\n", reg, ret); | 161 | "register %X - error %d\n", reg, ret); |
113 | return ret; | 162 | return ret; |
114 | } | 163 | } |
@@ -129,7 +178,7 @@ static int set_rtc_irq_bit(unsigned char bit) | |||
129 | 178 | ||
130 | val = rtc_irq_bits | bit; | 179 | val = rtc_irq_bits | bit; |
131 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; | 180 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; |
132 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 181 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
133 | if (ret == 0) | 182 | if (ret == 0) |
134 | rtc_irq_bits = val; | 183 | rtc_irq_bits = val; |
135 | 184 | ||
@@ -145,14 +194,14 @@ static int mask_rtc_irq_bit(unsigned char bit) | |||
145 | int ret; | 194 | int ret; |
146 | 195 | ||
147 | val = rtc_irq_bits & ~bit; | 196 | val = rtc_irq_bits & ~bit; |
148 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 197 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
149 | if (ret == 0) | 198 | if (ret == 0) |
150 | rtc_irq_bits = val; | 199 | rtc_irq_bits = val; |
151 | 200 | ||
152 | return ret; | 201 | return ret; |
153 | } | 202 | } |
154 | 203 | ||
155 | static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | 204 | static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) |
156 | { | 205 | { |
157 | int ret; | 206 | int ret; |
158 | 207 | ||
@@ -164,7 +213,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | |||
164 | return ret; | 213 | return ret; |
165 | } | 214 | } |
166 | 215 | ||
167 | static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | 216 | static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) |
168 | { | 217 | { |
169 | int ret; | 218 | int ret; |
170 | 219 | ||
@@ -177,7 +226,7 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
177 | } | 226 | } |
178 | 227 | ||
179 | /* | 228 | /* |
180 | * Gets current TWL4030 RTC time and date parameters. | 229 | * Gets current TWL RTC time and date parameters. |
181 | * | 230 | * |
182 | * The RTC's time/alarm representation is not what gmtime(3) requires | 231 | * The RTC's time/alarm representation is not what gmtime(3) requires |
183 | * Linux to use: | 232 | * Linux to use: |
@@ -185,24 +234,24 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
185 | * - Months are 1..12 vs Linux 0-11 | 234 | * - Months are 1..12 vs Linux 0-11 |
186 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | 235 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) |
187 | */ | 236 | */ |
188 | static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | 237 | static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) |
189 | { | 238 | { |
190 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 239 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
191 | int ret; | 240 | int ret; |
192 | u8 save_control; | 241 | u8 save_control; |
193 | 242 | ||
194 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 243 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
195 | if (ret < 0) | 244 | if (ret < 0) |
196 | return ret; | 245 | return ret; |
197 | 246 | ||
198 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; | 247 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; |
199 | 248 | ||
200 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 249 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
201 | if (ret < 0) | 250 | if (ret < 0) |
202 | return ret; | 251 | return ret; |
203 | 252 | ||
204 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 253 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
205 | REG_SECONDS_REG, ALL_TIME_REGS); | 254 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
206 | 255 | ||
207 | if (ret < 0) { | 256 | if (ret < 0) { |
208 | dev_err(dev, "rtc_read_time error %d\n", ret); | 257 | dev_err(dev, "rtc_read_time error %d\n", ret); |
@@ -219,7 +268,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
219 | return ret; | 268 | return ret; |
220 | } | 269 | } |
221 | 270 | ||
222 | static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | 271 | static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) |
223 | { | 272 | { |
224 | unsigned char save_control; | 273 | unsigned char save_control; |
225 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 274 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
@@ -233,18 +282,18 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
233 | rtc_data[6] = bin2bcd(tm->tm_year - 100); | 282 | rtc_data[6] = bin2bcd(tm->tm_year - 100); |
234 | 283 | ||
235 | /* Stop RTC while updating the TC registers */ | 284 | /* Stop RTC while updating the TC registers */ |
236 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 285 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
237 | if (ret < 0) | 286 | if (ret < 0) |
238 | goto out; | 287 | goto out; |
239 | 288 | ||
240 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 289 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
241 | twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 290 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
242 | if (ret < 0) | 291 | if (ret < 0) |
243 | goto out; | 292 | goto out; |
244 | 293 | ||
245 | /* update all the time registers in one shot */ | 294 | /* update all the time registers in one shot */ |
246 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, | 295 | ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, |
247 | REG_SECONDS_REG, ALL_TIME_REGS); | 296 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
248 | if (ret < 0) { | 297 | if (ret < 0) { |
249 | dev_err(dev, "rtc_set_time error %d\n", ret); | 298 | dev_err(dev, "rtc_set_time error %d\n", ret); |
250 | goto out; | 299 | goto out; |
@@ -252,22 +301,22 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
252 | 301 | ||
253 | /* Start back RTC */ | 302 | /* Start back RTC */ |
254 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; | 303 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; |
255 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 304 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
256 | 305 | ||
257 | out: | 306 | out: |
258 | return ret; | 307 | return ret; |
259 | } | 308 | } |
260 | 309 | ||
261 | /* | 310 | /* |
262 | * Gets current TWL4030 RTC alarm time. | 311 | * Gets current TWL RTC alarm time. |
263 | */ | 312 | */ |
264 | static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | 313 | static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) |
265 | { | 314 | { |
266 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 315 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
267 | int ret; | 316 | int ret; |
268 | 317 | ||
269 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 318 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
270 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 319 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
271 | if (ret < 0) { | 320 | if (ret < 0) { |
272 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | 321 | dev_err(dev, "rtc_read_alarm error %d\n", ret); |
273 | return ret; | 322 | return ret; |
@@ -288,12 +337,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
288 | return ret; | 337 | return ret; |
289 | } | 338 | } |
290 | 339 | ||
291 | static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 340 | static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
292 | { | 341 | { |
293 | unsigned char alarm_data[ALL_TIME_REGS + 1]; | 342 | unsigned char alarm_data[ALL_TIME_REGS + 1]; |
294 | int ret; | 343 | int ret; |
295 | 344 | ||
296 | ret = twl4030_rtc_alarm_irq_enable(dev, 0); | 345 | ret = twl_rtc_alarm_irq_enable(dev, 0); |
297 | if (ret) | 346 | if (ret) |
298 | goto out; | 347 | goto out; |
299 | 348 | ||
@@ -305,20 +354,20 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
305 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); | 354 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); |
306 | 355 | ||
307 | /* update all the alarm registers in one shot */ | 356 | /* update all the alarm registers in one shot */ |
308 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, | 357 | ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, |
309 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 358 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
310 | if (ret) { | 359 | if (ret) { |
311 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | 360 | dev_err(dev, "rtc_set_alarm error %d\n", ret); |
312 | goto out; | 361 | goto out; |
313 | } | 362 | } |
314 | 363 | ||
315 | if (alm->enabled) | 364 | if (alm->enabled) |
316 | ret = twl4030_rtc_alarm_irq_enable(dev, 1); | 365 | ret = twl_rtc_alarm_irq_enable(dev, 1); |
317 | out: | 366 | out: |
318 | return ret; | 367 | return ret; |
319 | } | 368 | } |
320 | 369 | ||
321 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | 370 | static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) |
322 | { | 371 | { |
323 | unsigned long events = 0; | 372 | unsigned long events = 0; |
324 | int ret = IRQ_NONE; | 373 | int ret = IRQ_NONE; |
@@ -333,7 +382,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
333 | local_irq_enable(); | 382 | local_irq_enable(); |
334 | #endif | 383 | #endif |
335 | 384 | ||
336 | res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 385 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
337 | if (res) | 386 | if (res) |
338 | goto out; | 387 | goto out; |
339 | /* | 388 | /* |
@@ -347,26 +396,28 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
347 | else | 396 | else |
348 | events |= RTC_IRQF | RTC_UF; | 397 | events |= RTC_IRQF | RTC_UF; |
349 | 398 | ||
350 | res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, | 399 | res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, |
351 | REG_RTC_STATUS_REG); | 400 | REG_RTC_STATUS_REG); |
352 | if (res) | 401 | if (res) |
353 | goto out; | 402 | goto out; |
354 | 403 | ||
355 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 | 404 | if (twl_class_is_4030()) { |
356 | * needs 2 reads to clear the interrupt. One read is done in | 405 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 |
357 | * do_twl4030_pwrirq(). Doing the second read, to clear | 406 | * needs 2 reads to clear the interrupt. One read is done in |
358 | * the bit. | 407 | * do_twl_pwrirq(). Doing the second read, to clear |
359 | * | 408 | * the bit. |
360 | * FIXME the reason PWR_ISR1 needs an extra read is that | 409 | * |
361 | * RTC_IF retriggered until we cleared REG_ALARM_M above. | 410 | * FIXME the reason PWR_ISR1 needs an extra read is that |
362 | * But re-reading like this is a bad hack; by doing so we | 411 | * RTC_IF retriggered until we cleared REG_ALARM_M above. |
363 | * risk wrongly clearing status for some other IRQ (losing | 412 | * But re-reading like this is a bad hack; by doing so we |
364 | * the interrupt). Be smarter about handling RTC_UF ... | 413 | * risk wrongly clearing status for some other IRQ (losing |
365 | */ | 414 | * the interrupt). Be smarter about handling RTC_UF ... |
366 | res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, | 415 | */ |
416 | res = twl_i2c_read_u8(TWL4030_MODULE_INT, | ||
367 | &rd_reg, TWL4030_INT_PWR_ISR1); | 417 | &rd_reg, TWL4030_INT_PWR_ISR1); |
368 | if (res) | 418 | if (res) |
369 | goto out; | 419 | goto out; |
420 | } | ||
370 | 421 | ||
371 | /* Notify RTC core on event */ | 422 | /* Notify RTC core on event */ |
372 | rtc_update_irq(rtc, 1, events); | 423 | rtc_update_irq(rtc, 1, events); |
@@ -376,18 +427,18 @@ out: | |||
376 | return ret; | 427 | return ret; |
377 | } | 428 | } |
378 | 429 | ||
379 | static struct rtc_class_ops twl4030_rtc_ops = { | 430 | static struct rtc_class_ops twl_rtc_ops = { |
380 | .read_time = twl4030_rtc_read_time, | 431 | .read_time = twl_rtc_read_time, |
381 | .set_time = twl4030_rtc_set_time, | 432 | .set_time = twl_rtc_set_time, |
382 | .read_alarm = twl4030_rtc_read_alarm, | 433 | .read_alarm = twl_rtc_read_alarm, |
383 | .set_alarm = twl4030_rtc_set_alarm, | 434 | .set_alarm = twl_rtc_set_alarm, |
384 | .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, | 435 | .alarm_irq_enable = twl_rtc_alarm_irq_enable, |
385 | .update_irq_enable = twl4030_rtc_update_irq_enable, | 436 | .update_irq_enable = twl_rtc_update_irq_enable, |
386 | }; | 437 | }; |
387 | 438 | ||
388 | /*----------------------------------------------------------------------*/ | 439 | /*----------------------------------------------------------------------*/ |
389 | 440 | ||
390 | static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | 441 | static int __devinit twl_rtc_probe(struct platform_device *pdev) |
391 | { | 442 | { |
392 | struct rtc_device *rtc; | 443 | struct rtc_device *rtc; |
393 | int ret = 0; | 444 | int ret = 0; |
@@ -398,7 +449,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
398 | return -EINVAL; | 449 | return -EINVAL; |
399 | 450 | ||
400 | rtc = rtc_device_register(pdev->name, | 451 | rtc = rtc_device_register(pdev->name, |
401 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); | 452 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); |
402 | if (IS_ERR(rtc)) { | 453 | if (IS_ERR(rtc)) { |
403 | ret = PTR_ERR(rtc); | 454 | ret = PTR_ERR(rtc); |
404 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 455 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
@@ -409,7 +460,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
409 | 460 | ||
410 | platform_set_drvdata(pdev, rtc); | 461 | platform_set_drvdata(pdev, rtc); |
411 | 462 | ||
412 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 463 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
413 | if (ret < 0) | 464 | if (ret < 0) |
414 | goto out1; | 465 | goto out1; |
415 | 466 | ||
@@ -420,11 +471,11 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
420 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); | 471 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); |
421 | 472 | ||
422 | /* Clear RTC Power up reset and pending alarm interrupts */ | 473 | /* Clear RTC Power up reset and pending alarm interrupts */ |
423 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); | 474 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); |
424 | if (ret < 0) | 475 | if (ret < 0) |
425 | goto out1; | 476 | goto out1; |
426 | 477 | ||
427 | ret = request_irq(irq, twl4030_rtc_interrupt, | 478 | ret = request_irq(irq, twl_rtc_interrupt, |
428 | IRQF_TRIGGER_RISING, | 479 | IRQF_TRIGGER_RISING, |
429 | dev_name(&rtc->dev), rtc); | 480 | dev_name(&rtc->dev), rtc); |
430 | if (ret < 0) { | 481 | if (ret < 0) { |
@@ -432,21 +483,28 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
432 | goto out1; | 483 | goto out1; |
433 | } | 484 | } |
434 | 485 | ||
486 | if (twl_class_is_6030()) { | ||
487 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
488 | REG_INT_MSK_LINE_A); | ||
489 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
490 | REG_INT_MSK_STS_A); | ||
491 | } | ||
492 | |||
435 | /* Check RTC module status, Enable if it is off */ | 493 | /* Check RTC module status, Enable if it is off */ |
436 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | 494 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); |
437 | if (ret < 0) | 495 | if (ret < 0) |
438 | goto out2; | 496 | goto out2; |
439 | 497 | ||
440 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | 498 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { |
441 | dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); | 499 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); |
442 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | 500 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; |
443 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | 501 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); |
444 | if (ret < 0) | 502 | if (ret < 0) |
445 | goto out2; | 503 | goto out2; |
446 | } | 504 | } |
447 | 505 | ||
448 | /* init cached IRQ enable bits */ | 506 | /* init cached IRQ enable bits */ |
449 | ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 507 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
450 | if (ret < 0) | 508 | if (ret < 0) |
451 | goto out2; | 509 | goto out2; |
452 | 510 | ||
@@ -461,10 +519,10 @@ out0: | |||
461 | } | 519 | } |
462 | 520 | ||
463 | /* | 521 | /* |
464 | * Disable all TWL4030 RTC module interrupts. | 522 | * Disable all TWL RTC module interrupts. |
465 | * Sets status flag to free. | 523 | * Sets status flag to free. |
466 | */ | 524 | */ |
467 | static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | 525 | static int __devexit twl_rtc_remove(struct platform_device *pdev) |
468 | { | 526 | { |
469 | /* leave rtc running, but disable irqs */ | 527 | /* leave rtc running, but disable irqs */ |
470 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 528 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
@@ -472,6 +530,13 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
472 | 530 | ||
473 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | 531 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); |
474 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | 532 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); |
533 | if (twl_class_is_6030()) { | ||
534 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
535 | REG_INT_MSK_LINE_A); | ||
536 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
537 | REG_INT_MSK_STS_A); | ||
538 | } | ||
539 | |||
475 | 540 | ||
476 | free_irq(irq, rtc); | 541 | free_irq(irq, rtc); |
477 | 542 | ||
@@ -480,7 +545,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
480 | return 0; | 545 | return 0; |
481 | } | 546 | } |
482 | 547 | ||
483 | static void twl4030_rtc_shutdown(struct platform_device *pdev) | 548 | static void twl_rtc_shutdown(struct platform_device *pdev) |
484 | { | 549 | { |
485 | /* mask timer interrupts, but leave alarm interrupts on to enable | 550 | /* mask timer interrupts, but leave alarm interrupts on to enable |
486 | power-on when alarm is triggered */ | 551 | power-on when alarm is triggered */ |
@@ -491,7 +556,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev) | |||
491 | 556 | ||
492 | static unsigned char irqstat; | 557 | static unsigned char irqstat; |
493 | 558 | ||
494 | static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 559 | static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
495 | { | 560 | { |
496 | irqstat = rtc_irq_bits; | 561 | irqstat = rtc_irq_bits; |
497 | 562 | ||
@@ -499,42 +564,47 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
499 | return 0; | 564 | return 0; |
500 | } | 565 | } |
501 | 566 | ||
502 | static int twl4030_rtc_resume(struct platform_device *pdev) | 567 | static int twl_rtc_resume(struct platform_device *pdev) |
503 | { | 568 | { |
504 | set_rtc_irq_bit(irqstat); | 569 | set_rtc_irq_bit(irqstat); |
505 | return 0; | 570 | return 0; |
506 | } | 571 | } |
507 | 572 | ||
508 | #else | 573 | #else |
509 | #define twl4030_rtc_suspend NULL | 574 | #define twl_rtc_suspend NULL |
510 | #define twl4030_rtc_resume NULL | 575 | #define twl_rtc_resume NULL |
511 | #endif | 576 | #endif |
512 | 577 | ||
513 | MODULE_ALIAS("platform:twl4030_rtc"); | 578 | MODULE_ALIAS("platform:twl_rtc"); |
514 | 579 | ||
515 | static struct platform_driver twl4030rtc_driver = { | 580 | static struct platform_driver twl4030rtc_driver = { |
516 | .probe = twl4030_rtc_probe, | 581 | .probe = twl_rtc_probe, |
517 | .remove = __devexit_p(twl4030_rtc_remove), | 582 | .remove = __devexit_p(twl_rtc_remove), |
518 | .shutdown = twl4030_rtc_shutdown, | 583 | .shutdown = twl_rtc_shutdown, |
519 | .suspend = twl4030_rtc_suspend, | 584 | .suspend = twl_rtc_suspend, |
520 | .resume = twl4030_rtc_resume, | 585 | .resume = twl_rtc_resume, |
521 | .driver = { | 586 | .driver = { |
522 | .owner = THIS_MODULE, | 587 | .owner = THIS_MODULE, |
523 | .name = "twl4030_rtc", | 588 | .name = "twl_rtc", |
524 | }, | 589 | }, |
525 | }; | 590 | }; |
526 | 591 | ||
527 | static int __init twl4030_rtc_init(void) | 592 | static int __init twl_rtc_init(void) |
528 | { | 593 | { |
594 | if (twl_class_is_4030()) | ||
595 | rtc_reg_map = (u8 *) twl4030_rtc_reg_map; | ||
596 | else | ||
597 | rtc_reg_map = (u8 *) twl6030_rtc_reg_map; | ||
598 | |||
529 | return platform_driver_register(&twl4030rtc_driver); | 599 | return platform_driver_register(&twl4030rtc_driver); |
530 | } | 600 | } |
531 | module_init(twl4030_rtc_init); | 601 | module_init(twl_rtc_init); |
532 | 602 | ||
533 | static void __exit twl4030_rtc_exit(void) | 603 | static void __exit twl_rtc_exit(void) |
534 | { | 604 | { |
535 | platform_driver_unregister(&twl4030rtc_driver); | 605 | platform_driver_unregister(&twl4030rtc_driver); |
536 | } | 606 | } |
537 | module_exit(twl4030_rtc_exit); | 607 | module_exit(twl_rtc_exit); |
538 | 608 | ||
539 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); | 609 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); |
540 | MODULE_LICENSE("GPL"); | 610 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c91edc572eb6..f16486635a8e 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -315,9 +315,9 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, | |||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | 318 | static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data) |
319 | void *data) | ||
320 | { | 319 | { |
320 | struct wm8350 *wm8350 = data; | ||
321 | struct rtc_device *rtc = wm8350->rtc.rtc; | 321 | struct rtc_device *rtc = wm8350->rtc.rtc; |
322 | int ret; | 322 | int ret; |
323 | 323 | ||
@@ -330,14 +330,18 @@ static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | |||
330 | dev_err(&(wm8350->rtc.pdev->dev), | 330 | dev_err(&(wm8350->rtc.pdev->dev), |
331 | "Failed to disable alarm: %d\n", ret); | 331 | "Failed to disable alarm: %d\n", ret); |
332 | } | 332 | } |
333 | |||
334 | return IRQ_HANDLED; | ||
333 | } | 335 | } |
334 | 336 | ||
335 | static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | 337 | static irqreturn_t wm8350_rtc_update_handler(int irq, void *data) |
336 | void *data) | ||
337 | { | 338 | { |
339 | struct wm8350 *wm8350 = data; | ||
338 | struct rtc_device *rtc = wm8350->rtc.rtc; | 340 | struct rtc_device *rtc = wm8350->rtc.rtc; |
339 | 341 | ||
340 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); | 342 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); |
343 | |||
344 | return IRQ_HANDLED; | ||
341 | } | 345 | } |
342 | 346 | ||
343 | static const struct rtc_class_ops wm8350_rtc_ops = { | 347 | static const struct rtc_class_ops wm8350_rtc_ops = { |
@@ -455,15 +459,14 @@ static int wm8350_rtc_probe(struct platform_device *pdev) | |||
455 | return ret; | 459 | return ret; |
456 | } | 460 | } |
457 | 461 | ||
458 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
459 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); | ||
460 | |||
461 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, | 462 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, |
462 | wm8350_rtc_update_handler, NULL); | 463 | wm8350_rtc_update_handler, 0, |
464 | "RTC Seconds", wm8350); | ||
465 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
463 | 466 | ||
464 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, | 467 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, |
465 | wm8350_rtc_alarm_handler, NULL); | 468 | wm8350_rtc_alarm_handler, 0, |
466 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); | 469 | "RTC Alarm", wm8350); |
467 | 470 | ||
468 | return 0; | 471 | return 0; |
469 | } | 472 | } |
@@ -473,8 +476,6 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
473 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 476 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
474 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | 477 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; |
475 | 478 | ||
476 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
477 | |||
478 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | 479 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); |
479 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | 480 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); |
480 | 481 | ||
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index bd9883f41e63..2be9f2fa41f9 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/usb/otg.h> | 35 | #include <linux/usb/otg.h> |
36 | #include <linux/i2c/twl4030.h> | 36 | #include <linux/i2c/twl.h> |
37 | #include <linux/regulator/consumer.h> | 37 | #include <linux/regulator/consumer.h> |
38 | #include <linux/err.h> | 38 | #include <linux/err.h> |
39 | 39 | ||
@@ -276,16 +276,16 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, | |||
276 | { | 276 | { |
277 | u8 check; | 277 | u8 check; |
278 | 278 | ||
279 | if ((twl4030_i2c_write_u8(module, data, address) >= 0) && | 279 | if ((twl_i2c_write_u8(module, data, address) >= 0) && |
280 | (twl4030_i2c_read_u8(module, &check, address) >= 0) && | 280 | (twl_i2c_read_u8(module, &check, address) >= 0) && |
281 | (check == data)) | 281 | (check == data)) |
282 | return 0; | 282 | return 0; |
283 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", | 283 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", |
284 | 1, module, address, check, data); | 284 | 1, module, address, check, data); |
285 | 285 | ||
286 | /* Failed once: Try again */ | 286 | /* Failed once: Try again */ |
287 | if ((twl4030_i2c_write_u8(module, data, address) >= 0) && | 287 | if ((twl_i2c_write_u8(module, data, address) >= 0) && |
288 | (twl4030_i2c_read_u8(module, &check, address) >= 0) && | 288 | (twl_i2c_read_u8(module, &check, address) >= 0) && |
289 | (check == data)) | 289 | (check == data)) |
290 | return 0; | 290 | return 0; |
291 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", | 291 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", |
@@ -303,7 +303,7 @@ static inline int twl4030_usb_write(struct twl4030_usb *twl, | |||
303 | { | 303 | { |
304 | int ret = 0; | 304 | int ret = 0; |
305 | 305 | ||
306 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address); | 306 | ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address); |
307 | if (ret < 0) | 307 | if (ret < 0) |
308 | dev_dbg(twl->dev, | 308 | dev_dbg(twl->dev, |
309 | "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); | 309 | "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); |
@@ -315,7 +315,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address) | |||
315 | u8 data; | 315 | u8 data; |
316 | int ret = 0; | 316 | int ret = 0; |
317 | 317 | ||
318 | ret = twl4030_i2c_read_u8(module, &data, address); | 318 | ret = twl_i2c_read_u8(module, &data, address); |
319 | if (ret >= 0) | 319 | if (ret >= 0) |
320 | ret = data; | 320 | ret = data; |
321 | else | 321 | else |
@@ -462,7 +462,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) | |||
462 | * SLEEP. We work around this by clearing the bit after usv3v1 | 462 | * SLEEP. We work around this by clearing the bit after usv3v1 |
463 | * is re-activated. This ensures that VUSB3V1 is really active. | 463 | * is re-activated. This ensures that VUSB3V1 is really active. |
464 | */ | 464 | */ |
465 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, | 465 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, |
466 | VUSB_DEDICATED2); | 466 | VUSB_DEDICATED2); |
467 | regulator_enable(twl->usb1v5); | 467 | regulator_enable(twl->usb1v5); |
468 | pwr &= ~PHY_PWR_PHYPWD; | 468 | pwr &= ~PHY_PWR_PHYPWD; |
@@ -505,44 +505,44 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) | |||
505 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | 505 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) |
506 | { | 506 | { |
507 | /* Enable writing to power configuration registers */ | 507 | /* Enable writing to power configuration registers */ |
508 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | 508 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); |
509 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); | 509 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); |
510 | 510 | ||
511 | /* put VUSB3V1 LDO in active state */ | 511 | /* put VUSB3V1 LDO in active state */ |
512 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); | 512 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); |
513 | 513 | ||
514 | /* input to VUSB3V1 LDO is from VBAT, not VBUS */ | 514 | /* input to VUSB3V1 LDO is from VBAT, not VBUS */ |
515 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); | 515 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); |
516 | 516 | ||
517 | /* Initialize 3.1V regulator */ | 517 | /* Initialize 3.1V regulator */ |
518 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); | 518 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); |
519 | 519 | ||
520 | twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); | 520 | twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); |
521 | if (IS_ERR(twl->usb3v1)) | 521 | if (IS_ERR(twl->usb3v1)) |
522 | return -ENODEV; | 522 | return -ENODEV; |
523 | 523 | ||
524 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); | 524 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); |
525 | 525 | ||
526 | /* Initialize 1.5V regulator */ | 526 | /* Initialize 1.5V regulator */ |
527 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); | 527 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); |
528 | 528 | ||
529 | twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); | 529 | twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); |
530 | if (IS_ERR(twl->usb1v5)) | 530 | if (IS_ERR(twl->usb1v5)) |
531 | goto fail1; | 531 | goto fail1; |
532 | 532 | ||
533 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); | 533 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); |
534 | 534 | ||
535 | /* Initialize 1.8V regulator */ | 535 | /* Initialize 1.8V regulator */ |
536 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); | 536 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); |
537 | 537 | ||
538 | twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); | 538 | twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); |
539 | if (IS_ERR(twl->usb1v8)) | 539 | if (IS_ERR(twl->usb1v8)) |
540 | goto fail2; | 540 | goto fail2; |
541 | 541 | ||
542 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | 542 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); |
543 | 543 | ||
544 | /* disable access to power configuration registers */ | 544 | /* disable access to power configuration registers */ |
545 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | 545 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); |
546 | 546 | ||
547 | return 0; | 547 | return 0; |
548 | 548 | ||
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index ad05da5ba3c7..4c10edecfb66 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | struct adp5520_bl { | 16 | struct adp5520_bl { |
17 | struct device *master; | 17 | struct device *master; |
18 | struct adp5520_backlight_platfrom_data *pdata; | 18 | struct adp5520_backlight_platform_data *pdata; |
19 | struct mutex lock; | 19 | struct mutex lock; |
20 | unsigned long cached_daylight_max; | 20 | unsigned long cached_daylight_max; |
21 | int id; | 21 | int id; |
@@ -31,29 +31,30 @@ static int adp5520_bl_set(struct backlight_device *bl, int brightness) | |||
31 | if (data->pdata->en_ambl_sens) { | 31 | if (data->pdata->en_ambl_sens) { |
32 | if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { | 32 | if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { |
33 | /* Disable Ambient Light auto adjust */ | 33 | /* Disable Ambient Light auto adjust */ |
34 | ret |= adp5520_clr_bits(master, BL_CONTROL, | 34 | ret |= adp5520_clr_bits(master, ADP5520_BL_CONTROL, |
35 | BL_AUTO_ADJ); | 35 | ADP5520_BL_AUTO_ADJ); |
36 | ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); | 36 | ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, |
37 | brightness); | ||
37 | } else { | 38 | } else { |
38 | /* | 39 | /* |
39 | * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust | 40 | * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust |
40 | * restore daylight l3 sysfs brightness | 41 | * restore daylight l3 sysfs brightness |
41 | */ | 42 | */ |
42 | ret |= adp5520_write(master, DAYLIGHT_MAX, | 43 | ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, |
43 | data->cached_daylight_max); | 44 | data->cached_daylight_max); |
44 | ret |= adp5520_set_bits(master, BL_CONTROL, | 45 | ret |= adp5520_set_bits(master, ADP5520_BL_CONTROL, |
45 | BL_AUTO_ADJ); | 46 | ADP5520_BL_AUTO_ADJ); |
46 | } | 47 | } |
47 | } else { | 48 | } else { |
48 | ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); | 49 | ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, brightness); |
49 | } | 50 | } |
50 | 51 | ||
51 | if (data->current_brightness && brightness == 0) | 52 | if (data->current_brightness && brightness == 0) |
52 | ret |= adp5520_set_bits(master, | 53 | ret |= adp5520_set_bits(master, |
53 | MODE_STATUS, DIM_EN); | 54 | ADP5520_MODE_STATUS, ADP5520_DIM_EN); |
54 | else if (data->current_brightness == 0 && brightness) | 55 | else if (data->current_brightness == 0 && brightness) |
55 | ret |= adp5520_clr_bits(master, | 56 | ret |= adp5520_clr_bits(master, |
56 | MODE_STATUS, DIM_EN); | 57 | ADP5520_MODE_STATUS, ADP5520_DIM_EN); |
57 | 58 | ||
58 | if (!ret) | 59 | if (!ret) |
59 | data->current_brightness = brightness; | 60 | data->current_brightness = brightness; |
@@ -79,7 +80,7 @@ static int adp5520_bl_get_brightness(struct backlight_device *bl) | |||
79 | int error; | 80 | int error; |
80 | uint8_t reg_val; | 81 | uint8_t reg_val; |
81 | 82 | ||
82 | error = adp5520_read(data->master, BL_VALUE, ®_val); | 83 | error = adp5520_read(data->master, ADP5520_BL_VALUE, ®_val); |
83 | 84 | ||
84 | return error ? data->current_brightness : reg_val; | 85 | return error ? data->current_brightness : reg_val; |
85 | } | 86 | } |
@@ -93,33 +94,46 @@ static int adp5520_bl_setup(struct backlight_device *bl) | |||
93 | { | 94 | { |
94 | struct adp5520_bl *data = bl_get_data(bl); | 95 | struct adp5520_bl *data = bl_get_data(bl); |
95 | struct device *master = data->master; | 96 | struct device *master = data->master; |
96 | struct adp5520_backlight_platfrom_data *pdata = data->pdata; | 97 | struct adp5520_backlight_platform_data *pdata = data->pdata; |
97 | int ret = 0; | 98 | int ret = 0; |
98 | 99 | ||
99 | ret |= adp5520_write(master, DAYLIGHT_MAX, pdata->l1_daylight_max); | 100 | ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, |
100 | ret |= adp5520_write(master, DAYLIGHT_DIM, pdata->l1_daylight_dim); | 101 | pdata->l1_daylight_max); |
102 | ret |= adp5520_write(master, ADP5520_DAYLIGHT_DIM, | ||
103 | pdata->l1_daylight_dim); | ||
101 | 104 | ||
102 | if (pdata->en_ambl_sens) { | 105 | if (pdata->en_ambl_sens) { |
103 | data->cached_daylight_max = pdata->l1_daylight_max; | 106 | data->cached_daylight_max = pdata->l1_daylight_max; |
104 | ret |= adp5520_write(master, OFFICE_MAX, pdata->l2_office_max); | 107 | ret |= adp5520_write(master, ADP5520_OFFICE_MAX, |
105 | ret |= adp5520_write(master, OFFICE_DIM, pdata->l2_office_dim); | 108 | pdata->l2_office_max); |
106 | ret |= adp5520_write(master, DARK_MAX, pdata->l3_dark_max); | 109 | ret |= adp5520_write(master, ADP5520_OFFICE_DIM, |
107 | ret |= adp5520_write(master, DARK_DIM, pdata->l3_dark_dim); | 110 | pdata->l2_office_dim); |
108 | ret |= adp5520_write(master, L2_TRIP, pdata->l2_trip); | 111 | ret |= adp5520_write(master, ADP5520_DARK_MAX, |
109 | ret |= adp5520_write(master, L2_HYS, pdata->l2_hyst); | 112 | pdata->l3_dark_max); |
110 | ret |= adp5520_write(master, L3_TRIP, pdata->l3_trip); | 113 | ret |= adp5520_write(master, ADP5520_DARK_DIM, |
111 | ret |= adp5520_write(master, L3_HYS, pdata->l3_hyst); | 114 | pdata->l3_dark_dim); |
112 | ret |= adp5520_write(master, ALS_CMPR_CFG, | 115 | ret |= adp5520_write(master, ADP5520_L2_TRIP, |
113 | ALS_CMPR_CFG_VAL(pdata->abml_filt, L3_EN)); | 116 | pdata->l2_trip); |
117 | ret |= adp5520_write(master, ADP5520_L2_HYS, | ||
118 | pdata->l2_hyst); | ||
119 | ret |= adp5520_write(master, ADP5520_L3_TRIP, | ||
120 | pdata->l3_trip); | ||
121 | ret |= adp5520_write(master, ADP5520_L3_HYS, | ||
122 | pdata->l3_hyst); | ||
123 | ret |= adp5520_write(master, ADP5520_ALS_CMPR_CFG, | ||
124 | ALS_CMPR_CFG_VAL(pdata->abml_filt, | ||
125 | ADP5520_L3_EN)); | ||
114 | } | 126 | } |
115 | 127 | ||
116 | ret |= adp5520_write(master, BL_CONTROL, | 128 | ret |= adp5520_write(master, ADP5520_BL_CONTROL, |
117 | BL_CTRL_VAL(pdata->fade_led_law, pdata->en_ambl_sens)); | 129 | BL_CTRL_VAL(pdata->fade_led_law, |
130 | pdata->en_ambl_sens)); | ||
118 | 131 | ||
119 | ret |= adp5520_write(master, BL_FADE, FADE_VAL(pdata->fade_in, | 132 | ret |= adp5520_write(master, ADP5520_BL_FADE, FADE_VAL(pdata->fade_in, |
120 | pdata->fade_out)); | 133 | pdata->fade_out)); |
121 | 134 | ||
122 | ret |= adp5520_set_bits(master, MODE_STATUS, BL_EN | DIM_EN); | 135 | ret |= adp5520_set_bits(master, ADP5520_MODE_STATUS, |
136 | ADP5520_BL_EN | ADP5520_DIM_EN); | ||
123 | 137 | ||
124 | return ret; | 138 | return ret; |
125 | } | 139 | } |
@@ -156,29 +170,31 @@ static ssize_t adp5520_store(struct device *dev, const char *buf, | |||
156 | } | 170 | } |
157 | 171 | ||
158 | static ssize_t adp5520_bl_dark_max_show(struct device *dev, | 172 | static ssize_t adp5520_bl_dark_max_show(struct device *dev, |
159 | struct device_attribute *attr, char *buf) | 173 | struct device_attribute *attr, char *buf) |
160 | { | 174 | { |
161 | return adp5520_show(dev, buf, DARK_MAX); | 175 | return adp5520_show(dev, buf, ADP5520_DARK_MAX); |
162 | } | 176 | } |
163 | 177 | ||
164 | static ssize_t adp5520_bl_dark_max_store(struct device *dev, | 178 | static ssize_t adp5520_bl_dark_max_store(struct device *dev, |
165 | struct device_attribute *attr, const char *buf, size_t count) | 179 | struct device_attribute *attr, |
180 | const char *buf, size_t count) | ||
166 | { | 181 | { |
167 | return adp5520_store(dev, buf, count, DARK_MAX); | 182 | return adp5520_store(dev, buf, count, ADP5520_DARK_MAX); |
168 | } | 183 | } |
169 | static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, | 184 | static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, |
170 | adp5520_bl_dark_max_store); | 185 | adp5520_bl_dark_max_store); |
171 | 186 | ||
172 | static ssize_t adp5520_bl_office_max_show(struct device *dev, | 187 | static ssize_t adp5520_bl_office_max_show(struct device *dev, |
173 | struct device_attribute *attr, char *buf) | 188 | struct device_attribute *attr, char *buf) |
174 | { | 189 | { |
175 | return adp5520_show(dev, buf, OFFICE_MAX); | 190 | return adp5520_show(dev, buf, ADP5520_OFFICE_MAX); |
176 | } | 191 | } |
177 | 192 | ||
178 | static ssize_t adp5520_bl_office_max_store(struct device *dev, | 193 | static ssize_t adp5520_bl_office_max_store(struct device *dev, |
179 | struct device_attribute *attr, const char *buf, size_t count) | 194 | struct device_attribute *attr, |
195 | const char *buf, size_t count) | ||
180 | { | 196 | { |
181 | return adp5520_store(dev, buf, count, OFFICE_MAX); | 197 | return adp5520_store(dev, buf, count, ADP5520_OFFICE_MAX); |
182 | } | 198 | } |
183 | static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, | 199 | static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, |
184 | adp5520_bl_office_max_store); | 200 | adp5520_bl_office_max_store); |
@@ -186,16 +202,17 @@ static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, | |||
186 | static ssize_t adp5520_bl_daylight_max_show(struct device *dev, | 202 | static ssize_t adp5520_bl_daylight_max_show(struct device *dev, |
187 | struct device_attribute *attr, char *buf) | 203 | struct device_attribute *attr, char *buf) |
188 | { | 204 | { |
189 | return adp5520_show(dev, buf, DAYLIGHT_MAX); | 205 | return adp5520_show(dev, buf, ADP5520_DAYLIGHT_MAX); |
190 | } | 206 | } |
191 | 207 | ||
192 | static ssize_t adp5520_bl_daylight_max_store(struct device *dev, | 208 | static ssize_t adp5520_bl_daylight_max_store(struct device *dev, |
193 | struct device_attribute *attr, const char *buf, size_t count) | 209 | struct device_attribute *attr, |
210 | const char *buf, size_t count) | ||
194 | { | 211 | { |
195 | struct adp5520_bl *data = dev_get_drvdata(dev); | 212 | struct adp5520_bl *data = dev_get_drvdata(dev); |
196 | 213 | ||
197 | strict_strtoul(buf, 10, &data->cached_daylight_max); | 214 | strict_strtoul(buf, 10, &data->cached_daylight_max); |
198 | return adp5520_store(dev, buf, count, DAYLIGHT_MAX); | 215 | return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX); |
199 | } | 216 | } |
200 | static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, | 217 | static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, |
201 | adp5520_bl_daylight_max_store); | 218 | adp5520_bl_daylight_max_store); |
@@ -203,14 +220,14 @@ static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, | |||
203 | static ssize_t adp5520_bl_dark_dim_show(struct device *dev, | 220 | static ssize_t adp5520_bl_dark_dim_show(struct device *dev, |
204 | struct device_attribute *attr, char *buf) | 221 | struct device_attribute *attr, char *buf) |
205 | { | 222 | { |
206 | return adp5520_show(dev, buf, DARK_DIM); | 223 | return adp5520_show(dev, buf, ADP5520_DARK_DIM); |
207 | } | 224 | } |
208 | 225 | ||
209 | static ssize_t adp5520_bl_dark_dim_store(struct device *dev, | 226 | static ssize_t adp5520_bl_dark_dim_store(struct device *dev, |
210 | struct device_attribute *attr, | 227 | struct device_attribute *attr, |
211 | const char *buf, size_t count) | 228 | const char *buf, size_t count) |
212 | { | 229 | { |
213 | return adp5520_store(dev, buf, count, DARK_DIM); | 230 | return adp5520_store(dev, buf, count, ADP5520_DARK_DIM); |
214 | } | 231 | } |
215 | static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, | 232 | static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, |
216 | adp5520_bl_dark_dim_store); | 233 | adp5520_bl_dark_dim_store); |
@@ -218,29 +235,29 @@ static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, | |||
218 | static ssize_t adp5520_bl_office_dim_show(struct device *dev, | 235 | static ssize_t adp5520_bl_office_dim_show(struct device *dev, |
219 | struct device_attribute *attr, char *buf) | 236 | struct device_attribute *attr, char *buf) |
220 | { | 237 | { |
221 | return adp5520_show(dev, buf, OFFICE_DIM); | 238 | return adp5520_show(dev, buf, ADP5520_OFFICE_DIM); |
222 | } | 239 | } |
223 | 240 | ||
224 | static ssize_t adp5520_bl_office_dim_store(struct device *dev, | 241 | static ssize_t adp5520_bl_office_dim_store(struct device *dev, |
225 | struct device_attribute *attr, | 242 | struct device_attribute *attr, |
226 | const char *buf, size_t count) | 243 | const char *buf, size_t count) |
227 | { | 244 | { |
228 | return adp5520_store(dev, buf, count, OFFICE_DIM); | 245 | return adp5520_store(dev, buf, count, ADP5520_OFFICE_DIM); |
229 | } | 246 | } |
230 | static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, | 247 | static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, |
231 | adp5520_bl_office_dim_store); | 248 | adp5520_bl_office_dim_store); |
232 | 249 | ||
233 | static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, | 250 | static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, |
234 | struct device_attribute *attr, char *buf) | 251 | struct device_attribute *attr, char *buf) |
235 | { | 252 | { |
236 | return adp5520_show(dev, buf, DAYLIGHT_DIM); | 253 | return adp5520_show(dev, buf, ADP5520_DAYLIGHT_DIM); |
237 | } | 254 | } |
238 | 255 | ||
239 | static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, | 256 | static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, |
240 | struct device_attribute *attr, | 257 | struct device_attribute *attr, |
241 | const char *buf, size_t count) | 258 | const char *buf, size_t count) |
242 | { | 259 | { |
243 | return adp5520_store(dev, buf, count, DAYLIGHT_DIM); | 260 | return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_DIM); |
244 | } | 261 | } |
245 | static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, | 262 | static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, |
246 | adp5520_bl_daylight_dim_store); | 263 | adp5520_bl_daylight_dim_store); |
@@ -316,7 +333,7 @@ static int __devexit adp5520_bl_remove(struct platform_device *pdev) | |||
316 | struct backlight_device *bl = platform_get_drvdata(pdev); | 333 | struct backlight_device *bl = platform_get_drvdata(pdev); |
317 | struct adp5520_bl *data = bl_get_data(bl); | 334 | struct adp5520_bl *data = bl_get_data(bl); |
318 | 335 | ||
319 | adp5520_clr_bits(data->master, MODE_STATUS, BL_EN); | 336 | adp5520_clr_bits(data->master, ADP5520_MODE_STATUS, ADP5520_BL_EN); |
320 | 337 | ||
321 | if (data->pdata->en_ambl_sens) | 338 | if (data->pdata->en_ambl_sens) |
322 | sysfs_remove_group(&bl->dev.kobj, | 339 | sysfs_remove_group(&bl->dev.kobj, |
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c index 760645d9dbb6..e3eccc9af78e 100644 --- a/drivers/video/omap/lcd_2430sdp.c +++ b/drivers/video/omap/lcd_2430sdp.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/i2c/twl4030.h> | 28 | #include <linux/i2c/twl.h> |
29 | 29 | ||
30 | #include <plat/mux.h> | 30 | #include <plat/mux.h> |
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
@@ -52,7 +52,7 @@ static unsigned enable_gpio; | |||
52 | #define TWL4030_VPLL2_DEV_GRP 0x33 | 52 | #define TWL4030_VPLL2_DEV_GRP 0x33 |
53 | #define TWL4030_VPLL2_DEDICATED 0x36 | 53 | #define TWL4030_VPLL2_DEDICATED 0x36 |
54 | 54 | ||
55 | #define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) | 55 | #define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) |
56 | 56 | ||
57 | 57 | ||
58 | static int sdp2430_panel_init(struct lcd_panel *panel, | 58 | static int sdp2430_panel_init(struct lcd_panel *panel, |
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c index cb46556f2973..8162a40d1522 100644 --- a/drivers/watchdog/twl4030_wdt.c +++ b/drivers/watchdog/twl4030_wdt.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/miscdevice.h> | 27 | #include <linux/miscdevice.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/i2c/twl4030.h> | 29 | #include <linux/i2c/twl.h> |
30 | 30 | ||
31 | #define TWL4030_WATCHDOG_CFG_REG_OFFS 0x3 | 31 | #define TWL4030_WATCHDOG_CFG_REG_OFFS 0x3 |
32 | 32 | ||
@@ -48,7 +48,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | |||
48 | 48 | ||
49 | static int twl4030_wdt_write(unsigned char val) | 49 | static int twl4030_wdt_write(unsigned char val) |
50 | { | 50 | { |
51 | return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, | 51 | return twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, |
52 | TWL4030_WATCHDOG_CFG_REG_OFFS); | 52 | TWL4030_WATCHDOG_CFG_REG_OFFS); |
53 | } | 53 | } |
54 | 54 | ||
diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h index 918c5354d9b8..08aa92278d71 100644 --- a/include/linux/i2c/tps65010.h +++ b/include/linux/i2c/tps65010.h | |||
@@ -72,6 +72,21 @@ | |||
72 | #define TPS_VDCDC1 0x0c | 72 | #define TPS_VDCDC1 0x0c |
73 | # define TPS_ENABLE_LP (1 << 3) | 73 | # define TPS_ENABLE_LP (1 << 3) |
74 | #define TPS_VDCDC2 0x0d | 74 | #define TPS_VDCDC2 0x0d |
75 | # define TPS_LP_COREOFF (1 << 7) | ||
76 | # define TPS_VCORE_1_8V (7<<4) | ||
77 | # define TPS_VCORE_1_5V (6 << 4) | ||
78 | # define TPS_VCORE_1_4V (5 << 4) | ||
79 | # define TPS_VCORE_1_3V (4 << 4) | ||
80 | # define TPS_VCORE_1_2V (3 << 4) | ||
81 | # define TPS_VCORE_1_1V (2 << 4) | ||
82 | # define TPS_VCORE_1_0V (1 << 4) | ||
83 | # define TPS_VCORE_0_85V (0 << 4) | ||
84 | # define TPS_VCORE_LP_1_2V (3 << 2) | ||
85 | # define TPS_VCORE_LP_1_1V (2 << 2) | ||
86 | # define TPS_VCORE_LP_1_0V (1 << 2) | ||
87 | # define TPS_VCORE_LP_0_85V (0 << 2) | ||
88 | # define TPS_VIB (1 << 1) | ||
89 | # define TPS_VCORE_DISCH (1 << 0) | ||
75 | #define TPS_VREGS1 0x0e | 90 | #define TPS_VREGS1 0x0e |
76 | # define TPS_LDO2_ENABLE (1 << 7) | 91 | # define TPS_LDO2_ENABLE (1 << 7) |
77 | # define TPS_LDO2_OFF (1 << 6) | 92 | # define TPS_LDO2_OFF (1 << 6) |
@@ -152,6 +167,10 @@ extern int tps65010_config_vregs1(unsigned value); | |||
152 | */ | 167 | */ |
153 | extern int tps65013_set_low_pwr(unsigned mode); | 168 | extern int tps65013_set_low_pwr(unsigned mode); |
154 | 169 | ||
170 | /* tps65010_set_vdcdc2 | ||
171 | * value to be written to VDCDC2 | ||
172 | */ | ||
173 | extern int tps65010_config_vdcdc2(unsigned value); | ||
155 | 174 | ||
156 | struct i2c_client; | 175 | struct i2c_client; |
157 | 176 | ||
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl.h index 5306a759cbde..bf1c5be1f5b6 100644 --- a/include/linux/i2c/twl4030.h +++ b/include/linux/i2c/twl.h | |||
@@ -22,8 +22,8 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #ifndef __TWL4030_H_ | 25 | #ifndef __TWL_H_ |
26 | #define __TWL4030_H_ | 26 | #define __TWL_H_ |
27 | 27 | ||
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/input/matrix_keypad.h> | 29 | #include <linux/input/matrix_keypad.h> |
@@ -61,28 +61,112 @@ | |||
61 | #define TWL4030_MODULE_PWMA 0x0E | 61 | #define TWL4030_MODULE_PWMA 0x0E |
62 | #define TWL4030_MODULE_PWMB 0x0F | 62 | #define TWL4030_MODULE_PWMB 0x0F |
63 | 63 | ||
64 | #define TWL5031_MODULE_ACCESSORY 0x10 | ||
65 | #define TWL5031_MODULE_INTERRUPTS 0x11 | ||
66 | |||
64 | /* Slave 3 (i2c address 0x4b) */ | 67 | /* Slave 3 (i2c address 0x4b) */ |
65 | #define TWL4030_MODULE_BACKUP 0x10 | 68 | #define TWL4030_MODULE_BACKUP 0x12 |
66 | #define TWL4030_MODULE_INT 0x11 | 69 | #define TWL4030_MODULE_INT 0x13 |
67 | #define TWL4030_MODULE_PM_MASTER 0x12 | 70 | #define TWL4030_MODULE_PM_MASTER 0x14 |
68 | #define TWL4030_MODULE_PM_RECEIVER 0x13 | 71 | #define TWL4030_MODULE_PM_RECEIVER 0x15 |
69 | #define TWL4030_MODULE_RTC 0x14 | 72 | #define TWL4030_MODULE_RTC 0x16 |
70 | #define TWL4030_MODULE_SECURED_REG 0x15 | 73 | #define TWL4030_MODULE_SECURED_REG 0x17 |
74 | |||
75 | #define TWL_MODULE_USB TWL4030_MODULE_USB | ||
76 | #define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE | ||
77 | #define TWL_MODULE_PIH TWL4030_MODULE_PIH | ||
78 | #define TWL_MODULE_MADC TWL4030_MODULE_MADC | ||
79 | #define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE | ||
80 | #define TWL_MODULE_PM_MASTER TWL4030_MODULE_PM_MASTER | ||
81 | #define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER | ||
82 | #define TWL_MODULE_RTC TWL4030_MODULE_RTC | ||
83 | |||
84 | #define GPIO_INTR_OFFSET 0 | ||
85 | #define KEYPAD_INTR_OFFSET 1 | ||
86 | #define BCI_INTR_OFFSET 2 | ||
87 | #define MADC_INTR_OFFSET 3 | ||
88 | #define USB_INTR_OFFSET 4 | ||
89 | #define BCI_PRES_INTR_OFFSET 9 | ||
90 | #define USB_PRES_INTR_OFFSET 10 | ||
91 | #define RTC_INTR_OFFSET 11 | ||
92 | |||
93 | /* | ||
94 | * Offset from TWL6030_IRQ_BASE / pdata->irq_base | ||
95 | */ | ||
96 | #define PWR_INTR_OFFSET 0 | ||
97 | #define HOTDIE_INTR_OFFSET 12 | ||
98 | #define SMPSLDO_INTR_OFFSET 13 | ||
99 | #define BATDETECT_INTR_OFFSET 14 | ||
100 | #define SIMDETECT_INTR_OFFSET 15 | ||
101 | #define MMCDETECT_INTR_OFFSET 16 | ||
102 | #define GASGAUGE_INTR_OFFSET 17 | ||
103 | #define USBOTG_INTR_OFFSET 4 | ||
104 | #define CHARGER_INTR_OFFSET 2 | ||
105 | #define RSV_INTR_OFFSET 0 | ||
106 | |||
107 | /* INT register offsets */ | ||
108 | #define REG_INT_STS_A 0x00 | ||
109 | #define REG_INT_STS_B 0x01 | ||
110 | #define REG_INT_STS_C 0x02 | ||
111 | |||
112 | #define REG_INT_MSK_LINE_A 0x03 | ||
113 | #define REG_INT_MSK_LINE_B 0x04 | ||
114 | #define REG_INT_MSK_LINE_C 0x05 | ||
115 | |||
116 | #define REG_INT_MSK_STS_A 0x06 | ||
117 | #define REG_INT_MSK_STS_B 0x07 | ||
118 | #define REG_INT_MSK_STS_C 0x08 | ||
119 | |||
120 | /* MASK INT REG GROUP A */ | ||
121 | #define TWL6030_PWR_INT_MASK 0x07 | ||
122 | #define TWL6030_RTC_INT_MASK 0x18 | ||
123 | #define TWL6030_HOTDIE_INT_MASK 0x20 | ||
124 | #define TWL6030_SMPSLDOA_INT_MASK 0xC0 | ||
125 | |||
126 | /* MASK INT REG GROUP B */ | ||
127 | #define TWL6030_SMPSLDOB_INT_MASK 0x01 | ||
128 | #define TWL6030_BATDETECT_INT_MASK 0x02 | ||
129 | #define TWL6030_SIMDETECT_INT_MASK 0x04 | ||
130 | #define TWL6030_MMCDETECT_INT_MASK 0x08 | ||
131 | #define TWL6030_GPADC_INT_MASK 0x60 | ||
132 | #define TWL6030_GASGAUGE_INT_MASK 0x80 | ||
133 | |||
134 | /* MASK INT REG GROUP C */ | ||
135 | #define TWL6030_USBOTG_INT_MASK 0x0F | ||
136 | #define TWL6030_CHARGER_CTRL_INT_MASK 0x10 | ||
137 | #define TWL6030_CHARGER_FAULT_INT_MASK 0x60 | ||
138 | |||
139 | |||
140 | #define TWL4030_CLASS_ID 0x4030 | ||
141 | #define TWL6030_CLASS_ID 0x6030 | ||
142 | unsigned int twl_rev(void); | ||
143 | #define GET_TWL_REV (twl_rev()) | ||
144 | #define TWL_CLASS_IS(class, id) \ | ||
145 | static inline int twl_class_is_ ##class(void) \ | ||
146 | { \ | ||
147 | return ((id) == (GET_TWL_REV)) ? 1 : 0; \ | ||
148 | } | ||
149 | |||
150 | TWL_CLASS_IS(4030, TWL4030_CLASS_ID) | ||
151 | TWL_CLASS_IS(6030, TWL6030_CLASS_ID) | ||
71 | 152 | ||
72 | /* | 153 | /* |
73 | * Read and write single 8-bit registers | 154 | * Read and write single 8-bit registers |
74 | */ | 155 | */ |
75 | int twl4030_i2c_write_u8(u8 mod_no, u8 val, u8 reg); | 156 | int twl_i2c_write_u8(u8 mod_no, u8 val, u8 reg); |
76 | int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); | 157 | int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); |
77 | 158 | ||
78 | /* | 159 | /* |
79 | * Read and write several 8-bit registers at once. | 160 | * Read and write several 8-bit registers at once. |
80 | * | 161 | * |
81 | * IMPORTANT: For twl4030_i2c_write(), allocate num_bytes + 1 | 162 | * IMPORTANT: For twl_i2c_write(), allocate num_bytes + 1 |
82 | * for the value, and populate your data starting at offset 1. | 163 | * for the value, and populate your data starting at offset 1. |
83 | */ | 164 | */ |
84 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | 165 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); |
85 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | 166 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); |
167 | |||
168 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); | ||
169 | int twl6030_interrupt_mask(u8 bit_mask, u8 offset); | ||
86 | 170 | ||
87 | /*----------------------------------------------------------------------*/ | 171 | /*----------------------------------------------------------------------*/ |
88 | 172 | ||
@@ -221,6 +305,38 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | |||
221 | 305 | ||
222 | /*----------------------------------------------------------------------*/ | 306 | /*----------------------------------------------------------------------*/ |
223 | 307 | ||
308 | /* | ||
309 | * Accessory Interrupts | ||
310 | */ | ||
311 | #define TWL5031_ACIIMR_LSB 0x05 | ||
312 | #define TWL5031_ACIIMR_MSB 0x06 | ||
313 | #define TWL5031_ACIIDR_LSB 0x07 | ||
314 | #define TWL5031_ACIIDR_MSB 0x08 | ||
315 | #define TWL5031_ACCISR1 0x0F | ||
316 | #define TWL5031_ACCIMR1 0x10 | ||
317 | #define TWL5031_ACCISR2 0x11 | ||
318 | #define TWL5031_ACCIMR2 0x12 | ||
319 | #define TWL5031_ACCSIR 0x13 | ||
320 | #define TWL5031_ACCEDR1 0x14 | ||
321 | #define TWL5031_ACCSIHCTRL 0x15 | ||
322 | |||
323 | /*----------------------------------------------------------------------*/ | ||
324 | |||
325 | /* | ||
326 | * Battery Charger Controller | ||
327 | */ | ||
328 | |||
329 | #define TWL5031_INTERRUPTS_BCIISR1 0x0 | ||
330 | #define TWL5031_INTERRUPTS_BCIIMR1 0x1 | ||
331 | #define TWL5031_INTERRUPTS_BCIISR2 0x2 | ||
332 | #define TWL5031_INTERRUPTS_BCIIMR2 0x3 | ||
333 | #define TWL5031_INTERRUPTS_BCISIR 0x4 | ||
334 | #define TWL5031_INTERRUPTS_BCIEDR1 0x5 | ||
335 | #define TWL5031_INTERRUPTS_BCIEDR2 0x6 | ||
336 | #define TWL5031_INTERRUPTS_BCISIHCTRL 0x7 | ||
337 | |||
338 | /*----------------------------------------------------------------------*/ | ||
339 | |||
224 | /* Power bus message definitions */ | 340 | /* Power bus message definitions */ |
225 | 341 | ||
226 | /* The TWL4030/5030 splits its power-management resources (the various | 342 | /* The TWL4030/5030 splits its power-management resources (the various |
@@ -250,6 +366,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | |||
250 | 366 | ||
251 | #define RES_TYPE_ALL 0x7 | 367 | #define RES_TYPE_ALL 0x7 |
252 | 368 | ||
369 | /* Resource states */ | ||
253 | #define RES_STATE_WRST 0xF | 370 | #define RES_STATE_WRST 0xF |
254 | #define RES_STATE_ACTIVE 0xE | 371 | #define RES_STATE_ACTIVE 0xE |
255 | #define RES_STATE_SLEEP 0x8 | 372 | #define RES_STATE_SLEEP 0x8 |
@@ -310,8 +427,18 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | |||
310 | #define MSG_SINGULAR(devgrp, id, state) \ | 427 | #define MSG_SINGULAR(devgrp, id, state) \ |
311 | ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) | 428 | ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) |
312 | 429 | ||
430 | #define MSG_BROADCAST_ALL(devgrp, state) \ | ||
431 | ((devgrp) << 5 | (state)) | ||
432 | |||
433 | #define MSG_BROADCAST_REF MSG_BROADCAST_ALL | ||
434 | #define MSG_BROADCAST_PROV MSG_BROADCAST_ALL | ||
435 | #define MSG_BROADCAST__CLK_RST MSG_BROADCAST_ALL | ||
313 | /*----------------------------------------------------------------------*/ | 436 | /*----------------------------------------------------------------------*/ |
314 | 437 | ||
438 | struct twl4030_clock_init_data { | ||
439 | bool ck32k_lowpwr_enable; | ||
440 | }; | ||
441 | |||
315 | struct twl4030_bci_platform_data { | 442 | struct twl4030_bci_platform_data { |
316 | int *battery_tmp_tbl; | 443 | int *battery_tmp_tbl; |
317 | unsigned int tblsize; | 444 | unsigned int tblsize; |
@@ -391,12 +518,15 @@ struct twl4030_resconfig { | |||
391 | u8 devgroup; /* Processor group that Power resource belongs to */ | 518 | u8 devgroup; /* Processor group that Power resource belongs to */ |
392 | u8 type; /* Power resource addressed, 6 / broadcast message */ | 519 | u8 type; /* Power resource addressed, 6 / broadcast message */ |
393 | u8 type2; /* Power resource addressed, 3 / broadcast message */ | 520 | u8 type2; /* Power resource addressed, 3 / broadcast message */ |
521 | u8 remap_off; /* off state remapping */ | ||
522 | u8 remap_sleep; /* sleep state remapping */ | ||
394 | }; | 523 | }; |
395 | 524 | ||
396 | struct twl4030_power_data { | 525 | struct twl4030_power_data { |
397 | struct twl4030_script **scripts; | 526 | struct twl4030_script **scripts; |
398 | unsigned num; | 527 | unsigned num; |
399 | struct twl4030_resconfig *resource_config; | 528 | struct twl4030_resconfig *resource_config; |
529 | #define TWL4030_RESCONFIG_UNDEF ((u8)-1) | ||
400 | }; | 530 | }; |
401 | 531 | ||
402 | extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); | 532 | extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); |
@@ -421,6 +551,7 @@ struct twl4030_codec_data { | |||
421 | 551 | ||
422 | struct twl4030_platform_data { | 552 | struct twl4030_platform_data { |
423 | unsigned irq_base, irq_end; | 553 | unsigned irq_base, irq_end; |
554 | struct twl4030_clock_init_data *clock; | ||
424 | struct twl4030_bci_platform_data *bci; | 555 | struct twl4030_bci_platform_data *bci; |
425 | struct twl4030_gpio_platform_data *gpio; | 556 | struct twl4030_gpio_platform_data *gpio; |
426 | struct twl4030_madc_platform_data *madc; | 557 | struct twl4030_madc_platform_data *madc; |
@@ -429,19 +560,31 @@ struct twl4030_platform_data { | |||
429 | struct twl4030_power_data *power; | 560 | struct twl4030_power_data *power; |
430 | struct twl4030_codec_data *codec; | 561 | struct twl4030_codec_data *codec; |
431 | 562 | ||
432 | /* LDO regulators */ | 563 | /* Common LDO regulators for TWL4030/TWL6030 */ |
433 | struct regulator_init_data *vdac; | 564 | struct regulator_init_data *vdac; |
565 | struct regulator_init_data *vaux1; | ||
566 | struct regulator_init_data *vaux2; | ||
567 | struct regulator_init_data *vaux3; | ||
568 | /* TWL4030 LDO regulators */ | ||
434 | struct regulator_init_data *vpll1; | 569 | struct regulator_init_data *vpll1; |
435 | struct regulator_init_data *vpll2; | 570 | struct regulator_init_data *vpll2; |
436 | struct regulator_init_data *vmmc1; | 571 | struct regulator_init_data *vmmc1; |
437 | struct regulator_init_data *vmmc2; | 572 | struct regulator_init_data *vmmc2; |
438 | struct regulator_init_data *vsim; | 573 | struct regulator_init_data *vsim; |
439 | struct regulator_init_data *vaux1; | ||
440 | struct regulator_init_data *vaux2; | ||
441 | struct regulator_init_data *vaux3; | ||
442 | struct regulator_init_data *vaux4; | 574 | struct regulator_init_data *vaux4; |
443 | 575 | struct regulator_init_data *vio; | |
444 | /* REVISIT more to come ... _nothing_ should be hard-wired */ | 576 | struct regulator_init_data *vdd1; |
577 | struct regulator_init_data *vdd2; | ||
578 | struct regulator_init_data *vintana1; | ||
579 | struct regulator_init_data *vintana2; | ||
580 | struct regulator_init_data *vintdig; | ||
581 | /* TWL6030 LDO regulators */ | ||
582 | struct regulator_init_data *vmmc; | ||
583 | struct regulator_init_data *vpp; | ||
584 | struct regulator_init_data *vusim; | ||
585 | struct regulator_init_data *vana; | ||
586 | struct regulator_init_data *vcxio; | ||
587 | struct regulator_init_data *vusb; | ||
445 | }; | 588 | }; |
446 | 589 | ||
447 | /*----------------------------------------------------------------------*/ | 590 | /*----------------------------------------------------------------------*/ |
@@ -473,6 +616,7 @@ int twl4030_sih_setup(int module); | |||
473 | * VIO is generally fixed. | 616 | * VIO is generally fixed. |
474 | */ | 617 | */ |
475 | 618 | ||
619 | /* TWL4030 SMPS/LDO's */ | ||
476 | /* EXTERNAL dc-to-dc buck converters */ | 620 | /* EXTERNAL dc-to-dc buck converters */ |
477 | #define TWL4030_REG_VDD1 0 | 621 | #define TWL4030_REG_VDD1 0 |
478 | #define TWL4030_REG_VDD2 1 | 622 | #define TWL4030_REG_VDD2 1 |
@@ -499,4 +643,31 @@ int twl4030_sih_setup(int module); | |||
499 | #define TWL4030_REG_VUSB1V8 18 | 643 | #define TWL4030_REG_VUSB1V8 18 |
500 | #define TWL4030_REG_VUSB3V1 19 | 644 | #define TWL4030_REG_VUSB3V1 19 |
501 | 645 | ||
646 | /* TWL6030 SMPS/LDO's */ | ||
647 | /* EXTERNAL dc-to-dc buck convertor contollable via SR */ | ||
648 | #define TWL6030_REG_VDD1 30 | ||
649 | #define TWL6030_REG_VDD2 31 | ||
650 | #define TWL6030_REG_VDD3 32 | ||
651 | |||
652 | /* Non SR compliant dc-to-dc buck convertors */ | ||
653 | #define TWL6030_REG_VMEM 33 | ||
654 | #define TWL6030_REG_V2V1 34 | ||
655 | #define TWL6030_REG_V1V29 35 | ||
656 | #define TWL6030_REG_V1V8 36 | ||
657 | |||
658 | /* EXTERNAL LDOs */ | ||
659 | #define TWL6030_REG_VAUX1_6030 37 | ||
660 | #define TWL6030_REG_VAUX2_6030 38 | ||
661 | #define TWL6030_REG_VAUX3_6030 39 | ||
662 | #define TWL6030_REG_VMMC 40 | ||
663 | #define TWL6030_REG_VPP 41 | ||
664 | #define TWL6030_REG_VUSIM 42 | ||
665 | #define TWL6030_REG_VANA 43 | ||
666 | #define TWL6030_REG_VCXIO 44 | ||
667 | #define TWL6030_REG_VDAC 45 | ||
668 | #define TWL6030_REG_VUSB 46 | ||
669 | |||
670 | /* INTERNAL LDOs */ | ||
671 | #define TWL6030_REG_VRTC 47 | ||
672 | |||
502 | #endif /* End of __TWL4030_H */ | 673 | #endif /* End of __TWL4030_H */ |
diff --git a/include/linux/mfd/88pm8607.h b/include/linux/mfd/88pm8607.h new file mode 100644 index 000000000000..f41b428d2cec --- /dev/null +++ b/include/linux/mfd/88pm8607.h | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * Marvell 88PM8607 Interface | ||
3 | * | ||
4 | * Copyright (C) 2009 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __LINUX_MFD_88PM8607_H | ||
13 | #define __LINUX_MFD_88PM8607_H | ||
14 | |||
15 | enum { | ||
16 | PM8607_ID_BUCK1 = 0, | ||
17 | PM8607_ID_BUCK2, | ||
18 | PM8607_ID_BUCK3, | ||
19 | |||
20 | PM8607_ID_LDO1, | ||
21 | PM8607_ID_LDO2, | ||
22 | PM8607_ID_LDO3, | ||
23 | PM8607_ID_LDO4, | ||
24 | PM8607_ID_LDO5, | ||
25 | PM8607_ID_LDO6, | ||
26 | PM8607_ID_LDO7, | ||
27 | PM8607_ID_LDO8, | ||
28 | PM8607_ID_LDO9, | ||
29 | PM8607_ID_LDO10, | ||
30 | PM8607_ID_LDO12, | ||
31 | PM8607_ID_LDO14, | ||
32 | |||
33 | PM8607_ID_RG_MAX, | ||
34 | }; | ||
35 | |||
36 | #define CHIP_ID (0x40) | ||
37 | #define CHIP_ID_MASK (0xF8) | ||
38 | |||
39 | /* Interrupt Registers */ | ||
40 | #define PM8607_STATUS_1 (0x01) | ||
41 | #define PM8607_STATUS_2 (0x02) | ||
42 | #define PM8607_INT_STATUS1 (0x03) | ||
43 | #define PM8607_INT_STATUS2 (0x04) | ||
44 | #define PM8607_INT_STATUS3 (0x05) | ||
45 | #define PM8607_INT_MASK_1 (0x06) | ||
46 | #define PM8607_INT_MASK_2 (0x07) | ||
47 | #define PM8607_INT_MASK_3 (0x08) | ||
48 | |||
49 | /* Regulator Control Registers */ | ||
50 | #define PM8607_LDO1 (0x10) | ||
51 | #define PM8607_LDO2 (0x11) | ||
52 | #define PM8607_LDO3 (0x12) | ||
53 | #define PM8607_LDO4 (0x13) | ||
54 | #define PM8607_LDO5 (0x14) | ||
55 | #define PM8607_LDO6 (0x15) | ||
56 | #define PM8607_LDO7 (0x16) | ||
57 | #define PM8607_LDO8 (0x17) | ||
58 | #define PM8607_LDO9 (0x18) | ||
59 | #define PM8607_LDO10 (0x19) | ||
60 | #define PM8607_LDO12 (0x1A) | ||
61 | #define PM8607_LDO14 (0x1B) | ||
62 | #define PM8607_SLEEP_MODE1 (0x1C) | ||
63 | #define PM8607_SLEEP_MODE2 (0x1D) | ||
64 | #define PM8607_SLEEP_MODE3 (0x1E) | ||
65 | #define PM8607_SLEEP_MODE4 (0x1F) | ||
66 | #define PM8607_GO (0x20) | ||
67 | #define PM8607_SLEEP_BUCK1 (0x21) | ||
68 | #define PM8607_SLEEP_BUCK2 (0x22) | ||
69 | #define PM8607_SLEEP_BUCK3 (0x23) | ||
70 | #define PM8607_BUCK1 (0x24) | ||
71 | #define PM8607_BUCK2 (0x25) | ||
72 | #define PM8607_BUCK3 (0x26) | ||
73 | #define PM8607_BUCK_CONTROLS (0x27) | ||
74 | #define PM8607_SUPPLIES_EN11 (0x2B) | ||
75 | #define PM8607_SUPPLIES_EN12 (0x2C) | ||
76 | #define PM8607_GROUP1 (0x2D) | ||
77 | #define PM8607_GROUP2 (0x2E) | ||
78 | #define PM8607_GROUP3 (0x2F) | ||
79 | #define PM8607_GROUP4 (0x30) | ||
80 | #define PM8607_GROUP5 (0x31) | ||
81 | #define PM8607_GROUP6 (0x32) | ||
82 | #define PM8607_SUPPLIES_EN21 (0x33) | ||
83 | #define PM8607_SUPPLIES_EN22 (0x34) | ||
84 | |||
85 | /* RTC Control Registers */ | ||
86 | #define PM8607_RTC1 (0xA0) | ||
87 | #define PM8607_RTC_COUNTER1 (0xA1) | ||
88 | #define PM8607_RTC_COUNTER2 (0xA2) | ||
89 | #define PM8607_RTC_COUNTER3 (0xA3) | ||
90 | #define PM8607_RTC_COUNTER4 (0xA4) | ||
91 | #define PM8607_RTC_EXPIRE1 (0xA5) | ||
92 | #define PM8607_RTC_EXPIRE2 (0xA6) | ||
93 | #define PM8607_RTC_EXPIRE3 (0xA7) | ||
94 | #define PM8607_RTC_EXPIRE4 (0xA8) | ||
95 | #define PM8607_RTC_TRIM1 (0xA9) | ||
96 | #define PM8607_RTC_TRIM2 (0xAA) | ||
97 | #define PM8607_RTC_TRIM3 (0xAB) | ||
98 | #define PM8607_RTC_TRIM4 (0xAC) | ||
99 | #define PM8607_RTC_MISC1 (0xAD) | ||
100 | #define PM8607_RTC_MISC2 (0xAE) | ||
101 | #define PM8607_RTC_MISC3 (0xAF) | ||
102 | |||
103 | /* Misc Registers */ | ||
104 | #define PM8607_CHIP_ID (0x00) | ||
105 | #define PM8607_LDO1 (0x10) | ||
106 | #define PM8607_DVC3 (0x26) | ||
107 | #define PM8607_MISC1 (0x40) | ||
108 | |||
109 | /* bit definitions for PM8607 events */ | ||
110 | #define PM8607_EVENT_ONKEY (1 << 0) | ||
111 | #define PM8607_EVENT_EXTON (1 << 1) | ||
112 | #define PM8607_EVENT_CHG (1 << 2) | ||
113 | #define PM8607_EVENT_BAT (1 << 3) | ||
114 | #define PM8607_EVENT_RTC (1 << 4) | ||
115 | #define PM8607_EVENT_CC (1 << 5) | ||
116 | #define PM8607_EVENT_VBAT (1 << 8) | ||
117 | #define PM8607_EVENT_VCHG (1 << 9) | ||
118 | #define PM8607_EVENT_VSYS (1 << 10) | ||
119 | #define PM8607_EVENT_TINT (1 << 11) | ||
120 | #define PM8607_EVENT_GPADC0 (1 << 12) | ||
121 | #define PM8607_EVENT_GPADC1 (1 << 13) | ||
122 | #define PM8607_EVENT_GPADC2 (1 << 14) | ||
123 | #define PM8607_EVENT_GPADC3 (1 << 15) | ||
124 | #define PM8607_EVENT_AUDIO_SHORT (1 << 16) | ||
125 | #define PM8607_EVENT_PEN (1 << 17) | ||
126 | #define PM8607_EVENT_HEADSET (1 << 18) | ||
127 | #define PM8607_EVENT_HOOK (1 << 19) | ||
128 | #define PM8607_EVENT_MICIN (1 << 20) | ||
129 | #define PM8607_EVENT_CHG_TIMEOUT (1 << 21) | ||
130 | #define PM8607_EVENT_CHG_DONE (1 << 22) | ||
131 | #define PM8607_EVENT_CHG_FAULT (1 << 23) | ||
132 | |||
133 | /* bit definitions of Status Query Interface */ | ||
134 | #define PM8607_STATUS_CC (1 << 3) | ||
135 | #define PM8607_STATUS_PEN (1 << 4) | ||
136 | #define PM8607_STATUS_HEADSET (1 << 5) | ||
137 | #define PM8607_STATUS_HOOK (1 << 6) | ||
138 | #define PM8607_STATUS_MICIN (1 << 7) | ||
139 | #define PM8607_STATUS_ONKEY (1 << 8) | ||
140 | #define PM8607_STATUS_EXTON (1 << 9) | ||
141 | #define PM8607_STATUS_CHG (1 << 10) | ||
142 | #define PM8607_STATUS_BAT (1 << 11) | ||
143 | #define PM8607_STATUS_VBUS (1 << 12) | ||
144 | #define PM8607_STATUS_OV (1 << 13) | ||
145 | |||
146 | /* bit definitions of BUCK3 */ | ||
147 | #define PM8607_BUCK3_DOUBLE (1 << 6) | ||
148 | |||
149 | /* bit definitions of Misc1 */ | ||
150 | #define PM8607_MISC1_PI2C (1 << 0) | ||
151 | |||
152 | /* Interrupt Number in 88PM8607 */ | ||
153 | enum { | ||
154 | PM8607_IRQ_ONKEY = 0, | ||
155 | PM8607_IRQ_EXTON, | ||
156 | PM8607_IRQ_CHG, | ||
157 | PM8607_IRQ_BAT, | ||
158 | PM8607_IRQ_RTC, | ||
159 | PM8607_IRQ_VBAT = 8, | ||
160 | PM8607_IRQ_VCHG, | ||
161 | PM8607_IRQ_VSYS, | ||
162 | PM8607_IRQ_TINT, | ||
163 | PM8607_IRQ_GPADC0, | ||
164 | PM8607_IRQ_GPADC1, | ||
165 | PM8607_IRQ_GPADC2, | ||
166 | PM8607_IRQ_GPADC3, | ||
167 | PM8607_IRQ_AUDIO_SHORT = 16, | ||
168 | PM8607_IRQ_PEN, | ||
169 | PM8607_IRQ_HEADSET, | ||
170 | PM8607_IRQ_HOOK, | ||
171 | PM8607_IRQ_MICIN, | ||
172 | PM8607_IRQ_CHG_FAIL, | ||
173 | PM8607_IRQ_CHG_DONE, | ||
174 | PM8607_IRQ_CHG_FAULT, | ||
175 | }; | ||
176 | |||
177 | enum { | ||
178 | PM8607_CHIP_A0 = 0x40, | ||
179 | PM8607_CHIP_A1 = 0x41, | ||
180 | PM8607_CHIP_B0 = 0x48, | ||
181 | }; | ||
182 | |||
183 | |||
184 | struct pm8607_chip { | ||
185 | struct device *dev; | ||
186 | struct mutex io_lock; | ||
187 | struct i2c_client *client; | ||
188 | |||
189 | int (*read)(struct pm8607_chip *chip, int reg, int bytes, void *dest); | ||
190 | int (*write)(struct pm8607_chip *chip, int reg, int bytes, void *src); | ||
191 | |||
192 | int buck3_double; /* DVC ramp slope double */ | ||
193 | unsigned char chip_id; | ||
194 | |||
195 | }; | ||
196 | |||
197 | #define PM8607_MAX_REGULATOR 15 /* 3 Bucks, 12 LDOs */ | ||
198 | |||
199 | enum { | ||
200 | GI2C_PORT = 0, | ||
201 | PI2C_PORT, | ||
202 | }; | ||
203 | |||
204 | struct pm8607_platform_data { | ||
205 | int i2c_port; /* Controlled by GI2C or PI2C */ | ||
206 | struct regulator_init_data *regulator[PM8607_MAX_REGULATOR]; | ||
207 | }; | ||
208 | |||
209 | extern int pm8607_reg_read(struct pm8607_chip *, int); | ||
210 | extern int pm8607_reg_write(struct pm8607_chip *, int, unsigned char); | ||
211 | extern int pm8607_bulk_read(struct pm8607_chip *, int, int, | ||
212 | unsigned char *); | ||
213 | extern int pm8607_bulk_write(struct pm8607_chip *, int, int, | ||
214 | unsigned char *); | ||
215 | extern int pm8607_set_bits(struct pm8607_chip *, int, unsigned char, | ||
216 | unsigned char); | ||
217 | #endif /* __LINUX_MFD_88PM8607_H */ | ||
diff --git a/include/linux/mfd/ab4500.h b/include/linux/mfd/ab4500.h new file mode 100644 index 000000000000..a42a7033ae53 --- /dev/null +++ b/include/linux/mfd/ab4500.h | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * AB4500 device core funtions, for client access | ||
11 | */ | ||
12 | #ifndef MFD_AB4500_H | ||
13 | #define MFD_AB4500_H | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | |||
17 | /* | ||
18 | * AB4500 bank addresses | ||
19 | */ | ||
20 | #define AB4500_SYS_CTRL1_BLOCK 0x1 | ||
21 | #define AB4500_SYS_CTRL2_BLOCK 0x2 | ||
22 | #define AB4500_REGU_CTRL1 0x3 | ||
23 | #define AB4500_REGU_CTRL2 0x4 | ||
24 | #define AB4500_USB 0x5 | ||
25 | #define AB4500_TVOUT 0x6 | ||
26 | #define AB4500_DBI 0x7 | ||
27 | #define AB4500_ECI_AV_ACC 0x8 | ||
28 | #define AB4500_RESERVED 0x9 | ||
29 | #define AB4500_GPADC 0xA | ||
30 | #define AB4500_CHARGER 0xB | ||
31 | #define AB4500_GAS_GAUGE 0xC | ||
32 | #define AB4500_AUDIO 0xD | ||
33 | #define AB4500_INTERRUPT 0xE | ||
34 | #define AB4500_RTC 0xF | ||
35 | #define AB4500_MISC 0x10 | ||
36 | #define AB4500_DEBUG 0x12 | ||
37 | #define AB4500_PROD_TEST 0x13 | ||
38 | #define AB4500_OTP_EMUL 0x15 | ||
39 | |||
40 | /* | ||
41 | * System control 1 register offsets. | ||
42 | * Bank = 0x01 | ||
43 | */ | ||
44 | #define AB4500_TURNON_STAT_REG 0x0100 | ||
45 | #define AB4500_RESET_STAT_REG 0x0101 | ||
46 | #define AB4500_PONKEY1_PRESS_STAT_REG 0x0102 | ||
47 | |||
48 | #define AB4500_FSM_STAT1_REG 0x0140 | ||
49 | #define AB4500_FSM_STAT2_REG 0x0141 | ||
50 | #define AB4500_SYSCLK_REQ_STAT_REG 0x0142 | ||
51 | #define AB4500_USB_STAT1_REG 0x0143 | ||
52 | #define AB4500_USB_STAT2_REG 0x0144 | ||
53 | #define AB4500_STATUS_SPARE1_REG 0x0145 | ||
54 | #define AB4500_STATUS_SPARE2_REG 0x0146 | ||
55 | |||
56 | #define AB4500_CTRL1_REG 0x0180 | ||
57 | #define AB4500_CTRL2_REG 0x0181 | ||
58 | |||
59 | /* | ||
60 | * System control 2 register offsets. | ||
61 | * bank = 0x02 | ||
62 | */ | ||
63 | #define AB4500_CTRL3_REG 0x0200 | ||
64 | #define AB4500_MAIN_WDOG_CTRL_REG 0x0201 | ||
65 | #define AB4500_MAIN_WDOG_TIMER_REG 0x0202 | ||
66 | #define AB4500_LOW_BAT_REG 0x0203 | ||
67 | #define AB4500_BATT_OK_REG 0x0204 | ||
68 | #define AB4500_SYSCLK_TIMER_REG 0x0205 | ||
69 | #define AB4500_SMPSCLK_CTRL_REG 0x0206 | ||
70 | #define AB4500_SMPSCLK_SEL1_REG 0x0207 | ||
71 | #define AB4500_SMPSCLK_SEL2_REG 0x0208 | ||
72 | #define AB4500_SMPSCLK_SEL3_REG 0x0209 | ||
73 | #define AB4500_SYSULPCLK_CONF_REG 0x020A | ||
74 | #define AB4500_SYSULPCLK_CTRL1_REG 0x020B | ||
75 | #define AB4500_SYSCLK_CTRL_REG 0x020C | ||
76 | #define AB4500_SYSCLK_REQ1_VALID_REG 0x020D | ||
77 | #define AB4500_SYSCLK_REQ_VALID_REG 0x020E | ||
78 | #define AB4500_SYSCTRL_SPARE_REG 0x020F | ||
79 | #define AB4500_PAD_CONF_REG 0x0210 | ||
80 | |||
81 | /* | ||
82 | * Regu control1 register offsets | ||
83 | * Bank = 0x03 | ||
84 | */ | ||
85 | #define AB4500_REGU_SERIAL_CTRL1_REG 0x0300 | ||
86 | #define AB4500_REGU_SERIAL_CTRL2_REG 0x0301 | ||
87 | #define AB4500_REGU_SERIAL_CTRL3_REG 0x0302 | ||
88 | #define AB4500_REGU_REQ_CTRL1_REG 0x0303 | ||
89 | #define AB4500_REGU_REQ_CTRL2_REG 0x0304 | ||
90 | #define AB4500_REGU_REQ_CTRL3_REG 0x0305 | ||
91 | #define AB4500_REGU_REQ_CTRL4_REG 0x0306 | ||
92 | #define AB4500_REGU_MISC1_REG 0x0380 | ||
93 | #define AB4500_REGU_OTGSUPPLY_CTRL_REG 0x0381 | ||
94 | #define AB4500_REGU_VUSB_CTRL_REG 0x0382 | ||
95 | #define AB4500_REGU_VAUDIO_SUPPLY_REG 0x0383 | ||
96 | #define AB4500_REGU_CTRL1_SPARE_REG 0x0384 | ||
97 | |||
98 | /* | ||
99 | * Regu control2 Vmod register offsets | ||
100 | */ | ||
101 | #define AB4500_REGU_VMOD_REGU_REG 0x0440 | ||
102 | #define AB4500_REGU_VMOD_SEL1_REG 0x0441 | ||
103 | #define AB4500_REGU_VMOD_SEL2_REG 0x0442 | ||
104 | #define AB4500_REGU_CTRL_DISCH_REG 0x0443 | ||
105 | #define AB4500_REGU_CTRL_DISCH2_REG 0x0444 | ||
106 | |||
107 | /* | ||
108 | * USB/ULPI register offsets | ||
109 | * Bank : 0x5 | ||
110 | */ | ||
111 | #define AB4500_USB_LINE_STAT_REG 0x0580 | ||
112 | #define AB4500_USB_LINE_CTRL1_REG 0x0581 | ||
113 | #define AB4500_USB_LINE_CTRL2_REG 0x0582 | ||
114 | #define AB4500_USB_LINE_CTRL3_REG 0x0583 | ||
115 | #define AB4500_USB_LINE_CTRL4_REG 0x0584 | ||
116 | #define AB4500_USB_LINE_CTRL5_REG 0x0585 | ||
117 | #define AB4500_USB_OTG_CTRL_REG 0x0587 | ||
118 | #define AB4500_USB_OTG_STAT_REG 0x0588 | ||
119 | #define AB4500_USB_OTG_STAT_REG 0x0588 | ||
120 | #define AB4500_USB_CTRL_SPARE_REG 0x0589 | ||
121 | #define AB4500_USB_PHY_CTRL_REG 0x058A | ||
122 | |||
123 | /* | ||
124 | * TVOUT / CTRL register offsets | ||
125 | * Bank : 0x06 | ||
126 | */ | ||
127 | #define AB4500_TVOUT_CTRL_REG 0x0680 | ||
128 | |||
129 | /* | ||
130 | * DBI register offsets | ||
131 | * Bank : 0x07 | ||
132 | */ | ||
133 | #define AB4500_DBI_REG1_REG 0x0700 | ||
134 | #define AB4500_DBI_REG2_REG 0x0701 | ||
135 | |||
136 | /* | ||
137 | * ECI regsiter offsets | ||
138 | * Bank : 0x08 | ||
139 | */ | ||
140 | #define AB4500_ECI_CTRL_REG 0x0800 | ||
141 | #define AB4500_ECI_HOOKLEVEL_REG 0x0801 | ||
142 | #define AB4500_ECI_DATAOUT_REG 0x0802 | ||
143 | #define AB4500_ECI_DATAIN_REG 0x0803 | ||
144 | |||
145 | /* | ||
146 | * AV Connector register offsets | ||
147 | * Bank : 0x08 | ||
148 | */ | ||
149 | #define AB4500_AV_CONN_REG 0x0840 | ||
150 | |||
151 | /* | ||
152 | * Accessory detection register offsets | ||
153 | * Bank : 0x08 | ||
154 | */ | ||
155 | #define AB4500_ACC_DET_DB1_REG 0x0880 | ||
156 | #define AB4500_ACC_DET_DB2_REG 0x0881 | ||
157 | |||
158 | /* | ||
159 | * GPADC register offsets | ||
160 | * Bank : 0x0A | ||
161 | */ | ||
162 | #define AB4500_GPADC_CTRL1_REG 0x0A00 | ||
163 | #define AB4500_GPADC_CTRL2_REG 0x0A01 | ||
164 | #define AB4500_GPADC_CTRL3_REG 0x0A02 | ||
165 | #define AB4500_GPADC_AUTO_TIMER_REG 0x0A03 | ||
166 | #define AB4500_GPADC_STAT_REG 0x0A04 | ||
167 | #define AB4500_GPADC_MANDATAL_REG 0x0A05 | ||
168 | #define AB4500_GPADC_MANDATAH_REG 0x0A06 | ||
169 | #define AB4500_GPADC_AUTODATAL_REG 0x0A07 | ||
170 | #define AB4500_GPADC_AUTODATAH_REG 0x0A08 | ||
171 | #define AB4500_GPADC_MUX_CTRL_REG 0x0A09 | ||
172 | |||
173 | /* | ||
174 | * Charger / status register offfsets | ||
175 | * Bank : 0x0B | ||
176 | */ | ||
177 | #define AB4500_CH_STATUS1_REG 0x0B00 | ||
178 | #define AB4500_CH_STATUS2_REG 0x0B01 | ||
179 | #define AB4500_CH_USBCH_STAT1_REG 0x0B02 | ||
180 | #define AB4500_CH_USBCH_STAT2_REG 0x0B03 | ||
181 | #define AB4500_CH_FSM_STAT_REG 0x0B04 | ||
182 | #define AB4500_CH_STAT_REG 0x0B05 | ||
183 | |||
184 | /* | ||
185 | * Charger / control register offfsets | ||
186 | * Bank : 0x0B | ||
187 | */ | ||
188 | #define AB4500_CH_VOLT_LVL_REG 0x0B40 | ||
189 | |||
190 | /* | ||
191 | * Charger / main control register offfsets | ||
192 | * Bank : 0x0B | ||
193 | */ | ||
194 | #define AB4500_MCH_CTRL1 0x0B80 | ||
195 | #define AB4500_MCH_CTRL2 0x0B81 | ||
196 | #define AB4500_MCH_IPT_CURLVL_REG 0x0B82 | ||
197 | #define AB4500_CH_WD_REG 0x0B83 | ||
198 | |||
199 | /* | ||
200 | * Charger / USB control register offsets | ||
201 | * Bank : 0x0B | ||
202 | */ | ||
203 | #define AB4500_USBCH_CTRL1_REG 0x0BC0 | ||
204 | #define AB4500_USBCH_CTRL2_REG 0x0BC1 | ||
205 | #define AB4500_USBCH_IPT_CRNTLVL_REG 0x0BC2 | ||
206 | |||
207 | /* | ||
208 | * RTC bank register offsets | ||
209 | * Bank : 0xF | ||
210 | */ | ||
211 | #define AB4500_RTC_SOFF_STAT_REG 0x0F00 | ||
212 | #define AB4500_RTC_CC_CONF_REG 0x0F01 | ||
213 | #define AB4500_RTC_READ_REQ_REG 0x0F02 | ||
214 | #define AB4500_RTC_WATCH_TSECMID_REG 0x0F03 | ||
215 | #define AB4500_RTC_WATCH_TSECHI_REG 0x0F04 | ||
216 | #define AB4500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | ||
217 | #define AB4500_RTC_WATCH_TMIN_MID_REG 0x0F06 | ||
218 | #define AB4500_RTC_WATCH_TMIN_HI_REG 0x0F07 | ||
219 | #define AB4500_RTC_ALRM_MIN_LOW_REG 0x0F08 | ||
220 | #define AB4500_RTC_ALRM_MIN_MID_REG 0x0F09 | ||
221 | #define AB4500_RTC_ALRM_MIN_HI_REG 0x0F0A | ||
222 | #define AB4500_RTC_STAT_REG 0x0F0B | ||
223 | #define AB4500_RTC_BKUP_CHG_REG 0x0F0C | ||
224 | #define AB4500_RTC_FORCE_BKUP_REG 0x0F0D | ||
225 | #define AB4500_RTC_CALIB_REG 0x0F0E | ||
226 | #define AB4500_RTC_SWITCH_STAT_REG 0x0F0F | ||
227 | |||
228 | /* | ||
229 | * PWM Out generators | ||
230 | * Bank: 0x10 | ||
231 | */ | ||
232 | #define AB4500_PWM_OUT_CTRL1_REG 0x1060 | ||
233 | #define AB4500_PWM_OUT_CTRL2_REG 0x1061 | ||
234 | #define AB4500_PWM_OUT_CTRL3_REG 0x1062 | ||
235 | #define AB4500_PWM_OUT_CTRL4_REG 0x1063 | ||
236 | #define AB4500_PWM_OUT_CTRL5_REG 0x1064 | ||
237 | #define AB4500_PWM_OUT_CTRL6_REG 0x1065 | ||
238 | #define AB4500_PWM_OUT_CTRL7_REG 0x1066 | ||
239 | |||
240 | #define AB4500_I2C_PAD_CTRL_REG 0x1067 | ||
241 | #define AB4500_REV_REG 0x1080 | ||
242 | |||
243 | /** | ||
244 | * struct ab4500 | ||
245 | * @spi: spi device structure | ||
246 | * @tx_buf: transmit buffer | ||
247 | * @rx_buf: receive buffer | ||
248 | * @lock: sync primitive | ||
249 | */ | ||
250 | struct ab4500 { | ||
251 | struct spi_device *spi; | ||
252 | unsigned long tx_buf[4]; | ||
253 | unsigned long rx_buf[4]; | ||
254 | struct mutex lock; | ||
255 | }; | ||
256 | |||
257 | int ab4500_write(struct ab4500 *ab4500, unsigned char block, | ||
258 | unsigned long addr, unsigned char data); | ||
259 | int ab4500_read(struct ab4500 *ab4500, unsigned char block, | ||
260 | unsigned long addr); | ||
261 | |||
262 | #endif /* MFD_AB4500_H */ | ||
diff --git a/include/linux/mfd/adp5520.h b/include/linux/mfd/adp5520.h new file mode 100644 index 000000000000..ac37558a4673 --- /dev/null +++ b/include/linux/mfd/adp5520.h | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * Definitions and platform data for Analog Devices | ||
3 | * ADP5520/ADP5501 MFD PMICs (Backlight, LED, GPIO and Keys) | ||
4 | * | ||
5 | * Copyright 2009 Analog Devices Inc. | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | |||
11 | #ifndef __LINUX_MFD_ADP5520_H | ||
12 | #define __LINUX_MFD_ADP5520_H | ||
13 | |||
14 | #define ID_ADP5520 5520 | ||
15 | #define ID_ADP5501 5501 | ||
16 | |||
17 | /* | ||
18 | * ADP5520/ADP5501 Register Map | ||
19 | */ | ||
20 | |||
21 | #define ADP5520_MODE_STATUS 0x00 | ||
22 | #define ADP5520_INTERRUPT_ENABLE 0x01 | ||
23 | #define ADP5520_BL_CONTROL 0x02 | ||
24 | #define ADP5520_BL_TIME 0x03 | ||
25 | #define ADP5520_BL_FADE 0x04 | ||
26 | #define ADP5520_DAYLIGHT_MAX 0x05 | ||
27 | #define ADP5520_DAYLIGHT_DIM 0x06 | ||
28 | #define ADP5520_OFFICE_MAX 0x07 | ||
29 | #define ADP5520_OFFICE_DIM 0x08 | ||
30 | #define ADP5520_DARK_MAX 0x09 | ||
31 | #define ADP5520_DARK_DIM 0x0A | ||
32 | #define ADP5520_BL_VALUE 0x0B | ||
33 | #define ADP5520_ALS_CMPR_CFG 0x0C | ||
34 | #define ADP5520_L2_TRIP 0x0D | ||
35 | #define ADP5520_L2_HYS 0x0E | ||
36 | #define ADP5520_L3_TRIP 0x0F | ||
37 | #define ADP5520_L3_HYS 0x10 | ||
38 | #define ADP5520_LED_CONTROL 0x11 | ||
39 | #define ADP5520_LED_TIME 0x12 | ||
40 | #define ADP5520_LED_FADE 0x13 | ||
41 | #define ADP5520_LED1_CURRENT 0x14 | ||
42 | #define ADP5520_LED2_CURRENT 0x15 | ||
43 | #define ADP5520_LED3_CURRENT 0x16 | ||
44 | |||
45 | /* | ||
46 | * ADP5520 Register Map | ||
47 | */ | ||
48 | |||
49 | #define ADP5520_GPIO_CFG_1 0x17 | ||
50 | #define ADP5520_GPIO_CFG_2 0x18 | ||
51 | #define ADP5520_GPIO_IN 0x19 | ||
52 | #define ADP5520_GPIO_OUT 0x1A | ||
53 | #define ADP5520_GPIO_INT_EN 0x1B | ||
54 | #define ADP5520_GPIO_INT_STAT 0x1C | ||
55 | #define ADP5520_GPIO_INT_LVL 0x1D | ||
56 | #define ADP5520_GPIO_DEBOUNCE 0x1E | ||
57 | #define ADP5520_GPIO_PULLUP 0x1F | ||
58 | #define ADP5520_KP_INT_STAT_1 0x20 | ||
59 | #define ADP5520_KP_INT_STAT_2 0x21 | ||
60 | #define ADP5520_KR_INT_STAT_1 0x22 | ||
61 | #define ADP5520_KR_INT_STAT_2 0x23 | ||
62 | #define ADP5520_KEY_STAT_1 0x24 | ||
63 | #define ADP5520_KEY_STAT_2 0x25 | ||
64 | |||
65 | /* | ||
66 | * MODE_STATUS bits | ||
67 | */ | ||
68 | |||
69 | #define ADP5520_nSTNBY (1 << 7) | ||
70 | #define ADP5520_BL_EN (1 << 6) | ||
71 | #define ADP5520_DIM_EN (1 << 5) | ||
72 | #define ADP5520_OVP_INT (1 << 4) | ||
73 | #define ADP5520_CMPR_INT (1 << 3) | ||
74 | #define ADP5520_GPI_INT (1 << 2) | ||
75 | #define ADP5520_KR_INT (1 << 1) | ||
76 | #define ADP5520_KP_INT (1 << 0) | ||
77 | |||
78 | /* | ||
79 | * INTERRUPT_ENABLE bits | ||
80 | */ | ||
81 | |||
82 | #define ADP5520_AUTO_LD_EN (1 << 4) | ||
83 | #define ADP5520_CMPR_IEN (1 << 3) | ||
84 | #define ADP5520_OVP_IEN (1 << 2) | ||
85 | #define ADP5520_KR_IEN (1 << 1) | ||
86 | #define ADP5520_KP_IEN (1 << 0) | ||
87 | |||
88 | /* | ||
89 | * BL_CONTROL bits | ||
90 | */ | ||
91 | |||
92 | #define ADP5520_BL_LVL ((x) << 5) | ||
93 | #define ADP5520_BL_LAW ((x) << 4) | ||
94 | #define ADP5520_BL_AUTO_ADJ (1 << 3) | ||
95 | #define ADP5520_OVP_EN (1 << 2) | ||
96 | #define ADP5520_FOVR (1 << 1) | ||
97 | #define ADP5520_KP_BL_EN (1 << 0) | ||
98 | |||
99 | /* | ||
100 | * ALS_CMPR_CFG bits | ||
101 | */ | ||
102 | |||
103 | #define ADP5520_L3_OUT (1 << 3) | ||
104 | #define ADP5520_L2_OUT (1 << 2) | ||
105 | #define ADP5520_L3_EN (1 << 1) | ||
106 | |||
107 | #define ADP5020_MAX_BRIGHTNESS 0x7F | ||
108 | |||
109 | #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) | ||
110 | #define BL_CTRL_VAL(law, auto) (((1 & (auto)) << 3) | ((0x3 & (law)) << 4)) | ||
111 | #define ALS_CMPR_CFG_VAL(filt, l3_en) (((0x7 & filt) << 5) | l3_en) | ||
112 | |||
113 | /* | ||
114 | * LEDs subdevice bits and masks | ||
115 | */ | ||
116 | |||
117 | #define ADP5520_01_MAXLEDS 3 | ||
118 | |||
119 | #define ADP5520_FLAG_LED_MASK 0x3 | ||
120 | #define ADP5520_FLAG_OFFT_SHIFT 8 | ||
121 | #define ADP5520_FLAG_OFFT_MASK 0x3 | ||
122 | |||
123 | #define ADP5520_R3_MODE (1 << 5) | ||
124 | #define ADP5520_C3_MODE (1 << 4) | ||
125 | #define ADP5520_LED_LAW (1 << 3) | ||
126 | #define ADP5520_LED3_EN (1 << 2) | ||
127 | #define ADP5520_LED2_EN (1 << 1) | ||
128 | #define ADP5520_LED1_EN (1 << 0) | ||
129 | |||
130 | /* | ||
131 | * GPIO subdevice bits and masks | ||
132 | */ | ||
133 | |||
134 | #define ADP5520_MAXGPIOS 8 | ||
135 | |||
136 | #define ADP5520_GPIO_C3 (1 << 7) /* LED2 or GPIO7 aka C3 */ | ||
137 | #define ADP5520_GPIO_C2 (1 << 6) | ||
138 | #define ADP5520_GPIO_C1 (1 << 5) | ||
139 | #define ADP5520_GPIO_C0 (1 << 4) | ||
140 | #define ADP5520_GPIO_R3 (1 << 3) /* LED3 or GPIO3 aka R3 */ | ||
141 | #define ADP5520_GPIO_R2 (1 << 2) | ||
142 | #define ADP5520_GPIO_R1 (1 << 1) | ||
143 | #define ADP5520_GPIO_R0 (1 << 0) | ||
144 | |||
145 | struct adp5520_gpio_platform_data { | ||
146 | unsigned gpio_start; | ||
147 | u8 gpio_en_mask; | ||
148 | u8 gpio_pullup_mask; | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * Keypad subdevice bits and masks | ||
153 | */ | ||
154 | |||
155 | #define ADP5520_MAXKEYS 16 | ||
156 | |||
157 | #define ADP5520_COL_C3 (1 << 7) /* LED2 or GPIO7 aka C3 */ | ||
158 | #define ADP5520_COL_C2 (1 << 6) | ||
159 | #define ADP5520_COL_C1 (1 << 5) | ||
160 | #define ADP5520_COL_C0 (1 << 4) | ||
161 | #define ADP5520_ROW_R3 (1 << 3) /* LED3 or GPIO3 aka R3 */ | ||
162 | #define ADP5520_ROW_R2 (1 << 2) | ||
163 | #define ADP5520_ROW_R1 (1 << 1) | ||
164 | #define ADP5520_ROW_R0 (1 << 0) | ||
165 | |||
166 | #define ADP5520_KEY(row, col) (col + row * 4) | ||
167 | #define ADP5520_KEYMAPSIZE ADP5520_MAXKEYS | ||
168 | |||
169 | struct adp5520_keys_platform_data { | ||
170 | int rows_en_mask; /* Number of rows */ | ||
171 | int cols_en_mask; /* Number of columns */ | ||
172 | const unsigned short *keymap; /* Pointer to keymap */ | ||
173 | unsigned short keymapsize; /* Keymap size */ | ||
174 | unsigned repeat:1; /* Enable key repeat */ | ||
175 | }; | ||
176 | |||
177 | |||
178 | /* | ||
179 | * LEDs subdevice platform data | ||
180 | */ | ||
181 | |||
182 | #define FLAG_ID_ADP5520_LED1_ADP5501_LED0 1 /* ADP5520 PIN ILED */ | ||
183 | #define FLAG_ID_ADP5520_LED2_ADP5501_LED1 2 /* ADP5520 PIN C3 */ | ||
184 | #define FLAG_ID_ADP5520_LED3_ADP5501_LED2 3 /* ADP5520 PIN R3 */ | ||
185 | |||
186 | #define ADP5520_LED_DIS_BLINK (0 << ADP5520_FLAG_OFFT_SHIFT) | ||
187 | #define ADP5520_LED_OFFT_600ms (1 << ADP5520_FLAG_OFFT_SHIFT) | ||
188 | #define ADP5520_LED_OFFT_800ms (2 << ADP5520_FLAG_OFFT_SHIFT) | ||
189 | #define ADP5520_LED_OFFT_1200ms (3 << ADP5520_FLAG_OFFT_SHIFT) | ||
190 | |||
191 | #define ADP5520_LED_ONT_200ms 0 | ||
192 | #define ADP5520_LED_ONT_600ms 1 | ||
193 | #define ADP5520_LED_ONT_800ms 2 | ||
194 | #define ADP5520_LED_ONT_1200ms 3 | ||
195 | |||
196 | struct adp5520_leds_platform_data { | ||
197 | int num_leds; | ||
198 | struct led_info *leds; | ||
199 | u8 fade_in; /* Backlight Fade-In Timer */ | ||
200 | u8 fade_out; /* Backlight Fade-Out Timer */ | ||
201 | u8 led_on_time; | ||
202 | }; | ||
203 | |||
204 | /* | ||
205 | * Backlight subdevice platform data | ||
206 | */ | ||
207 | |||
208 | #define ADP5520_FADE_T_DIS 0 /* Fade Timer Disabled */ | ||
209 | #define ADP5520_FADE_T_300ms 1 /* 0.3 Sec */ | ||
210 | #define ADP5520_FADE_T_600ms 2 | ||
211 | #define ADP5520_FADE_T_900ms 3 | ||
212 | #define ADP5520_FADE_T_1200ms 4 | ||
213 | #define ADP5520_FADE_T_1500ms 5 | ||
214 | #define ADP5520_FADE_T_1800ms 6 | ||
215 | #define ADP5520_FADE_T_2100ms 7 | ||
216 | #define ADP5520_FADE_T_2400ms 8 | ||
217 | #define ADP5520_FADE_T_2700ms 9 | ||
218 | #define ADP5520_FADE_T_3000ms 10 | ||
219 | #define ADP5520_FADE_T_3500ms 11 | ||
220 | #define ADP5520_FADE_T_4000ms 12 | ||
221 | #define ADP5520_FADE_T_4500ms 13 | ||
222 | #define ADP5520_FADE_T_5000ms 14 | ||
223 | #define ADP5520_FADE_T_5500ms 15 /* 5.5 Sec */ | ||
224 | |||
225 | #define ADP5520_BL_LAW_LINEAR 0 | ||
226 | #define ADP5520_BL_LAW_SQUARE 1 | ||
227 | #define ADP5520_BL_LAW_CUBIC1 2 | ||
228 | #define ADP5520_BL_LAW_CUBIC2 3 | ||
229 | |||
230 | #define ADP5520_BL_AMBL_FILT_80ms 0 /* Light sensor filter time */ | ||
231 | #define ADP5520_BL_AMBL_FILT_160ms 1 | ||
232 | #define ADP5520_BL_AMBL_FILT_320ms 2 | ||
233 | #define ADP5520_BL_AMBL_FILT_640ms 3 | ||
234 | #define ADP5520_BL_AMBL_FILT_1280ms 4 | ||
235 | #define ADP5520_BL_AMBL_FILT_2560ms 5 | ||
236 | #define ADP5520_BL_AMBL_FILT_5120ms 6 | ||
237 | #define ADP5520_BL_AMBL_FILT_10240ms 7 /* 10.24 sec */ | ||
238 | |||
239 | /* | ||
240 | * Blacklight current 0..30mA | ||
241 | */ | ||
242 | #define ADP5520_BL_CUR_mA(I) ((I * 127) / 30) | ||
243 | |||
244 | /* | ||
245 | * L2 comparator current 0..1000uA | ||
246 | */ | ||
247 | #define ADP5520_L2_COMP_CURR_uA(I) ((I * 255) / 1000) | ||
248 | |||
249 | /* | ||
250 | * L3 comparator current 0..127uA | ||
251 | */ | ||
252 | #define ADP5520_L3_COMP_CURR_uA(I) ((I * 255) / 127) | ||
253 | |||
254 | struct adp5520_backlight_platform_data { | ||
255 | u8 fade_in; /* Backlight Fade-In Timer */ | ||
256 | u8 fade_out; /* Backlight Fade-Out Timer */ | ||
257 | u8 fade_led_law; /* fade-on/fade-off transfer characteristic */ | ||
258 | |||
259 | u8 en_ambl_sens; /* 1 = enable ambient light sensor */ | ||
260 | u8 abml_filt; /* Light sensor filter time */ | ||
261 | u8 l1_daylight_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
262 | u8 l1_daylight_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
263 | u8 l2_office_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
264 | u8 l2_office_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
265 | u8 l3_dark_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
266 | u8 l3_dark_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ | ||
267 | u8 l2_trip; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1000 uA */ | ||
268 | u8 l2_hyst; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1000 uA */ | ||
269 | u8 l3_trip; /* use L3_COMP_CURR_uA(I) 0 <= I <= 127 uA */ | ||
270 | u8 l3_hyst; /* use L3_COMP_CURR_uA(I) 0 <= I <= 127 uA */ | ||
271 | }; | ||
272 | |||
273 | /* | ||
274 | * MFD chip platform data | ||
275 | */ | ||
276 | |||
277 | struct adp5520_platform_data { | ||
278 | struct adp5520_keys_platform_data *keys; | ||
279 | struct adp5520_gpio_platform_data *gpio; | ||
280 | struct adp5520_leds_platform_data *leds; | ||
281 | struct adp5520_backlight_platform_data *backlight; | ||
282 | }; | ||
283 | |||
284 | /* | ||
285 | * MFD chip functions | ||
286 | */ | ||
287 | |||
288 | extern int adp5520_read(struct device *dev, int reg, uint8_t *val); | ||
289 | extern int adp5520_write(struct device *dev, int reg, u8 val); | ||
290 | extern int adp5520_clr_bits(struct device *dev, int reg, uint8_t bit_mask); | ||
291 | extern int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask); | ||
292 | |||
293 | extern int adp5520_register_notifier(struct device *dev, | ||
294 | struct notifier_block *nb, unsigned int events); | ||
295 | |||
296 | extern int adp5520_unregister_notifier(struct device *dev, | ||
297 | struct notifier_block *nb, unsigned int events); | ||
298 | |||
299 | #endif /* __LINUX_MFD_ADP5520_H */ | ||
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 3402042ddc31..40c372165f3e 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h | |||
@@ -231,9 +231,6 @@ void pcap_set_ts_bits(struct pcap_chip *, u32); | |||
231 | #define PCAP_LED_4MA 1 | 231 | #define PCAP_LED_4MA 1 |
232 | #define PCAP_LED_5MA 2 | 232 | #define PCAP_LED_5MA 2 |
233 | #define PCAP_LED_9MA 3 | 233 | #define PCAP_LED_9MA 3 |
234 | #define PCAP_LED_GPIO_VAL_MASK 0x00ffffff | ||
235 | #define PCAP_LED_GPIO_EN 0x01000000 | ||
236 | #define PCAP_LED_GPIO_INVERT 0x02000000 | ||
237 | #define PCAP_LED_T_MASK 0xf | 234 | #define PCAP_LED_T_MASK 0xf |
238 | #define PCAP_LED_C_MASK 0x3 | 235 | #define PCAP_LED_C_MASK 0x3 |
239 | #define PCAP_BL_MASK 0x1f | 236 | #define PCAP_BL_MASK 0x1f |
diff --git a/include/linux/mfd/mc13783-private.h b/include/linux/mfd/mc13783-private.h index 47e698cb0f16..95cf9360553f 100644 --- a/include/linux/mfd/mc13783-private.h +++ b/include/linux/mfd/mc13783-private.h | |||
@@ -24,52 +24,23 @@ | |||
24 | 24 | ||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/mfd/mc13783.h> | 26 | #include <linux/mfd/mc13783.h> |
27 | #include <linux/workqueue.h> | ||
28 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
29 | 28 | #include <linux/interrupt.h> | |
30 | struct mc13783_irq { | ||
31 | void (*handler)(int, void *); | ||
32 | void *data; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_NUM_IRQ 2 | ||
36 | #define MC13783_IRQ_TS 0 | ||
37 | #define MC13783_IRQ_REGULATOR 1 | ||
38 | |||
39 | #define MC13783_ADC_MODE_TS 1 | ||
40 | #define MC13783_ADC_MODE_SINGLE_CHAN 2 | ||
41 | #define MC13783_ADC_MODE_MULT_CHAN 3 | ||
42 | 29 | ||
43 | struct mc13783 { | 30 | struct mc13783 { |
44 | int revision; | 31 | struct spi_device *spidev; |
45 | struct device *dev; | 32 | struct mutex lock; |
46 | struct spi_device *spi_device; | ||
47 | |||
48 | int (*read_dev)(void *data, char reg, int count, u32 *dst); | ||
49 | int (*write_dev)(void *data, char reg, int count, const u32 *src); | ||
50 | |||
51 | struct mutex io_lock; | ||
52 | void *io_data; | ||
53 | int irq; | 33 | int irq; |
54 | unsigned int flags; | 34 | int flags; |
55 | 35 | ||
56 | struct mc13783_irq irq_handler[MC13783_NUM_IRQ]; | 36 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; |
57 | struct work_struct work; | 37 | void *irqdata[MC13783_NUM_IRQ]; |
58 | struct completion adc_done; | ||
59 | unsigned int ts_active; | ||
60 | struct mutex adc_conv_lock; | ||
61 | 38 | ||
39 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
62 | struct mc13783_regulator_init_data *regulators; | 40 | struct mc13783_regulator_init_data *regulators; |
63 | int num_regulators; | 41 | int num_regulators; |
64 | }; | 42 | }; |
65 | 43 | ||
66 | int mc13783_reg_read(struct mc13783 *, int reg_num, u32 *); | ||
67 | int mc13783_reg_write(struct mc13783 *, int, u32); | ||
68 | int mc13783_set_bits(struct mc13783 *, int, u32, u32); | ||
69 | int mc13783_free_irq(struct mc13783 *mc13783, int irq); | ||
70 | int mc13783_register_irq(struct mc13783 *mc13783, int irq, | ||
71 | void (*handler) (int, void *), void *data); | ||
72 | |||
73 | #define MC13783_REG_INTERRUPT_STATUS_0 0 | 44 | #define MC13783_REG_INTERRUPT_STATUS_0 0 |
74 | #define MC13783_REG_INTERRUPT_MASK_0 1 | 45 | #define MC13783_REG_INTERRUPT_MASK_0 1 |
75 | #define MC13783_REG_INTERRUPT_SENSE_0 2 | 46 | #define MC13783_REG_INTERRUPT_SENSE_0 2 |
@@ -136,55 +107,6 @@ int mc13783_register_irq(struct mc13783 *mc13783, int irq, | |||
136 | #define MC13783_REG_TEST_3 63 | 107 | #define MC13783_REG_TEST_3 63 |
137 | #define MC13783_REG_NB 64 | 108 | #define MC13783_REG_NB 64 |
138 | 109 | ||
139 | |||
140 | /* | ||
141 | * Interrupt Status | ||
142 | */ | ||
143 | #define MC13783_INT_STAT_ADCDONEI (1 << 0) | ||
144 | #define MC13783_INT_STAT_ADCBISDONEI (1 << 1) | ||
145 | #define MC13783_INT_STAT_TSI (1 << 2) | ||
146 | #define MC13783_INT_STAT_WHIGHI (1 << 3) | ||
147 | #define MC13783_INT_STAT_WLOWI (1 << 4) | ||
148 | #define MC13783_INT_STAT_CHGDETI (1 << 6) | ||
149 | #define MC13783_INT_STAT_CHGOVI (1 << 7) | ||
150 | #define MC13783_INT_STAT_CHGREVI (1 << 8) | ||
151 | #define MC13783_INT_STAT_CHGSHORTI (1 << 9) | ||
152 | #define MC13783_INT_STAT_CCCVI (1 << 10) | ||
153 | #define MC13783_INT_STAT_CHGCURRI (1 << 11) | ||
154 | #define MC13783_INT_STAT_BPONI (1 << 12) | ||
155 | #define MC13783_INT_STAT_LOBATLI (1 << 13) | ||
156 | #define MC13783_INT_STAT_LOBATHI (1 << 14) | ||
157 | #define MC13783_INT_STAT_UDPI (1 << 15) | ||
158 | #define MC13783_INT_STAT_USBI (1 << 16) | ||
159 | #define MC13783_INT_STAT_IDI (1 << 19) | ||
160 | #define MC13783_INT_STAT_Unused (1 << 20) | ||
161 | #define MC13783_INT_STAT_SE1I (1 << 21) | ||
162 | #define MC13783_INT_STAT_CKDETI (1 << 22) | ||
163 | #define MC13783_INT_STAT_UDMI (1 << 23) | ||
164 | |||
165 | /* | ||
166 | * Interrupt Mask | ||
167 | */ | ||
168 | #define MC13783_INT_MASK_ADCDONEM (1 << 0) | ||
169 | #define MC13783_INT_MASK_ADCBISDONEM (1 << 1) | ||
170 | #define MC13783_INT_MASK_TSM (1 << 2) | ||
171 | #define MC13783_INT_MASK_WHIGHM (1 << 3) | ||
172 | #define MC13783_INT_MASK_WLOWM (1 << 4) | ||
173 | #define MC13783_INT_MASK_CHGDETM (1 << 6) | ||
174 | #define MC13783_INT_MASK_CHGOVM (1 << 7) | ||
175 | #define MC13783_INT_MASK_CHGREVM (1 << 8) | ||
176 | #define MC13783_INT_MASK_CHGSHORTM (1 << 9) | ||
177 | #define MC13783_INT_MASK_CCCVM (1 << 10) | ||
178 | #define MC13783_INT_MASK_CHGCURRM (1 << 11) | ||
179 | #define MC13783_INT_MASK_BPONM (1 << 12) | ||
180 | #define MC13783_INT_MASK_LOBATLM (1 << 13) | ||
181 | #define MC13783_INT_MASK_LOBATHM (1 << 14) | ||
182 | #define MC13783_INT_MASK_UDPM (1 << 15) | ||
183 | #define MC13783_INT_MASK_USBM (1 << 16) | ||
184 | #define MC13783_INT_MASK_IDM (1 << 19) | ||
185 | #define MC13783_INT_MASK_SE1M (1 << 21) | ||
186 | #define MC13783_INT_MASK_CKDETM (1 << 22) | ||
187 | |||
188 | /* | 110 | /* |
189 | * Reg Regulator Mode 0 | 111 | * Reg Regulator Mode 0 |
190 | */ | 112 | */ |
@@ -284,113 +206,15 @@ int mc13783_register_irq(struct mc13783 *mc13783, int irq, | |||
284 | #define MC13783_SWCTRL_SW3_STBY (1 << 21) | 206 | #define MC13783_SWCTRL_SW3_STBY (1 << 21) |
285 | #define MC13783_SWCTRL_SW3_MODE (1 << 22) | 207 | #define MC13783_SWCTRL_SW3_MODE (1 << 22) |
286 | 208 | ||
287 | /* | 209 | static inline int mc13783_set_bits(struct mc13783 *mc13783, unsigned int offset, |
288 | * ADC/Touch | 210 | u32 mask, u32 val) |
289 | */ | 211 | { |
290 | #define MC13783_ADC0_LICELLCON (1 << 0) | 212 | int ret; |
291 | #define MC13783_ADC0_CHRGICON (1 << 1) | 213 | mc13783_lock(mc13783); |
292 | #define MC13783_ADC0_BATICON (1 << 2) | 214 | ret = mc13783_reg_rmw(mc13783, offset, mask, val); |
293 | #define MC13783_ADC0_RTHEN (1 << 3) | 215 | mc13783_unlock(mc13783); |
294 | #define MC13783_ADC0_DTHEN (1 << 4) | ||
295 | #define MC13783_ADC0_UIDEN (1 << 5) | ||
296 | #define MC13783_ADC0_ADOUTEN (1 << 6) | ||
297 | #define MC13783_ADC0_ADOUTPER (1 << 7) | ||
298 | #define MC13783_ADC0_ADREFEN (1 << 10) | ||
299 | #define MC13783_ADC0_ADREFMODE (1 << 11) | ||
300 | #define MC13783_ADC0_TSMOD0 (1 << 12) | ||
301 | #define MC13783_ADC0_TSMOD1 (1 << 13) | ||
302 | #define MC13783_ADC0_TSMOD2 (1 << 14) | ||
303 | #define MC13783_ADC0_CHRGRAWDIV (1 << 15) | ||
304 | #define MC13783_ADC0_ADINC1 (1 << 16) | ||
305 | #define MC13783_ADC0_ADINC2 (1 << 17) | ||
306 | #define MC13783_ADC0_WCOMP (1 << 18) | ||
307 | #define MC13783_ADC0_ADCBIS0 (1 << 23) | ||
308 | |||
309 | #define MC13783_ADC1_ADEN (1 << 0) | ||
310 | #define MC13783_ADC1_RAND (1 << 1) | ||
311 | #define MC13783_ADC1_ADSEL (1 << 3) | ||
312 | #define MC13783_ADC1_TRIGMASK (1 << 4) | ||
313 | #define MC13783_ADC1_ADA10 (1 << 5) | ||
314 | #define MC13783_ADC1_ADA11 (1 << 6) | ||
315 | #define MC13783_ADC1_ADA12 (1 << 7) | ||
316 | #define MC13783_ADC1_ADA20 (1 << 8) | ||
317 | #define MC13783_ADC1_ADA21 (1 << 9) | ||
318 | #define MC13783_ADC1_ADA22 (1 << 10) | ||
319 | #define MC13783_ADC1_ATO0 (1 << 11) | ||
320 | #define MC13783_ADC1_ATO1 (1 << 12) | ||
321 | #define MC13783_ADC1_ATO2 (1 << 13) | ||
322 | #define MC13783_ADC1_ATO3 (1 << 14) | ||
323 | #define MC13783_ADC1_ATO4 (1 << 15) | ||
324 | #define MC13783_ADC1_ATO5 (1 << 16) | ||
325 | #define MC13783_ADC1_ATO6 (1 << 17) | ||
326 | #define MC13783_ADC1_ATO7 (1 << 18) | ||
327 | #define MC13783_ADC1_ATOX (1 << 19) | ||
328 | #define MC13783_ADC1_ASC (1 << 20) | ||
329 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | ||
330 | #define MC13783_ADC1_ADONESHOT (1 << 22) | ||
331 | #define MC13783_ADC1_ADCBIS1 (1 << 23) | ||
332 | |||
333 | #define MC13783_ADC1_CHAN0_SHIFT 5 | ||
334 | #define MC13783_ADC1_CHAN1_SHIFT 8 | ||
335 | |||
336 | #define MC13783_ADC2_ADD10 (1 << 2) | ||
337 | #define MC13783_ADC2_ADD11 (1 << 3) | ||
338 | #define MC13783_ADC2_ADD12 (1 << 4) | ||
339 | #define MC13783_ADC2_ADD13 (1 << 5) | ||
340 | #define MC13783_ADC2_ADD14 (1 << 6) | ||
341 | #define MC13783_ADC2_ADD15 (1 << 7) | ||
342 | #define MC13783_ADC2_ADD16 (1 << 8) | ||
343 | #define MC13783_ADC2_ADD17 (1 << 9) | ||
344 | #define MC13783_ADC2_ADD18 (1 << 10) | ||
345 | #define MC13783_ADC2_ADD19 (1 << 11) | ||
346 | #define MC13783_ADC2_ADD20 (1 << 14) | ||
347 | #define MC13783_ADC2_ADD21 (1 << 15) | ||
348 | #define MC13783_ADC2_ADD22 (1 << 16) | ||
349 | #define MC13783_ADC2_ADD23 (1 << 17) | ||
350 | #define MC13783_ADC2_ADD24 (1 << 18) | ||
351 | #define MC13783_ADC2_ADD25 (1 << 19) | ||
352 | #define MC13783_ADC2_ADD26 (1 << 20) | ||
353 | #define MC13783_ADC2_ADD27 (1 << 21) | ||
354 | #define MC13783_ADC2_ADD28 (1 << 22) | ||
355 | #define MC13783_ADC2_ADD29 (1 << 23) | ||
356 | 216 | ||
357 | #define MC13783_ADC3_WHIGH0 (1 << 0) | 217 | return ret; |
358 | #define MC13783_ADC3_WHIGH1 (1 << 1) | 218 | } |
359 | #define MC13783_ADC3_WHIGH2 (1 << 2) | ||
360 | #define MC13783_ADC3_WHIGH3 (1 << 3) | ||
361 | #define MC13783_ADC3_WHIGH4 (1 << 4) | ||
362 | #define MC13783_ADC3_WHIGH5 (1 << 5) | ||
363 | #define MC13783_ADC3_ICID0 (1 << 6) | ||
364 | #define MC13783_ADC3_ICID1 (1 << 7) | ||
365 | #define MC13783_ADC3_ICID2 (1 << 8) | ||
366 | #define MC13783_ADC3_WLOW0 (1 << 9) | ||
367 | #define MC13783_ADC3_WLOW1 (1 << 10) | ||
368 | #define MC13783_ADC3_WLOW2 (1 << 11) | ||
369 | #define MC13783_ADC3_WLOW3 (1 << 12) | ||
370 | #define MC13783_ADC3_WLOW4 (1 << 13) | ||
371 | #define MC13783_ADC3_WLOW5 (1 << 14) | ||
372 | #define MC13783_ADC3_ADCBIS2 (1 << 23) | ||
373 | |||
374 | #define MC13783_ADC4_ADDBIS10 (1 << 2) | ||
375 | #define MC13783_ADC4_ADDBIS11 (1 << 3) | ||
376 | #define MC13783_ADC4_ADDBIS12 (1 << 4) | ||
377 | #define MC13783_ADC4_ADDBIS13 (1 << 5) | ||
378 | #define MC13783_ADC4_ADDBIS14 (1 << 6) | ||
379 | #define MC13783_ADC4_ADDBIS15 (1 << 7) | ||
380 | #define MC13783_ADC4_ADDBIS16 (1 << 8) | ||
381 | #define MC13783_ADC4_ADDBIS17 (1 << 9) | ||
382 | #define MC13783_ADC4_ADDBIS18 (1 << 10) | ||
383 | #define MC13783_ADC4_ADDBIS19 (1 << 11) | ||
384 | #define MC13783_ADC4_ADDBIS20 (1 << 14) | ||
385 | #define MC13783_ADC4_ADDBIS21 (1 << 15) | ||
386 | #define MC13783_ADC4_ADDBIS22 (1 << 16) | ||
387 | #define MC13783_ADC4_ADDBIS23 (1 << 17) | ||
388 | #define MC13783_ADC4_ADDBIS24 (1 << 18) | ||
389 | #define MC13783_ADC4_ADDBIS25 (1 << 19) | ||
390 | #define MC13783_ADC4_ADDBIS26 (1 << 20) | ||
391 | #define MC13783_ADC4_ADDBIS27 (1 << 21) | ||
392 | #define MC13783_ADC4_ADDBIS28 (1 << 22) | ||
393 | #define MC13783_ADC4_ADDBIS29 (1 << 23) | ||
394 | 219 | ||
395 | #endif /* __LINUX_MFD_MC13783_PRIV_H */ | 220 | #endif /* __LINUX_MFD_MC13783_PRIV_H */ |
396 | |||
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h index b3a2a7243573..35680409b8cf 100644 --- a/include/linux/mfd/mc13783.h +++ b/include/linux/mfd/mc13783.h | |||
@@ -1,28 +1,50 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | 2 | * Copyright 2009 Pengutronix |
3 | * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> | ||
3 | * | 4 | * |
4 | * Initial development of this code was funded by | 5 | * This program is free software; you can redistribute it and/or modify it under |
5 | * Phytec Messtechnik GmbH, http://www.phytec.de | 6 | * the terms of the GNU General Public License version 2 as published by the |
6 | * | 7 | * Free Software Foundation. |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | 8 | */ |
9 | #ifndef __LINUX_MFD_MC13783_H | ||
10 | #define __LINUX_MFD_MC13783_H | ||
21 | 11 | ||
22 | #ifndef __INCLUDE_LINUX_MFD_MC13783_H | 12 | #include <linux/interrupt.h> |
23 | #define __INCLUDE_LINUX_MFD_MC13783_H | ||
24 | 13 | ||
25 | struct mc13783; | 14 | struct mc13783; |
15 | |||
16 | void mc13783_lock(struct mc13783 *mc13783); | ||
17 | void mc13783_unlock(struct mc13783 *mc13783); | ||
18 | |||
19 | int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val); | ||
20 | int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val); | ||
21 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | ||
22 | u32 mask, u32 val); | ||
23 | |||
24 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, | ||
25 | irq_handler_t handler, const char *name, void *dev); | ||
26 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, | ||
27 | irq_handler_t handler, const char *name, void *dev); | ||
28 | int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev); | ||
29 | int mc13783_ackirq(struct mc13783 *mc13783, int irq); | ||
30 | |||
31 | int mc13783_mask(struct mc13783 *mc13783, int irq); | ||
32 | int mc13783_unmask(struct mc13783 *mc13783, int irq); | ||
33 | |||
34 | #define MC13783_ADC0 43 | ||
35 | #define MC13783_ADC0_ADREFEN (1 << 10) | ||
36 | #define MC13783_ADC0_ADREFMODE (1 << 11) | ||
37 | #define MC13783_ADC0_TSMOD0 (1 << 12) | ||
38 | #define MC13783_ADC0_TSMOD1 (1 << 13) | ||
39 | #define MC13783_ADC0_TSMOD2 (1 << 14) | ||
40 | #define MC13783_ADC0_ADINC1 (1 << 16) | ||
41 | #define MC13783_ADC0_ADINC2 (1 << 17) | ||
42 | |||
43 | #define MC13783_ADC0_TSMOD_MASK (MC13783_ADC0_TSMOD0 | \ | ||
44 | MC13783_ADC0_TSMOD1 | \ | ||
45 | MC13783_ADC0_TSMOD2) | ||
46 | |||
47 | /* to be cleaned up */ | ||
26 | struct regulator_init_data; | 48 | struct regulator_init_data; |
27 | 49 | ||
28 | struct mc13783_regulator_init_data { | 50 | struct mc13783_regulator_init_data { |
@@ -30,23 +52,30 @@ struct mc13783_regulator_init_data { | |||
30 | struct regulator_init_data *init_data; | 52 | struct regulator_init_data *init_data; |
31 | }; | 53 | }; |
32 | 54 | ||
33 | struct mc13783_platform_data { | 55 | struct mc13783_regulator_platform_data { |
34 | struct mc13783_regulator_init_data *regulators; | ||
35 | int num_regulators; | 56 | int num_regulators; |
36 | unsigned int flags; | 57 | struct mc13783_regulator_init_data *regulators; |
37 | }; | 58 | }; |
38 | 59 | ||
39 | /* mc13783_platform_data flags */ | 60 | struct mc13783_platform_data { |
61 | int num_regulators; | ||
62 | struct mc13783_regulator_init_data *regulators; | ||
63 | |||
40 | #define MC13783_USE_TOUCHSCREEN (1 << 0) | 64 | #define MC13783_USE_TOUCHSCREEN (1 << 0) |
41 | #define MC13783_USE_CODEC (1 << 1) | 65 | #define MC13783_USE_CODEC (1 << 1) |
42 | #define MC13783_USE_ADC (1 << 2) | 66 | #define MC13783_USE_ADC (1 << 2) |
43 | #define MC13783_USE_RTC (1 << 3) | 67 | #define MC13783_USE_RTC (1 << 3) |
44 | #define MC13783_USE_REGULATOR (1 << 4) | 68 | #define MC13783_USE_REGULATOR (1 << 4) |
69 | unsigned int flags; | ||
70 | }; | ||
71 | |||
72 | #define MC13783_ADC_MODE_TS 1 | ||
73 | #define MC13783_ADC_MODE_SINGLE_CHAN 2 | ||
74 | #define MC13783_ADC_MODE_MULT_CHAN 3 | ||
45 | 75 | ||
46 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | 76 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, |
47 | unsigned int channel, unsigned int *sample); | 77 | unsigned int channel, unsigned int *sample); |
48 | 78 | ||
49 | void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status); | ||
50 | 79 | ||
51 | #define MC13783_SW_SW1A 0 | 80 | #define MC13783_SW_SW1A 0 |
52 | #define MC13783_SW_SW1B 1 | 81 | #define MC13783_SW_SW1B 1 |
@@ -80,5 +109,46 @@ void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status); | |||
80 | #define MC13783_REGU_V3 29 | 109 | #define MC13783_REGU_V3 29 |
81 | #define MC13783_REGU_V4 30 | 110 | #define MC13783_REGU_V4 30 |
82 | 111 | ||
83 | #endif /* __INCLUDE_LINUX_MFD_MC13783_H */ | 112 | #define MC13783_IRQ_ADCDONE 0 |
113 | #define MC13783_IRQ_ADCBISDONE 1 | ||
114 | #define MC13783_IRQ_TS 2 | ||
115 | #define MC13783_IRQ_WHIGH 3 | ||
116 | #define MC13783_IRQ_WLOW 4 | ||
117 | #define MC13783_IRQ_CHGDET 6 | ||
118 | #define MC13783_IRQ_CHGOV 7 | ||
119 | #define MC13783_IRQ_CHGREV 8 | ||
120 | #define MC13783_IRQ_CHGSHORT 9 | ||
121 | #define MC13783_IRQ_CCCV 10 | ||
122 | #define MC13783_IRQ_CHGCURR 11 | ||
123 | #define MC13783_IRQ_BPON 12 | ||
124 | #define MC13783_IRQ_LOBATL 13 | ||
125 | #define MC13783_IRQ_LOBATH 14 | ||
126 | #define MC13783_IRQ_UDP 15 | ||
127 | #define MC13783_IRQ_USB 16 | ||
128 | #define MC13783_IRQ_ID 19 | ||
129 | #define MC13783_IRQ_SE1 21 | ||
130 | #define MC13783_IRQ_CKDET 22 | ||
131 | #define MC13783_IRQ_UDM 23 | ||
132 | #define MC13783_IRQ_1HZ 24 | ||
133 | #define MC13783_IRQ_TODA 25 | ||
134 | #define MC13783_IRQ_ONOFD1 27 | ||
135 | #define MC13783_IRQ_ONOFD2 28 | ||
136 | #define MC13783_IRQ_ONOFD3 29 | ||
137 | #define MC13783_IRQ_SYSRST 30 | ||
138 | #define MC13783_IRQ_RTCRST 31 | ||
139 | #define MC13783_IRQ_PC 32 | ||
140 | #define MC13783_IRQ_WARM 33 | ||
141 | #define MC13783_IRQ_MEMHLD 34 | ||
142 | #define MC13783_IRQ_PWRRDY 35 | ||
143 | #define MC13783_IRQ_THWARNL 36 | ||
144 | #define MC13783_IRQ_THWARNH 37 | ||
145 | #define MC13783_IRQ_CLK 38 | ||
146 | #define MC13783_IRQ_SEMAF 39 | ||
147 | #define MC13783_IRQ_MC2B 41 | ||
148 | #define MC13783_IRQ_HSDET 42 | ||
149 | #define MC13783_IRQ_HSL 43 | ||
150 | #define MC13783_IRQ_ALSPTH 44 | ||
151 | #define MC13783_IRQ_AHSSHORT 45 | ||
152 | #define MC13783_NUM_IRQ 46 | ||
84 | 153 | ||
154 | #endif /* __LINUX_MFD_MC13783_H */ | ||
diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index 9aba7b779fbc..d9034cc87f18 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h | |||
@@ -40,10 +40,6 @@ struct pcf50633_platform_data { | |||
40 | u8 resumers[5]; | 40 | u8 resumers[5]; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct pcf50633_subdev_pdata { | ||
44 | struct pcf50633 *pcf; | ||
45 | }; | ||
46 | |||
47 | struct pcf50633_irq { | 43 | struct pcf50633_irq { |
48 | void (*handler) (int, void *); | 44 | void (*handler) (int, void *); |
49 | void *data; | 45 | void *data; |
@@ -217,5 +213,9 @@ enum pcf50633_reg_int5 { | |||
217 | #define PCF50633_REG_LEDCTL 0x2a | 213 | #define PCF50633_REG_LEDCTL 0x2a |
218 | #define PCF50633_REG_LEDDIM 0x2b | 214 | #define PCF50633_REG_LEDDIM 0x2b |
219 | 215 | ||
220 | #endif | 216 | static inline struct pcf50633 *dev_to_pcf50633(struct device *dev) |
217 | { | ||
218 | return dev_get_drvdata(dev); | ||
219 | } | ||
221 | 220 | ||
221 | #endif | ||
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 91eb493bf14c..5184b79c700b 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #define __MFD_WM831X_CORE_H__ | 16 | #define __MFD_WM831X_CORE_H__ |
17 | 17 | ||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/workqueue.h> | ||
20 | 19 | ||
21 | /* | 20 | /* |
22 | * Register values. | 21 | * Register values. |
@@ -117,6 +116,7 @@ | |||
117 | #define WM831X_DC3_SLEEP_CONTROL 0x4063 | 116 | #define WM831X_DC3_SLEEP_CONTROL 0x4063 |
118 | #define WM831X_DC4_CONTROL 0x4064 | 117 | #define WM831X_DC4_CONTROL 0x4064 |
119 | #define WM831X_DC4_SLEEP_CONTROL 0x4065 | 118 | #define WM831X_DC4_SLEEP_CONTROL 0x4065 |
119 | #define WM832X_DC4_SLEEP_CONTROL 0x4067 | ||
120 | #define WM831X_EPE1_CONTROL 0x4066 | 120 | #define WM831X_EPE1_CONTROL 0x4066 |
121 | #define WM831X_EPE2_CONTROL 0x4067 | 121 | #define WM831X_EPE2_CONTROL 0x4067 |
122 | #define WM831X_LDO1_CONTROL 0x4068 | 122 | #define WM831X_LDO1_CONTROL 0x4068 |
@@ -235,6 +235,8 @@ | |||
235 | 235 | ||
236 | struct regulator_dev; | 236 | struct regulator_dev; |
237 | 237 | ||
238 | #define WM831X_NUM_IRQ_REGS 5 | ||
239 | |||
238 | struct wm831x { | 240 | struct wm831x { |
239 | struct mutex io_lock; | 241 | struct mutex io_lock; |
240 | 242 | ||
@@ -248,10 +250,11 @@ struct wm831x { | |||
248 | 250 | ||
249 | int irq; /* Our chip IRQ */ | 251 | int irq; /* Our chip IRQ */ |
250 | struct mutex irq_lock; | 252 | struct mutex irq_lock; |
251 | struct workqueue_struct *irq_wq; | ||
252 | struct work_struct irq_work; | ||
253 | unsigned int irq_base; | 253 | unsigned int irq_base; |
254 | int irq_masks[5]; | 254 | int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ |
255 | int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ | ||
256 | |||
257 | int num_gpio; | ||
255 | 258 | ||
256 | struct mutex auxadc_lock; | 259 | struct mutex auxadc_lock; |
257 | 260 | ||
@@ -278,12 +281,30 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, | |||
278 | int wm831x_irq_init(struct wm831x *wm831x, int irq); | 281 | int wm831x_irq_init(struct wm831x *wm831x, int irq); |
279 | void wm831x_irq_exit(struct wm831x *wm831x); | 282 | void wm831x_irq_exit(struct wm831x *wm831x); |
280 | 283 | ||
281 | int __must_check wm831x_request_irq(struct wm831x *wm831x, | 284 | static inline int __must_check wm831x_request_irq(struct wm831x *wm831x, |
282 | unsigned int irq, irq_handler_t handler, | 285 | unsigned int irq, |
283 | unsigned long flags, const char *name, | 286 | irq_handler_t handler, |
284 | void *dev); | 287 | unsigned long flags, |
285 | void wm831x_free_irq(struct wm831x *wm831x, unsigned int, void *); | 288 | const char *name, |
286 | void wm831x_disable_irq(struct wm831x *wm831x, int irq); | 289 | void *dev) |
287 | void wm831x_enable_irq(struct wm831x *wm831x, int irq); | 290 | { |
291 | return request_threaded_irq(irq, NULL, handler, flags, name, dev); | ||
292 | } | ||
293 | |||
294 | static inline void wm831x_free_irq(struct wm831x *wm831x, | ||
295 | unsigned int irq, void *dev) | ||
296 | { | ||
297 | free_irq(irq, dev); | ||
298 | } | ||
299 | |||
300 | static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
301 | { | ||
302 | disable_irq(irq); | ||
303 | } | ||
304 | |||
305 | static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq) | ||
306 | { | ||
307 | enable_irq(irq); | ||
308 | } | ||
288 | 309 | ||
289 | #endif | 310 | #endif |
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 90d820260aad..415c228743d5 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h | |||
@@ -91,6 +91,7 @@ struct wm831x_pdata { | |||
91 | /** Called after subdevices are set up */ | 91 | /** Called after subdevices are set up */ |
92 | int (*post_init)(struct wm831x *wm831x); | 92 | int (*post_init)(struct wm831x *wm831x); |
93 | 93 | ||
94 | int irq_base; | ||
94 | int gpio_base; | 95 | int gpio_base; |
95 | struct wm831x_backlight_pdata *backlight; | 96 | struct wm831x_backlight_pdata *backlight; |
96 | struct wm831x_backup_pdata *backup; | 97 | struct wm831x_backup_pdata *backup; |
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index 1d595de6a055..43868899bf49 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/workqueue.h> | 18 | #include <linux/interrupt.h> |
19 | 19 | ||
20 | #include <linux/mfd/wm8350/audio.h> | 20 | #include <linux/mfd/wm8350/audio.h> |
21 | #include <linux/mfd/wm8350/gpio.h> | 21 | #include <linux/mfd/wm8350/gpio.h> |
@@ -601,7 +601,7 @@ extern const u16 wm8352_mode3_defaults[]; | |||
601 | struct wm8350; | 601 | struct wm8350; |
602 | 602 | ||
603 | struct wm8350_irq { | 603 | struct wm8350_irq { |
604 | void (*handler) (struct wm8350 *, int, void *); | 604 | irq_handler_t handler; |
605 | void *data; | 605 | void *data; |
606 | }; | 606 | }; |
607 | 607 | ||
@@ -646,10 +646,12 @@ struct wm8350 { | |||
646 | * @init: Function called during driver initialisation. Should be | 646 | * @init: Function called during driver initialisation. Should be |
647 | * used by the platform to configure GPIO functions and similar. | 647 | * used by the platform to configure GPIO functions and similar. |
648 | * @irq_high: Set if WM8350 IRQ is active high. | 648 | * @irq_high: Set if WM8350 IRQ is active high. |
649 | * @irq_base: Base IRQ for genirq (not currently used). | ||
649 | */ | 650 | */ |
650 | struct wm8350_platform_data { | 651 | struct wm8350_platform_data { |
651 | int (*init)(struct wm8350 *wm8350); | 652 | int (*init)(struct wm8350 *wm8350); |
652 | int irq_high; | 653 | int irq_high; |
654 | int irq_base; | ||
653 | }; | 655 | }; |
654 | 656 | ||
655 | 657 | ||
@@ -676,11 +678,13 @@ int wm8350_block_write(struct wm8350 *wm8350, int reg, int size, u16 *src); | |||
676 | * WM8350 internal interrupts | 678 | * WM8350 internal interrupts |
677 | */ | 679 | */ |
678 | int wm8350_register_irq(struct wm8350 *wm8350, int irq, | 680 | int wm8350_register_irq(struct wm8350 *wm8350, int irq, |
679 | void (*handler) (struct wm8350 *, int, void *), | 681 | irq_handler_t handler, unsigned long flags, |
680 | void *data); | 682 | const char *name, void *data); |
681 | int wm8350_free_irq(struct wm8350 *wm8350, int irq); | 683 | int wm8350_free_irq(struct wm8350 *wm8350, int irq); |
682 | int wm8350_mask_irq(struct wm8350 *wm8350, int irq); | 684 | int wm8350_mask_irq(struct wm8350 *wm8350, int irq); |
683 | int wm8350_unmask_irq(struct wm8350 *wm8350, int irq); | 685 | int wm8350_unmask_irq(struct wm8350 *wm8350, int irq); |
684 | 686 | int wm8350_irq_init(struct wm8350 *wm8350, int irq, | |
687 | struct wm8350_platform_data *pdata); | ||
688 | int wm8350_irq_exit(struct wm8350 *wm8350); | ||
685 | 689 | ||
686 | #endif | 690 | #endif |
diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h index ed91e8f5d298..71af3d6ebe9d 100644 --- a/include/linux/mfd/wm8350/gpio.h +++ b/include/linux/mfd/wm8350/gpio.h | |||
@@ -173,6 +173,24 @@ | |||
173 | #define WM8350_GPIO_DEBOUNCE_ON 1 | 173 | #define WM8350_GPIO_DEBOUNCE_ON 1 |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * R30 (0x1E) - GPIO Interrupt Status | ||
177 | */ | ||
178 | #define WM8350_GP12_EINT 0x1000 | ||
179 | #define WM8350_GP11_EINT 0x0800 | ||
180 | #define WM8350_GP10_EINT 0x0400 | ||
181 | #define WM8350_GP9_EINT 0x0200 | ||
182 | #define WM8350_GP8_EINT 0x0100 | ||
183 | #define WM8350_GP7_EINT 0x0080 | ||
184 | #define WM8350_GP6_EINT 0x0040 | ||
185 | #define WM8350_GP5_EINT 0x0020 | ||
186 | #define WM8350_GP4_EINT 0x0010 | ||
187 | #define WM8350_GP3_EINT 0x0008 | ||
188 | #define WM8350_GP2_EINT 0x0004 | ||
189 | #define WM8350_GP1_EINT 0x0002 | ||
190 | #define WM8350_GP0_EINT 0x0001 | ||
191 | |||
192 | |||
193 | /* | ||
176 | * R128 (0x80) - GPIO Debounce | 194 | * R128 (0x80) - GPIO Debounce |
177 | */ | 195 | */ |
178 | #define WM8350_GP12_DB 0x1000 | 196 | #define WM8350_GP12_DB 0x1000 |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 5f1681f6ca76..2a27f7b56726 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/i2c/twl4030.h> | 29 | #include <linux/i2c/twl.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
@@ -175,7 +175,7 @@ static int twl4030_write(struct snd_soc_codec *codec, | |||
175 | { | 175 | { |
176 | twl4030_write_reg_cache(codec, reg, value); | 176 | twl4030_write_reg_cache(codec, reg, value); |
177 | if (likely(reg < TWL4030_REG_SW_SHADOW)) | 177 | if (likely(reg < TWL4030_REG_SW_SHADOW)) |
178 | return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, | 178 | return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, |
179 | reg); | 179 | reg); |
180 | else | 180 | else |
181 | return 0; | 181 | return 0; |
@@ -261,7 +261,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec) | |||
261 | do { | 261 | do { |
262 | /* this takes a little while, so don't slam i2c */ | 262 | /* this takes a little while, so don't slam i2c */ |
263 | udelay(2000); | 263 | udelay(2000); |
264 | twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | 264 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, |
265 | TWL4030_REG_ANAMICL); | 265 | TWL4030_REG_ANAMICL); |
266 | } while ((i++ < 100) && | 266 | } while ((i++ < 100) && |
267 | ((byte & TWL4030_CNCL_OFFSET_START) == | 267 | ((byte & TWL4030_CNCL_OFFSET_START) == |
@@ -542,7 +542,7 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ | |||
542 | break; \ | 542 | break; \ |
543 | case SND_SOC_DAPM_POST_PMD: \ | 543 | case SND_SOC_DAPM_POST_PMD: \ |
544 | reg_val = twl4030_read_reg_cache(w->codec, reg); \ | 544 | reg_val = twl4030_read_reg_cache(w->codec, reg); \ |
545 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ | 545 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ |
546 | reg_val & (~mask), \ | 546 | reg_val & (~mask), \ |
547 | reg); \ | 547 | reg); \ |
548 | break; \ | 548 | break; \ |
@@ -679,7 +679,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
679 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | 679 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / |
680 | twl4030->sysclk) + 1); | 680 | twl4030->sysclk) + 1); |
681 | /* Bypass the reg_cache to mute the headset */ | 681 | /* Bypass the reg_cache to mute the headset */ |
682 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 682 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
683 | hs_gain & (~0x0f), | 683 | hs_gain & (~0x0f), |
684 | TWL4030_REG_HS_GAIN_SET); | 684 | TWL4030_REG_HS_GAIN_SET); |
685 | 685 | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index f82125d9e85a..ebbf11b653a4 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1340,9 +1340,10 @@ static int wm8350_resume(struct platform_device *pdev) | |||
1340 | return 0; | 1340 | return 0; |
1341 | } | 1341 | } |
1342 | 1342 | ||
1343 | static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | 1343 | static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) |
1344 | { | 1344 | { |
1345 | struct wm8350_data *priv = data; | 1345 | struct wm8350_data *priv = data; |
1346 | struct wm8350 *wm8350 = priv->codec.control_data; | ||
1346 | u16 reg; | 1347 | u16 reg; |
1347 | int report; | 1348 | int report; |
1348 | int mask; | 1349 | int mask; |
@@ -1365,7 +1366,7 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | |||
1365 | 1366 | ||
1366 | if (!jack->jack) { | 1367 | if (!jack->jack) { |
1367 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | 1368 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); |
1368 | return; | 1369 | return IRQ_NONE; |
1369 | } | 1370 | } |
1370 | 1371 | ||
1371 | /* Debounce */ | 1372 | /* Debounce */ |
@@ -1378,6 +1379,8 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | |||
1378 | report = 0; | 1379 | report = 0; |
1379 | 1380 | ||
1380 | snd_soc_jack_report(jack->jack, report, jack->report); | 1381 | snd_soc_jack_report(jack->jack, report, jack->report); |
1382 | |||
1383 | return IRQ_HANDLED; | ||
1381 | } | 1384 | } |
1382 | 1385 | ||
1383 | /** | 1386 | /** |
@@ -1421,9 +1424,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | |||
1421 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); | 1424 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); |
1422 | 1425 | ||
1423 | /* Sync status */ | 1426 | /* Sync status */ |
1424 | wm8350_hp_jack_handler(wm8350, irq, priv); | 1427 | wm8350_hp_jack_handler(irq, priv); |
1425 | |||
1426 | wm8350_unmask_irq(wm8350, irq); | ||
1427 | 1428 | ||
1428 | return 0; | 1429 | return 0; |
1429 | } | 1430 | } |
@@ -1482,12 +1483,16 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1482 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, | 1483 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, |
1483 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); | 1484 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); |
1484 | 1485 | ||
1485 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | 1486 | /* Make sure jack detect is disabled to start off with */ |
1486 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | 1487 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, |
1488 | WM8350_JDL_ENA | WM8350_JDR_ENA); | ||
1489 | |||
1487 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, | 1490 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, |
1488 | wm8350_hp_jack_handler, priv); | 1491 | wm8350_hp_jack_handler, 0, "Left jack detect", |
1492 | priv); | ||
1489 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, | 1493 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, |
1490 | wm8350_hp_jack_handler, priv); | 1494 | wm8350_hp_jack_handler, 0, "Right jack detect", |
1495 | priv); | ||
1491 | 1496 | ||
1492 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1497 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1493 | if (ret < 0) { | 1498 | if (ret < 0) { |
@@ -1516,8 +1521,6 @@ static int wm8350_remove(struct platform_device *pdev) | |||
1516 | WM8350_JDL_ENA | WM8350_JDR_ENA); | 1521 | WM8350_JDL_ENA | WM8350_JDR_ENA); |
1517 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | 1522 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); |
1518 | 1523 | ||
1519 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
1520 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
1521 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | 1524 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); |
1522 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | 1525 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); |
1523 | 1526 | ||