0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/delay.h>
0010 #include <linux/io.h>
0011 #include <linux/phy/phy.h>
0012 #include <linux/regmap.h>
0013 #include "phy-samsung-usb2.h"
0014
0015
0016 #define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0
0017 #define EXYNOS_5250_REFCLKSEL_XO 0x1
0018 #define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2
0019
0020 #define EXYNOS_5250_FSEL_9MHZ6 0x0
0021 #define EXYNOS_5250_FSEL_10MHZ 0x1
0022 #define EXYNOS_5250_FSEL_12MHZ 0x2
0023 #define EXYNOS_5250_FSEL_19MHZ2 0x3
0024 #define EXYNOS_5250_FSEL_20MHZ 0x4
0025 #define EXYNOS_5250_FSEL_24MHZ 0x5
0026 #define EXYNOS_5250_FSEL_50MHZ 0x7
0027
0028
0029 #define EXYNOS_5250_HOSTPHYCTRL0 0x0
0030
0031 #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)
0032 #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19
0033 #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
0034 (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
0035 #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16
0036 #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
0037 (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
0038 #define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)
0039 #define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)
0040 #define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)
0041 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)
0042 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)
0043 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)
0044 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)
0045 #define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)
0046 #define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)
0047 #define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)
0048 #define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)
0049 #define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)
0050 #define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)
0051 #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)
0052
0053
0054 #define EXYNOS_5250_HSICPHYCTRL1 0x10
0055 #define EXYNOS_5250_HSICPHYCTRL2 0x20
0056
0057 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)
0058 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)
0059 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)
0060 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)
0061 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)
0062 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)
0063 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)
0064 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)
0065 #define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)
0066 #define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)
0067 #define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)
0068 #define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)
0069 #define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)
0070 #define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)
0071
0072
0073 #define EXYNOS_5250_HOSTEHCICTRL 0x30
0074 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)
0075 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)
0076 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)
0077 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)
0078 #define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)
0079 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19
0080 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
0081 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
0082 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13
0083 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
0084 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
0085 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7
0086 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
0087 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
0088 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1
0089 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
0090 (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
0091 #define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)
0092
0093
0094 #define EXYNOS_5250_HOSTOHCICTRL 0x34
0095 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1
0096 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
0097 (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
0098 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)
0099
0100
0101 #define EXYNOS_5250_USBOTGSYS 0x38
0102 #define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)
0103 #define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)
0104 #define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)
0105 #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9
0106 #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
0107 (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
0108 #define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)
0109 #define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)
0110 #define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4
0111 #define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
0112 (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
0113 #define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)
0114 #define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)
0115 #define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)
0116 #define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)
0117
0118
0119 #define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704
0120 #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708
0121 #define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C
0122 #define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)
0123
0124
0125 #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
0126 #define EXYNOS_5250_MODE_SWITCH_MASK 1
0127 #define EXYNOS_5250_MODE_SWITCH_DEVICE 0
0128 #define EXYNOS_5250_MODE_SWITCH_HOST 1
0129
0130 enum exynos4x12_phy_id {
0131 EXYNOS5250_DEVICE,
0132 EXYNOS5250_HOST,
0133 EXYNOS5250_HSIC0,
0134 EXYNOS5250_HSIC1,
0135 };
0136
0137
0138
0139
0140
0141 static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
0142 {
0143
0144
0145 switch (rate) {
0146 case 9600 * KHZ:
0147 *reg = EXYNOS_5250_FSEL_9MHZ6;
0148 break;
0149 case 10 * MHZ:
0150 *reg = EXYNOS_5250_FSEL_10MHZ;
0151 break;
0152 case 12 * MHZ:
0153 *reg = EXYNOS_5250_FSEL_12MHZ;
0154 break;
0155 case 19200 * KHZ:
0156 *reg = EXYNOS_5250_FSEL_19MHZ2;
0157 break;
0158 case 20 * MHZ:
0159 *reg = EXYNOS_5250_FSEL_20MHZ;
0160 break;
0161 case 24 * MHZ:
0162 *reg = EXYNOS_5250_FSEL_24MHZ;
0163 break;
0164 case 50 * MHZ:
0165 *reg = EXYNOS_5250_FSEL_50MHZ;
0166 break;
0167 default:
0168 return -EINVAL;
0169 }
0170
0171 return 0;
0172 }
0173
0174 static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
0175 {
0176 struct samsung_usb2_phy_driver *drv = inst->drv;
0177 u32 offset;
0178 u32 mask = EXYNOS_5250_USB_ISOL_ENABLE;
0179
0180 if (drv->cfg == &exynos5250_usb2_phy_config &&
0181 inst->cfg->id == EXYNOS5250_DEVICE)
0182 offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
0183 else if (drv->cfg == &exynos5250_usb2_phy_config &&
0184 inst->cfg->id == EXYNOS5250_HOST)
0185 offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
0186 else if (drv->cfg == &exynos5420_usb2_phy_config &&
0187 inst->cfg->id == EXYNOS5250_HOST)
0188 offset = EXYNOS_5420_USB_ISOL_HOST_OFFSET;
0189 else
0190 return;
0191
0192 regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
0193 }
0194
0195 static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
0196 {
0197 struct samsung_usb2_phy_driver *drv = inst->drv;
0198 u32 ctrl0;
0199 u32 otg;
0200 u32 ehci;
0201 u32 ohci;
0202 u32 hsic;
0203
0204 switch (inst->cfg->id) {
0205 case EXYNOS5250_DEVICE:
0206 regmap_update_bits(drv->reg_sys,
0207 EXYNOS_5250_MODE_SWITCH_OFFSET,
0208 EXYNOS_5250_MODE_SWITCH_MASK,
0209 EXYNOS_5250_MODE_SWITCH_DEVICE);
0210
0211
0212 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0213
0214 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
0215 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
0216
0217 otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
0218 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
0219 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
0220 otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
0221 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
0222 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
0223 EXYNOS_5250_USBOTGSYS_OTGDISABLE;
0224
0225 otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
0226 otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
0227 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
0228 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0229 udelay(100);
0230 otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
0231 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
0232 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
0233 EXYNOS_5250_USBOTGSYS_OTGDISABLE);
0234 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0235
0236
0237 break;
0238 case EXYNOS5250_HOST:
0239 case EXYNOS5250_HSIC0:
0240 case EXYNOS5250_HSIC1:
0241
0242 ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
0243
0244 ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
0245 ctrl0 |= drv->ref_reg_val <<
0246 EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
0247
0248
0249 ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
0250 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
0251 EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
0252 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
0253 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
0254 ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
0255 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
0256 EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
0257 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
0258 udelay(10);
0259 ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
0260 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
0261 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
0262
0263
0264 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0265
0266 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
0267 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
0268
0269 otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
0270 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
0271 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
0272 otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
0273 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
0274 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
0275 EXYNOS_5250_USBOTGSYS_OTGDISABLE;
0276
0277 otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
0278 otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
0279 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
0280 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0281 udelay(10);
0282 otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
0283 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
0284 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
0285
0286
0287 hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
0288 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
0289 EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
0290 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
0291 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
0292 udelay(10);
0293 hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
0294 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
0295 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
0296
0297
0298 udelay(80);
0299
0300
0301 ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
0302 ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
0303 EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
0304 EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
0305 EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
0306 writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
0307
0308
0309 ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
0310
0311 ohci |= 0x1 << 3;
0312 writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
0313
0314 break;
0315 }
0316 exynos5250_isol(inst, 0);
0317
0318 return 0;
0319 }
0320
0321 static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
0322 {
0323 struct samsung_usb2_phy_driver *drv = inst->drv;
0324 u32 ctrl0;
0325 u32 otg;
0326 u32 hsic;
0327
0328 exynos5250_isol(inst, 1);
0329
0330 switch (inst->cfg->id) {
0331 case EXYNOS5250_DEVICE:
0332 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0333 otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
0334 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
0335 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
0336 writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
0337 break;
0338 case EXYNOS5250_HOST:
0339 ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
0340 ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
0341 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
0342 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
0343 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
0344 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
0345 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
0346 break;
0347 case EXYNOS5250_HSIC0:
0348 case EXYNOS5250_HSIC1:
0349 hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
0350 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
0351 EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
0352 EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
0353 EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
0354 );
0355 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
0356 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
0357 break;
0358 }
0359
0360 return 0;
0361 }
0362
0363
0364 static const struct samsung_usb2_common_phy exynos5250_phys[] = {
0365 {
0366 .label = "device",
0367 .id = EXYNOS5250_DEVICE,
0368 .power_on = exynos5250_power_on,
0369 .power_off = exynos5250_power_off,
0370 },
0371 {
0372 .label = "host",
0373 .id = EXYNOS5250_HOST,
0374 .power_on = exynos5250_power_on,
0375 .power_off = exynos5250_power_off,
0376 },
0377 {
0378 .label = "hsic0",
0379 .id = EXYNOS5250_HSIC0,
0380 .power_on = exynos5250_power_on,
0381 .power_off = exynos5250_power_off,
0382 },
0383 {
0384 .label = "hsic1",
0385 .id = EXYNOS5250_HSIC1,
0386 .power_on = exynos5250_power_on,
0387 .power_off = exynos5250_power_off,
0388 },
0389 };
0390
0391 static const struct samsung_usb2_common_phy exynos5420_phys[] = {
0392 {
0393 .label = "host",
0394 .id = EXYNOS5250_HOST,
0395 .power_on = exynos5250_power_on,
0396 .power_off = exynos5250_power_off,
0397 },
0398 {
0399 .label = "hsic",
0400 .id = EXYNOS5250_HSIC0,
0401 .power_on = exynos5250_power_on,
0402 .power_off = exynos5250_power_off,
0403 },
0404 };
0405
0406 const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
0407 .has_mode_switch = 1,
0408 .num_phys = ARRAY_SIZE(exynos5250_phys),
0409 .phys = exynos5250_phys,
0410 .rate_to_clk = exynos5250_rate_to_clk,
0411 };
0412
0413 const struct samsung_usb2_phy_config exynos5420_usb2_phy_config = {
0414 .has_mode_switch = 1,
0415 .num_phys = ARRAY_SIZE(exynos5420_phys),
0416 .phys = exynos5420_phys,
0417 .rate_to_clk = exynos5250_rate_to_clk,
0418 };