diff options
Diffstat (limited to 'arch/arm/mach-omap2/usb-host.c')
-rw-r--r-- | arch/arm/mach-omap2/usb-host.c | 160 |
1 files changed, 158 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 5706bdccf45e..aa27d7f5cbb7 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c | |||
@@ -22,8 +22,12 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | 25 | #include <linux/regulator/machine.h> | |
26 | #include <asm/io.h> | 26 | #include <linux/regulator/fixed.h> |
27 | #include <linux/string.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/usb/phy.h> | ||
27 | 31 | ||
28 | #include "soc.h" | 32 | #include "soc.h" |
29 | #include "omap_device.h" | 33 | #include "omap_device.h" |
@@ -526,3 +530,155 @@ void __init usbhs_init(struct usbhs_omap_platform_data *pdata) | |||
526 | } | 530 | } |
527 | 531 | ||
528 | #endif | 532 | #endif |
533 | |||
534 | /* Template for PHY regulators */ | ||
535 | static struct fixed_voltage_config hsusb_reg_config = { | ||
536 | /* .supply_name filled later */ | ||
537 | .microvolts = 3300000, | ||
538 | .gpio = -1, /* updated later */ | ||
539 | .startup_delay = 70000, /* 70msec */ | ||
540 | .enable_high = 1, /* updated later */ | ||
541 | .enabled_at_boot = 0, /* keep in RESET */ | ||
542 | /* .init_data filled later */ | ||
543 | }; | ||
544 | |||
545 | static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */ | ||
546 | static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */ | ||
547 | |||
548 | /** | ||
549 | * usbhs_add_regulator - Add a gpio based fixed voltage regulator device | ||
550 | * @name: name for the regulator | ||
551 | * @dev_id: device id of the device this regulator supplies power to | ||
552 | * @dev_supply: supply name that the device expects | ||
553 | * @gpio: GPIO number | ||
554 | * @polarity: 1 - Active high, 0 - Active low | ||
555 | */ | ||
556 | static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, | ||
557 | int gpio, int polarity) | ||
558 | { | ||
559 | struct regulator_consumer_supply *supplies; | ||
560 | struct regulator_init_data *reg_data; | ||
561 | struct fixed_voltage_config *config; | ||
562 | struct platform_device *pdev; | ||
563 | int ret; | ||
564 | |||
565 | supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); | ||
566 | if (!supplies) | ||
567 | return -ENOMEM; | ||
568 | |||
569 | supplies->supply = dev_supply; | ||
570 | supplies->dev_name = dev_id; | ||
571 | |||
572 | reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL); | ||
573 | if (!reg_data) | ||
574 | return -ENOMEM; | ||
575 | |||
576 | reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; | ||
577 | reg_data->consumer_supplies = supplies; | ||
578 | reg_data->num_consumer_supplies = 1; | ||
579 | |||
580 | config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), | ||
581 | GFP_KERNEL); | ||
582 | if (!config) | ||
583 | return -ENOMEM; | ||
584 | |||
585 | config->supply_name = name; | ||
586 | config->gpio = gpio; | ||
587 | config->enable_high = polarity; | ||
588 | config->init_data = reg_data; | ||
589 | |||
590 | /* create a regulator device */ | ||
591 | pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); | ||
592 | if (!pdev) | ||
593 | return -ENOMEM; | ||
594 | |||
595 | pdev->id = PLATFORM_DEVID_AUTO; | ||
596 | pdev->name = reg_name; | ||
597 | pdev->dev.platform_data = config; | ||
598 | |||
599 | ret = platform_device_register(pdev); | ||
600 | if (ret) | ||
601 | pr_err("%s: Failed registering regulator %s for %s\n", | ||
602 | __func__, name, dev_id); | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) | ||
608 | { | ||
609 | char *rail_name; | ||
610 | int i, len; | ||
611 | struct platform_device *pdev; | ||
612 | char *phy_id; | ||
613 | |||
614 | /* the phy_id will be something like "nop_usb_xceiv.1" */ | ||
615 | len = strlen(nop_name) + 3; /* 3 -> ".1" and NULL terminator */ | ||
616 | |||
617 | for (i = 0; i < num_phys; i++) { | ||
618 | |||
619 | if (!phy->port) { | ||
620 | pr_err("%s: Invalid port 0. Must start from 1\n", | ||
621 | __func__); | ||
622 | continue; | ||
623 | } | ||
624 | |||
625 | /* do we need a NOP PHY device ? */ | ||
626 | if (!gpio_is_valid(phy->reset_gpio) && | ||
627 | !gpio_is_valid(phy->vcc_gpio)) | ||
628 | continue; | ||
629 | |||
630 | /* create a NOP PHY device */ | ||
631 | pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); | ||
632 | if (!pdev) | ||
633 | return -ENOMEM; | ||
634 | |||
635 | pdev->id = phy->port; | ||
636 | pdev->name = nop_name; | ||
637 | pdev->dev.platform_data = phy->platform_data; | ||
638 | |||
639 | phy_id = kmalloc(len, GFP_KERNEL); | ||
640 | if (!phy_id) | ||
641 | return -ENOMEM; | ||
642 | |||
643 | scnprintf(phy_id, len, "nop_usb_xceiv.%d\n", | ||
644 | pdev->id); | ||
645 | |||
646 | if (platform_device_register(pdev)) { | ||
647 | pr_err("%s: Failed to register device %s\n", | ||
648 | __func__, phy_id); | ||
649 | continue; | ||
650 | } | ||
651 | |||
652 | usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id); | ||
653 | |||
654 | /* Do we need RESET regulator ? */ | ||
655 | if (gpio_is_valid(phy->reset_gpio)) { | ||
656 | |||
657 | rail_name = kmalloc(13, GFP_KERNEL); | ||
658 | if (!rail_name) | ||
659 | return -ENOMEM; | ||
660 | |||
661 | scnprintf(rail_name, 13, "hsusb%d_reset", phy->port); | ||
662 | |||
663 | usbhs_add_regulator(rail_name, phy_id, "reset", | ||
664 | phy->reset_gpio, 1); | ||
665 | } | ||
666 | |||
667 | /* Do we need VCC regulator ? */ | ||
668 | if (gpio_is_valid(phy->vcc_gpio)) { | ||
669 | |||
670 | rail_name = kmalloc(13, GFP_KERNEL); | ||
671 | if (!rail_name) | ||
672 | return -ENOMEM; | ||
673 | |||
674 | scnprintf(rail_name, 13, "hsusb%d_vcc", phy->port); | ||
675 | |||
676 | usbhs_add_regulator(rail_name, phy_id, "vcc", | ||
677 | phy->vcc_gpio, phy->vcc_polarity); | ||
678 | } | ||
679 | |||
680 | phy++; | ||
681 | } | ||
682 | |||
683 | return 0; | ||
684 | } | ||