@@ -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));
@@ -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);
@@ -24,6 +24,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
+#include <linux/usb/musb.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -38,7 +39,7 @@
#include <mach/common.h>
#include <mach/mmc.h>
#include <mach/nand.h>
-
+#include <mach/gpio.h>
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);
@@ -28,6 +28,7 @@
#include <linux/io.h>
#include <linux/phy.h>
#include <linux/clk.h>
+#include <linux/usb/musb.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -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);
@@ -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);
@@ -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 ... */
@@ -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,
};
@@ -12,6 +12,8 @@
#ifndef __ARCH_ARM_MACH_DAVINCI_COMMON_H
#define __ARCH_ARM_MACH_DAVINCI_COMMON_H
+#include <linux/usb/musb.h>
+
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;
@@ -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 */
@@ -14,6 +14,9 @@
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/cputype.h>
+#include <mach/gpio.h>
+
+#include <asm/mach-types.h>
#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);
}
@@ -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"
@@ -37,20 +37,12 @@
#include <mach/gpio.h>
#include <mach/cputype.h>
-#include <asm/mach-types.h>
-
#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) {
@@ -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
@@ -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
@@ -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 */