linux/drivers/phy/ti/phy-ti-pipe3.c
<<
>>
Prefs
   1/*
   2 * phy-ti-pipe3 - PIPE3 PHY driver.
   3 *
   4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * Author: Kishon Vijay Abraham I <kishon@ti.com>
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/slab.h>
  22#include <linux/phy/phy.h>
  23#include <linux/of.h>
  24#include <linux/clk.h>
  25#include <linux/err.h>
  26#include <linux/io.h>
  27#include <linux/pm_runtime.h>
  28#include <linux/delay.h>
  29#include <linux/phy/omap_control_phy.h>
  30#include <linux/of_platform.h>
  31#include <linux/mfd/syscon.h>
  32#include <linux/regmap.h>
  33
  34#define PLL_STATUS              0x00000004
  35#define PLL_GO                  0x00000008
  36#define PLL_CONFIGURATION1      0x0000000C
  37#define PLL_CONFIGURATION2      0x00000010
  38#define PLL_CONFIGURATION3      0x00000014
  39#define PLL_CONFIGURATION4      0x00000020
  40
  41#define PLL_REGM_MASK           0x001FFE00
  42#define PLL_REGM_SHIFT          0x9
  43#define PLL_REGM_F_MASK         0x0003FFFF
  44#define PLL_REGM_F_SHIFT        0x0
  45#define PLL_REGN_MASK           0x000001FE
  46#define PLL_REGN_SHIFT          0x1
  47#define PLL_SELFREQDCO_MASK     0x0000000E
  48#define PLL_SELFREQDCO_SHIFT    0x1
  49#define PLL_SD_MASK             0x0003FC00
  50#define PLL_SD_SHIFT            10
  51#define SET_PLL_GO              0x1
  52#define PLL_LDOPWDN             BIT(15)
  53#define PLL_TICOPWDN            BIT(16)
  54#define PLL_LOCK                0x2
  55#define PLL_IDLE                0x1
  56
  57#define SATA_PLL_SOFT_RESET     BIT(18)
  58
  59#define PIPE3_PHY_PWRCTL_CLK_CMD_MASK   0x003FC000
  60#define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT  14
  61
  62#define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK  0xFFC00000
  63#define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 22
  64
  65#define PIPE3_PHY_TX_RX_POWERON         0x3
  66#define PIPE3_PHY_TX_RX_POWEROFF        0x0
  67
  68#define PCIE_PCS_MASK                   0xFF0000
  69#define PCIE_PCS_DELAY_COUNT_SHIFT      0x10
  70
  71/*
  72 * This is an Empirical value that works, need to confirm the actual
  73 * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
  74 * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
  75 */
  76#define PLL_IDLE_TIME   100     /* in milliseconds */
  77#define PLL_LOCK_TIME   100     /* in milliseconds */
  78
  79struct pipe3_dpll_params {
  80        u16     m;
  81        u8      n;
  82        u8      freq:3;
  83        u8      sd;
  84        u32     mf;
  85};
  86
  87struct pipe3_dpll_map {
  88        unsigned long rate;
  89        struct pipe3_dpll_params params;
  90};
  91
  92struct ti_pipe3 {
  93        void __iomem            *pll_ctrl_base;
  94        struct device           *dev;
  95        struct device           *control_dev;
  96        struct clk              *wkupclk;
  97        struct clk              *sys_clk;
  98        struct clk              *refclk;
  99        struct clk              *div_clk;
 100        struct pipe3_dpll_map   *dpll_map;
 101        struct regmap           *phy_power_syscon; /* ctrl. reg. acces */
 102        struct regmap           *pcs_syscon; /* ctrl. reg. acces */
 103        struct regmap           *dpll_reset_syscon; /* ctrl. reg. acces */
 104        unsigned int            dpll_reset_reg; /* reg. index within syscon */
 105        unsigned int            power_reg; /* power reg. index within syscon */
 106        unsigned int            pcie_pcs_reg; /* pcs reg. index in syscon */
 107        bool                    sata_refclk_enabled;
 108};
 109
 110static struct pipe3_dpll_map dpll_map_usb[] = {
 111        {12000000, {1250, 5, 4, 20, 0} },       /* 12 MHz */
 112        {16800000, {3125, 20, 4, 20, 0} },      /* 16.8 MHz */
 113        {19200000, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
 114        {20000000, {1000, 7, 4, 10, 0} },       /* 20 MHz */
 115        {26000000, {1250, 12, 4, 20, 0} },      /* 26 MHz */
 116        {38400000, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
 117        { },                                    /* Terminator */
 118};
 119
 120static struct pipe3_dpll_map dpll_map_sata[] = {
 121        {12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
 122        {16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
 123        {19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
 124        {20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
 125        {26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
 126        {38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
 127        { },                                    /* Terminator */
 128};
 129
 130static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset)
 131{
 132        return __raw_readl(addr + offset);
 133}
 134
 135static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset,
 136        u32 data)
 137{
 138        __raw_writel(data, addr + offset);
 139}
 140
 141static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
 142{
 143        unsigned long rate;
 144        struct pipe3_dpll_map *dpll_map = phy->dpll_map;
 145
 146        rate = clk_get_rate(phy->sys_clk);
 147
 148        for (; dpll_map->rate; dpll_map++) {
 149                if (rate == dpll_map->rate)
 150                        return &dpll_map->params;
 151        }
 152
 153        dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
 154
 155        return NULL;
 156}
 157
 158static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy);
 159static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
 160
 161static int ti_pipe3_power_off(struct phy *x)
 162{
 163        u32 val;
 164        int ret;
 165        struct ti_pipe3 *phy = phy_get_drvdata(x);
 166
 167        if (!phy->phy_power_syscon) {
 168                omap_control_phy_power(phy->control_dev, 0);
 169                return 0;
 170        }
 171
 172        val = PIPE3_PHY_TX_RX_POWEROFF << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
 173
 174        ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
 175                                 PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val);
 176        return ret;
 177}
 178
 179static int ti_pipe3_power_on(struct phy *x)
 180{
 181        u32 val;
 182        u32 mask;
 183        int ret;
 184        unsigned long rate;
 185        struct ti_pipe3 *phy = phy_get_drvdata(x);
 186
 187        if (!phy->phy_power_syscon) {
 188                omap_control_phy_power(phy->control_dev, 1);
 189                return 0;
 190        }
 191
 192        rate = clk_get_rate(phy->sys_clk);
 193        if (!rate) {
 194                dev_err(phy->dev, "Invalid clock rate\n");
 195                return -EINVAL;
 196        }
 197        rate = rate / 1000000;
 198        mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
 199                  OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK;
 200        val = PIPE3_PHY_TX_RX_POWERON << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
 201        val |= rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
 202
 203        ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
 204                                 mask, val);
 205        return ret;
 206}
 207
 208static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
 209{
 210        u32             val;
 211        unsigned long   timeout;
 212
 213        timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
 214        do {
 215                cpu_relax();
 216                val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 217                if (val & PLL_LOCK)
 218                        return 0;
 219        } while (!time_after(jiffies, timeout));
 220
 221        dev_err(phy->dev, "DPLL failed to lock\n");
 222        return -EBUSY;
 223}
 224
 225static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
 226{
 227        u32                     val;
 228        struct pipe3_dpll_params *dpll_params;
 229
 230        dpll_params = ti_pipe3_get_dpll_params(phy);
 231        if (!dpll_params)
 232                return -EINVAL;
 233
 234        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 235        val &= ~PLL_REGN_MASK;
 236        val |= dpll_params->n << PLL_REGN_SHIFT;
 237        ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 238
 239        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 240        val &= ~PLL_SELFREQDCO_MASK;
 241        val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
 242        ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 243
 244        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 245        val &= ~PLL_REGM_MASK;
 246        val |= dpll_params->m << PLL_REGM_SHIFT;
 247        ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 248
 249        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
 250        val &= ~PLL_REGM_F_MASK;
 251        val |= dpll_params->mf << PLL_REGM_F_SHIFT;
 252        ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
 253
 254        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
 255        val &= ~PLL_SD_MASK;
 256        val |= dpll_params->sd << PLL_SD_SHIFT;
 257        ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
 258
 259        ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
 260
 261        return ti_pipe3_dpll_wait_lock(phy);
 262}
 263
 264static int ti_pipe3_init(struct phy *x)
 265{
 266        struct ti_pipe3 *phy = phy_get_drvdata(x);
 267        u32 val;
 268        int ret = 0;
 269
 270        ti_pipe3_enable_clocks(phy);
 271        /*
 272         * Set pcie_pcs register to 0x96 for proper functioning of phy
 273         * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
 274         * 18-1804.
 275         */
 276        if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
 277                if (!phy->pcs_syscon) {
 278                        omap_control_pcie_pcs(phy->control_dev, 0x96);
 279                        return 0;
 280                }
 281
 282                val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT;
 283                ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg,
 284                                         PCIE_PCS_MASK, val);
 285                return ret;
 286        }
 287
 288        /* Bring it out of IDLE if it is IDLE */
 289        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 290        if (val & PLL_IDLE) {
 291                val &= ~PLL_IDLE;
 292                ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 293                ret = ti_pipe3_dpll_wait_lock(phy);
 294        }
 295
 296        /* SATA has issues if re-programmed when locked */
 297        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 298        if ((val & PLL_LOCK) && of_device_is_compatible(phy->dev->of_node,
 299                                                        "ti,phy-pipe3-sata"))
 300                return ret;
 301
 302        /* Program the DPLL */
 303        ret = ti_pipe3_dpll_program(phy);
 304        if (ret) {
 305                ti_pipe3_disable_clocks(phy);
 306                return -EINVAL;
 307        }
 308
 309        return ret;
 310}
 311
 312static int ti_pipe3_exit(struct phy *x)
 313{
 314        struct ti_pipe3 *phy = phy_get_drvdata(x);
 315        u32 val;
 316        unsigned long timeout;
 317
 318        /* If dpll_reset_syscon is not present we wont power down SATA DPLL
 319         * due to Errata i783
 320         */
 321        if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") &&
 322            !phy->dpll_reset_syscon)
 323                return 0;
 324
 325        /* PCIe doesn't have internal DPLL */
 326        if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
 327                /* Put DPLL in IDLE mode */
 328                val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 329                val |= PLL_IDLE;
 330                ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 331
 332                /* wait for LDO and Oscillator to power down */
 333                timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
 334                do {
 335                        cpu_relax();
 336                        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 337                        if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
 338                                break;
 339                } while (!time_after(jiffies, timeout));
 340
 341                if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
 342                        dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
 343                                val);
 344                        return -EBUSY;
 345                }
 346        }
 347
 348        /* i783: SATA needs control bit toggle after PLL unlock */
 349        if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) {
 350                regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
 351                                   SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET);
 352                regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
 353                                   SATA_PLL_SOFT_RESET, 0);
 354        }
 355
 356        ti_pipe3_disable_clocks(phy);
 357
 358        return 0;
 359}
 360static const struct phy_ops ops = {
 361        .init           = ti_pipe3_init,
 362        .exit           = ti_pipe3_exit,
 363        .power_on       = ti_pipe3_power_on,
 364        .power_off      = ti_pipe3_power_off,
 365        .owner          = THIS_MODULE,
 366};
 367
 368static const struct of_device_id ti_pipe3_id_table[];
 369
 370static int ti_pipe3_get_clk(struct ti_pipe3 *phy)
 371{
 372        struct clk *clk;
 373        struct device *dev = phy->dev;
 374        struct device_node *node = dev->of_node;
 375
 376        phy->refclk = devm_clk_get(dev, "refclk");
 377        if (IS_ERR(phy->refclk)) {
 378                dev_err(dev, "unable to get refclk\n");
 379                /* older DTBs have missing refclk in SATA PHY
 380                 * so don't bail out in case of SATA PHY.
 381                 */
 382                if (!of_device_is_compatible(node, "ti,phy-pipe3-sata"))
 383                        return PTR_ERR(phy->refclk);
 384        }
 385
 386        if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 387                phy->wkupclk = devm_clk_get(dev, "wkupclk");
 388                if (IS_ERR(phy->wkupclk)) {
 389                        dev_err(dev, "unable to get wkupclk\n");
 390                        return PTR_ERR(phy->wkupclk);
 391                }
 392        } else {
 393                phy->wkupclk = ERR_PTR(-ENODEV);
 394        }
 395
 396        if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie") ||
 397            phy->phy_power_syscon) {
 398                phy->sys_clk = devm_clk_get(dev, "sysclk");
 399                if (IS_ERR(phy->sys_clk)) {
 400                        dev_err(dev, "unable to get sysclk\n");
 401                        return -EINVAL;
 402                }
 403        }
 404
 405        if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
 406                clk = devm_clk_get(dev, "dpll_ref");
 407                if (IS_ERR(clk)) {
 408                        dev_err(dev, "unable to get dpll ref clk\n");
 409                        return PTR_ERR(clk);
 410                }
 411                clk_set_rate(clk, 1500000000);
 412
 413                clk = devm_clk_get(dev, "dpll_ref_m2");
 414                if (IS_ERR(clk)) {
 415                        dev_err(dev, "unable to get dpll ref m2 clk\n");
 416                        return PTR_ERR(clk);
 417                }
 418                clk_set_rate(clk, 100000000);
 419
 420                clk = devm_clk_get(dev, "phy-div");
 421                if (IS_ERR(clk)) {
 422                        dev_err(dev, "unable to get phy-div clk\n");
 423                        return PTR_ERR(clk);
 424                }
 425                clk_set_rate(clk, 100000000);
 426
 427                phy->div_clk = devm_clk_get(dev, "div-clk");
 428                if (IS_ERR(phy->div_clk)) {
 429                        dev_err(dev, "unable to get div-clk\n");
 430                        return PTR_ERR(phy->div_clk);
 431                }
 432        } else {
 433                phy->div_clk = ERR_PTR(-ENODEV);
 434        }
 435
 436        return 0;
 437}
 438
 439static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
 440{
 441        struct device *dev = phy->dev;
 442        struct device_node *node = dev->of_node;
 443        struct device_node *control_node;
 444        struct platform_device *control_pdev;
 445
 446        phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node,
 447                                                        "syscon-phy-power");
 448        if (IS_ERR(phy->phy_power_syscon)) {
 449                dev_dbg(dev,
 450                        "can't get syscon-phy-power, using control device\n");
 451                phy->phy_power_syscon = NULL;
 452        } else {
 453                if (of_property_read_u32_index(node,
 454                                               "syscon-phy-power", 1,
 455                                               &phy->power_reg)) {
 456                        dev_err(dev, "couldn't get power reg. offset\n");
 457                        return -EINVAL;
 458                }
 459        }
 460
 461        if (!phy->phy_power_syscon) {
 462                control_node = of_parse_phandle(node, "ctrl-module", 0);
 463                if (!control_node) {
 464                        dev_err(dev, "Failed to get control device phandle\n");
 465                        return -EINVAL;
 466                }
 467
 468                control_pdev = of_find_device_by_node(control_node);
 469                if (!control_pdev) {
 470                        dev_err(dev, "Failed to get control device\n");
 471                        return -EINVAL;
 472                }
 473
 474                phy->control_dev = &control_pdev->dev;
 475        }
 476
 477        if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
 478                phy->pcs_syscon = syscon_regmap_lookup_by_phandle(node,
 479                                                                  "syscon-pcs");
 480                if (IS_ERR(phy->pcs_syscon)) {
 481                        dev_dbg(dev,
 482                                "can't get syscon-pcs, using omap control\n");
 483                        phy->pcs_syscon = NULL;
 484                } else {
 485                        if (of_property_read_u32_index(node,
 486                                                       "syscon-pcs", 1,
 487                                                       &phy->pcie_pcs_reg)) {
 488                                dev_err(dev,
 489                                        "couldn't get pcie pcs reg. offset\n");
 490                                return -EINVAL;
 491                        }
 492                }
 493        }
 494
 495        if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 496                phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node,
 497                                                        "syscon-pllreset");
 498                if (IS_ERR(phy->dpll_reset_syscon)) {
 499                        dev_info(dev,
 500                                 "can't get syscon-pllreset, sata dpll won't idle\n");
 501                        phy->dpll_reset_syscon = NULL;
 502                } else {
 503                        if (of_property_read_u32_index(node,
 504                                                       "syscon-pllreset", 1,
 505                                                       &phy->dpll_reset_reg)) {
 506                                dev_err(dev,
 507                                        "couldn't get pllreset reg. offset\n");
 508                                return -EINVAL;
 509                        }
 510                }
 511        }
 512
 513        return 0;
 514}
 515
 516static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
 517{
 518        struct resource *res;
 519        const struct of_device_id *match;
 520        struct device *dev = phy->dev;
 521        struct device_node *node = dev->of_node;
 522        struct platform_device *pdev = to_platform_device(dev);
 523
 524        if (of_device_is_compatible(node, "ti,phy-pipe3-pcie"))
 525                return 0;
 526
 527        match = of_match_device(ti_pipe3_id_table, dev);
 528        if (!match)
 529                return -EINVAL;
 530
 531        phy->dpll_map = (struct pipe3_dpll_map *)match->data;
 532        if (!phy->dpll_map) {
 533                dev_err(dev, "no DPLL data\n");
 534                return -EINVAL;
 535        }
 536
 537        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 538                                           "pll_ctrl");
 539        phy->pll_ctrl_base = devm_ioremap_resource(dev, res);
 540        return PTR_ERR_OR_ZERO(phy->pll_ctrl_base);
 541}
 542
 543static int ti_pipe3_probe(struct platform_device *pdev)
 544{
 545        struct ti_pipe3 *phy;
 546        struct phy *generic_phy;
 547        struct phy_provider *phy_provider;
 548        struct device_node *node = pdev->dev.of_node;
 549        struct device *dev = &pdev->dev;
 550        int ret;
 551
 552        phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 553        if (!phy)
 554                return -ENOMEM;
 555
 556        phy->dev                = dev;
 557
 558        ret = ti_pipe3_get_pll_base(phy);
 559        if (ret)
 560                return ret;
 561
 562        ret = ti_pipe3_get_sysctrl(phy);
 563        if (ret)
 564                return ret;
 565
 566        ret = ti_pipe3_get_clk(phy);
 567        if (ret)
 568                return ret;
 569
 570        platform_set_drvdata(pdev, phy);
 571        pm_runtime_enable(dev);
 572
 573        /*
 574         * Prevent auto-disable of refclk for SATA PHY due to Errata i783
 575         */
 576        if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 577                if (!IS_ERR(phy->refclk)) {
 578                        clk_prepare_enable(phy->refclk);
 579                        phy->sata_refclk_enabled = true;
 580                }
 581        }
 582
 583        generic_phy = devm_phy_create(dev, NULL, &ops);
 584        if (IS_ERR(generic_phy))
 585                return PTR_ERR(generic_phy);
 586
 587        phy_set_drvdata(generic_phy, phy);
 588
 589        ti_pipe3_power_off(generic_phy);
 590
 591        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 592        return PTR_ERR_OR_ZERO(phy_provider);
 593}
 594
 595static int ti_pipe3_remove(struct platform_device *pdev)
 596{
 597        pm_runtime_disable(&pdev->dev);
 598
 599        return 0;
 600}
 601
 602static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
 603{
 604        int ret = 0;
 605
 606        if (!IS_ERR(phy->refclk)) {
 607                ret = clk_prepare_enable(phy->refclk);
 608                if (ret) {
 609                        dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
 610                        return ret;
 611                }
 612        }
 613
 614        if (!IS_ERR(phy->wkupclk)) {
 615                ret = clk_prepare_enable(phy->wkupclk);
 616                if (ret) {
 617                        dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
 618                        goto disable_refclk;
 619                }
 620        }
 621
 622        if (!IS_ERR(phy->div_clk)) {
 623                ret = clk_prepare_enable(phy->div_clk);
 624                if (ret) {
 625                        dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
 626                        goto disable_wkupclk;
 627                }
 628        }
 629
 630        return 0;
 631
 632disable_wkupclk:
 633        if (!IS_ERR(phy->wkupclk))
 634                clk_disable_unprepare(phy->wkupclk);
 635
 636disable_refclk:
 637        if (!IS_ERR(phy->refclk))
 638                clk_disable_unprepare(phy->refclk);
 639
 640        return ret;
 641}
 642
 643static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
 644{
 645        if (!IS_ERR(phy->wkupclk))
 646                clk_disable_unprepare(phy->wkupclk);
 647        if (!IS_ERR(phy->refclk)) {
 648                clk_disable_unprepare(phy->refclk);
 649                /*
 650                 * SATA refclk needs an additional disable as we left it
 651                 * on in probe to avoid Errata i783
 652                 */
 653                if (phy->sata_refclk_enabled) {
 654                        clk_disable_unprepare(phy->refclk);
 655                        phy->sata_refclk_enabled = false;
 656                }
 657        }
 658
 659        if (!IS_ERR(phy->div_clk))
 660                clk_disable_unprepare(phy->div_clk);
 661}
 662
 663static const struct of_device_id ti_pipe3_id_table[] = {
 664        {
 665                .compatible = "ti,phy-usb3",
 666                .data = dpll_map_usb,
 667        },
 668        {
 669                .compatible = "ti,omap-usb3",
 670                .data = dpll_map_usb,
 671        },
 672        {
 673                .compatible = "ti,phy-pipe3-sata",
 674                .data = dpll_map_sata,
 675        },
 676        {
 677                .compatible = "ti,phy-pipe3-pcie",
 678        },
 679        {}
 680};
 681MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
 682
 683static struct platform_driver ti_pipe3_driver = {
 684        .probe          = ti_pipe3_probe,
 685        .remove         = ti_pipe3_remove,
 686        .driver         = {
 687                .name   = "ti-pipe3",
 688                .of_match_table = ti_pipe3_id_table,
 689        },
 690};
 691
 692module_platform_driver(ti_pipe3_driver);
 693
 694MODULE_ALIAS("platform:ti_pipe3");
 695MODULE_AUTHOR("Texas Instruments Inc.");
 696MODULE_DESCRIPTION("TI PIPE3 phy driver");
 697MODULE_LICENSE("GPL v2");
 698