From patchwork Mon Mar 18 12:51:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 2292981 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 2BD18DF215 for ; Mon, 18 Mar 2013 14:51:26 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UHbLw-000702-W8; Mon, 18 Mar 2013 14:47:57 +0000 Received: from arroyo.ext.ti.com ([192.94.94.40]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UHZXL-0006aS-9i for linux-arm-kernel@lists.infradead.org; Mon, 18 Mar 2013 12:51:39 +0000 Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id r2ICpPVK007059; Mon, 18 Mar 2013 07:51:25 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id r2ICpPTR016671; Mon, 18 Mar 2013 07:51:25 -0500 Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.2.342.3; Mon, 18 Mar 2013 07:51:25 -0500 Received: from localhost.localdomain (h114-173.vpn.ti.com [172.24.114.173]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id r2ICpJt0020871; Mon, 18 Mar 2013 07:51:23 -0500 From: Roger Quadros To: Subject: [PATCH v3 2/4] ARM: OMAP2+: omap-usb-host: Add usbhs_init_phys() Date: Mon, 18 Mar 2013 14:51:16 +0200 Message-ID: <1363611078-13002-3-git-send-email-rogerq@ti.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1363611078-13002-1-git-send-email-rogerq@ti.com> References: <1363611078-13002-1-git-send-email-rogerq@ti.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130318_085137_369422_11D2424A X-CRM114-Status: GOOD ( 16.96 ) X-Spam-Score: -9.4 (---------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-9.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [192.94.94.40 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -2.5 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, balbi@ti.com, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rogerq@ti.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This helper allows board support code to add the PHY's VCC and RESET regulators which are GPIO controlled as well as the NOP PHY device. Signed-off-by: Roger Quadros --- arch/arm/mach-omap2/usb-host.c | 177 +++++++++++++++++++++++++++++++++++++++- arch/arm/mach-omap2/usb.h | 9 ++ 2 files changed, 184 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 5706bdc..49a2c3f 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -22,8 +22,12 @@ #include #include #include - -#include +#include +#include +#include +#include +#include +#include #include "soc.h" #include "omap_device.h" @@ -526,3 +530,172 @@ void __init usbhs_init(struct usbhs_omap_platform_data *pdata) } #endif + +/* Template for PHY regulators */ +static struct regulator_consumer_supply hsusb_reg_supplies[] = { + { /* .supply & .dev_name filled later */ }, +}; + +static struct regulator_init_data hsusb_reg_data = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = hsusb_reg_supplies, + .num_consumer_supplies = ARRAY_SIZE(hsusb_reg_supplies), +}; + +static struct fixed_voltage_config hsusb_reg_config = { + /* .supply_name filled later */ + .microvolts = 3300000, + .gpio = -1, /* updated later */ + .startup_delay = 70000, /* 70msec */ + .enable_high = 1, /* updated later */ + .enabled_at_boot = 0, /* keep in RESET */ + /* .init_data filled later */ +}; + +static struct platform_device_info hsusb_reg_pdev_info = { + .name = "reg-fixed-voltage", + .id = PLATFORM_DEVID_AUTO, +}; + +static const char *reset_supply = "reset"; +static const char *vcc_supply = "vcc"; +static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */ + +int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) +{ + struct regulator_consumer_supply *supplies; + struct regulator_init_data *reg_data; + struct fixed_voltage_config *config; + char *supply_name; + int i, len; + struct platform_device *pdev; + char *phy_id; + + /* the phy_id will be something like "nop_usb_xceiv.1" */ + len = strlen(nop_name) + 3; /* 3 -> ".1" and NULL terminator */ + + for (i = 0; i < num_phys; i++) { + + if (!phy->port) { + pr_err("%s: Invalid port 0. Must start from 1\n", + __func__); + continue; + } + + /* do we need a NOP PHY device ? */ + if (!gpio_is_valid(phy->reset_gpio) && + !gpio_is_valid(phy->vcc_gpio)) + continue; + + /* create a NOP PHY device */ + pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); + if (!pdev) + return -ENOMEM; + + pdev->id = phy->port; + pdev->name = nop_name; + pdev->dev.platform_data = phy->platform_data; + + phy_id = kmalloc(len, GFP_KERNEL); + if (!phy_id) + return -ENOMEM; + + scnprintf(phy_id, len, "nop_usb_xceiv.%d\n", + pdev->id); + + if (platform_device_register(pdev)) { + pr_err("%s: Failed to register device %s\n", + __func__, phy_id); + continue; + } + + usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id); + + /* Do we need RESET regulator ? */ + if (!gpio_is_valid(phy->reset_gpio)) + goto check_vcc; + + supplies = kmemdup(hsusb_reg_supplies, + ARRAY_SIZE(hsusb_reg_supplies) * + sizeof(struct regulator_consumer_supply), + GFP_KERNEL); + if (!supplies) + return -ENOMEM; + + supplies->supply = reset_supply; + supplies->dev_name = phy_id; + + reg_data = kmemdup(&hsusb_reg_data, sizeof(hsusb_reg_data), + GFP_KERNEL); + if (!reg_data) + return -ENOMEM; + + reg_data->consumer_supplies = supplies; + + config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), + GFP_KERNEL); + if (!config) + return -ENOMEM; + + supply_name = kmalloc(13, GFP_KERNEL); + if (!supply_name) + return -ENOMEM; + + scnprintf(supply_name, 13, "hsusb%d_reset", phy->port); + config->supply_name = supply_name; + config->gpio = phy->reset_gpio; + config->init_data = reg_data; + + hsusb_reg_pdev_info.data = config; + hsusb_reg_pdev_info.size_data = sizeof(hsusb_reg_config); + platform_device_register_full(&hsusb_reg_pdev_info); + +check_vcc: + /* Do we need VCC regulator? */ + if (!gpio_is_valid(phy->vcc_gpio)) + goto next; + + supplies = kmemdup(hsusb_reg_supplies, + ARRAY_SIZE(hsusb_reg_supplies) * + sizeof(struct regulator_consumer_supply), + GFP_KERNEL); + if (!supplies) + return -ENOMEM; + + supplies->supply = vcc_supply; + supplies->dev_name = phy_id; + + reg_data = kmemdup(&hsusb_reg_data, sizeof(hsusb_reg_data), + GFP_KERNEL); + if (!reg_data) + return -ENOMEM; + + reg_data->consumer_supplies = supplies; + + config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), + GFP_KERNEL); + if (!config) + return -ENOMEM; + + supply_name = kmalloc(13, GFP_KERNEL); + if (!supply_name) + return -ENOMEM; + + scnprintf(supply_name, 13, "hsusb%d_vcc", phy->port); + config->supply_name = supply_name; + config->gpio = phy->vcc_gpio; + config->enable_high = phy->vcc_polarity; + config->init_data = reg_data; + + hsusb_reg_pdev_info.data = config; + hsusb_reg_pdev_info.size_data = sizeof(hsusb_reg_config); + platform_device_register_full(&hsusb_reg_pdev_info); + +next: + phy++; + } + + return 0; +} diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h index 3319f5c..e7261eb 100644 --- a/arch/arm/mach-omap2/usb.h +++ b/arch/arm/mach-omap2/usb.h @@ -53,8 +53,17 @@ #define USBPHY_OTGSESSEND_EN (1 << 20) #define USBPHY_DATA_POLARITY (1 << 23) +struct usbhs_phy_data { + int port; /* 1 indexed port number */ + int reset_gpio; + int vcc_gpio; + bool vcc_polarity; /* 1 active high, 0 active low */ + void *platform_data; +}; + extern void usb_musb_init(struct omap_musb_board_data *board_data); extern void usbhs_init(struct usbhs_omap_platform_data *pdata); +extern int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys); extern void am35x_musb_reset(void); extern void am35x_musb_phy_power(u8 on);