root/drivers/phy/samsung/phy-exynos4x12-usb2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exynos4x12_rate_to_clk
  2. exynos4x12_isol
  3. exynos4x12_setup_clk
  4. exynos4x12_phy_pwr
  5. exynos4x12_power_on_int
  6. exynos4x12_power_on
  7. exynos4x12_power_off_int
  8. exynos4x12_power_off

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
   4  *
   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 
  17 /* PHY power control */
  18 #define EXYNOS_4x12_UPHYPWR                     0x0
  19 
  20 #define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND        BIT(0)
  21 #define EXYNOS_4x12_UPHYPWR_PHY0_PWR            BIT(3)
  22 #define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR        BIT(4)
  23 #define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP          BIT(5)
  24 #define EXYNOS_4x12_UPHYPWR_PHY0 ( \
  25         EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
  26         EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
  27         EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
  28         EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
  29 
  30 #define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND        BIT(6)
  31 #define EXYNOS_4x12_UPHYPWR_PHY1_PWR            BIT(7)
  32 #define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP          BIT(8)
  33 #define EXYNOS_4x12_UPHYPWR_PHY1 ( \
  34         EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
  35         EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
  36         EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
  37 
  38 #define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND       BIT(9)
  39 #define EXYNOS_4x12_UPHYPWR_HSIC0_PWR           BIT(10)
  40 #define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP         BIT(11)
  41 #define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
  42         EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
  43         EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
  44         EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
  45 
  46 #define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND       BIT(12)
  47 #define EXYNOS_4x12_UPHYPWR_HSIC1_PWR           BIT(13)
  48 #define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP         BIT(14)
  49 #define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
  50         EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
  51         EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
  52         EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
  53 
  54 /* PHY clock control */
  55 #define EXYNOS_4x12_UPHYCLK                     0x4
  56 
  57 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK        (0x7 << 0)
  58 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET      0
  59 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6       (0x0 << 0)
  60 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ       (0x1 << 0)
  61 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ       (0x2 << 0)
  62 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2      (0x3 << 0)
  63 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ       (0x4 << 0)
  64 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ       (0x5 << 0)
  65 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ       (0x7 << 0)
  66 
  67 #define EXYNOS_3250_UPHYCLK_REFCLKSEL           (0x2 << 8)
  68 
  69 #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP      BIT(3)
  70 #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON      BIT(4)
  71 #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON      BIT(7)
  72 
  73 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK    (0x7f << 10)
  74 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET  10
  75 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ   (0x24 << 10)
  76 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ   (0x1c << 10)
  77 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ   (0x1a << 10)
  78 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2  (0x15 << 10)
  79 #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ   (0x14 << 10)
  80 
  81 /* PHY reset control */
  82 #define EXYNOS_4x12_UPHYRST                     0x8
  83 
  84 #define EXYNOS_4x12_URSTCON_PHY0                BIT(0)
  85 #define EXYNOS_4x12_URSTCON_OTG_HLINK           BIT(1)
  86 #define EXYNOS_4x12_URSTCON_OTG_PHYLINK         BIT(2)
  87 #define EXYNOS_4x12_URSTCON_HOST_PHY            BIT(3)
  88 /* The following bit defines are presented in the
  89  * order taken from the Exynos4412 reference manual.
  90  *
  91  * During experiments with the hardware and debugging
  92  * it was determined that the hardware behaves contrary
  93  * to the manual.
  94  *
  95  * The following bit values were chaned accordingly to the
  96  * results of real hardware experiments.
  97  */
  98 #define EXYNOS_4x12_URSTCON_PHY1                BIT(4)
  99 #define EXYNOS_4x12_URSTCON_HSIC0               BIT(6)
 100 #define EXYNOS_4x12_URSTCON_HSIC1               BIT(5)
 101 #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL       BIT(7)
 102 #define EXYNOS_4x12_URSTCON_HOST_LINK_P0        BIT(10)
 103 #define EXYNOS_4x12_URSTCON_HOST_LINK_P1        BIT(9)
 104 #define EXYNOS_4x12_URSTCON_HOST_LINK_P2        BIT(8)
 105 
 106 /* Isolation, configured in the power management unit */
 107 #define EXYNOS_4x12_USB_ISOL_OFFSET             0x704
 108 #define EXYNOS_4x12_USB_ISOL_OTG                BIT(0)
 109 #define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET       0x708
 110 #define EXYNOS_4x12_USB_ISOL_HSIC0              BIT(0)
 111 #define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET       0x70c
 112 #define EXYNOS_4x12_USB_ISOL_HSIC1              BIT(0)
 113 
 114 /* Mode switching SUB Device <-> Host */
 115 #define EXYNOS_4x12_MODE_SWITCH_OFFSET          0x21c
 116 #define EXYNOS_4x12_MODE_SWITCH_MASK            1
 117 #define EXYNOS_4x12_MODE_SWITCH_DEVICE          0
 118 #define EXYNOS_4x12_MODE_SWITCH_HOST            1
 119 
 120 enum exynos4x12_phy_id {
 121         EXYNOS4x12_DEVICE,
 122         EXYNOS4x12_HOST,
 123         EXYNOS4x12_HSIC0,
 124         EXYNOS4x12_HSIC1,
 125         EXYNOS4x12_NUM_PHYS,
 126 };
 127 
 128 /*
 129  * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
 130  * can be written to the phy register.
 131  */
 132 static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
 133 {
 134         /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
 135 
 136         switch (rate) {
 137         case 9600 * KHZ:
 138                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
 139                 break;
 140         case 10 * MHZ:
 141                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
 142                 break;
 143         case 12 * MHZ:
 144                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
 145                 break;
 146         case 19200 * KHZ:
 147                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
 148                 break;
 149         case 20 * MHZ:
 150                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
 151                 break;
 152         case 24 * MHZ:
 153                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
 154                 break;
 155         case 50 * MHZ:
 156                 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
 157                 break;
 158         default:
 159                 return -EINVAL;
 160         }
 161 
 162         return 0;
 163 }
 164 
 165 static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
 166 {
 167         struct samsung_usb2_phy_driver *drv = inst->drv;
 168         u32 offset;
 169         u32 mask;
 170 
 171         switch (inst->cfg->id) {
 172         case EXYNOS4x12_DEVICE:
 173         case EXYNOS4x12_HOST:
 174                 offset = EXYNOS_4x12_USB_ISOL_OFFSET;
 175                 mask = EXYNOS_4x12_USB_ISOL_OTG;
 176                 break;
 177         case EXYNOS4x12_HSIC0:
 178                 offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
 179                 mask = EXYNOS_4x12_USB_ISOL_HSIC0;
 180                 break;
 181         case EXYNOS4x12_HSIC1:
 182                 offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
 183                 mask = EXYNOS_4x12_USB_ISOL_HSIC1;
 184                 break;
 185         default:
 186                 return;
 187         }
 188 
 189         regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
 190 }
 191 
 192 static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
 193 {
 194         struct samsung_usb2_phy_driver *drv = inst->drv;
 195         u32 clk;
 196 
 197         clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 198         clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
 199 
 200         if (drv->cfg->has_refclk_sel)
 201                 clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
 202 
 203         clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
 204         clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
 205         writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 206 }
 207 
 208 static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 209 {
 210         struct samsung_usb2_phy_driver *drv = inst->drv;
 211         u32 rstbits = 0;
 212         u32 phypwr = 0;
 213         u32 rst;
 214         u32 pwr;
 215 
 216         switch (inst->cfg->id) {
 217         case EXYNOS4x12_DEVICE:
 218                 phypwr =        EXYNOS_4x12_UPHYPWR_PHY0;
 219                 rstbits =       EXYNOS_4x12_URSTCON_PHY0;
 220                 break;
 221         case EXYNOS4x12_HOST:
 222                 phypwr =        EXYNOS_4x12_UPHYPWR_PHY1;
 223                 rstbits =       EXYNOS_4x12_URSTCON_HOST_PHY |
 224                                 EXYNOS_4x12_URSTCON_PHY1 |
 225                                 EXYNOS_4x12_URSTCON_HOST_LINK_P0;
 226                 break;
 227         case EXYNOS4x12_HSIC0:
 228                 phypwr =        EXYNOS_4x12_UPHYPWR_HSIC0;
 229                 rstbits =       EXYNOS_4x12_URSTCON_HSIC0 |
 230                                 EXYNOS_4x12_URSTCON_HOST_LINK_P1;
 231                 break;
 232         case EXYNOS4x12_HSIC1:
 233                 phypwr =        EXYNOS_4x12_UPHYPWR_HSIC1;
 234                 rstbits =       EXYNOS_4x12_URSTCON_HSIC1 |
 235                                 EXYNOS_4x12_URSTCON_HOST_LINK_P1;
 236                 break;
 237         }
 238 
 239         if (on) {
 240                 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 241                 pwr &= ~phypwr;
 242                 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 243 
 244                 rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
 245                 rst |= rstbits;
 246                 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
 247                 udelay(10);
 248                 rst &= ~rstbits;
 249                 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
 250                 /* The following delay is necessary for the reset sequence to be
 251                  * completed */
 252                 udelay(80);
 253         } else {
 254                 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 255                 pwr |= phypwr;
 256                 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 257         }
 258 }
 259 
 260 static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
 261 {
 262         if (inst->int_cnt++ > 0)
 263                 return;
 264 
 265         exynos4x12_setup_clk(inst);
 266         exynos4x12_isol(inst, 0);
 267         exynos4x12_phy_pwr(inst, 1);
 268 }
 269 
 270 static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
 271 {
 272         struct samsung_usb2_phy_driver *drv = inst->drv;
 273 
 274         if (inst->ext_cnt++ > 0)
 275                 return 0;
 276 
 277         if (inst->cfg->id == EXYNOS4x12_HOST) {
 278                 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
 279                                                 EXYNOS_4x12_MODE_SWITCH_MASK,
 280                                                 EXYNOS_4x12_MODE_SWITCH_HOST);
 281                 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 282         }
 283 
 284         if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
 285                 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
 286                                                 EXYNOS_4x12_MODE_SWITCH_MASK,
 287                                                 EXYNOS_4x12_MODE_SWITCH_DEVICE);
 288 
 289         if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
 290                 inst->cfg->id == EXYNOS4x12_HSIC1) {
 291                 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 292                 exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
 293         }
 294 
 295         exynos4x12_power_on_int(inst);
 296 
 297         return 0;
 298 }
 299 
 300 static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
 301 {
 302         if (inst->int_cnt-- > 1)
 303                 return;
 304 
 305         exynos4x12_isol(inst, 1);
 306         exynos4x12_phy_pwr(inst, 0);
 307 }
 308 
 309 static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
 310 {
 311         struct samsung_usb2_phy_driver *drv = inst->drv;
 312 
 313         if (inst->ext_cnt-- > 1)
 314                 return 0;
 315 
 316         if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
 317                 regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
 318                                                 EXYNOS_4x12_MODE_SWITCH_MASK,
 319                                                 EXYNOS_4x12_MODE_SWITCH_HOST);
 320 
 321         if (inst->cfg->id == EXYNOS4x12_HOST)
 322                 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
 323 
 324         if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
 325                 inst->cfg->id == EXYNOS4x12_HSIC1) {
 326                 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
 327                 exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
 328         }
 329 
 330         exynos4x12_power_off_int(inst);
 331 
 332         return 0;
 333 }
 334 
 335 
 336 static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
 337         {
 338                 .label          = "device",
 339                 .id             = EXYNOS4x12_DEVICE,
 340                 .power_on       = exynos4x12_power_on,
 341                 .power_off      = exynos4x12_power_off,
 342         },
 343         {
 344                 .label          = "host",
 345                 .id             = EXYNOS4x12_HOST,
 346                 .power_on       = exynos4x12_power_on,
 347                 .power_off      = exynos4x12_power_off,
 348         },
 349         {
 350                 .label          = "hsic0",
 351                 .id             = EXYNOS4x12_HSIC0,
 352                 .power_on       = exynos4x12_power_on,
 353                 .power_off      = exynos4x12_power_off,
 354         },
 355         {
 356                 .label          = "hsic1",
 357                 .id             = EXYNOS4x12_HSIC1,
 358                 .power_on       = exynos4x12_power_on,
 359                 .power_off      = exynos4x12_power_off,
 360         },
 361 };
 362 
 363 const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
 364         .has_refclk_sel         = 1,
 365         .num_phys               = 1,
 366         .phys                   = exynos4x12_phys,
 367         .rate_to_clk            = exynos4x12_rate_to_clk,
 368 };
 369 
 370 const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
 371         .has_mode_switch        = 1,
 372         .num_phys               = EXYNOS4x12_NUM_PHYS,
 373         .phys                   = exynos4x12_phys,
 374         .rate_to_clk            = exynos4x12_rate_to_clk,
 375 };

/* [<][>][^][v][top][bottom][index][help] */