Home | History | Annotate | Download | only in host
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * SAMSUNG EXYNOS USB HOST EHCI Controller
      4  *
      5  * Copyright (C) 2012 Samsung Electronics Co.Ltd
      6  *	Vivek Gautam <gautam.vivek (at) samsung.com>
      7  */
      8 
      9 #include <common.h>
     10 #include <dm.h>
     11 #include <fdtdec.h>
     12 #include <linux/libfdt.h>
     13 #include <malloc.h>
     14 #include <usb.h>
     15 #include <asm/arch/cpu.h>
     16 #include <asm/arch/ehci.h>
     17 #include <asm/arch/system.h>
     18 #include <asm/arch/power.h>
     19 #include <asm/gpio.h>
     20 #include <linux/errno.h>
     21 #include <linux/compat.h>
     22 #include "ehci.h"
     23 
     24 /* Declare global data pointer */
     25 DECLARE_GLOBAL_DATA_PTR;
     26 
     27 struct exynos_ehci_platdata {
     28 	struct usb_platdata usb_plat;
     29 	fdt_addr_t hcd_base;
     30 	fdt_addr_t phy_base;
     31 	struct gpio_desc vbus_gpio;
     32 };
     33 
     34 /**
     35  * Contains pointers to register base addresses
     36  * for the usb controller.
     37  */
     38 struct exynos_ehci {
     39 	struct ehci_ctrl ctrl;
     40 	struct exynos_usb_phy *usb;
     41 	struct ehci_hccr *hcd;
     42 };
     43 
     44 static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
     45 {
     46 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
     47 	const void *blob = gd->fdt_blob;
     48 	unsigned int node;
     49 	int depth;
     50 
     51 	/*
     52 	 * Get the base address for XHCI controller from the device node
     53 	 */
     54 	plat->hcd_base = devfdt_get_addr(dev);
     55 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
     56 		debug("Can't get the XHCI register base address\n");
     57 		return -ENXIO;
     58 	}
     59 
     60 	depth = 0;
     61 	node = fdtdec_next_compatible_subnode(blob, dev_of_offset(dev),
     62 				COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
     63 	if (node <= 0) {
     64 		debug("XHCI: Can't get device node for usb3-phy controller\n");
     65 		return -ENODEV;
     66 	}
     67 
     68 	/*
     69 	 * Get the base address for usbphy from the device node
     70 	 */
     71 	plat->phy_base = fdtdec_get_addr(blob, node, "reg");
     72 	if (plat->phy_base == FDT_ADDR_T_NONE) {
     73 		debug("Can't get the usbphy register address\n");
     74 		return -ENXIO;
     75 	}
     76 
     77 	/* Vbus gpio */
     78 	gpio_request_by_name(dev, "samsung,vbus-gpio", 0,
     79 			     &plat->vbus_gpio, GPIOD_IS_OUT);
     80 
     81 	return 0;
     82 }
     83 
     84 static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
     85 {
     86 	u32 hsic_ctrl;
     87 
     88 	clrbits_le32(&usb->usbphyctrl0,
     89 			HOST_CTRL0_FSEL_MASK |
     90 			HOST_CTRL0_COMMONON_N |
     91 			/* HOST Phy setting */
     92 			HOST_CTRL0_PHYSWRST |
     93 			HOST_CTRL0_PHYSWRSTALL |
     94 			HOST_CTRL0_SIDDQ |
     95 			HOST_CTRL0_FORCESUSPEND |
     96 			HOST_CTRL0_FORCESLEEP);
     97 
     98 	setbits_le32(&usb->usbphyctrl0,
     99 			/* Setting up the ref freq */
    100 			(CLK_24MHZ << 16) |
    101 			/* HOST Phy setting */
    102 			HOST_CTRL0_LINKSWRST |
    103 			HOST_CTRL0_UTMISWRST);
    104 	udelay(10);
    105 	clrbits_le32(&usb->usbphyctrl0,
    106 			HOST_CTRL0_LINKSWRST |
    107 			HOST_CTRL0_UTMISWRST);
    108 
    109 	/* HSIC Phy Setting */
    110 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
    111 			HSIC_CTRL_FORCESLEEP |
    112 			HSIC_CTRL_SIDDQ);
    113 
    114 	clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
    115 	clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
    116 
    117 	hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK)
    118 				<< HSIC_CTRL_REFCLKDIV_SHIFT)
    119 			| ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK)
    120 				<< HSIC_CTRL_REFCLKSEL_SHIFT)
    121 			| HSIC_CTRL_UTMISWRST);
    122 
    123 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
    124 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
    125 
    126 	udelay(10);
    127 
    128 	clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST |
    129 					HSIC_CTRL_UTMISWRST);
    130 
    131 	clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST |
    132 					HSIC_CTRL_UTMISWRST);
    133 
    134 	udelay(20);
    135 
    136 	/* EHCI Ctrl setting */
    137 	setbits_le32(&usb->ehcictrl,
    138 			EHCICTRL_ENAINCRXALIGN |
    139 			EHCICTRL_ENAINCR4 |
    140 			EHCICTRL_ENAINCR8 |
    141 			EHCICTRL_ENAINCR16);
    142 }
    143 
    144 static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
    145 {
    146 	writel(CLK_24MHZ, &usb->usbphyclk);
    147 
    148 	clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
    149 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
    150 		PHYPWR_NORMAL_MASK_PHY0));
    151 
    152 	setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
    153 	udelay(10);
    154 	clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
    155 }
    156 
    157 static void setup_usb_phy(struct exynos_usb_phy *usb)
    158 {
    159 	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
    160 
    161 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
    162 
    163 	if (cpu_is_exynos5())
    164 		exynos5_setup_usb_phy(usb);
    165 	else if (cpu_is_exynos4())
    166 		if (proid_is_exynos4412())
    167 			exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)
    168 						 usb);
    169 }
    170 
    171 static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
    172 {
    173 	u32 hsic_ctrl;
    174 
    175 	/* HOST_PHY reset */
    176 	setbits_le32(&usb->usbphyctrl0,
    177 			HOST_CTRL0_PHYSWRST |
    178 			HOST_CTRL0_PHYSWRSTALL |
    179 			HOST_CTRL0_SIDDQ |
    180 			HOST_CTRL0_FORCESUSPEND |
    181 			HOST_CTRL0_FORCESLEEP);
    182 
    183 	/* HSIC Phy reset */
    184 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
    185 			HSIC_CTRL_FORCESLEEP |
    186 			HSIC_CTRL_SIDDQ |
    187 			HSIC_CTRL_PHYSWRST);
    188 
    189 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
    190 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
    191 }
    192 
    193 static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
    194 {
    195 	setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
    196 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
    197 		PHYPWR_NORMAL_MASK_PHY0));
    198 }
    199 
    200 /* Reset the EHCI host controller. */
    201 static void reset_usb_phy(struct exynos_usb_phy *usb)
    202 {
    203 	if (cpu_is_exynos5())
    204 		exynos5_reset_usb_phy(usb);
    205 	else if (cpu_is_exynos4())
    206 		if (proid_is_exynos4412())
    207 			exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)
    208 						 usb);
    209 
    210 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
    211 }
    212 
    213 static int ehci_usb_probe(struct udevice *dev)
    214 {
    215 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
    216 	struct exynos_ehci *ctx = dev_get_priv(dev);
    217 	struct ehci_hcor *hcor;
    218 
    219 	ctx->hcd = (struct ehci_hccr *)plat->hcd_base;
    220 	ctx->usb = (struct exynos_usb_phy *)plat->phy_base;
    221 
    222 	/* setup the Vbus gpio here */
    223 	if (dm_gpio_is_valid(&plat->vbus_gpio))
    224 		dm_gpio_set_value(&plat->vbus_gpio, 1);
    225 
    226 	setup_usb_phy(ctx->usb);
    227 	hcor = (struct ehci_hcor *)((uint32_t)ctx->hcd +
    228 			HC_LENGTH(ehci_readl(&ctx->hcd->cr_capbase)));
    229 
    230 	return ehci_register(dev, ctx->hcd, hcor, NULL, 0, USB_INIT_HOST);
    231 }
    232 
    233 static int ehci_usb_remove(struct udevice *dev)
    234 {
    235 	struct exynos_ehci *ctx = dev_get_priv(dev);
    236 	int ret;
    237 
    238 	ret = ehci_deregister(dev);
    239 	if (ret)
    240 		return ret;
    241 	reset_usb_phy(ctx->usb);
    242 
    243 	return 0;
    244 }
    245 
    246 static const struct udevice_id ehci_usb_ids[] = {
    247 	{ .compatible = "samsung,exynos-ehci" },
    248 	{ }
    249 };
    250 
    251 U_BOOT_DRIVER(usb_ehci) = {
    252 	.name	= "ehci_exynos",
    253 	.id	= UCLASS_USB,
    254 	.of_match = ehci_usb_ids,
    255 	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
    256 	.probe = ehci_usb_probe,
    257 	.remove = ehci_usb_remove,
    258 	.ops	= &ehci_usb_ops,
    259 	.priv_auto_alloc_size = sizeof(struct exynos_ehci),
    260 	.platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata),
    261 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
    262 };
    263