summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/usb-host.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/usb-host.c')
-rw-r--r--arch/arm/mach-omap2/usb-host.c76
1 files changed, 76 insertions, 0 deletions
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);
+}
+