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