diff options
author | Mike Rapoport <mike@compulab.co.il> | 2009-02-02 01:57:51 -0500 |
---|---|---|
committer | Eric Miao <eric.miao@marvell.com> | 2009-02-02 04:40:16 -0500 |
commit | 6432f46c4ffd0a85cab5313bc989a6db32bc0eb4 (patch) | |
tree | e2c72256bc068043d544c764443d1406db4e336a /arch/arm/mach-pxa/em-x270.c | |
parent | 6489c611db095356645ca1a2689e93c63caeb310 (diff) |
[ARM] pxa/em-x270: update MMC/SDIO implementation
Signed-off-by: Mike Rapoport <mike@compulab.co.il>
Signed-off-by: Eric Miao <eric.miao@marvell.com>
Diffstat (limited to 'arch/arm/mach-pxa/em-x270.c')
-rw-r--r-- | arch/arm/mach-pxa/em-x270.c | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 1aaae97de7d3..05f9e9e1224b 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c | |||
@@ -43,12 +43,12 @@ | |||
43 | #include <mach/pxa2xx_spi.h> | 43 | #include <mach/pxa2xx_spi.h> |
44 | 44 | ||
45 | #include "generic.h" | 45 | #include "generic.h" |
46 | #include "devices.h" | ||
46 | 47 | ||
47 | /* GPIO IRQ usage */ | 48 | /* GPIO IRQ usage */ |
48 | #define GPIO41_ETHIRQ (41) | 49 | #define GPIO41_ETHIRQ (41) |
49 | #define GPIO13_MMC_CD (13) | 50 | #define GPIO13_MMC_CD (13) |
50 | #define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) | 51 | #define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) |
51 | #define EM_X270_MMC_CD IRQ_GPIO(GPIO13_MMC_CD) | ||
52 | 52 | ||
53 | /* NAND control GPIOs */ | 53 | /* NAND control GPIOs */ |
54 | #define GPIO11_NAND_CS (11) | 54 | #define GPIO11_NAND_CS (11) |
@@ -56,6 +56,7 @@ | |||
56 | 56 | ||
57 | /* Miscelaneous GPIOs */ | 57 | /* Miscelaneous GPIOs */ |
58 | #define GPIO93_CAM_RESET (93) | 58 | #define GPIO93_CAM_RESET (93) |
59 | #define GPIO95_MMC_WP (95) | ||
59 | 60 | ||
60 | static unsigned long em_x270_pin_config[] = { | 61 | static unsigned long em_x270_pin_config[] = { |
61 | /* AC'97 */ | 62 | /* AC'97 */ |
@@ -163,7 +164,8 @@ static unsigned long em_x270_pin_config[] = { | |||
163 | GPIO18_RDY, | 164 | GPIO18_RDY, |
164 | 165 | ||
165 | /* GPIO */ | 166 | /* GPIO */ |
166 | GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, | 167 | GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, /* sleep/resume button */ |
168 | GPIO95_GPIO, /* MMC Write protect */ | ||
167 | 169 | ||
168 | /* power controls */ | 170 | /* power controls */ |
169 | GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ | 171 | GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ |
@@ -464,47 +466,86 @@ static inline void em_x270_init_ohci(void) {} | |||
464 | 466 | ||
465 | /* MCI controller setup */ | 467 | /* MCI controller setup */ |
466 | #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) | 468 | #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) |
469 | static struct regulator *em_x270_sdio_ldo; | ||
470 | |||
467 | static int em_x270_mci_init(struct device *dev, | 471 | static int em_x270_mci_init(struct device *dev, |
468 | irq_handler_t em_x270_detect_int, | 472 | irq_handler_t em_x270_detect_int, |
469 | void *data) | 473 | void *data) |
470 | { | 474 | { |
471 | int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int, | 475 | int err; |
472 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | 476 | |
477 | em_x270_sdio_ldo = regulator_get(dev, "vcc sdio"); | ||
478 | if (IS_ERR(em_x270_sdio_ldo)) { | ||
479 | dev_err(dev, "can't request SDIO power supply: %ld\n", | ||
480 | PTR_ERR(em_x270_sdio_ldo)); | ||
481 | return PTR_ERR(em_x270_sdio_ldo); | ||
482 | } | ||
483 | |||
484 | err = request_irq(gpio_to_irq(GPIO13_MMC_CD), em_x270_detect_int, | ||
485 | IRQF_DISABLED | IRQF_TRIGGER_RISING | | ||
486 | IRQF_TRIGGER_FALLING, | ||
473 | "MMC card detect", data); | 487 | "MMC card detect", data); |
474 | if (err) { | 488 | if (err) { |
475 | printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n", | 489 | dev_err(dev, "can't request MMC card detect IRQ: %d\n", err); |
476 | __func__, err); | 490 | goto err_irq; |
477 | return err; | 491 | } |
492 | |||
493 | err = gpio_request(GPIO95_MMC_WP, "MMC WP"); | ||
494 | if (err) { | ||
495 | dev_err(dev, "can't request MMC write protect: %d\n", err); | ||
496 | goto err_gpio_wp; | ||
478 | } | 497 | } |
479 | 498 | ||
499 | gpio_direction_input(GPIO95_MMC_WP); | ||
500 | |||
480 | return 0; | 501 | return 0; |
502 | |||
503 | err_gpio_wp: | ||
504 | free_irq(gpio_to_irq(GPIO13_MMC_CD), data); | ||
505 | err_irq: | ||
506 | regulator_put(em_x270_sdio_ldo); | ||
507 | |||
508 | return err; | ||
481 | } | 509 | } |
482 | 510 | ||
483 | static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) | 511 | static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) |
484 | { | 512 | { |
485 | /* | 513 | struct pxamci_platform_data* p_d = dev->platform_data; |
486 | FIXME: current hardware implementation does not allow to | 514 | |
487 | enable/disable MMC power. This will be fixed in next HW releases, | 515 | if ((1 << vdd) & p_d->ocr_mask) { |
488 | and we'll need to add implmentation here. | 516 | int vdd_uV = (2000 + (vdd - __ffs(MMC_VDD_20_21)) * 100) * 1000; |
489 | */ | 517 | |
490 | return; | 518 | regulator_set_voltage(em_x270_sdio_ldo, vdd_uV, vdd_uV); |
519 | regulator_enable(em_x270_sdio_ldo); | ||
520 | } else { | ||
521 | regulator_disable(em_x270_sdio_ldo); | ||
522 | } | ||
491 | } | 523 | } |
492 | 524 | ||
493 | static void em_x270_mci_exit(struct device *dev, void *data) | 525 | static void em_x270_mci_exit(struct device *dev, void *data) |
494 | { | 526 | { |
495 | int irq = gpio_to_irq(GPIO13_MMC_CD); | 527 | free_irq(gpio_to_irq(GPIO13_MMC_CD), data); |
496 | free_irq(irq, data); | 528 | } |
529 | |||
530 | static int em_x270_mci_get_ro(struct device *dev) | ||
531 | { | ||
532 | return gpio_get_value(GPIO95_MMC_WP); | ||
497 | } | 533 | } |
498 | 534 | ||
499 | static struct pxamci_platform_data em_x270_mci_platform_data = { | 535 | static struct pxamci_platform_data em_x270_mci_platform_data = { |
500 | .ocr_mask = MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31, | 536 | .ocr_mask = MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23| |
537 | MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27| | ||
538 | MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30| | ||
539 | MMC_VDD_30_31|MMC_VDD_31_32, | ||
501 | .init = em_x270_mci_init, | 540 | .init = em_x270_mci_init, |
502 | .setpower = em_x270_mci_setpower, | 541 | .setpower = em_x270_mci_setpower, |
542 | .get_ro = em_x270_mci_get_ro, | ||
503 | .exit = em_x270_mci_exit, | 543 | .exit = em_x270_mci_exit, |
504 | }; | 544 | }; |
505 | 545 | ||
506 | static void __init em_x270_init_mmc(void) | 546 | static void __init em_x270_init_mmc(void) |
507 | { | 547 | { |
548 | em_x270_mci_platform_data.detect_delay = msecs_to_jiffies(250); | ||
508 | pxa_set_mci_info(&em_x270_mci_platform_data); | 549 | pxa_set_mci_info(&em_x270_mci_platform_data); |
509 | } | 550 | } |
510 | #else | 551 | #else |
@@ -757,6 +798,13 @@ static struct regulator_consumer_supply ldo5_consumers[] = { | |||
757 | }, | 798 | }, |
758 | }; | 799 | }; |
759 | 800 | ||
801 | static struct regulator_consumer_supply ldo10_consumers[] = { | ||
802 | { | ||
803 | .dev = &pxa_device_mci.dev, | ||
804 | .supply = "vcc sdio", | ||
805 | }, | ||
806 | }; | ||
807 | |||
760 | static struct regulator_consumer_supply ldo12_consumers[] = { | 808 | static struct regulator_consumer_supply ldo12_consumers[] = { |
761 | { | 809 | { |
762 | .dev = NULL, | 810 | .dev = NULL, |
@@ -795,6 +843,19 @@ static struct regulator_init_data ldo5_data = { | |||
795 | .consumer_supplies = ldo5_consumers, | 843 | .consumer_supplies = ldo5_consumers, |
796 | }; | 844 | }; |
797 | 845 | ||
846 | static struct regulator_init_data ldo10_data = { | ||
847 | .constraints = { | ||
848 | .min_uV = 2000000, | ||
849 | .max_uV = 3200000, | ||
850 | .state_mem = { | ||
851 | .enabled = 0, | ||
852 | }, | ||
853 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, | ||
854 | }, | ||
855 | .num_consumer_supplies = ARRAY_SIZE(ldo10_consumers), | ||
856 | .consumer_supplies = ldo10_consumers, | ||
857 | }; | ||
858 | |||
798 | static struct regulator_init_data ldo12_data = { | 859 | static struct regulator_init_data ldo12_data = { |
799 | .constraints = { | 860 | .constraints = { |
800 | .min_uV = 3000000, | 861 | .min_uV = 3000000, |
@@ -835,6 +896,10 @@ struct da903x_subdev_info em_x270_da9030_subdevs[] = { | |||
835 | .platform_data = &ldo5_data, | 896 | .platform_data = &ldo5_data, |
836 | }, { | 897 | }, { |
837 | .name = "da903x-regulator", | 898 | .name = "da903x-regulator", |
899 | .id = DA9030_ID_LDO10, | ||
900 | .platform_data = &ldo10_data, | ||
901 | }, { | ||
902 | .name = "da903x-regulator", | ||
838 | .id = DA9030_ID_LDO12, | 903 | .id = DA9030_ID_LDO12, |
839 | .platform_data = &ldo12_data, | 904 | .platform_data = &ldo12_data, |
840 | }, { | 905 | }, { |