From patchwork Wed Oct 7 17:53:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Subbrathnam, Swaminathan" X-Patchwork-Id: 52304 Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n97HNUAQ009796 for ; Wed, 7 Oct 2009 17:23:30 GMT Received: from dlep33.itg.ti.com ([157.170.170.112]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id n97HLYRt028877 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 7 Oct 2009 12:21:35 -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 n97HLXD0024875; Wed, 7 Oct 2009 12:21:33 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 21ADE8062A; Wed, 7 Oct 2009 12:21:11 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dbdp31.itg.ti.com (dbdp31.itg.ti.com [172.24.170.98]) by linux.omap.com (Postfix) with ESMTP id B75648062A for ; Wed, 7 Oct 2009 12:20:39 -0500 (CDT) Received: from localhost.localdomain (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id n97HKato009706; Wed, 7 Oct 2009 22:50:38 +0530 (IST) From: Swaminathan S To: davinci-linux-open-source@linux.davincidsp.com Date: Wed, 7 Oct 2009 23:23:08 +0530 Message-Id: <1254937992-2291-4-git-send-email-swami.iyer@ti.com> X-Mailer: git-send-email 1.6.0.rc1.64.g61192 In-Reply-To: <1254937992-2291-1-git-send-email-swami.iyer@ti.com> References: <1254937992-2291-1-git-send-email-swami.iyer@ti.com> Cc: linux-usb@vger.kernel.org, Ravi B Subject: [PATCH 3/7] Subscribes for USB resources for TI-DM646x EVM 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 diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 24e0e13..49103a6 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -60,6 +61,7 @@ /* CPLD Register 0 bits to control ATA */ #define DM646X_EVM_ATA_RST BIT(0) #define DM646X_EVM_ATA_PWD BIT(1) +#define DM646X_EVM_USB_VBUS BIT(7) #define DM646X_EVM_PHY_MASK (0x2) #define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ @@ -88,14 +90,33 @@ static void __iomem *vpif_vsclkdis_reg; /* spin lock for updating above registers */ static spinlock_t vpif_reg_lock; +static int dm646x_evm_set_vbus(struct device *dev, int is_on); +static struct musb_hdrc_platform_data usb_evm_data[] = { + { +#if defined(CONFIG_USB_MUSB_OTG) + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) + .mode = MUSB_PERIPHERAL, +#elif defined(CONFIG_USB_MUSB_HOST) + .mode = MUSB_HOST, +#endif + .power = 255, + .potpgt = 8, + .set_vbus = dm646x_evm_set_vbus, + } +}; + static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; +struct i2c_client *cpld_reg0_client; /* CPLD Register 0 Client: used for I/O Control */ static int cpld_reg0_probe(struct i2c_client *client, const struct i2c_device_id *id) { + cpld_reg0_client = client; + if (HAS_ATA) { u8 data; struct i2c_msg msg[2] = { @@ -652,6 +673,8 @@ static __init void evm_init(void) soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; + + dm646x_usb_configure(usb_evm_data, ARRAY_SIZE(usb_evm_data)); } static __init void davinci_dm646x_evm_irq_init(void) @@ -659,6 +682,55 @@ static __init void davinci_dm646x_evm_irq_init(void) davinci_irq_init(); } +/* Initiate the I2C command to the expander to turn on/off the VBUS line */ +static int vbus_state = -1; +static void evm_deferred_drvvbus(struct work_struct *ignored) +{ + u8 data; + + struct i2c_msg msg[2] = { + { + .addr = cpld_reg0_client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &data, + }, + { + .addr = cpld_reg0_client->addr, + .flags = 0, + .len = 1, + .buf = &data, + }, + }; + + i2c_transfer(cpld_reg0_client->adapter, msg, 1); + if (vbus_state) + data |= DM646X_EVM_USB_VBUS; + else + data &= ~DM646X_EVM_USB_VBUS; + + i2c_transfer(cpld_reg0_client->adapter, msg + 1, 1); + vbus_state = !vbus_state; +} + +/* + * DM644x EVM USB VBUS handler. On TI DM644x EVM USB VBUS is controller + * through I2C expander (0x3A) lines. Tthis function schedules a + * work thread to handle the actual VBUS on/off operations. + */ +static int dm646x_evm_set_vbus(struct device *dev, int is_on) +{ + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + + is_on = is_on ? 1 : 0; + if (vbus_state == is_on) + return 0; + + vbus_state = !is_on; + schedule_work(&evm_vbus_work); + return 0; +} + MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 36e4fb4..2276c6a 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "clock.h" #include "mux.h" @@ -315,6 +317,12 @@ static struct clk vpif1_clk = { .flags = ALWAYS_ENABLED, }; +static struct clk usb_clk = { + .name = "usb", + .parent = &pll1_sysclk3, + .lpsc = DAVINCI_LPSC_USB, +}; + struct davinci_clk dm646x_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "aux", &aux_clkin), @@ -355,6 +363,7 @@ struct davinci_clk dm646x_clks[] = { CLK("palm_bk3710", NULL, &ide_clk), CLK(NULL, "vpif0", &vpif0_clk), CLK(NULL, "vpif1", &vpif1_clk), + CLK(NULL, "usb", &usb_clk), CLK(NULL, NULL, NULL), }; @@ -930,6 +939,87 @@ void __init dm646x_init(void) davinci_common_init(&davinci_soc_info_dm646x); } +/* + * Configure the USB PHY for DM644x platforms. + */ +static int dm646x_usb_phy_config(struct device *dev, u8 mode, int is_on) +{ + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + if (is_on) { + /* power everything up; start the on-chip PHY and its PLL */ + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; + phy_ctrl |= USBPHY_NDATAPOL | USBPHY_SESSION_VBUS; + switch (mode) { + case MUSB_PERIPHERAL: + phy_ctrl |= USBPHY_PERI_USBID; + break; + case MUSB_HOST: + phy_ctrl &= ~USBPHY_VBDTCTEN; + break; + } + + } else { + /* powerdown the on-chip PHY, its PLL, and the OTG block */ + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | + USBPHY_PHYPLLON); + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; + } + + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + if (is_on) { + /* wait for PLL to lock before proceeding */ + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) + cpu_relax(); + } + + return 0; +} + +static struct resource usb_resources[] = { + { + .start = DAVINCI_USB_OTG_BASE, + .end = DAVINCI_USB_OTG_BASE + 0x5ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_DM646X_USBINT, + .flags = IORESOURCE_IRQ, + }, + { + .start = IRQ_DM646X_USBDMAINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct plat_res_data dm646x_usb_res; +static struct usb_plat_data dm646x_usb_plat_data; +/* + * Initialize DM644x related USB information such as Memory maps, IRQ etc. + * Since DM644x supprot a single MUSB controller initialize the instance + * value to 1. + */ +void dm646x_usb_configure(struct musb_hdrc_platform_data *pdata, u8 num_inst) +{ + pdata->phy_config = dm646x_usb_phy_config; + + dm646x_usb_res.plat_data = pdata; + dm646x_usb_res.res_data = usb_resources; + dm646x_usb_res.num_res = ARRAY_SIZE(usb_resources); + + dm646x_usb_plat_data.prdata = &dm646x_usb_res; + dm646x_usb_plat_data.num_inst = num_inst; + + /* Call the generic platform register function. The USB + * configuration w.r.t no. of ep's, capabalities etc. are common + * across DaVinci platforms and hence allow the generic handler + * to populate the information. + */ + setup_usb(&dm646x_usb_plat_data); +} + static int __init dm646x_init_devices(void) { if (!cpu_is_davinci_dm646x()) @@ -940,3 +1030,4 @@ static int __init dm646x_init_devices(void) return 0; } postcore_initcall(dm646x_init_devices); + diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 8cec746..3c49bfa 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -16,6 +16,7 @@ #include #include #include +#include #define DM646X_EMAC_BASE (0x01C80000) #define DM646X_EMAC_CNTRL_OFFSET (0x0000) @@ -30,6 +31,8 @@ void __init dm646x_init(void); void __init dm646x_init_ide(void); void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); void __init dm646x_init_mcasp1(struct snd_platform_data *pdata); +extern void dm646x_usb_configure(struct musb_hdrc_platform_data *pdata, + u8 num_inst); void dm646x_video_init(void); diff --git a/arch/arm/mach-davinci/include/mach/usb_davinci.h b/arch/arm/mach-davinci/include/mach/usb_davinci.h index 02f8af7..eaa84f1 100644 --- a/arch/arm/mach-davinci/include/mach/usb_davinci.h +++ b/arch/arm/mach-davinci/include/mach/usb_davinci.h @@ -27,7 +27,9 @@ /* Integrated highspeed/otg PHY */ #define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) - +#define USBPHY_NDATAPOL BIT(18) +#define USBPHY_SESSION_VBUS BIT(17) +#define USBPHY_PERI_USBID BIT(16) #define USBPHY_PHYCLKGD BIT(8) #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ #define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */