From 52e6935774afa45121df6a712c17f91f8f6c4f99 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 25 Mar 2015 12:22:55 -0600 Subject: dm: usb: exynos: Adjust XHCI driver to support driver model Support driver model in the exynos XHCI driver. Signed-off-by: Simon Glass Reviewed-by: Marek Vasut --- drivers/usb/host/xhci-exynos5.c | 120 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c index 3f86fdca89..23c7ecc5d8 100644 --- a/drivers/usb/host/xhci-exynos5.c +++ b/drivers/usb/host/xhci-exynos5.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -32,20 +33,76 @@ /* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_DM_USB +struct exynos_xhci_platdata { + fdt_addr_t hcd_base; + fdt_addr_t phy_base; + struct gpio_desc vbus_gpio; +}; +#endif + /** * Contains pointers to register base addresses * for the usb controller. */ struct exynos_xhci { +#ifdef CONFIG_DM_USB + struct usb_platdata usb_plat; +#endif + struct xhci_ctrl ctrl; struct exynos_usb3_phy *usb3_phy; struct xhci_hccr *hcd; struct dwc3 *dwc3_reg; +#ifndef CONFIG_DM_USB struct gpio_desc vbus_gpio; +#endif }; +#ifndef CONFIG_DM_USB static struct exynos_xhci exynos; +#endif -#ifdef CONFIG_OF_CONTROL +#ifdef CONFIG_DM_USB +static int xhci_usb_ofdata_to_platdata(struct udevice *dev) +{ + struct exynos_xhci_platdata *plat = dev_get_platdata(dev); + const void *blob = gd->fdt_blob; + unsigned int node; + int depth; + + /* + * Get the base address for XHCI controller from the device node + */ + plat->hcd_base = fdtdec_get_addr(blob, dev->of_offset, "reg"); + if (plat->hcd_base == FDT_ADDR_T_NONE) { + debug("Can't get the XHCI register base address\n"); + return -ENXIO; + } + + depth = 0; + node = fdtdec_next_compatible_subnode(blob, dev->of_offset, + COMPAT_SAMSUNG_EXYNOS5_USB3_PHY, &depth); + if (node <= 0) { + debug("XHCI: Can't get device node for usb3-phy controller\n"); + return -ENODEV; + } + + /* + * Get the base address for usbphy from the device node + */ + plat->phy_base = fdtdec_get_addr(blob, node, "reg"); + if (plat->phy_base == FDT_ADDR_T_NONE) { + debug("Can't get the usbphy register address\n"); + return -ENXIO; + } + + /* Vbus gpio */ + gpio_request_by_name(dev, "samsung,vbus-gpio", 0, + &plat->vbus_gpio, GPIOD_IS_OUT); + + return 0; +} +#else static int exynos_usb3_parse_dt(const void *blob, struct exynos_xhci *exynos) { fdt_addr_t addr; @@ -283,6 +340,7 @@ static void exynos_xhci_core_exit(struct exynos_xhci *exynos) exynos5_usb3_phy_exit(exynos->usb3_phy); } +#ifndef CONFIG_DM_USB int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { struct exynos_xhci *ctx = &exynos; @@ -326,3 +384,63 @@ void xhci_hcd_stop(int index) exynos_xhci_core_exit(ctx); } +#endif + +#ifdef CONFIG_DM_USB +static int xhci_usb_probe(struct udevice *dev) +{ + struct exynos_xhci_platdata *plat = dev_get_platdata(dev); + struct exynos_xhci *ctx = dev_get_priv(dev); + struct xhci_hcor *hcor; + int ret; + + ctx->hcd = (struct xhci_hccr *)plat->hcd_base; + ctx->usb3_phy = (struct exynos_usb3_phy *)plat->phy_base; + ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); + hcor = (struct xhci_hcor *)((uint32_t)ctx->hcd + + HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase))); + + /* setup the Vbus gpio here */ + if (dm_gpio_is_valid(&plat->vbus_gpio)) + dm_gpio_set_value(&plat->vbus_gpio, 1); + + ret = exynos_xhci_core_init(ctx); + if (ret) { + puts("XHCI: failed to initialize controller\n"); + return -EINVAL; + } + + return xhci_register(dev, ctx->hcd, hcor); +} + +static int xhci_usb_remove(struct udevice *dev) +{ + struct exynos_xhci *ctx = dev_get_priv(dev); + int ret; + + ret = xhci_deregister(dev); + if (ret) + return ret; + exynos_xhci_core_exit(ctx); + + return 0; +} + +static const struct udevice_id xhci_usb_ids[] = { + { .compatible = "samsung,exynos5250-xhci" }, + { } +}; + +U_BOOT_DRIVER(usb_xhci) = { + .name = "xhci_exynos", + .id = UCLASS_USB, + .of_match = xhci_usb_ids, + .ofdata_to_platdata = xhci_usb_ofdata_to_platdata, + .probe = xhci_usb_probe, + .remove = xhci_usb_remove, + .ops = &xhci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct exynos_xhci_platdata), + .priv_auto_alloc_size = sizeof(struct exynos_xhci), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif -- cgit v1.2.1