Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Samsung Exynos5 SoC series USB DRD PHY driver
0004  *
0005  * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
0006  *
0007  * Copyright (C) 2014 Samsung Electronics Co., Ltd.
0008  * Author: Vivek Gautam <gautam.vivek@samsung.com>
0009  */
0010 
0011 #include <linux/clk.h>
0012 #include <linux/delay.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_device.h>
0019 #include <linux/iopoll.h>
0020 #include <linux/phy/phy.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/mutex.h>
0023 #include <linux/mfd/syscon.h>
0024 #include <linux/regmap.h>
0025 #include <linux/regulator/consumer.h>
0026 #include <linux/soc/samsung/exynos-regs-pmu.h>
0027 
0028 /* Exynos USB PHY registers */
0029 #define EXYNOS5_FSEL_9MHZ6      0x0
0030 #define EXYNOS5_FSEL_10MHZ      0x1
0031 #define EXYNOS5_FSEL_12MHZ      0x2
0032 #define EXYNOS5_FSEL_19MHZ2     0x3
0033 #define EXYNOS5_FSEL_20MHZ      0x4
0034 #define EXYNOS5_FSEL_24MHZ      0x5
0035 #define EXYNOS5_FSEL_50MHZ      0x7
0036 
0037 /* Exynos5: USB 3.0 DRD PHY registers */
0038 #define EXYNOS5_DRD_LINKSYSTEM          0x04
0039 
0040 #define LINKSYSTEM_FLADJ_MASK           (0x3f << 1)
0041 #define LINKSYSTEM_FLADJ(_x)            ((_x) << 1)
0042 #define LINKSYSTEM_XHCI_VERSION_CONTROL     BIT(27)
0043 
0044 #define EXYNOS5_DRD_PHYUTMI         0x08
0045 
0046 #define PHYUTMI_OTGDISABLE          BIT(6)
0047 #define PHYUTMI_FORCESUSPEND            BIT(1)
0048 #define PHYUTMI_FORCESLEEP          BIT(0)
0049 
0050 #define EXYNOS5_DRD_PHYPIPE         0x0c
0051 
0052 #define EXYNOS5_DRD_PHYCLKRST           0x10
0053 
0054 #define PHYCLKRST_EN_UTMISUSPEND        BIT(31)
0055 
0056 #define PHYCLKRST_SSC_REFCLKSEL_MASK        (0xff << 23)
0057 #define PHYCLKRST_SSC_REFCLKSEL(_x)     ((_x) << 23)
0058 
0059 #define PHYCLKRST_SSC_RANGE_MASK        (0x03 << 21)
0060 #define PHYCLKRST_SSC_RANGE(_x)         ((_x) << 21)
0061 
0062 #define PHYCLKRST_SSC_EN            BIT(20)
0063 #define PHYCLKRST_REF_SSP_EN            BIT(19)
0064 #define PHYCLKRST_REF_CLKDIV2           BIT(18)
0065 
0066 #define PHYCLKRST_MPLL_MULTIPLIER_MASK      (0x7f << 11)
0067 #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF    (0x19 << 11)
0068 #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF   (0x32 << 11)
0069 #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
0070 #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
0071 #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF  (0x02 << 11)
0072 
0073 #define PHYCLKRST_FSEL_UTMI_MASK        (0x7 << 5)
0074 #define PHYCLKRST_FSEL_PIPE_MASK        (0x7 << 8)
0075 #define PHYCLKRST_FSEL(_x)          ((_x) << 5)
0076 #define PHYCLKRST_FSEL_PAD_100MHZ       (0x27 << 5)
0077 #define PHYCLKRST_FSEL_PAD_24MHZ        (0x2a << 5)
0078 #define PHYCLKRST_FSEL_PAD_20MHZ        (0x31 << 5)
0079 #define PHYCLKRST_FSEL_PAD_19_2MHZ      (0x38 << 5)
0080 
0081 #define PHYCLKRST_RETENABLEN            BIT(4)
0082 
0083 #define PHYCLKRST_REFCLKSEL_MASK        (0x03 << 2)
0084 #define PHYCLKRST_REFCLKSEL_PAD_REFCLK      (0x2 << 2)
0085 #define PHYCLKRST_REFCLKSEL_EXT_REFCLK      (0x3 << 2)
0086 
0087 #define PHYCLKRST_PORTRESET         BIT(1)
0088 #define PHYCLKRST_COMMONONN         BIT(0)
0089 
0090 #define EXYNOS5_DRD_PHYREG0         0x14
0091 #define PHYREG0_SSC_REF_CLK_SEL         BIT(21)
0092 #define PHYREG0_SSC_RANGE           BIT(20)
0093 #define PHYREG0_CR_WRITE            BIT(19)
0094 #define PHYREG0_CR_READ             BIT(18)
0095 #define PHYREG0_CR_DATA_IN(_x)          ((_x) << 2)
0096 #define PHYREG0_CR_CAP_DATA         BIT(1)
0097 #define PHYREG0_CR_CAP_ADDR         BIT(0)
0098 
0099 #define EXYNOS5_DRD_PHYREG1         0x18
0100 #define PHYREG1_CR_DATA_OUT(_x)         ((_x) << 1)
0101 #define PHYREG1_CR_ACK              BIT(0)
0102 
0103 #define EXYNOS5_DRD_PHYPARAM0           0x1c
0104 
0105 #define PHYPARAM0_REF_USE_PAD           BIT(31)
0106 #define PHYPARAM0_REF_LOSLEVEL_MASK     (0x1f << 26)
0107 #define PHYPARAM0_REF_LOSLEVEL          (0x9 << 26)
0108 
0109 #define EXYNOS5_DRD_PHYPARAM1           0x20
0110 
0111 #define PHYPARAM1_PCS_TXDEEMPH_MASK     (0x1f << 0)
0112 #define PHYPARAM1_PCS_TXDEEMPH          (0x1c)
0113 
0114 #define EXYNOS5_DRD_PHYTERM         0x24
0115 
0116 #define EXYNOS5_DRD_PHYTEST         0x28
0117 
0118 #define PHYTEST_POWERDOWN_SSP           BIT(3)
0119 #define PHYTEST_POWERDOWN_HSP           BIT(2)
0120 
0121 #define EXYNOS5_DRD_PHYADP          0x2c
0122 
0123 #define EXYNOS5_DRD_PHYUTMICLKSEL       0x30
0124 
0125 #define PHYUTMICLKSEL_UTMI_CLKSEL       BIT(2)
0126 
0127 #define EXYNOS5_DRD_PHYRESUME           0x34
0128 #define EXYNOS5_DRD_LINKPORT            0x44
0129 
0130 /* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
0131 #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN      (0x15)
0132 #define LOSLEVEL_OVRD_IN_LOS_BIAS_5420          (0x5 << 13)
0133 #define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT       (0x0 << 13)
0134 #define LOSLEVEL_OVRD_IN_EN             (0x1 << 10)
0135 #define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT      (0x9 << 0)
0136 
0137 #define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN    (0x12)
0138 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420      (0x5 << 13)
0139 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT       (0x4 << 13)
0140 
0141 #define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG        (0x1010)
0142 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M     (0x4 << 4)
0143 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M      (0x8 << 4)
0144 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M      (0x8 << 4)
0145 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M  (0x20 << 4)
0146 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5     (0x20 << 4)
0147 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M     (0x40 << 4)
0148 
0149 #define KHZ 1000
0150 #define MHZ (KHZ * KHZ)
0151 
0152 enum exynos5_usbdrd_phy_id {
0153     EXYNOS5_DRDPHY_UTMI,
0154     EXYNOS5_DRDPHY_PIPE3,
0155     EXYNOS5_DRDPHYS_NUM,
0156 };
0157 
0158 struct phy_usb_instance;
0159 struct exynos5_usbdrd_phy;
0160 
0161 struct exynos5_usbdrd_phy_config {
0162     u32 id;
0163     void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
0164     void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
0165     unsigned int (*set_refclk)(struct phy_usb_instance *inst);
0166 };
0167 
0168 struct exynos5_usbdrd_phy_drvdata {
0169     const struct exynos5_usbdrd_phy_config *phy_cfg;
0170     u32 pmu_offset_usbdrd0_phy;
0171     u32 pmu_offset_usbdrd1_phy;
0172     bool has_common_clk_gate;
0173 };
0174 
0175 /**
0176  * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
0177  * @dev: pointer to device instance of this platform device
0178  * @reg_phy: usb phy controller register memory base
0179  * @clk: phy clock for register access
0180  * @pipeclk: clock for pipe3 phy
0181  * @utmiclk: clock for utmi+ phy
0182  * @itpclk: clock for ITP generation
0183  * @drv_data: pointer to SoC level driver data structure
0184  * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
0185  *      instances each with its 'phy' and 'phy_cfg'.
0186  * @extrefclk: frequency select settings when using 'separate
0187  *         reference clocks' for SS and HS operations
0188  * @ref_clk: reference clock to PHY block from which PHY's
0189  *       operational clocks are derived
0190  * @vbus: VBUS regulator for phy
0191  * @vbus_boost: Boost regulator for VBUS present on few Exynos boards
0192  */
0193 struct exynos5_usbdrd_phy {
0194     struct device *dev;
0195     void __iomem *reg_phy;
0196     struct clk *clk;
0197     struct clk *pipeclk;
0198     struct clk *utmiclk;
0199     struct clk *itpclk;
0200     const struct exynos5_usbdrd_phy_drvdata *drv_data;
0201     struct phy_usb_instance {
0202         struct phy *phy;
0203         u32 index;
0204         struct regmap *reg_pmu;
0205         u32 pmu_offset;
0206         const struct exynos5_usbdrd_phy_config *phy_cfg;
0207     } phys[EXYNOS5_DRDPHYS_NUM];
0208     u32 extrefclk;
0209     struct clk *ref_clk;
0210     struct regulator *vbus;
0211     struct regulator *vbus_boost;
0212 };
0213 
0214 static inline
0215 struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
0216 {
0217     return container_of((inst), struct exynos5_usbdrd_phy,
0218                 phys[(inst)->index]);
0219 }
0220 
0221 /*
0222  * exynos5_rate_to_clk() converts the supplied clock rate to the value that
0223  * can be written to the phy register.
0224  */
0225 static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
0226 {
0227     /* EXYNOS5_FSEL_MASK */
0228 
0229     switch (rate) {
0230     case 9600 * KHZ:
0231         *reg = EXYNOS5_FSEL_9MHZ6;
0232         break;
0233     case 10 * MHZ:
0234         *reg = EXYNOS5_FSEL_10MHZ;
0235         break;
0236     case 12 * MHZ:
0237         *reg = EXYNOS5_FSEL_12MHZ;
0238         break;
0239     case 19200 * KHZ:
0240         *reg = EXYNOS5_FSEL_19MHZ2;
0241         break;
0242     case 20 * MHZ:
0243         *reg = EXYNOS5_FSEL_20MHZ;
0244         break;
0245     case 24 * MHZ:
0246         *reg = EXYNOS5_FSEL_24MHZ;
0247         break;
0248     case 50 * MHZ:
0249         *reg = EXYNOS5_FSEL_50MHZ;
0250         break;
0251     default:
0252         return -EINVAL;
0253     }
0254 
0255     return 0;
0256 }
0257 
0258 static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
0259                         unsigned int on)
0260 {
0261     unsigned int val;
0262 
0263     if (!inst->reg_pmu)
0264         return;
0265 
0266     val = on ? 0 : EXYNOS4_PHY_ENABLE;
0267 
0268     regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
0269                EXYNOS4_PHY_ENABLE, val);
0270 }
0271 
0272 /*
0273  * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
0274  * from clock core. Further sets multiplier values and spread spectrum
0275  * clock settings for SuperSpeed operations.
0276  */
0277 static unsigned int
0278 exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
0279 {
0280     u32 reg;
0281     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0282 
0283     /* restore any previous reference clock settings */
0284     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0285 
0286     /* Use EXTREFCLK as ref clock */
0287     reg &= ~PHYCLKRST_REFCLKSEL_MASK;
0288     reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
0289 
0290     /* FSEL settings corresponding to reference clock */
0291     reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
0292         PHYCLKRST_MPLL_MULTIPLIER_MASK |
0293         PHYCLKRST_SSC_REFCLKSEL_MASK;
0294     switch (phy_drd->extrefclk) {
0295     case EXYNOS5_FSEL_50MHZ:
0296         reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
0297             PHYCLKRST_SSC_REFCLKSEL(0x00));
0298         break;
0299     case EXYNOS5_FSEL_24MHZ:
0300         reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
0301             PHYCLKRST_SSC_REFCLKSEL(0x88));
0302         break;
0303     case EXYNOS5_FSEL_20MHZ:
0304         reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
0305             PHYCLKRST_SSC_REFCLKSEL(0x00));
0306         break;
0307     case EXYNOS5_FSEL_19MHZ2:
0308         reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
0309             PHYCLKRST_SSC_REFCLKSEL(0x88));
0310         break;
0311     default:
0312         dev_dbg(phy_drd->dev, "unsupported ref clk\n");
0313         break;
0314     }
0315 
0316     return reg;
0317 }
0318 
0319 /*
0320  * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
0321  * from clock core. Further sets the FSEL values for HighSpeed operations.
0322  */
0323 static unsigned int
0324 exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
0325 {
0326     u32 reg;
0327     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0328 
0329     /* restore any previous reference clock settings */
0330     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0331 
0332     reg &= ~PHYCLKRST_REFCLKSEL_MASK;
0333     reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
0334 
0335     reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
0336         PHYCLKRST_MPLL_MULTIPLIER_MASK |
0337         PHYCLKRST_SSC_REFCLKSEL_MASK;
0338     reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
0339 
0340     return reg;
0341 }
0342 
0343 static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
0344 {
0345     u32 reg;
0346 
0347     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0348     /* Set Tx De-Emphasis level */
0349     reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
0350     reg |=  PHYPARAM1_PCS_TXDEEMPH;
0351     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0352 
0353     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0354     reg &= ~PHYTEST_POWERDOWN_SSP;
0355     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0356 }
0357 
0358 static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
0359 {
0360     u32 reg;
0361 
0362     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0363     /* Set Loss-of-Signal Detector sensitivity */
0364     reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
0365     reg |=  PHYPARAM0_REF_LOSLEVEL;
0366     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0367 
0368     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0369     /* Set Tx De-Emphasis level */
0370     reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
0371     reg |=  PHYPARAM1_PCS_TXDEEMPH;
0372     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0373 
0374     /* UTMI Power Control */
0375     writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
0376 
0377     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0378     reg &= ~PHYTEST_POWERDOWN_HSP;
0379     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0380 }
0381 
0382 static int exynos5_usbdrd_phy_init(struct phy *phy)
0383 {
0384     int ret;
0385     u32 reg;
0386     struct phy_usb_instance *inst = phy_get_drvdata(phy);
0387     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0388 
0389     ret = clk_prepare_enable(phy_drd->clk);
0390     if (ret)
0391         return ret;
0392 
0393     /* Reset USB 3.0 PHY */
0394     writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0395     writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
0396 
0397     /*
0398      * Setting the Frame length Adj value[6:1] to default 0x20
0399      * See xHCI 1.0 spec, 5.2.4
0400      */
0401     reg =   LINKSYSTEM_XHCI_VERSION_CONTROL |
0402         LINKSYSTEM_FLADJ(0x20);
0403     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
0404 
0405     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0406     /* Select PHY CLK source */
0407     reg &= ~PHYPARAM0_REF_USE_PAD;
0408     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0409 
0410     /* This bit must be set for both HS and SS operations */
0411     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
0412     reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
0413     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
0414 
0415     /* UTMI or PIPE3 specific init */
0416     inst->phy_cfg->phy_init(phy_drd);
0417 
0418     /* reference clock settings */
0419     reg = inst->phy_cfg->set_refclk(inst);
0420 
0421         /* Digital power supply in normal operating mode */
0422     reg |=  PHYCLKRST_RETENABLEN |
0423         /* Enable ref clock for SS function */
0424         PHYCLKRST_REF_SSP_EN |
0425         /* Enable spread spectrum */
0426         PHYCLKRST_SSC_EN |
0427         /* Power down HS Bias and PLL blocks in suspend mode */
0428         PHYCLKRST_COMMONONN |
0429         /* Reset the port */
0430         PHYCLKRST_PORTRESET;
0431 
0432     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0433 
0434     udelay(10);
0435 
0436     reg &= ~PHYCLKRST_PORTRESET;
0437     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0438 
0439     clk_disable_unprepare(phy_drd->clk);
0440 
0441     return 0;
0442 }
0443 
0444 static int exynos5_usbdrd_phy_exit(struct phy *phy)
0445 {
0446     int ret;
0447     u32 reg;
0448     struct phy_usb_instance *inst = phy_get_drvdata(phy);
0449     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0450 
0451     ret = clk_prepare_enable(phy_drd->clk);
0452     if (ret)
0453         return ret;
0454 
0455     reg =   PHYUTMI_OTGDISABLE |
0456         PHYUTMI_FORCESUSPEND |
0457         PHYUTMI_FORCESLEEP;
0458     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
0459 
0460     /* Resetting the PHYCLKRST enable bits to reduce leakage current */
0461     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0462     reg &= ~(PHYCLKRST_REF_SSP_EN |
0463          PHYCLKRST_SSC_EN |
0464          PHYCLKRST_COMMONONN);
0465     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0466 
0467     /* Control PHYTEST to remove leakage current */
0468     reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0469     reg |=  PHYTEST_POWERDOWN_SSP |
0470         PHYTEST_POWERDOWN_HSP;
0471     writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0472 
0473     clk_disable_unprepare(phy_drd->clk);
0474 
0475     return 0;
0476 }
0477 
0478 static int exynos5_usbdrd_phy_power_on(struct phy *phy)
0479 {
0480     int ret;
0481     struct phy_usb_instance *inst = phy_get_drvdata(phy);
0482     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0483 
0484     dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
0485 
0486     clk_prepare_enable(phy_drd->ref_clk);
0487     if (!phy_drd->drv_data->has_common_clk_gate) {
0488         clk_prepare_enable(phy_drd->pipeclk);
0489         clk_prepare_enable(phy_drd->utmiclk);
0490         clk_prepare_enable(phy_drd->itpclk);
0491     }
0492 
0493     /* Enable VBUS supply */
0494     if (phy_drd->vbus_boost) {
0495         ret = regulator_enable(phy_drd->vbus_boost);
0496         if (ret) {
0497             dev_err(phy_drd->dev,
0498                 "Failed to enable VBUS boost supply\n");
0499             goto fail_vbus;
0500         }
0501     }
0502 
0503     if (phy_drd->vbus) {
0504         ret = regulator_enable(phy_drd->vbus);
0505         if (ret) {
0506             dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
0507             goto fail_vbus_boost;
0508         }
0509     }
0510 
0511     /* Power-on PHY*/
0512     inst->phy_cfg->phy_isol(inst, 0);
0513 
0514     return 0;
0515 
0516 fail_vbus_boost:
0517     if (phy_drd->vbus_boost)
0518         regulator_disable(phy_drd->vbus_boost);
0519 
0520 fail_vbus:
0521     clk_disable_unprepare(phy_drd->ref_clk);
0522     if (!phy_drd->drv_data->has_common_clk_gate) {
0523         clk_disable_unprepare(phy_drd->itpclk);
0524         clk_disable_unprepare(phy_drd->utmiclk);
0525         clk_disable_unprepare(phy_drd->pipeclk);
0526     }
0527 
0528     return ret;
0529 }
0530 
0531 static int exynos5_usbdrd_phy_power_off(struct phy *phy)
0532 {
0533     struct phy_usb_instance *inst = phy_get_drvdata(phy);
0534     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0535 
0536     dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
0537 
0538     /* Power-off the PHY */
0539     inst->phy_cfg->phy_isol(inst, 1);
0540 
0541     /* Disable VBUS supply */
0542     if (phy_drd->vbus)
0543         regulator_disable(phy_drd->vbus);
0544     if (phy_drd->vbus_boost)
0545         regulator_disable(phy_drd->vbus_boost);
0546 
0547     clk_disable_unprepare(phy_drd->ref_clk);
0548     if (!phy_drd->drv_data->has_common_clk_gate) {
0549         clk_disable_unprepare(phy_drd->itpclk);
0550         clk_disable_unprepare(phy_drd->pipeclk);
0551         clk_disable_unprepare(phy_drd->utmiclk);
0552     }
0553 
0554     return 0;
0555 }
0556 
0557 static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
0558                 u32 val, u32 cmd)
0559 {
0560     unsigned int result;
0561     int err;
0562 
0563     writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0564 
0565     err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
0566                  result, (result & PHYREG1_CR_ACK), 1, 100);
0567     if (err == -ETIMEDOUT) {
0568         dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val);
0569         return err;
0570     }
0571 
0572     writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0573 
0574     err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
0575                  result, !(result & PHYREG1_CR_ACK), 1, 100);
0576     if (err == -ETIMEDOUT) {
0577         dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val);
0578         return err;
0579     }
0580 
0581     return 0;
0582 }
0583 
0584 static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
0585                  u32 addr, u32 data)
0586 {
0587     int ret;
0588 
0589     /* Write Address */
0590     writel(PHYREG0_CR_DATA_IN(addr),
0591            phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0592     ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
0593                    PHYREG0_CR_CAP_ADDR);
0594     if (ret)
0595         return ret;
0596 
0597     /* Write Data */
0598     writel(PHYREG0_CR_DATA_IN(data),
0599            phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0600     ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
0601                    PHYREG0_CR_CAP_DATA);
0602     if (ret)
0603         return ret;
0604 
0605     ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
0606                    PHYREG0_CR_WRITE);
0607 
0608     return ret;
0609 }
0610 
0611 /*
0612  * Calibrate few PHY parameters using CR_PORT register to meet
0613  * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,
0614  * which have 28nm USB 3.0 DRD PHY.
0615  */
0616 static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
0617 {
0618     unsigned int temp;
0619     int ret = 0;
0620 
0621     /*
0622      * Change los_bias to (0x5) for 28nm PHY from a
0623      * default value (0x0); los_level is set as default
0624      * (0x9) as also reflected in los_level[30:26] bits
0625      * of PHYPARAM0 register.
0626      */
0627     temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
0628         LOSLEVEL_OVRD_IN_EN |
0629         LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
0630     ret = crport_ctrl_write(phy_drd,
0631                 EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
0632                 temp);
0633     if (ret) {
0634         dev_err(phy_drd->dev,
0635             "Failed setting Loss-of-Signal level for SuperSpeed\n");
0636         return ret;
0637     }
0638 
0639     /*
0640      * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
0641      * to raise Tx signal level from its default value of (0x4)
0642      */
0643     temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
0644     ret = crport_ctrl_write(phy_drd,
0645                 EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
0646                 temp);
0647     if (ret) {
0648         dev_err(phy_drd->dev,
0649             "Failed setting Tx-Vboost-Level for SuperSpeed\n");
0650         return ret;
0651     }
0652 
0653     /*
0654      * Set proper time to wait for RxDetect measurement, for
0655      * desired reference clock of PHY, by tuning the CR_PORT
0656      * register LANE0.TX_DEBUG which is internal to PHY.
0657      * This fixes issue with few USB 3.0 devices, which are
0658      * not detected (not even generate interrupts on the bus
0659      * on insertion) without this change.
0660      * e.g. Samsung SUM-TSB16S 3.0 USB drive.
0661      */
0662     switch (phy_drd->extrefclk) {
0663     case EXYNOS5_FSEL_50MHZ:
0664         temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
0665         break;
0666     case EXYNOS5_FSEL_20MHZ:
0667     case EXYNOS5_FSEL_19MHZ2:
0668         temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
0669         break;
0670     case EXYNOS5_FSEL_24MHZ:
0671     default:
0672         temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
0673         break;
0674     }
0675 
0676     ret = crport_ctrl_write(phy_drd,
0677                 EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
0678                 temp);
0679     if (ret)
0680         dev_err(phy_drd->dev,
0681             "Fail to set RxDet measurement time for SuperSpeed\n");
0682 
0683     return ret;
0684 }
0685 
0686 static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
0687                     struct of_phandle_args *args)
0688 {
0689     struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
0690 
0691     if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
0692         return ERR_PTR(-ENODEV);
0693 
0694     return phy_drd->phys[args->args[0]].phy;
0695 }
0696 
0697 static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
0698 {
0699     struct phy_usb_instance *inst = phy_get_drvdata(phy);
0700     struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0701 
0702     if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
0703         return exynos5420_usbdrd_phy_calibrate(phy_drd);
0704     return 0;
0705 }
0706 
0707 static const struct phy_ops exynos5_usbdrd_phy_ops = {
0708     .init       = exynos5_usbdrd_phy_init,
0709     .exit       = exynos5_usbdrd_phy_exit,
0710     .power_on   = exynos5_usbdrd_phy_power_on,
0711     .power_off  = exynos5_usbdrd_phy_power_off,
0712     .calibrate  = exynos5_usbdrd_phy_calibrate,
0713     .owner      = THIS_MODULE,
0714 };
0715 
0716 static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
0717 {
0718     unsigned long ref_rate;
0719     int ret;
0720 
0721     phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
0722     if (IS_ERR(phy_drd->clk)) {
0723         dev_err(phy_drd->dev, "Failed to get phy clock\n");
0724         return PTR_ERR(phy_drd->clk);
0725     }
0726 
0727     phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
0728     if (IS_ERR(phy_drd->ref_clk)) {
0729         dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
0730         return PTR_ERR(phy_drd->ref_clk);
0731     }
0732     ref_rate = clk_get_rate(phy_drd->ref_clk);
0733 
0734     ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
0735     if (ret) {
0736         dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
0737             ref_rate);
0738         return ret;
0739     }
0740 
0741     if (!phy_drd->drv_data->has_common_clk_gate) {
0742         phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
0743         if (IS_ERR(phy_drd->pipeclk)) {
0744             dev_info(phy_drd->dev,
0745                  "PIPE3 phy operational clock not specified\n");
0746             phy_drd->pipeclk = NULL;
0747         }
0748 
0749         phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
0750         if (IS_ERR(phy_drd->utmiclk)) {
0751             dev_info(phy_drd->dev,
0752                  "UTMI phy operational clock not specified\n");
0753             phy_drd->utmiclk = NULL;
0754         }
0755 
0756         phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
0757         if (IS_ERR(phy_drd->itpclk)) {
0758             dev_info(phy_drd->dev,
0759                  "ITP clock from main OSC not specified\n");
0760             phy_drd->itpclk = NULL;
0761         }
0762     }
0763 
0764     return 0;
0765 }
0766 
0767 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
0768     {
0769         .id     = EXYNOS5_DRDPHY_UTMI,
0770         .phy_isol   = exynos5_usbdrd_phy_isol,
0771         .phy_init   = exynos5_usbdrd_utmi_init,
0772         .set_refclk = exynos5_usbdrd_utmi_set_refclk,
0773     },
0774     {
0775         .id     = EXYNOS5_DRDPHY_PIPE3,
0776         .phy_isol   = exynos5_usbdrd_phy_isol,
0777         .phy_init   = exynos5_usbdrd_pipe3_init,
0778         .set_refclk = exynos5_usbdrd_pipe3_set_refclk,
0779     },
0780 };
0781 
0782 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
0783     .phy_cfg        = phy_cfg_exynos5,
0784     .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0785     .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
0786     .has_common_clk_gate    = true,
0787 };
0788 
0789 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
0790     .phy_cfg        = phy_cfg_exynos5,
0791     .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0792     .has_common_clk_gate    = true,
0793 };
0794 
0795 static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
0796     .phy_cfg        = phy_cfg_exynos5,
0797     .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0798     .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
0799     .has_common_clk_gate    = false,
0800 };
0801 
0802 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
0803     .phy_cfg        = phy_cfg_exynos5,
0804     .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0805     .has_common_clk_gate    = false,
0806 };
0807 
0808 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
0809     {
0810         .compatible = "samsung,exynos5250-usbdrd-phy",
0811         .data = &exynos5250_usbdrd_phy
0812     }, {
0813         .compatible = "samsung,exynos5420-usbdrd-phy",
0814         .data = &exynos5420_usbdrd_phy
0815     }, {
0816         .compatible = "samsung,exynos5433-usbdrd-phy",
0817         .data = &exynos5433_usbdrd_phy
0818     }, {
0819         .compatible = "samsung,exynos7-usbdrd-phy",
0820         .data = &exynos7_usbdrd_phy
0821     },
0822     { },
0823 };
0824 MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
0825 
0826 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
0827 {
0828     struct device *dev = &pdev->dev;
0829     struct device_node *node = dev->of_node;
0830     struct exynos5_usbdrd_phy *phy_drd;
0831     struct phy_provider *phy_provider;
0832     const struct exynos5_usbdrd_phy_drvdata *drv_data;
0833     struct regmap *reg_pmu;
0834     u32 pmu_offset;
0835     int i, ret;
0836     int channel;
0837 
0838     phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
0839     if (!phy_drd)
0840         return -ENOMEM;
0841 
0842     dev_set_drvdata(dev, phy_drd);
0843     phy_drd->dev = dev;
0844 
0845     phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);
0846     if (IS_ERR(phy_drd->reg_phy))
0847         return PTR_ERR(phy_drd->reg_phy);
0848 
0849     drv_data = of_device_get_match_data(dev);
0850     if (!drv_data)
0851         return -EINVAL;
0852 
0853     phy_drd->drv_data = drv_data;
0854 
0855     ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
0856     if (ret) {
0857         dev_err(dev, "Failed to initialize clocks\n");
0858         return ret;
0859     }
0860 
0861     reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
0862                            "samsung,pmu-syscon");
0863     if (IS_ERR(reg_pmu)) {
0864         dev_err(dev, "Failed to lookup PMU regmap\n");
0865         return PTR_ERR(reg_pmu);
0866     }
0867 
0868     /*
0869      * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
0870      * each having separate power control registers.
0871      * 'channel' facilitates to set such registers.
0872      */
0873     channel = of_alias_get_id(node, "usbdrdphy");
0874     if (channel < 0)
0875         dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
0876 
0877     switch (channel) {
0878     case 1:
0879         pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
0880         break;
0881     case 0:
0882     default:
0883         pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
0884         break;
0885     }
0886 
0887     /* Get Vbus regulators */
0888     phy_drd->vbus = devm_regulator_get(dev, "vbus");
0889     if (IS_ERR(phy_drd->vbus)) {
0890         ret = PTR_ERR(phy_drd->vbus);
0891         if (ret == -EPROBE_DEFER)
0892             return ret;
0893 
0894         dev_warn(dev, "Failed to get VBUS supply regulator\n");
0895         phy_drd->vbus = NULL;
0896     }
0897 
0898     phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
0899     if (IS_ERR(phy_drd->vbus_boost)) {
0900         ret = PTR_ERR(phy_drd->vbus_boost);
0901         if (ret == -EPROBE_DEFER)
0902             return ret;
0903 
0904         dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
0905         phy_drd->vbus_boost = NULL;
0906     }
0907 
0908     dev_vdbg(dev, "Creating usbdrd_phy phy\n");
0909 
0910     for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
0911         struct phy *phy = devm_phy_create(dev, NULL,
0912                           &exynos5_usbdrd_phy_ops);
0913         if (IS_ERR(phy)) {
0914             dev_err(dev, "Failed to create usbdrd_phy phy\n");
0915             return PTR_ERR(phy);
0916         }
0917 
0918         phy_drd->phys[i].phy = phy;
0919         phy_drd->phys[i].index = i;
0920         phy_drd->phys[i].reg_pmu = reg_pmu;
0921         phy_drd->phys[i].pmu_offset = pmu_offset;
0922         phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
0923         phy_set_drvdata(phy, &phy_drd->phys[i]);
0924     }
0925 
0926     phy_provider = devm_of_phy_provider_register(dev,
0927                              exynos5_usbdrd_phy_xlate);
0928     if (IS_ERR(phy_provider)) {
0929         dev_err(phy_drd->dev, "Failed to register phy provider\n");
0930         return PTR_ERR(phy_provider);
0931     }
0932 
0933     return 0;
0934 }
0935 
0936 static struct platform_driver exynos5_usb3drd_phy = {
0937     .probe  = exynos5_usbdrd_phy_probe,
0938     .driver = {
0939         .of_match_table = exynos5_usbdrd_phy_of_match,
0940         .name       = "exynos5_usb3drd_phy",
0941         .suppress_bind_attrs = true,
0942     }
0943 };
0944 
0945 module_platform_driver(exynos5_usb3drd_phy);
0946 MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");
0947 MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
0948 MODULE_LICENSE("GPL v2");
0949 MODULE_ALIAS("platform:exynos5_usb3drd_phy");