aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/usb-host.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/usb-host.c')
-rw-r--r--arch/arm/mach-omap2/usb-host.c160
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 */
535static 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
545static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */
546static 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 */
556static 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
607int 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}