419 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support4 *5 * Copyright (C) 2013 Samsung Electronics Co., Ltd.6 * Author: Kamil Debski <k.debski@samsung.com>7 */8 9#include <linux/delay.h>10#include <linux/io.h>11#include <linux/phy/phy.h>12#include <linux/regmap.h>13#include "phy-samsung-usb2.h"14 15/* Exynos USB PHY registers */16#define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x017#define EXYNOS_5250_REFCLKSEL_XO 0x118#define EXYNOS_5250_REFCLKSEL_CLKCORE 0x219 20#define EXYNOS_5250_FSEL_9MHZ6 0x021#define EXYNOS_5250_FSEL_10MHZ 0x122#define EXYNOS_5250_FSEL_12MHZ 0x223#define EXYNOS_5250_FSEL_19MHZ2 0x324#define EXYNOS_5250_FSEL_20MHZ 0x425#define EXYNOS_5250_FSEL_24MHZ 0x526#define EXYNOS_5250_FSEL_50MHZ 0x727 28/* Normal host */29#define EXYNOS_5250_HOSTPHYCTRL0 0x030 31#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)32#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 1933#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \34 (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)35#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 1636#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \37 (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)38#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)39#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)40#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)41#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)42#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)43#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)44#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)45#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)46#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)47#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)48#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)49#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)50#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)51#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)52 53/* HSIC0 & HSIC1 */54#define EXYNOS_5250_HSICPHYCTRL1 0x1055#define EXYNOS_5250_HSICPHYCTRL2 0x2056 57#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)58#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)59#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)60#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)61#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)62#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)63#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)64#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)65#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)66#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)67#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)68#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)69#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)70#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)71 72/* EHCI control */73#define EXYNOS_5250_HOSTEHCICTRL 0x3074#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)75#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)76#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)77#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)78#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)79#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 1980#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \81 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)82#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 1383#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \84 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)85#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 786#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \87 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)88#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 189#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \90 (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)91#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)92 93/* OHCI control */94#define EXYNOS_5250_HOSTOHCICTRL 0x3495#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 196#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \97 (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)98#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)99 100/* USBOTG */101#define EXYNOS_5250_USBOTGSYS 0x38102#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)103#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)104#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)105#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9106#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \107 (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)108#define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)109#define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)110#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4111#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \112 (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)113#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)114#define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)115#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)116#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)117 118/* Isolation, configured in the power management unit */119#define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704120#define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708121#define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C122#define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)123 124/* Mode switch register */125#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230126#define EXYNOS_5250_MODE_SWITCH_MASK 1127#define EXYNOS_5250_MODE_SWITCH_DEVICE 0128#define EXYNOS_5250_MODE_SWITCH_HOST 1129 130enum exynos4x12_phy_id {131 EXYNOS5250_DEVICE,132 EXYNOS5250_HOST,133 EXYNOS5250_HSIC0,134 EXYNOS5250_HSIC1,135};136 137/*138 * exynos5250_rate_to_clk() converts the supplied clock rate to the value that139 * can be written to the phy register.140 */141static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)142{143 /* EXYNOS_5250_FSEL_MASK */144 145 switch (rate) {146 case 9600 * KHZ:147 *reg = EXYNOS_5250_FSEL_9MHZ6;148 break;149 case 10 * MHZ:150 *reg = EXYNOS_5250_FSEL_10MHZ;151 break;152 case 12 * MHZ:153 *reg = EXYNOS_5250_FSEL_12MHZ;154 break;155 case 19200 * KHZ:156 *reg = EXYNOS_5250_FSEL_19MHZ2;157 break;158 case 20 * MHZ:159 *reg = EXYNOS_5250_FSEL_20MHZ;160 break;161 case 24 * MHZ:162 *reg = EXYNOS_5250_FSEL_24MHZ;163 break;164 case 50 * MHZ:165 *reg = EXYNOS_5250_FSEL_50MHZ;166 break;167 default:168 return -EINVAL;169 }170 171 return 0;172}173 174static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)175{176 struct samsung_usb2_phy_driver *drv = inst->drv;177 u32 offset;178 u32 mask = EXYNOS_5250_USB_ISOL_ENABLE;179 180 if (drv->cfg == &exynos5250_usb2_phy_config &&181 inst->cfg->id == EXYNOS5250_DEVICE)182 offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;183 else if (drv->cfg == &exynos5250_usb2_phy_config &&184 inst->cfg->id == EXYNOS5250_HOST)185 offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;186 else if (drv->cfg == &exynos5420_usb2_phy_config &&187 inst->cfg->id == EXYNOS5250_HOST)188 offset = EXYNOS_5420_USB_ISOL_HOST_OFFSET;189 else190 return;191 192 regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);193}194 195static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)196{197 struct samsung_usb2_phy_driver *drv = inst->drv;198 u32 ctrl0;199 u32 otg;200 u32 ehci;201 u32 ohci;202 u32 hsic;203 204 switch (inst->cfg->id) {205 case EXYNOS5250_DEVICE:206 regmap_update_bits(drv->reg_sys,207 EXYNOS_5250_MODE_SWITCH_OFFSET,208 EXYNOS_5250_MODE_SWITCH_MASK,209 EXYNOS_5250_MODE_SWITCH_DEVICE);210 211 /* OTG configuration */212 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);213 /* The clock */214 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;215 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;216 /* Reset */217 otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |218 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |219 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);220 otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |221 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |222 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |223 EXYNOS_5250_USBOTGSYS_OTGDISABLE;224 /* Ref clock */225 otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;226 otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<227 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;228 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);229 udelay(100);230 otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |231 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |232 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |233 EXYNOS_5250_USBOTGSYS_OTGDISABLE);234 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);235 236 237 break;238 case EXYNOS5250_HOST:239 case EXYNOS5250_HSIC0:240 case EXYNOS5250_HSIC1:241 /* Host registers configuration */242 ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);243 /* The clock */244 ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;245 ctrl0 |= drv->ref_reg_val <<246 EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;247 248 /* Reset */249 ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |250 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |251 EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |252 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |253 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);254 ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |255 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |256 EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;257 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);258 udelay(10);259 ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |260 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);261 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);262 263 /* OTG configuration */264 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);265 /* The clock */266 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;267 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;268 /* Reset */269 otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |270 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |271 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);272 otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |273 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |274 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |275 EXYNOS_5250_USBOTGSYS_OTGDISABLE;276 /* Ref clock */277 otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;278 otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<279 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;280 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);281 udelay(10);282 otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |283 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |284 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);285 286 /* HSIC phy configuration */287 hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |288 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |289 EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);290 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);291 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);292 udelay(10);293 hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;294 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);295 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);296 /* The following delay is necessary for the reset sequence to be297 * completed */298 udelay(80);299 300 /* Enable EHCI DMA burst */301 ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);302 ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |303 EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |304 EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |305 EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;306 writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);307 308 /* OHCI settings */309 ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);310 /* Following code is based on the old driver */311 ohci |= 0x1 << 3;312 writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);313 314 break;315 }316 exynos5250_isol(inst, 0);317 318 return 0;319}320 321static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)322{323 struct samsung_usb2_phy_driver *drv = inst->drv;324 u32 ctrl0;325 u32 otg;326 u32 hsic;327 328 exynos5250_isol(inst, 1);329 330 switch (inst->cfg->id) {331 case EXYNOS5250_DEVICE:332 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);333 otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |334 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |335 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);336 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);337 break;338 case EXYNOS5250_HOST:339 ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);340 ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |341 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |342 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |343 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |344 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);345 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);346 break;347 case EXYNOS5250_HSIC0:348 case EXYNOS5250_HSIC1:349 hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |350 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |351 EXYNOS_5250_HSICPHYCTRLX_SIDDQ |352 EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |353 EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND354 );355 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);356 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);357 break;358 }359 360 return 0;361}362 363 364static const struct samsung_usb2_common_phy exynos5250_phys[] = {365 {366 .label = "device",367 .id = EXYNOS5250_DEVICE,368 .power_on = exynos5250_power_on,369 .power_off = exynos5250_power_off,370 },371 {372 .label = "host",373 .id = EXYNOS5250_HOST,374 .power_on = exynos5250_power_on,375 .power_off = exynos5250_power_off,376 },377 {378 .label = "hsic0",379 .id = EXYNOS5250_HSIC0,380 .power_on = exynos5250_power_on,381 .power_off = exynos5250_power_off,382 },383 {384 .label = "hsic1",385 .id = EXYNOS5250_HSIC1,386 .power_on = exynos5250_power_on,387 .power_off = exynos5250_power_off,388 },389};390 391static const struct samsung_usb2_common_phy exynos5420_phys[] = {392 {393 .label = "host",394 .id = EXYNOS5250_HOST,395 .power_on = exynos5250_power_on,396 .power_off = exynos5250_power_off,397 },398 {399 .label = "hsic",400 .id = EXYNOS5250_HSIC0,401 .power_on = exynos5250_power_on,402 .power_off = exynos5250_power_off,403 },404};405 406const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {407 .has_mode_switch = 1,408 .num_phys = ARRAY_SIZE(exynos5250_phys),409 .phys = exynos5250_phys,410 .rate_to_clk = exynos5250_rate_to_clk,411};412 413const struct samsung_usb2_phy_config exynos5420_usb2_phy_config = {414 .has_mode_switch = 1,415 .num_phys = ARRAY_SIZE(exynos5420_phys),416 .phys = exynos5420_phys,417 .rate_to_clk = exynos5250_rate_to_clk,418};419