10b56e9a7SVivek Gautam /* 20b56e9a7SVivek Gautam * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support 30b56e9a7SVivek Gautam * 40b56e9a7SVivek Gautam * Copyright (C) 2013 Samsung Electronics Co., Ltd. 50b56e9a7SVivek Gautam * Author: Kamil Debski <k.debski@samsung.com> 60b56e9a7SVivek Gautam * 70b56e9a7SVivek Gautam * This program is free software; you can redistribute it and/or modify 80b56e9a7SVivek Gautam * it under the terms of the GNU General Public License version 2 as 90b56e9a7SVivek Gautam * published by the Free Software Foundation. 100b56e9a7SVivek Gautam */ 110b56e9a7SVivek Gautam 120b56e9a7SVivek Gautam #include <linux/delay.h> 130b56e9a7SVivek Gautam #include <linux/io.h> 140b56e9a7SVivek Gautam #include <linux/phy/phy.h> 150b56e9a7SVivek Gautam #include <linux/regmap.h> 160b56e9a7SVivek Gautam #include "phy-samsung-usb2.h" 170b56e9a7SVivek Gautam 180b56e9a7SVivek Gautam /* Exynos USB PHY registers */ 190b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0 200b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_XO 0x1 210b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2 220b56e9a7SVivek Gautam 230b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_9MHZ6 0x0 240b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_10MHZ 0x1 250b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_12MHZ 0x2 260b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_19MHZ2 0x3 270b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_20MHZ 0x4 280b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_24MHZ 0x5 290b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_50MHZ 0x7 300b56e9a7SVivek Gautam 310b56e9a7SVivek Gautam /* Normal host */ 320b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0 0x0 330b56e9a7SVivek Gautam 340b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31) 350b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19 360b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \ 370b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT) 380b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16 390b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \ 400b56e9a7SVivek Gautam (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT) 410b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11) 420b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10) 430b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9) 440b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7) 450b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7) 460b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7) 470b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7) 480b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6) 490b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5) 500b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4) 510b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3) 520b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2) 530b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1) 540b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0) 550b56e9a7SVivek Gautam 560b56e9a7SVivek Gautam /* HSIC0 & HSIC1 */ 570b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRL1 0x10 580b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRL2 0x20 590b56e9a7SVivek Gautam 600b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23) 610b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23) 620b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16) 630b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16) 640b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16) 650b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16) 660b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16) 670b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16) 680b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6) 690b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5) 700b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4) 710b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3) 720b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2) 730b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0) 740b56e9a7SVivek Gautam 750b56e9a7SVivek Gautam /* EHCI control */ 760b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL 0x30 770b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29) 780b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28) 790b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27) 800b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26) 810b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25) 820b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19 830b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \ 840b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT) 850b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13 860b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \ 870b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT) 880b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7 890b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \ 900b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT) 910b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1 920b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \ 930b56e9a7SVivek Gautam (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT) 940b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0) 950b56e9a7SVivek Gautam 960b56e9a7SVivek Gautam /* OHCI control */ 970b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL 0x34 980b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1 990b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \ 1000b56e9a7SVivek Gautam (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT) 1010b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0) 1020b56e9a7SVivek Gautam 1030b56e9a7SVivek Gautam /* USBOTG */ 1040b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS 0x38 1050b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14) 1060b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13) 1070b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12) 1080b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9 1090b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \ 1100b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT) 1110b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8) 1120b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7) 1130b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4 1140b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FSEL_MASK \ 1150b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT) 1160b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3) 1170b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2) 1180b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1) 1190b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0) 1200b56e9a7SVivek Gautam 1210b56e9a7SVivek Gautam /* Isolation, configured in the power management unit */ 1220b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704 1230b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_OTG BIT(0) 1240b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708 1250b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_HOST BIT(0) 1260b56e9a7SVivek Gautam 1270b56e9a7SVivek Gautam /* Mode swtich register */ 1280b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230 1290b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_MASK 1 1300b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_DEVICE 0 1310b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_HOST 1 1320b56e9a7SVivek Gautam 1330b56e9a7SVivek Gautam enum exynos4x12_phy_id { 1340b56e9a7SVivek Gautam EXYNOS5250_DEVICE, 1350b56e9a7SVivek Gautam EXYNOS5250_HOST, 1360b56e9a7SVivek Gautam EXYNOS5250_HSIC0, 1370b56e9a7SVivek Gautam EXYNOS5250_HSIC1, 1380b56e9a7SVivek Gautam EXYNOS5250_NUM_PHYS, 1390b56e9a7SVivek Gautam }; 1400b56e9a7SVivek Gautam 1410b56e9a7SVivek Gautam /* 1420b56e9a7SVivek Gautam * exynos5250_rate_to_clk() converts the supplied clock rate to the value that 1430b56e9a7SVivek Gautam * can be written to the phy register. 1440b56e9a7SVivek Gautam */ 1450b56e9a7SVivek Gautam static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg) 1460b56e9a7SVivek Gautam { 1470b56e9a7SVivek Gautam /* EXYNOS_5250_FSEL_MASK */ 1480b56e9a7SVivek Gautam 1490b56e9a7SVivek Gautam switch (rate) { 1500b56e9a7SVivek Gautam case 9600 * KHZ: 1510b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_9MHZ6; 1520b56e9a7SVivek Gautam break; 1530b56e9a7SVivek Gautam case 10 * MHZ: 1540b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_10MHZ; 1550b56e9a7SVivek Gautam break; 1560b56e9a7SVivek Gautam case 12 * MHZ: 1570b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_12MHZ; 1580b56e9a7SVivek Gautam break; 1590b56e9a7SVivek Gautam case 19200 * KHZ: 1600b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_19MHZ2; 1610b56e9a7SVivek Gautam break; 1620b56e9a7SVivek Gautam case 20 * MHZ: 1630b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_20MHZ; 1640b56e9a7SVivek Gautam break; 1650b56e9a7SVivek Gautam case 24 * MHZ: 1660b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_24MHZ; 1670b56e9a7SVivek Gautam break; 1680b56e9a7SVivek Gautam case 50 * MHZ: 1690b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_50MHZ; 1700b56e9a7SVivek Gautam break; 1710b56e9a7SVivek Gautam default: 1720b56e9a7SVivek Gautam return -EINVAL; 1730b56e9a7SVivek Gautam } 1740b56e9a7SVivek Gautam 1750b56e9a7SVivek Gautam return 0; 1760b56e9a7SVivek Gautam } 1770b56e9a7SVivek Gautam 1780b56e9a7SVivek Gautam static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on) 1790b56e9a7SVivek Gautam { 1800b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv; 1810b56e9a7SVivek Gautam u32 offset; 1820b56e9a7SVivek Gautam u32 mask; 1830b56e9a7SVivek Gautam 1840b56e9a7SVivek Gautam switch (inst->cfg->id) { 1850b56e9a7SVivek Gautam case EXYNOS5250_DEVICE: 1860b56e9a7SVivek Gautam offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET; 1870b56e9a7SVivek Gautam mask = EXYNOS_5250_USB_ISOL_OTG; 1880b56e9a7SVivek Gautam break; 1890b56e9a7SVivek Gautam case EXYNOS5250_HOST: 1900b56e9a7SVivek Gautam offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET; 1910b56e9a7SVivek Gautam mask = EXYNOS_5250_USB_ISOL_HOST; 1920b56e9a7SVivek Gautam break; 1930b56e9a7SVivek Gautam default: 1940b56e9a7SVivek Gautam return; 1950b56e9a7SVivek Gautam } 1960b56e9a7SVivek Gautam 1970b56e9a7SVivek Gautam regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); 1980b56e9a7SVivek Gautam } 1990b56e9a7SVivek Gautam 2000b56e9a7SVivek Gautam static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst) 2010b56e9a7SVivek Gautam { 2020b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv; 2030b56e9a7SVivek Gautam u32 ctrl0; 2040b56e9a7SVivek Gautam u32 otg; 2050b56e9a7SVivek Gautam u32 ehci; 2060b56e9a7SVivek Gautam u32 ohci; 2070b56e9a7SVivek Gautam u32 hsic; 2080b56e9a7SVivek Gautam 2090b56e9a7SVivek Gautam switch (inst->cfg->id) { 2100b56e9a7SVivek Gautam case EXYNOS5250_DEVICE: 2110b56e9a7SVivek Gautam regmap_update_bits(drv->reg_sys, 2120b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_OFFSET, 2130b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_MASK, 2140b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_DEVICE); 2150b56e9a7SVivek Gautam 2160b56e9a7SVivek Gautam /* OTG configuration */ 2170b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); 2180b56e9a7SVivek Gautam /* The clock */ 2190b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK; 2200b56e9a7SVivek Gautam otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT; 2210b56e9a7SVivek Gautam /* Reset */ 2220b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | 2230b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP | 2240b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG); 2250b56e9a7SVivek Gautam otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST | 2260b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | 2270b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | 2280b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE; 2290b56e9a7SVivek Gautam /* Ref clock */ 2300b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK; 2310b56e9a7SVivek Gautam otg |= EXYNOS_5250_REFCLKSEL_CLKCORE << 2320b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT; 2330b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); 2340b56e9a7SVivek Gautam udelay(100); 2350b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST | 2360b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | 2370b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | 2380b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE); 2390b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); 2400b56e9a7SVivek Gautam 2410b56e9a7SVivek Gautam 2420b56e9a7SVivek Gautam break; 2430b56e9a7SVivek Gautam case EXYNOS5250_HOST: 2440b56e9a7SVivek Gautam case EXYNOS5250_HSIC0: 2450b56e9a7SVivek Gautam case EXYNOS5250_HSIC1: 2460b56e9a7SVivek Gautam /* Host registers configuration */ 2470b56e9a7SVivek Gautam ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); 2480b56e9a7SVivek Gautam /* The clock */ 2490b56e9a7SVivek Gautam ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK; 2500b56e9a7SVivek Gautam ctrl0 |= drv->ref_reg_val << 2510b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT; 2520b56e9a7SVivek Gautam 2530b56e9a7SVivek Gautam /* Reset */ 2540b56e9a7SVivek Gautam ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | 2550b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL | 2560b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | 2570b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | 2580b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP); 2590b56e9a7SVivek Gautam ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | 2600b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST | 2610b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N; 2620b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); 2630b56e9a7SVivek Gautam udelay(10); 2640b56e9a7SVivek Gautam ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | 2650b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST); 2660b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); 2670b56e9a7SVivek Gautam 2680b56e9a7SVivek Gautam /* OTG configuration */ 2690b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); 2700b56e9a7SVivek Gautam /* The clock */ 2710b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK; 2720b56e9a7SVivek Gautam otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT; 2730b56e9a7SVivek Gautam /* Reset */ 2740b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | 2750b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP | 2760b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG); 2770b56e9a7SVivek Gautam otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST | 2780b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | 2790b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | 2800b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE; 2810b56e9a7SVivek Gautam /* Ref clock */ 2820b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK; 2830b56e9a7SVivek Gautam otg |= EXYNOS_5250_REFCLKSEL_CLKCORE << 2840b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT; 2850b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); 2860b56e9a7SVivek Gautam udelay(10); 2870b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST | 2880b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | 2890b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET); 2900b56e9a7SVivek Gautam 2910b56e9a7SVivek Gautam /* HSIC phy configuration */ 2920b56e9a7SVivek Gautam hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | 2930b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | 2940b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_PHYSWRST); 2950b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); 2960b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); 2970b56e9a7SVivek Gautam udelay(10); 2980b56e9a7SVivek Gautam hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST; 2990b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); 3000b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); 3010b56e9a7SVivek Gautam /* The following delay is necessary for the reset sequence to be 3020b56e9a7SVivek Gautam * completed */ 3030b56e9a7SVivek Gautam udelay(80); 3040b56e9a7SVivek Gautam 3050b56e9a7SVivek Gautam /* Enable EHCI DMA burst */ 3060b56e9a7SVivek Gautam ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); 3070b56e9a7SVivek Gautam ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN | 3080b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 | 3090b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 | 3100b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR16; 3110b56e9a7SVivek Gautam writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); 3120b56e9a7SVivek Gautam 3130b56e9a7SVivek Gautam /* OHCI settings */ 3140b56e9a7SVivek Gautam ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); 3150b56e9a7SVivek Gautam /* Following code is based on the old driver */ 3160b56e9a7SVivek Gautam ohci |= 0x1 << 3; 3170b56e9a7SVivek Gautam writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); 3180b56e9a7SVivek Gautam 3190b56e9a7SVivek Gautam break; 3200b56e9a7SVivek Gautam } 3210b56e9a7SVivek Gautam exynos5250_isol(inst, 0); 3220b56e9a7SVivek Gautam 3230b56e9a7SVivek Gautam return 0; 3240b56e9a7SVivek Gautam } 3250b56e9a7SVivek Gautam 3260b56e9a7SVivek Gautam static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst) 3270b56e9a7SVivek Gautam { 3280b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv; 3290b56e9a7SVivek Gautam u32 ctrl0; 3300b56e9a7SVivek Gautam u32 otg; 3310b56e9a7SVivek Gautam u32 hsic; 3320b56e9a7SVivek Gautam 3330b56e9a7SVivek Gautam exynos5250_isol(inst, 1); 3340b56e9a7SVivek Gautam 3350b56e9a7SVivek Gautam switch (inst->cfg->id) { 3360b56e9a7SVivek Gautam case EXYNOS5250_DEVICE: 3370b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); 3380b56e9a7SVivek Gautam otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | 3390b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG | 3400b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP); 3410b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); 3420b56e9a7SVivek Gautam break; 3430b56e9a7SVivek Gautam case EXYNOS5250_HOST: 3440b56e9a7SVivek Gautam ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); 3450b56e9a7SVivek Gautam ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | 3460b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | 3470b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP | 3480b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | 3490b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL); 3500b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); 3510b56e9a7SVivek Gautam break; 3520b56e9a7SVivek Gautam case EXYNOS5250_HSIC0: 3530b56e9a7SVivek Gautam case EXYNOS5250_HSIC1: 3540b56e9a7SVivek Gautam hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | 3550b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | 3560b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_SIDDQ | 3570b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP | 3580b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND 3590b56e9a7SVivek Gautam ); 3600b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); 3610b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); 3620b56e9a7SVivek Gautam break; 3630b56e9a7SVivek Gautam } 3640b56e9a7SVivek Gautam 3650b56e9a7SVivek Gautam return 0; 3660b56e9a7SVivek Gautam } 3670b56e9a7SVivek Gautam 3680b56e9a7SVivek Gautam 3690b56e9a7SVivek Gautam static const struct samsung_usb2_common_phy exynos5250_phys[] = { 3700b56e9a7SVivek Gautam { 3710b56e9a7SVivek Gautam .label = "device", 3720b56e9a7SVivek Gautam .id = EXYNOS5250_DEVICE, 3730b56e9a7SVivek Gautam .power_on = exynos5250_power_on, 3740b56e9a7SVivek Gautam .power_off = exynos5250_power_off, 3750b56e9a7SVivek Gautam }, 3760b56e9a7SVivek Gautam { 3770b56e9a7SVivek Gautam .label = "host", 3780b56e9a7SVivek Gautam .id = EXYNOS5250_HOST, 3790b56e9a7SVivek Gautam .power_on = exynos5250_power_on, 3800b56e9a7SVivek Gautam .power_off = exynos5250_power_off, 3810b56e9a7SVivek Gautam }, 3820b56e9a7SVivek Gautam { 3830b56e9a7SVivek Gautam .label = "hsic0", 3840b56e9a7SVivek Gautam .id = EXYNOS5250_HSIC0, 3850b56e9a7SVivek Gautam .power_on = exynos5250_power_on, 3860b56e9a7SVivek Gautam .power_off = exynos5250_power_off, 3870b56e9a7SVivek Gautam }, 3880b56e9a7SVivek Gautam { 3890b56e9a7SVivek Gautam .label = "hsic1", 3900b56e9a7SVivek Gautam .id = EXYNOS5250_HSIC1, 3910b56e9a7SVivek Gautam .power_on = exynos5250_power_on, 3920b56e9a7SVivek Gautam .power_off = exynos5250_power_off, 3930b56e9a7SVivek Gautam }, 3940b56e9a7SVivek Gautam }; 3950b56e9a7SVivek Gautam 3960b56e9a7SVivek Gautam const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = { 3970b56e9a7SVivek Gautam .has_mode_switch = 1, 3980b56e9a7SVivek Gautam .num_phys = EXYNOS5250_NUM_PHYS, 3990b56e9a7SVivek Gautam .phys = exynos5250_phys, 4000b56e9a7SVivek Gautam .rate_to_clk = exynos5250_rate_to_clk, 4010b56e9a7SVivek Gautam }; 402