aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/board-generic.c2
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c94
-rw-r--r--arch/arm/mach-omap2/cclock3xxx_data.c2
-rw-r--r--arch/arm/mach-omap2/cclock44xx_data.c37
-rw-r--r--arch/arm/mach-omap2/common.h2
-rw-r--r--arch/arm/mach-omap2/usb-host.c76
-rw-r--r--arch/arm/mach-omap2/usb.h4
7 files changed, 178 insertions, 39 deletions
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 53cb380b7877..5c519aa59109 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -50,6 +50,8 @@ static void __init omap_generic_init(void)
omap4_panda_display_init_of();
else if (of_machine_is_compatible("ti,omap4-sdp"))
omap_4430sdp_display_init_of();
+
+ usbhost_init_of();
}
#ifdef CONFIG_SOC_OMAP2420
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 769c1feee1c4..884aecca547b 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -146,45 +146,73 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
.phy_reset = false,
.reset_gpio_port[0] = -EINVAL,
.reset_gpio_port[1] = -EINVAL,
- .reset_gpio_port[2] = -EINVAL
+ .reset_gpio_port[2] = -EINVAL,
+ .clk[0] = "auxclk3_ck", /* FREF_CLK3 provides 19.2 MHz clock to PHY */
+ .clkrate[0] = 19200000,
};
-static struct gpio panda_ehci_gpios[] __initdata = {
- { GPIO_HUB_POWER, GPIOF_OUT_INIT_LOW, "hub_power" },
- { GPIO_HUB_NRESET, GPIOF_OUT_INIT_LOW, "hub_nreset" },
+/*
+ * hub_nreset also enables the ULPI PHY
+ * ULPI PHY is always powered
+ * hub_power enables a 3.3V regulator for (hub + eth) chip
+ * however there's no point having ULPI PHY in use alone
+ * since it's only connected to the (hub + eth) chip
+ */
+
+static struct regulator_init_data panda_hub = {
+ .constraints = {
+ .name = "vhub",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
};
-static void __init omap4_ehci_init(void)
-{
- int ret;
- struct clk *phy_ref_clk;
+static struct fixed_voltage_config panda_vhub = {
+ .supply_name = "vhub",
+ .microvolts = 3300000,
+ .gpio = GPIO_HUB_POWER,
+ .startup_delay = 70000, /* 70msec */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &panda_hub,
+};
- /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
- phy_ref_clk = clk_get(NULL, "auxclk3_ck");
- if (IS_ERR(phy_ref_clk)) {
- pr_err("Cannot request auxclk3\n");
- return;
- }
- clk_set_rate(phy_ref_clk, 19200000);
- clk_prepare_enable(phy_ref_clk);
-
- /* disable the power to the usb hub prior to init and reset phy+hub */
- ret = gpio_request_array(panda_ehci_gpios,
- ARRAY_SIZE(panda_ehci_gpios));
- if (ret) {
- pr_err("Unable to initialize EHCI power/reset\n");
- return;
- }
+static struct platform_device omap_vhub_device = {
+ .name = "reg-fixed-voltage",
+ .id = 2,
+ .dev = {
+ .platform_data = &panda_vhub,
+ },
+};
- gpio_export(GPIO_HUB_POWER, 0);
- gpio_export(GPIO_HUB_NRESET, 0);
- gpio_set_value(GPIO_HUB_NRESET, 1);
+static struct regulator_init_data panda_ulpireset = {
+ /*
+ * idea is that when operating ulpireset, regulator api will make
+ * sure that the hub+eth chip is powered, since it's the "parent"
+ */
+ .supply_regulator = "vhub", /* we are a child of vhub */
+ .constraints = {
+ .name = "hsusb0",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
- usbhs_init(&usbhs_bdata);
+static struct fixed_voltage_config panda_vulpireset = {
+ .supply_name = "hsusb0", /* this name is magic for hsusb driver */
+ .microvolts = 3300000,
+ .gpio = GPIO_HUB_NRESET,
+ .startup_delay = 70000, /* 70msec */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &panda_ulpireset,
+};
- /* enable power to hub */
- gpio_set_value(GPIO_HUB_POWER, 1);
-}
+static struct platform_device omap_vulpireset_device = {
+ .name = "reg-fixed-voltage",
+ .id = 3,
+ .dev = {
+ .platform_data = &panda_vulpireset,
+ },
+};
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_UTMI,
@@ -443,10 +471,12 @@ static void __init omap4_panda_init(void)
omap4_panda_i2c_init();
platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
platform_device_register(&omap_vwlan_device);
+ platform_device_register(&omap_vhub_device);
+ platform_device_register(&omap_vulpireset_device);
omap_serial_init();
omap_sdrc_init(NULL, NULL);
omap4_twl6030_hsmmc_init(mmc);
- omap4_ehci_init();
+ usbhs_init(&usbhs_bdata);
usb_musb_init(&musb_board_data);
omap4_panda_display_init();
}
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 6ef87580c33f..38669ce50530 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -3394,8 +3394,6 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
- CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
- CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
index a2cc046b47f4..846da90b2173 100644
--- a/arch/arm/mach-omap2/cclock44xx_data.c
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -1404,10 +1404,17 @@ static struct clk_hw_omap usb_host_fs_fck_hw = {
DEFINE_STRUCT_CLK(usb_host_fs_fck, usb_host_fs_fck_parent_names,
usb_host_fs_fck_ops);
-static const char *utmi_p1_gfclk_parents[] = {
+static const struct clksel utmi_p1_clk_sel[] = {
+ { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+ { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
+};
+
+static const char *usb_host_hs_utmi_p1_clk_parents[] = {
"init_60m_fclk", "xclk60mhsp1_ck",
};
+#if 0
DEFINE_CLK_MUX(utmi_p1_gfclk, utmi_p1_gfclk_parents, NULL, 0x0,
OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
OMAP4430_CLKSEL_UTMI_P1_SHIFT, OMAP4430_CLKSEL_UTMI_P1_WIDTH,
@@ -1416,11 +1423,25 @@ DEFINE_CLK_MUX(utmi_p1_gfclk, utmi_p1_gfclk_parents, NULL, 0x0,
DEFINE_CLK_GATE(usb_host_hs_utmi_p1_clk, "utmi_p1_gfclk", &utmi_p1_gfclk, 0x0,
OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT, 0x0, NULL);
+#else
+DEFINE_CLK_OMAP_MUX_GATE(usb_host_hs_utmi_p1_clk, "l3_init_clkdm",
+ utmi_p1_clk_sel, OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_CLKSEL_UTMI_P1_MASK,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
+ NULL, usb_host_hs_utmi_p1_clk_parents, dmic_fck_ops);
+#endif /* #if 0 */
-static const char *utmi_p2_gfclk_parents[] = {
- "init_60m_fclk", "xclk60mhsp2_ck",
+static const struct clksel utmi_p2_clk_sel[] = {
+ { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+ { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+ { .parent = NULL },
};
+static const char *usb_host_hs_utmi_p2_clk_parents[] = {
+ "init_60m_fclk", "xclk60mhsp2_ck",
+};
+#if 0
DEFINE_CLK_MUX(utmi_p2_gfclk, utmi_p2_gfclk_parents, NULL, 0x0,
OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
OMAP4430_CLKSEL_UTMI_P2_SHIFT, OMAP4430_CLKSEL_UTMI_P2_WIDTH,
@@ -1429,6 +1450,14 @@ DEFINE_CLK_MUX(utmi_p2_gfclk, utmi_p2_gfclk_parents, NULL, 0x0,
DEFINE_CLK_GATE(usb_host_hs_utmi_p2_clk, "utmi_p2_gfclk", &utmi_p2_gfclk, 0x0,
OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT, 0x0, NULL);
+#else
+DEFINE_CLK_OMAP_MUX_GATE(usb_host_hs_utmi_p2_clk, "l3_init_clkdm",
+ utmi_p2_clk_sel, OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_CLKSEL_UTMI_P2_MASK,
+ OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
+ NULL, usb_host_hs_utmi_p2_clk_parents, dmic_fck_ops);
+#endif /* #if 0 */
DEFINE_CLK_GATE(usb_host_hs_utmi_p3_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
@@ -1876,9 +1905,7 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X),
- CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
- CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X),
CLK(NULL, "usb_host_hs_utmi_p2_clk", &usb_host_hs_utmi_p2_clk, CK_443X),
CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X),
CLK(NULL, "usb_host_hs_hsic480m_p1_clk", &usb_host_hs_hsic480m_p1_clk, CK_443X),
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 948bcaa82eb6..a285e019ddba 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -286,5 +286,7 @@ extern void omap_reserve(void);
struct omap_hwmod;
extern int omap_dss_reset(struct omap_hwmod *);
+void __init usbhost_init_of(void);
+
#endif /* __ASSEMBLER__ */
#endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 2e44e8a22884..08c663174f75 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -22,6 +22,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <asm/io.h>
@@ -494,6 +496,8 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
usbhs_data.port_mode[i] = pdata->port_mode[i];
+ usbhs_data.clk[i] = pdata->clk[i];
+ usbhs_data.clkrate[i] = pdata->clkrate[i];
usbtll_data.port_mode[i] = pdata->port_mode[i];
ohci_data.port_mode[i] = pdata->port_mode[i];
ehci_data.port_mode[i] = pdata->port_mode[i];
@@ -504,6 +508,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
ohci_data.es2_compatibility = pdata->es2_compatibility;
usbhs_data.ehci_data = &ehci_data;
usbhs_data.ohci_data = &ohci_data;
+ usbhs_data.nports = pdata->nports;
if (cpu_is_omap34xx()) {
setup_ehci_io_mux(pdata->port_mode);
@@ -557,3 +562,74 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
}
#endif
+
+static struct usbhs_omap_board_data bdata;
+
+#define USBHS_NODE "usb-host"
+
+/**
+ * usbhost_init_of - initialize USB Host subsystem from device tree
+ *
+ * Scans the device tree for required information and populates
+ * platform data for the OMAP USB High Speed Host subsystem
+ */
+void __init usbhost_init_of(void)
+{
+ int r;
+ struct device_node *node, *child;
+ int num_ports;
+ int i;
+
+ node = of_find_node_by_name(NULL, USBHS_NODE);
+ if (!node) {
+ pr_err("%s could not find OF node : %s\n",
+ __func__, USBHS_NODE);
+ return;
+ }
+
+ r = of_property_read_u32(node, "num_ports", &num_ports);
+ if (r) {
+ pr_err("%s num_ports not specified in OF node %s\n",
+ __func__, USBHS_NODE);
+ } else {
+ bdata.nports = num_ports;
+ }
+
+ r = of_property_read_bool(node, "phy_reset");
+ bdata.phy_reset = r;
+
+ i = 0;
+ for_each_child_of_node(node, child) {
+ int mode;
+ const char *clk_name;
+ u32 clk_rate;
+
+ r = of_property_read_u32(child, "mode", &mode);
+ if (r) {
+ pr_err("%s mode not specified in OF node %s port %d\n",
+ __func__, USBHS_NODE, i);
+ bdata.port_mode[i] = OMAP_USBHS_PORT_MODE_UNUSED;
+ } else {
+ bdata.port_mode[i] = mode;
+ }
+
+ r = of_get_named_gpio(child, "reset_gpio", 0);
+ if (gpio_is_valid(r))
+ bdata.reset_gpio_port[i] = r;
+ else
+ bdata.reset_gpio_port[i] = -EINVAL;
+
+ clk_name = of_get_property(child, "clk", NULL);
+ if (clk_name)
+ bdata.clk[i] = clk_name;
+
+ r = of_property_read_u32(child, "clkrate", &clk_rate);
+ if (!r)
+ bdata.clkrate[i] = clk_rate;
+
+ i++;
+ }
+
+ usbhs_init(&bdata);
+}
+
diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h
index 9b986ead7c45..856ff43a611f 100644
--- a/arch/arm/mach-omap2/usb.h
+++ b/arch/arm/mach-omap2/usb.h
@@ -54,6 +54,7 @@
#define USBPHY_DATA_POLARITY (1 << 23)
struct usbhs_omap_board_data {
+ int nports;
enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS];
/* have to be valid if phy_reset is true and portx is in phy mode */
@@ -69,6 +70,9 @@ struct usbhs_omap_board_data {
* Each PHY can have a separate regulator.
*/
struct regulator *regulator[OMAP3_HS_USB_PORTS];
+
+ const char *clk[OMAP3_HS_USB_PORTS];
+ unsigned long int clkrate[OMAP3_HS_USB_PORTS];
};
extern void usb_musb_init(struct omap_musb_board_data *board_data);