mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-30 18:05:48 +01:00 
			
		
		
		
	dm: usb: exynos: Add driver model support to exynos EHCI
Update this driver with driver model support for USB. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Marek Vasut <marex@denx.de>
This commit is contained in:
		| @@ -8,6 +8,7 @@ | ||||
|  */ | ||||
|  | ||||
| #include <common.h> | ||||
| #include <dm.h> | ||||
| #include <fdtdec.h> | ||||
| #include <libfdt.h> | ||||
| #include <malloc.h> | ||||
| @@ -24,19 +25,73 @@ | ||||
| /* Declare global data pointer */ | ||||
| DECLARE_GLOBAL_DATA_PTR; | ||||
|  | ||||
| #ifdef CONFIG_DM_USB | ||||
| struct exynos_ehci_platdata { | ||||
| 	struct usb_platdata usb_plat; | ||||
| 	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_ehci { | ||||
| 	struct ehci_ctrl ctrl; | ||||
| 	struct exynos_usb_phy *usb; | ||||
| 	struct ehci_hccr *hcd; | ||||
| #ifndef CONFIG_DM_USB | ||||
| 	struct gpio_desc vbus_gpio; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #ifndef CONFIG_DM_USB | ||||
| static struct exynos_ehci exynos; | ||||
| #endif | ||||
|  | ||||
| #ifdef CONFIG_OF_CONTROL | ||||
| #ifdef CONFIG_DM_USB | ||||
| static int ehci_usb_ofdata_to_platdata(struct udevice *dev) | ||||
| { | ||||
| 	struct exynos_ehci_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 = dev_get_addr(dev); | ||||
| 	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_EXYNOS_USB_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_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) | ||||
| { | ||||
| 	fdt_addr_t addr; | ||||
| @@ -215,6 +270,7 @@ static void reset_usb_phy(struct exynos_usb_phy *usb) | ||||
| 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE); | ||||
| } | ||||
|  | ||||
| #ifndef CONFIG_DM_USB | ||||
| /* | ||||
|  * EHCI-initialization | ||||
|  * Create the appropriate control structures to manage | ||||
| @@ -268,3 +324,57 @@ int ehci_hcd_stop(int index) | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifdef CONFIG_DM_USB | ||||
| static int ehci_usb_probe(struct udevice *dev) | ||||
| { | ||||
| 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev); | ||||
| 	struct exynos_ehci *ctx = dev_get_priv(dev); | ||||
| 	struct ehci_hcor *hcor; | ||||
|  | ||||
| 	ctx->hcd = (struct ehci_hccr *)plat->hcd_base; | ||||
| 	ctx->usb = (struct exynos_usb_phy *)plat->phy_base; | ||||
| 	hcor = (struct ehci_hcor *)((uint32_t)ctx->hcd + | ||||
| 			HC_LENGTH(ehci_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); | ||||
|  | ||||
| 	setup_usb_phy(ctx->usb); | ||||
|  | ||||
| 	return ehci_register(dev, ctx->hcd, hcor, NULL, 0, USB_INIT_HOST); | ||||
| } | ||||
|  | ||||
| static int ehci_usb_remove(struct udevice *dev) | ||||
| { | ||||
| 	struct exynos_ehci *ctx = dev_get_priv(dev); | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = ehci_deregister(dev); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 	reset_usb_phy(ctx->usb); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static const struct udevice_id ehci_usb_ids[] = { | ||||
| 	{ .compatible = "samsung,exynos-ehci" }, | ||||
| 	{ } | ||||
| }; | ||||
|  | ||||
| U_BOOT_DRIVER(usb_ehci) = { | ||||
| 	.name	= "ehci_exynos", | ||||
| 	.id	= UCLASS_USB, | ||||
| 	.of_match = ehci_usb_ids, | ||||
| 	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata, | ||||
| 	.probe = ehci_usb_probe, | ||||
| 	.remove = ehci_usb_remove, | ||||
| 	.ops	= &ehci_usb_ops, | ||||
| 	.priv_auto_alloc_size = sizeof(struct exynos_ehci), | ||||
| 	.platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata), | ||||
| 	.flags	= DM_FLAG_ALLOC_PRIV_DMA, | ||||
| }; | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user