Skip to content

Commit

Permalink
USB: add platform glue driver for FSL USB DR controller
Browse files Browse the repository at this point in the history
Replace FSL USB platform code by simple platform driver for
creation of FSL USB platform devices.

The driver creates platform devices based on the information
from USB nodes in the flat device tree. This is the replacement
for old arch fsl_soc usb code removed by this patch. The driver
uses usual of-style binding, available EHCI-HCD and UDC
drivers can be bound to the created devices. The new of-style
driver additionaly instantiates USB OTG platform device, as the
appropriate USB OTG driver will be added soon.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Anatolij Gustschin authored and Greg Kroah-Hartman committed Oct 22, 2010
1 parent 99c1e4f commit 126512e
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 163 deletions.
163 changes: 0 additions & 163 deletions arch/powerpc/sysdev/fsl_soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void)
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */

static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
{
if (!phy_type)
return FSL_USB2_PHY_NONE;
if (!strcasecmp(phy_type, "ulpi"))
return FSL_USB2_PHY_ULPI;
if (!strcasecmp(phy_type, "utmi"))
return FSL_USB2_PHY_UTMI;
if (!strcasecmp(phy_type, "utmi_wide"))
return FSL_USB2_PHY_UTMI_WIDE;
if (!strcasecmp(phy_type, "serial"))
return FSL_USB2_PHY_SERIAL;

return FSL_USB2_PHY_NONE;
}

static int __init fsl_usb_of_init(void)
{
struct device_node *np;
unsigned int i = 0;
struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
*usb_dev_dr_client = NULL;
int ret;

for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;

memset(&r, 0, sizeof(r));
memset(&usb_data, 0, sizeof(usb_data));

ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto err;

of_irq_to_resource(np, 0, &r[1]);

usb_dev_mph =
platform_device_register_simple("fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_mph)) {
ret = PTR_ERR(usb_dev_mph);
goto err;
}

usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;

usb_data.operating_mode = FSL_USB2_MPH_HOST;

prop = of_get_property(np, "port0", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;

prop = of_get_property(np, "port1", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;

prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);

ret =
platform_device_add_data(usb_dev_mph, &usb_data,
sizeof(struct
fsl_usb2_platform_data));
if (ret)
goto unreg_mph;
i++;
}

for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;

if (!of_device_is_available(np))
continue;

memset(&r, 0, sizeof(r));
memset(&usb_data, 0, sizeof(usb_data));

ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto unreg_mph;

of_irq_to_resource(np, 0, &r[1]);

prop = of_get_property(np, "dr_mode", NULL);

if (!prop || !strcmp(prop, "host")) {
usb_data.operating_mode = FSL_USB2_DR_HOST;
usb_dev_dr_host = platform_device_register_simple(
"fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_dr_host)) {
ret = PTR_ERR(usb_dev_dr_host);
goto err;
}
} else if (prop && !strcmp(prop, "peripheral")) {
usb_data.operating_mode = FSL_USB2_DR_DEVICE;
usb_dev_dr_client = platform_device_register_simple(
"fsl-usb2-udc", i, r, 2);
if (IS_ERR(usb_dev_dr_client)) {
ret = PTR_ERR(usb_dev_dr_client);
goto err;
}
} else if (prop && !strcmp(prop, "otg")) {
usb_data.operating_mode = FSL_USB2_DR_OTG;
usb_dev_dr_host = platform_device_register_simple(
"fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_dr_host)) {
ret = PTR_ERR(usb_dev_dr_host);
goto err;
}
usb_dev_dr_client = platform_device_register_simple(
"fsl-usb2-udc", i, r, 2);
if (IS_ERR(usb_dev_dr_client)) {
ret = PTR_ERR(usb_dev_dr_client);
goto err;
}
} else {
ret = -EINVAL;
goto err;
}

prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);

if (usb_dev_dr_host) {
usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
dev.coherent_dma_mask;
if ((ret = platform_device_add_data(usb_dev_dr_host,
&usb_data, sizeof(struct
fsl_usb2_platform_data))))
goto unreg_dr;
}
if (usb_dev_dr_client) {
usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
dev.coherent_dma_mask;
if ((ret = platform_device_add_data(usb_dev_dr_client,
&usb_data, sizeof(struct
fsl_usb2_platform_data))))
goto unreg_dr;
}
i++;
}
return 0;

unreg_dr:
if (usb_dev_dr_host)
platform_device_unregister(usb_dev_dr_host);
if (usb_dev_dr_client)
platform_device_unregister(usb_dev_dr_client);
unreg_mph:
if (usb_dev_mph)
platform_device_unregister(usb_dev_mph);
err:
return ret;
}

arch_initcall(fsl_usb_of_init);

#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static __be32 __iomem *rstcr;

Expand Down
1 change: 1 addition & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
depends on FSL_SOC || ARCH_MXC
select USB_GADGET_DUALSPEED
select USB_FSL_MPH_DR_OF
help
Some of Freescale PowerPC processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode.
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,14 @@ config XPS_USB_HCD_XILINX
support both high speed and full speed devices, or high speed
devices only.

config USB_FSL_MPH_DR_OF
tristate

config USB_EHCI_FSL
bool "Support for Freescale on-chip EHCI USB controller"
depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF
---help---
Variation of ARC USB block used in some Freescale chips.

Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o

Loading

0 comments on commit 126512e

Please sign in to comment.