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
0017
0018 #define EXYNOS_4x12_UPHYPWR 0x0
0019
0020 #define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND BIT(0)
0021 #define EXYNOS_4x12_UPHYPWR_PHY0_PWR BIT(3)
0022 #define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR BIT(4)
0023 #define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP BIT(5)
0024 #define EXYNOS_4x12_UPHYPWR_PHY0 ( \
0025 EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
0026 EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
0027 EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
0028 EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
0029
0030 #define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND BIT(6)
0031 #define EXYNOS_4x12_UPHYPWR_PHY1_PWR BIT(7)
0032 #define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP BIT(8)
0033 #define EXYNOS_4x12_UPHYPWR_PHY1 ( \
0034 EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
0035 EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
0036 EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
0037
0038 #define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND BIT(9)
0039 #define EXYNOS_4x12_UPHYPWR_HSIC0_PWR BIT(10)
0040 #define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP BIT(11)
0041 #define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
0042 EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
0043 EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
0044 EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
0045
0046 #define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND BIT(12)
0047 #define EXYNOS_4x12_UPHYPWR_HSIC1_PWR BIT(13)
0048 #define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP BIT(14)
0049 #define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
0050 EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
0051 EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
0052 EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
0053
0054
0055 #define EXYNOS_4x12_UPHYCLK 0x4
0056
0057 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK (0x7 << 0)
0058 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET 0
0059 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6 (0x0 << 0)
0060 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ (0x1 << 0)
0061 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
0062 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2 (0x3 << 0)
0063 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ (0x4 << 0)
0064 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0)
0065 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0)
0066
0067 #define EXYNOS_3250_UPHYCLK_REFCLKSEL (0x2 << 8)
0068
0069 #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3)
0070 #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4)
0071 #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7)
0072
0073 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK (0x7f << 10)
0074 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET 10
0075 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ (0x24 << 10)
0076 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ (0x1c << 10)
0077 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ (0x1a << 10)
0078 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10)
0079 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ (0x14 << 10)
0080
0081
0082 #define EXYNOS_4x12_UPHYRST 0x8
0083
0084 #define EXYNOS_4x12_URSTCON_PHY0 BIT(0)
0085 #define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1)
0086 #define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
0087 #define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 #define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
0099 #define EXYNOS_4x12_URSTCON_HSIC0 BIT(6)
0100 #define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
0101 #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
0102 #define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(10)
0103 #define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
0104 #define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(8)
0105
0106
0107 #define EXYNOS_4x12_USB_ISOL_OFFSET 0x704
0108 #define EXYNOS_4x12_USB_ISOL_OTG BIT(0)
0109 #define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET 0x708
0110 #define EXYNOS_4x12_USB_ISOL_HSIC0 BIT(0)
0111 #define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET 0x70c
0112 #define EXYNOS_4x12_USB_ISOL_HSIC1 BIT(0)
0113
0114
0115 #define EXYNOS_4x12_MODE_SWITCH_OFFSET 0x21c
0116 #define EXYNOS_4x12_MODE_SWITCH_MASK 1
0117 #define EXYNOS_4x12_MODE_SWITCH_DEVICE 0
0118 #define EXYNOS_4x12_MODE_SWITCH_HOST 1
0119
0120 enum exynos4x12_phy_id {
0121 EXYNOS4x12_DEVICE,
0122 EXYNOS4x12_HOST,
0123 EXYNOS4x12_HSIC0,
0124 EXYNOS4x12_HSIC1,
0125 EXYNOS4x12_NUM_PHYS,
0126 };
0127
0128
0129
0130
0131
0132 static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
0133 {
0134
0135
0136 switch (rate) {
0137 case 9600 * KHZ:
0138 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
0139 break;
0140 case 10 * MHZ:
0141 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
0142 break;
0143 case 12 * MHZ:
0144 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
0145 break;
0146 case 19200 * KHZ:
0147 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
0148 break;
0149 case 20 * MHZ:
0150 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
0151 break;
0152 case 24 * MHZ:
0153 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
0154 break;
0155 case 50 * MHZ:
0156 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
0157 break;
0158 default:
0159 return -EINVAL;
0160 }
0161
0162 return 0;
0163 }
0164
0165 static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
0166 {
0167 struct samsung_usb2_phy_driver *drv = inst->drv;
0168 u32 offset;
0169 u32 mask;
0170
0171 switch (inst->cfg->id) {
0172 case EXYNOS4x12_DEVICE:
0173 case EXYNOS4x12_HOST:
0174 offset = EXYNOS_4x12_USB_ISOL_OFFSET;
0175 mask = EXYNOS_4x12_USB_ISOL_OTG;
0176 break;
0177 case EXYNOS4x12_HSIC0:
0178 offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
0179 mask = EXYNOS_4x12_USB_ISOL_HSIC0;
0180 break;
0181 case EXYNOS4x12_HSIC1:
0182 offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
0183 mask = EXYNOS_4x12_USB_ISOL_HSIC1;
0184 break;
0185 default:
0186 return;
0187 }
0188
0189 regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
0190 }
0191
0192 static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
0193 {
0194 struct samsung_usb2_phy_driver *drv = inst->drv;
0195 u32 clk;
0196
0197 clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
0198 clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
0199
0200 if (drv->cfg->has_refclk_sel)
0201 clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
0202
0203 clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
0204 clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
0205 writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
0206 }
0207
0208 static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
0209 {
0210 struct samsung_usb2_phy_driver *drv = inst->drv;
0211 u32 rstbits = 0;
0212 u32 phypwr = 0;
0213 u32 rst;
0214 u32 pwr;
0215
0216 switch (inst->cfg->id) {
0217 case EXYNOS4x12_DEVICE:
0218 phypwr = EXYNOS_4x12_UPHYPWR_PHY0;
0219 rstbits = EXYNOS_4x12_URSTCON_PHY0;
0220 break;
0221 case EXYNOS4x12_HOST:
0222 phypwr = EXYNOS_4x12_UPHYPWR_PHY1;
0223 rstbits = EXYNOS_4x12_URSTCON_HOST_PHY |
0224 EXYNOS_4x12_URSTCON_PHY1 |
0225 EXYNOS_4x12_URSTCON_HOST_LINK_P0;
0226 break;
0227 case EXYNOS4x12_HSIC0:
0228 phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
0229 rstbits = EXYNOS_4x12_URSTCON_HSIC0 |
0230 EXYNOS_4x12_URSTCON_HOST_LINK_P1;
0231 break;
0232 case EXYNOS4x12_HSIC1:
0233 phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
0234 rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
0235 EXYNOS_4x12_URSTCON_HOST_LINK_P1;
0236 break;
0237 }
0238
0239 if (on) {
0240 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
0241 pwr &= ~phypwr;
0242 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
0243
0244 rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
0245 rst |= rstbits;
0246 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
0247 udelay(10);
0248 rst &= ~rstbits;
0249 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
0250
0251
0252 udelay(80);
0253 } else {
0254 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
0255 pwr |= phypwr;
0256 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
0257 }
0258 }
0259
0260 static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
0261 {
0262 if (inst->int_cnt++ > 0)
0263 return;
0264
0265 exynos4x12_setup_clk(inst);
0266 exynos4x12_isol(inst, 0);
0267 exynos4x12_phy_pwr(inst, 1);
0268 }
0269
0270 static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
0271 {
0272 struct samsung_usb2_phy_driver *drv = inst->drv;
0273
0274 if (inst->ext_cnt++ > 0)
0275 return 0;
0276
0277 if (inst->cfg->id == EXYNOS4x12_HOST) {
0278 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
0279 EXYNOS_4x12_MODE_SWITCH_MASK,
0280 EXYNOS_4x12_MODE_SWITCH_HOST);
0281 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
0282 }
0283
0284 if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
0285 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
0286 EXYNOS_4x12_MODE_SWITCH_MASK,
0287 EXYNOS_4x12_MODE_SWITCH_DEVICE);
0288
0289 if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
0290 inst->cfg->id == EXYNOS4x12_HSIC1) {
0291 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
0292 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
0293 }
0294
0295 exynos4x12_power_on_int(inst);
0296
0297 return 0;
0298 }
0299
0300 static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
0301 {
0302 if (inst->int_cnt-- > 1)
0303 return;
0304
0305 exynos4x12_isol(inst, 1);
0306 exynos4x12_phy_pwr(inst, 0);
0307 }
0308
0309 static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
0310 {
0311 struct samsung_usb2_phy_driver *drv = inst->drv;
0312
0313 if (inst->ext_cnt-- > 1)
0314 return 0;
0315
0316 if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
0317 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
0318 EXYNOS_4x12_MODE_SWITCH_MASK,
0319 EXYNOS_4x12_MODE_SWITCH_HOST);
0320
0321 if (inst->cfg->id == EXYNOS4x12_HOST)
0322 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
0323
0324 if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
0325 inst->cfg->id == EXYNOS4x12_HSIC1) {
0326 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
0327 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
0328 }
0329
0330 exynos4x12_power_off_int(inst);
0331
0332 return 0;
0333 }
0334
0335
0336 static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
0337 {
0338 .label = "device",
0339 .id = EXYNOS4x12_DEVICE,
0340 .power_on = exynos4x12_power_on,
0341 .power_off = exynos4x12_power_off,
0342 },
0343 {
0344 .label = "host",
0345 .id = EXYNOS4x12_HOST,
0346 .power_on = exynos4x12_power_on,
0347 .power_off = exynos4x12_power_off,
0348 },
0349 {
0350 .label = "hsic0",
0351 .id = EXYNOS4x12_HSIC0,
0352 .power_on = exynos4x12_power_on,
0353 .power_off = exynos4x12_power_off,
0354 },
0355 {
0356 .label = "hsic1",
0357 .id = EXYNOS4x12_HSIC1,
0358 .power_on = exynos4x12_power_on,
0359 .power_off = exynos4x12_power_off,
0360 },
0361 };
0362
0363 const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
0364 .has_refclk_sel = 1,
0365 .num_phys = 1,
0366 .phys = exynos4x12_phys,
0367 .rate_to_clk = exynos4x12_rate_to_clk,
0368 };
0369
0370 const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
0371 .has_mode_switch = 1,
0372 .num_phys = EXYNOS4x12_NUM_PHYS,
0373 .phys = exynos4x12_phys,
0374 .rate_to_clk = exynos4x12_rate_to_clk,
0375 };