From patchwork Wed Sep 16 15:55:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: miguel.aguilar@ridgerun.com X-Patchwork-Id: 48021 Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8GFwrJ8023729 for ; Wed, 16 Sep 2009 15:58:54 GMT Received: from dlep33.itg.ti.com ([157.170.170.112]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id n8GFtW5m011524; Wed, 16 Sep 2009 10:55:32 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep33.itg.ti.com (8.13.7/8.13.7) with ESMTP id n8GFtViI005237; Wed, 16 Sep 2009 10:55:31 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 83D3680627; Wed, 16 Sep 2009 10:55:31 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp52.itg.ti.com (dflp52.itg.ti.com [128.247.22.96]) by linux.omap.com (Postfix) with ESMTP id 0A3AE80626 for ; Wed, 16 Sep 2009 10:55:29 -0500 (CDT) Received: from white.ext.ti.com (localhost [127.0.0.1]) by dflp52.itg.ti.com (8.13.7/8.13.7) with ESMTP id n8GFtS7U012536 for ; Wed, 16 Sep 2009 10:55:28 -0500 (CDT) Received: from mail36-va3-R.bigfish.com (mail-va3.bigfish.com [216.32.180.111]) by white.ext.ti.com (8.13.7/8.13.7) with ESMTP id n8GFtSJE005105 for ; Wed, 16 Sep 2009 10:55:28 -0500 Received: from mail36-va3 (localhost.localdomain [127.0.0.1]) by mail36-va3-R.bigfish.com (Postfix) with ESMTP id 0DB8FC20168 for ; Wed, 16 Sep 2009 15:55:28 +0000 (UTC) X-SpamScore: 7 X-BigFish: vps7(zza4b1ozz1202hzzz2fh66h) X-Spam-TCS-SCL: 5:0 X-FB-SS: 5, X-MS-Exchange-Organization-Antispam-Report: OrigIP: 74.208.67.6; Service: EHS Received: by mail36-va3 (MessageSwitch) id 1253116522111549_9156; Wed, 16 Sep 2009 15:55:22 +0000 (UCT) Received: from mail.navvo.net (mail.navvo.net [74.208.67.6]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail36-va3.bigfish.com (Postfix) with ESMTP id DC9C412C8064; Wed, 16 Sep 2009 15:55:21 +0000 (UTC) Received: from [201.198.127.70] (helo=localhost.localdomain) by mail.navvo.net with esmtpa (Exim 4.63) (envelope-from ) id 1Mnwqk-0002cM-1z; Wed, 16 Sep 2009 10:55:20 -0500 From: miguel.aguilar@ridgerun.com To: nsnehaprabha@ti.com, khilman@deeprootsystems.com, swami.iyer@ti.com Date: Wed, 16 Sep 2009 09:55:10 -0600 Message-Id: <1253116510-9523-1-git-send-email-miguel.aguilar@ridgerun.com> X-Mailer: git-send-email 1.6.0.4 X-SA-Exim-Connect-IP: 201.198.127.70 X-SA-Exim-Mail-From: miguel.aguilar@ridgerun.com X-Spam-Checker-Version: SpamAssassin 3.1.7-deb (2006-10-05) on mail.navvo.net X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00, NO_REAL_NAME autolearn=ham version=3.1.7-deb X-SA-Exim-Version: 4.2.1 (built Tue, 09 Jan 2007 17:23:22 +0000) X-SA-Exim-Scanned: Yes (on mail.navvo.net) Cc: davinci-linux-open-source@linux.davincidsp.com, clark.becker@ridgerun.com, santiago.nunez@ridgerun.com, todd.fischer@ridgerun.com, Miguel Aguilar Subject: [RFC] [PATCH] Move SoC and board specific code from USB DaVinci driver to the corresponding files X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.4 Precedence: list List-Id: davinci-linux-open-source.linux.davincidsp.com List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com From: Miguel Aguilar Swami, I would like to share this patch with you, it could be useful for you. This patch moves al the SoC and board specific stuff from the USB DaVinci Driver to the corresponding SoC and board files. The idea is that each board file provides a set_vbus function depending on how each board handles it by using the musb platform data. This patch was tested on DM355 EVM and Leopard Board, and DM365 EVM. On the DM6446 this is not tested yet. Signed-off-by: Miguel Aguilar --- arch/arm/mach-davinci/board-dm355-evm.c | 35 +++++++- arch/arm/mach-davinci/board-dm355-leopard.c | 23 +++++- arch/arm/mach-davinci/board-dm365-evm.c | 38 +++++++++- arch/arm/mach-davinci/board-dm644x-evm.c | 61 ++++++++++++++- arch/arm/mach-davinci/board-sffsdr.c | 4 +- arch/arm/mach-davinci/dm355.c | 20 +++++ arch/arm/mach-davinci/dm365.c | 2 +- arch/arm/mach-davinci/include/mach/common.h | 23 +++++- arch/arm/mach-davinci/include/mach/dm355.h | 1 + arch/arm/mach-davinci/usb.c | 11 ++- drivers/usb/musb/Kconfig | 4 +- drivers/usb/musb/davinci.c | 110 ++------------------------- drivers/usb/musb/davinci.h | 5 +- drivers/usb/musb/musb_core.c | 1 + include/linux/usb/musb.h | 9 ++- 15 files changed, 212 insertions(+), 135 deletions(-) diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index 9f25fd8..a06fcdb 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -229,6 +229,34 @@ static struct davinci_mmc_config dm355evm_mmc_config = { #define USB_ID_VALUE 1 /* ID pulled low */ #endif +struct musb_hdrc_platform_data dm355evm_usb_data; + +static void dm355evm_usb_configure(void) +{ + /* + * DM355 EVM swaps D+/D- for signal integrity, and + * is clocked from the main 24 MHz crystal. + */ + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 9); + phy_ctrl |= USBPHY_DATAPOL; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* DM355 SoC configuration */ + dm355_init_usb(); + + /* + * Set the gpio 2 as output to toggle the USB ID + * according the USB mode host or gadget + */ + gpio_request(2, "usb_id_toggle"); + gpio_direction_output(2, USB_ID_VALUE); + + /* irlml6401 switches over 1A in under 8 msec */ + setup_usb(500, 8, &dm355evm_usb_data); +} + static struct spi_eeprom at25640a = { .byte_len = SZ_64K / 8, .name = "at25640a", @@ -271,14 +299,11 @@ static __init void dm355_evm_init(void) * but could be 0x0400008c for about 25% faster page reads. */ - gpio_request(2, "usb_id_toggle"); - gpio_direction_output(2, USB_ID_VALUE); - /* irlml6401 switches over 1A in under 8 msec */ - setup_usb(500, 8); - davinci_setup_mmc(0, &dm355evm_mmc_config); davinci_setup_mmc(1, &dm355evm_mmc_config); + dm355evm_usb_configure(); + dm355_init_spi0(BIT(0), dm355_evm_spi_info, ARRAY_SIZE(dm355_evm_spi_info)); diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index 84ad5d1..4b3042f 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -225,6 +225,24 @@ static struct davinci_mmc_config dm355leopard_mmc_config = { #define USB_ID_VALUE 1 /* ID pulled low */ #endif +struct musb_hdrc_platform_data dm355leopard_usb_data; + +static void dm355leopard_usb_configure(void) +{ + /* DM355 SoC configuration */ + dm355_init_usb(); + + /* + * Set the gpio 2 as output to toggle the USB ID + * according the USB mode host or gadget + */ + gpio_request(2, "usb_id_toggle"); + gpio_direction_output(2, USB_ID_VALUE); + + /* irlml6401 switches over 1A in under 8 msec */ + setup_usb(500, 8, &dm355leopard_usb_data); +} + static struct spi_eeprom at25640a = { .byte_len = SZ_64K / 8, .name = "at25640a", @@ -267,10 +285,7 @@ static __init void dm355_leopard_init(void) * but could be 0x0400008c for about 25% faster page reads. */ - gpio_request(2, "usb_id_toggle"); - gpio_direction_output(2, USB_ID_VALUE); - /* irlml6401 switches over 1A in under 8 msec */ - setup_usb(500, 8); + dm355leopard_usb_configure(); davinci_setup_mmc(0, &dm355leopard_mmc_config); davinci_setup_mmc(1, &dm355leopard_mmc_config); diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index f6adf79..327b681 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ #include #include #include - +#include static inline int have_imager(void) { @@ -52,7 +53,6 @@ static inline int have_tvp7002(void) return 0; } - #define DM365_ASYNC_EMIF_CONTROL_BASE 0x01d10000 #define DM365_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 #define DM365_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 @@ -270,6 +270,39 @@ static void dm365evm_mmc_configure(void) davinci_cfg_reg(DM365_SD1_DATA0); } +static void dm365evm_set_vbus(struct musb * musb, int is_on) +{ + u32 state; + + if((is_on == VBUS_ON) || (is_on == VBUS_ON_INMEDIATE)) + state = 1; + else + state = 0; + + gpio_set_value(33, state); +} + +struct musb_hdrc_platform_data dm365evm_usb_data = { + .set_vbus = &dm365evm_set_vbus, +}; + +static void dm365evm_usb_configure(void) +{ + /* DM365 EVM uses the main clock of 24MHz */ + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 12); + phy_ctrl |= USBPHY_CLKFREQ_24MHZ; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* Setup the gpio used to turn on/off the VBUS */ + davinci_cfg_reg(DM365_GPIO33); + gpio_request(33, "usb"); + gpio_direction_output(33, 1); + + setup_usb(500, 8, &dm365evm_usb_data); +} + static void __init evm_init_i2c(void) { davinci_init_i2c(&i2c_pdata); @@ -471,6 +504,7 @@ static __init void dm365_evm_init(void) dm365evm_emac_configure(); dm365evm_mmc_configure(); + dm365evm_usb_configure(); davinci_setup_mmc(0, &dm365evm_mmc_config); diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 31cf84f..61ccf20 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,8 @@ #define DM644X_EVM_PHY_MASK (0x2) #define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ +#define GPIO_nVBUS_DRV 144 + #define DAVINCI_CFC_ATA_BASE 0x01C66000 #define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 @@ -369,7 +372,6 @@ static struct pcf857x_platform_data pcf_data_u18 = { .teardown = evm_u18_teardown, }; - /* U35 - various I/O signals used to manage USB, CF, ATA, etc */ static int @@ -405,12 +407,59 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) gpio_request(gpio + 7, "nCF_SEL"); gpio_direction_output(gpio + 7, 1); - /* irlml6401 switches over 1A, in under 8 msec; + return 0; +} + +static int vbus_state = -1; + +/* I2C operations are always synchronous, and require a task context. + * With unloaded systems, using the shared workqueue seems to suffice + * to satisfy the 100msec A_WAIT_VRISE timeout... + */ +static void evm_deferred_drvvbus(struct work_struct *ignored) +{ + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + vbus_state = !vbus_state; +} + +static void dm6446evm_set_vbus(struct musb *musb, int is_on) +{ + int inmediate; + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + + if ((is_on == VBUS_ON_INMEDIATE) || (is_on == VBUS_OFF_INMEDIATE)) + inmediate = 1; + + if ((is_on == VBUS_OFF) || (is_on == VBUS_OFF_INMEDIATE)) + is_on = 0; + else + is_on = 1; + + if (vbus_state == is_on) + return; + + vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ + + if (inmediate) + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + else + schedule_work(&evm_vbus_work); + + if (inmediate) + vbus_state = is_on; +} + +static struct musb_hdrc_platform_data dm6446evm_usb_data = { + .set_vbus = &dm6446evm_set_vbus, +}; + +static void dm6446evm_usb_configure(void) +{ + /* + * irlml6401 switches over 1A, in under 8 msec; * now it can be managed by nDRV_VBUS ... */ - setup_usb(500, 8); - - return 0; + setup_usb(500, 8, &dm6446evm_usb_data); } static int @@ -669,6 +718,8 @@ static __init void davinci_evm_init(void) davinci_setup_mmc(0, &dm6446evm_mmc_config); + dm6446evm_usb_configure(); + davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 7acdfd8..71dd26b 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -154,6 +154,8 @@ static void __init davinci_sffsdr_map_io(void) dm644x_init(); } +struct musb_hdrc_platform_data davinci_sffsdr_usb_data; + static __init void davinci_sffsdr_init(void) { struct davinci_soc_info *soc_info = &davinci_soc_info; @@ -164,7 +166,7 @@ static __init void davinci_sffsdr_init(void) davinci_serial_init(&uart_config); soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; - setup_usb(0, 0); /* We support only peripheral mode. */ + setup_usb(0, 0, &davinci_sffsdr_usb_data); /* We support only peripheral mode. */ /* mux VLYNQ pins */ davinci_cfg_reg(DM644X_VLYNQEN); diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 4f42169..fceab24 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -37,6 +37,10 @@ #define DM355_UART2_BASE (IO_PHYS + 0x206000) +#define DM355_DEEPSLEEP IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DRVVBUS_FORCE BIT(2) +#define DRVVBUS_OVERRIDE BIT(1) + /* * Device specific clocks */ @@ -767,6 +771,22 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .sram_len = SZ_32K, }; +void __init dm355_init_usb(void) +{ + /* On dm355, the default-A state machine needs DRVVBUS control. + * If we won't be a host, there's no need to turn it on. + */ + u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); + +#if defined(CONFIG_USB_MUSB_HOST) + deepsleep &= ~DRVVBUS_OVERRIDE; +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) + deepsleep &= ~DRVVBUS_FORCE; + deepsleep |= DRVVBUS_OVERRIDE; +#endif + __raw_writel(deepsleep, DM355_DEEPSLEEP); +} + void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata) { /* we don't use ASP1 IRQs, or we'd need to mux them ... */ diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e815174..6c948b1 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -369,7 +369,7 @@ static struct clk timer3_clk = { static struct clk usb_clk = { .name = "usb", - .parent = &pll2_sysclk1, + .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_USB, }; diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 1fd3917..65aad5c 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -12,6 +12,8 @@ #ifndef __ARCH_ARM_MACH_DAVINCI_COMMON_H #define __ARCH_ARM_MACH_DAVINCI_COMMON_H +#include + struct sys_timer; extern struct sys_timer davinci_timer; @@ -21,10 +23,23 @@ extern void __iomem *davinci_intc_base; extern int davinci_intc_type; /* parameters describe VBUS sourcing for host mode */ -extern void setup_usb(unsigned mA, unsigned potpgt_msec); +extern void setup_usb(unsigned mA, unsigned potpgt_msec, + struct musb_hdrc_platform_data * board_usb_data); -/* parameters describe VBUS sourcing for host mode */ -extern void setup_usb(unsigned mA, unsigned potpgt_msec); +/* Integrated highspeed/otg PHY */ +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) +#define USBPHY_CLKFREQ_24MHZ BIT(13) +#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ +#define USBPHY_PHYCLKGD BIT(8) +#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ +#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ +#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */ +#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */ +#define USBPHY_CLKO1SEL BIT(3) +#define USBPHY_OSCPDWN BIT(2) +#define USBPHY_OTGPDWN BIT(1) +#define USBPHY_PHYPDWN BIT(0) struct davinci_timer_instance { void __iomem *base; diff --git a/arch/arm/mach-davinci/include/mach/dm355.h b/arch/arm/mach-davinci/include/mach/dm355.h index 03faaef..0959d3d 100644 --- a/arch/arm/mach-davinci/include/mach/dm355.h +++ b/arch/arm/mach-davinci/include/mach/dm355.h @@ -23,5 +23,6 @@ void __init dm355_init(void); void dm355_init_spi0(unsigned chipselect_mask, struct spi_board_info *info, unsigned len); void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata); +void __init dm355_init_usb(void); #endif /* __ASM_ARCH_DM355_H */ diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 06f5593..480653e 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -14,6 +14,9 @@ #include #include #include +#include + +#include #define DAVINCI_USB_OTG_BASE 0x01C64000 @@ -77,7 +80,6 @@ static struct platform_device usb_dev = { .name = "musb_hdrc", .id = -1, .dev = { - .platform_data = &usb_data, .dma_mask = &usb_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), }, @@ -85,7 +87,8 @@ static struct platform_device usb_dev = { .num_resources = ARRAY_SIZE(usb_resources), }; -void __init setup_usb(unsigned mA, unsigned potpgt_msec) +void __init setup_usb(unsigned mA, unsigned potpgt_msec, + struct musb_hdrc_platform_data * board_usb_data) { usb_data.power = mA / 2; usb_data.potpgt = potpgt_msec / 2; @@ -97,6 +100,10 @@ void __init setup_usb(unsigned mA, unsigned potpgt_msec) } else /* other devices don't have dedicated CPPI IRQ */ usb_dev.num_resources = 2; + /* Setup the plaform data including the board specific structures */ + usb_data.set_vbus = board_usb_data->set_vbus; + usb_dev.dev.platform_data = &usb_data; + platform_device_register(&usb_dev); } diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 803adcb..9878a64 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -23,7 +23,7 @@ config USB_MUSB_HDRC or the USB host role, or both. Texas Instruments familiies using this IP include DaVinci - (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. + (35x, 36x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. @@ -42,7 +42,7 @@ config USB_MUSB_SOC default y if (BF54x && !BF544) default y if (BF52x && !BF522 && !BF523) -comment "DaVinci 35x and 644x USB support" +comment "DaVinci 35x, 36x, 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI comment "OMAP 243x high speed USB support" diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index e16ff60..a2b1bbd 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -37,20 +37,12 @@ #include #include -#include - #include "musb_core.h" -#ifdef CONFIG_MACH_DAVINCI_EVM -#define GPIO_nVBUS_DRV 144 -#endif - #include "davinci.h" #include "cppi_dma.h" - #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) -#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) /* REVISIT (PM) we should be able to keep the PHY in low power mode most * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 @@ -135,69 +127,12 @@ void musb_platform_disable(struct musb *musb) WARNING("dma still active\n"); } - #ifdef CONFIG_USB_MUSB_HDRC_HCD #define portstate(stmt) stmt #else #define portstate(stmt) #endif - -/* - * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, - * which doesn't wire DRVVBUS to the FET that switches it. Unclear - * if that's a problem with the DM6446 chip or just with that board. - * - * In either case, the DM355 EVM automates DRVVBUS the normal way, - * when J10 is out, and TI documents it as handling OTG. - */ - -#ifdef CONFIG_MACH_DAVINCI_EVM - -static int vbus_state = -1; - -/* I2C operations are always synchronous, and require a task context. - * With unloaded systems, using the shared workqueue seems to suffice - * to satisfy the 100msec A_WAIT_VRISE timeout... - */ -static void evm_deferred_drvvbus(struct work_struct *ignored) -{ - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); - vbus_state = !vbus_state; -} - -#endif /* EVM */ - -static void davinci_source_power(struct musb *musb, int is_on, int immediate) -{ -#ifdef CONFIG_MACH_DAVINCI_EVM - if (is_on) - is_on = 1; - - if (vbus_state == is_on) - return; - vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ - - if (machine_is_davinci_evm()) { - static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); - - if (immediate) - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); - else - schedule_work(&evm_vbus_work); - } - if (immediate) - vbus_state = is_on; -#endif -} - -static void davinci_set_vbus(struct musb *musb, int is_on) -{ - WARN_ON(is_on && is_peripheral_active(musb)); - davinci_source_power(musb, is_on, 0); -} - - #define POLL_SECONDS 2 static struct timer_list otg_workaround; @@ -346,7 +281,8 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) /* NOTE: this must complete poweron within 100 msec * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. */ - davinci_source_power(musb, drvvbus, 0); + if(musb->board_set_vbus && !is_peripheral_enabled(musb)) + musb->board_set_vbus(musb, drvvbus); DBG(2, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", otg_state_string(musb), @@ -399,34 +335,8 @@ int __init musb_platform_init(struct musb *musb) if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); - musb->board_set_vbus = davinci_set_vbus; - davinci_source_power(musb, 0, 1); - - /* dm355 EVM swaps D+/D- for signal integrity, and - * is clocked from the main 24 MHz crystal. - */ - if (machine_is_davinci_dm355_evm()) { - u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); - - phy_ctrl &= ~(3 << 9); - phy_ctrl |= USBPHY_DATAPOL; - __raw_writel(phy_ctrl, USB_PHY_CTRL); - } - - /* On dm355, the default-A state machine needs DRVVBUS control. - * If we won't be a host, there's no need to turn it on. - */ - if (cpu_is_davinci_dm355()) { - u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); - - if (is_host_enabled(musb)) { - deepsleep &= ~DRVVBUS_OVERRIDE; - } else { - deepsleep &= ~DRVVBUS_FORCE; - deepsleep |= DRVVBUS_OVERRIDE; - } - __raw_writel(deepsleep, DM355_DEEPSLEEP); - } + if(musb->board_set_vbus && !is_peripheral_enabled(musb)) + musb->board_set_vbus(musb,VBUS_OFF_INMEDIATE); /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -454,16 +364,8 @@ int musb_platform_exit(struct musb *musb) if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); - /* force VBUS off */ - if (cpu_is_davinci_dm355()) { - u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); - - deepsleep &= ~DRVVBUS_FORCE; - deepsleep |= DRVVBUS_OVERRIDE; - __raw_writel(deepsleep, DM355_DEEPSLEEP); - } - - davinci_source_power(musb, 0 /*off*/, 1); + if(musb->board_set_vbus && !is_peripheral_enabled(musb)) + musb->board_set_vbus(musb, VBUS_OFF_INMEDIATE); /* delay, to avoid problems with module reload */ if (is_host_enabled(musb) && musb->xceiv->default_a) { diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 046c844..0df133d 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -16,6 +16,7 @@ /* Integrated highspeed/otg PHY */ #define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_CLKFREQ_24MHZ BIT(13) #define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ #define USBPHY_PHYCLKGD BIT(8) #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ @@ -27,10 +28,6 @@ #define USBPHY_OTGPDWN BIT(1) #define USBPHY_PHYPDWN BIT(0) -#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) -#define DRVVBUS_FORCE BIT(2) -#define DRVVBUS_OVERRIDE BIT(1) - /* For now include usb OTG module registers here */ #define DAVINCI_USB_VERSION_REG 0x00 #define DAVINCI_USB_CTRL_REG 0x04 diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c7c1ca0..deb3458 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1926,6 +1926,7 @@ bad_config: musb->board_set_power = plat->set_power; musb->set_clock = plat->set_clock; musb->min_power = plat->min_power; + musb->board_set_vbus = plat->set_vbus; /* Clock usage is chip-specific ... functional clock (DaVinci, * OMAP2430), or PHY ref (some TUSB6010 boards). All this core diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index d437556..cd4139b 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h @@ -57,6 +57,8 @@ struct musb_hdrc_config { }; +extern struct musb dev; + struct musb_hdrc_platform_data { /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */ u8 mode; @@ -65,7 +67,7 @@ struct musb_hdrc_platform_data { const char *clock; /* (HOST or OTG) switch VBUS on/off */ - int (*set_vbus)(struct device *dev, int is_on); + void (*set_vbus)(struct musb * dev, int is_on); /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */ u8 power; @@ -86,6 +88,11 @@ struct musb_hdrc_platform_data { struct musb_hdrc_config *config; }; +/* VBUS states */ +#define VBUS_OFF 0 +#define VBUS_ON 1 +#define VBUS_OFF_INMEDIATE 2 +#define VBUS_ON_INMEDIATE 3 /* TUSB 6010 support */