linux/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/delay.h>
   8
   9#include "dsi_phy.h"
  10#include "dsi.xml.h"
  11#include "dsi_phy_28nm_8960.xml.h"
  12
  13/*
  14 * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):
  15 *
  16 *
  17 *                        +------+
  18 *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)
  19 *  F * byte_clk    |     +------+
  20 *                  | bit clock divider (F / 8)
  21 *                  |
  22 *                  |     +------+
  23 *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG
  24 *                  |     +------+                 | (sets parent rate)
  25 *                  | byte clock divider (F)       |
  26 *                  |                              |
  27 *                  |                              o---> To esc RCG
  28 *                  |                                (doesn't set parent rate)
  29 *                  |
  30 *                  |     +------+
  31 *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG
  32 *                        +------+                 | (sets parent rate)
  33 *                  dsi clock divider (F * magic)  |
  34 *                                                 |
  35 *                                                 o---> To pixel rcg
  36 *                                                  (doesn't set parent rate)
  37 */
  38
  39#define POLL_MAX_READS          8000
  40#define POLL_TIMEOUT_US         1
  41
  42#define VCO_REF_CLK_RATE        27000000
  43#define VCO_MIN_RATE            600000000
  44#define VCO_MAX_RATE            1200000000
  45
  46#define VCO_PREF_DIV_RATIO      27
  47
  48struct pll_28nm_cached_state {
  49        unsigned long vco_rate;
  50        u8 postdiv3;
  51        u8 postdiv2;
  52        u8 postdiv1;
  53};
  54
  55struct clk_bytediv {
  56        struct clk_hw hw;
  57        void __iomem *reg;
  58};
  59
  60struct dsi_pll_28nm {
  61        struct clk_hw clk_hw;
  62
  63        struct msm_dsi_phy *phy;
  64
  65        struct pll_28nm_cached_state cached_state;
  66};
  67
  68#define to_pll_28nm(x)  container_of(x, struct dsi_pll_28nm, clk_hw)
  69
  70static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
  71                                    int nb_tries, int timeout_us)
  72{
  73        bool pll_locked = false;
  74        u32 val;
  75
  76        while (nb_tries--) {
  77                val = dsi_phy_read(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_RDY);
  78                pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);
  79
  80                if (pll_locked)
  81                        break;
  82
  83                udelay(timeout_us);
  84        }
  85        DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
  86
  87        return pll_locked;
  88}
  89
  90/*
  91 * Clock Callbacks
  92 */
  93static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
  94                                     unsigned long parent_rate)
  95{
  96        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
  97        void __iomem *base = pll_28nm->phy->pll_base;
  98        u32 val, temp, fb_divider;
  99
 100        DBG("rate=%lu, parent's=%lu", rate, parent_rate);
 101
 102        temp = rate / 10;
 103        val = VCO_REF_CLK_RATE / 10;
 104        fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
 105        fb_divider = fb_divider / 2 - 1;
 106        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1,
 107                        fb_divider & 0xff);
 108
 109        val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
 110
 111        val |= (fb_divider >> 8) & 0x07;
 112
 113        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2,
 114                        val);
 115
 116        val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
 117
 118        val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;
 119
 120        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3,
 121                        val);
 122
 123        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6,
 124                        0xf);
 125
 126        val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
 127        val |= 0x7 << 4;
 128        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
 129                        val);
 130
 131        return 0;
 132}
 133
 134static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
 135{
 136        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 137
 138        return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
 139                                        POLL_TIMEOUT_US);
 140}
 141
 142static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
 143                                                  unsigned long parent_rate)
 144{
 145        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 146        void __iomem *base = pll_28nm->phy->pll_base;
 147        unsigned long vco_rate;
 148        u32 status, fb_divider, temp, ref_divider;
 149
 150        VERB("parent_rate=%lu", parent_rate);
 151
 152        status = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
 153
 154        if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {
 155                fb_divider = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
 156                fb_divider &= 0xff;
 157                temp = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
 158                fb_divider = (temp << 8) | fb_divider;
 159                fb_divider += 1;
 160
 161                ref_divider = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
 162                ref_divider &= 0x3f;
 163                ref_divider += 1;
 164
 165                /* multiply by 2 */
 166                vco_rate = (parent_rate / ref_divider) * fb_divider * 2;
 167        } else {
 168                vco_rate = 0;
 169        }
 170
 171        DBG("returning vco rate = %lu", vco_rate);
 172
 173        return vco_rate;
 174}
 175
 176static int dsi_pll_28nm_vco_prepare(struct clk_hw *hw)
 177{
 178        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 179        struct device *dev = &pll_28nm->phy->pdev->dev;
 180        void __iomem *base = pll_28nm->phy->pll_base;
 181        bool locked;
 182        unsigned int bit_div, byte_div;
 183        int max_reads = 1000, timeout_us = 100;
 184        u32 val;
 185
 186        DBG("id=%d", pll_28nm->phy->id);
 187
 188        if (unlikely(pll_28nm->phy->pll_on))
 189                return 0;
 190
 191        /*
 192         * before enabling the PLL, configure the bit clock divider since we
 193         * don't expose it as a clock to the outside world
 194         * 1: read back the byte clock divider that should already be set
 195         * 2: divide by 8 to get bit clock divider
 196         * 3: write it to POSTDIV1
 197         */
 198        val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
 199        byte_div = val + 1;
 200        bit_div = byte_div / 8;
 201
 202        val = dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
 203        val &= ~0xf;
 204        val |= (bit_div - 1);
 205        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8, val);
 206
 207        /* enable the PLL */
 208        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0,
 209                        DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE);
 210
 211        locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
 212
 213        if (unlikely(!locked)) {
 214                DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
 215                return -EINVAL;
 216        }
 217
 218        DBG("DSI PLL lock success");
 219        pll_28nm->phy->pll_on = true;
 220
 221        return 0;
 222}
 223
 224static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
 225{
 226        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 227
 228        DBG("id=%d", pll_28nm->phy->id);
 229
 230        if (unlikely(!pll_28nm->phy->pll_on))
 231                return;
 232
 233        dsi_phy_write(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0, 0x00);
 234
 235        pll_28nm->phy->pll_on = false;
 236}
 237
 238static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw,
 239                unsigned long rate, unsigned long *parent_rate)
 240{
 241        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 242
 243        if      (rate < pll_28nm->phy->cfg->min_pll_rate)
 244                return  pll_28nm->phy->cfg->min_pll_rate;
 245        else if (rate > pll_28nm->phy->cfg->max_pll_rate)
 246                return  pll_28nm->phy->cfg->max_pll_rate;
 247        else
 248                return rate;
 249}
 250
 251static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
 252        .round_rate = dsi_pll_28nm_clk_round_rate,
 253        .set_rate = dsi_pll_28nm_clk_set_rate,
 254        .recalc_rate = dsi_pll_28nm_clk_recalc_rate,
 255        .prepare = dsi_pll_28nm_vco_prepare,
 256        .unprepare = dsi_pll_28nm_vco_unprepare,
 257        .is_enabled = dsi_pll_28nm_clk_is_enabled,
 258};
 259
 260/*
 261 * Custom byte clock divier clk_ops
 262 *
 263 * This clock is the entry point to configuring the PLL. The user (dsi host)
 264 * will set this clock's rate to the desired byte clock rate. The VCO lock
 265 * frequency is a multiple of the byte clock rate. The multiplication factor
 266 * (shown as F in the diagram above) is a function of the byte clock rate.
 267 *
 268 * This custom divider clock ensures that its parent (VCO) is set to the
 269 * desired rate, and that the byte clock postdivider (POSTDIV2) is configured
 270 * accordingly
 271 */
 272#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)
 273
 274static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,
 275                unsigned long parent_rate)
 276{
 277        struct clk_bytediv *bytediv = to_clk_bytediv(hw);
 278        unsigned int div;
 279
 280        div = dsi_phy_read(bytediv->reg) & 0xff;
 281
 282        return parent_rate / (div + 1);
 283}
 284
 285/* find multiplication factor(wrt byte clock) at which the VCO should be set */
 286static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)
 287{
 288        unsigned long bit_mhz;
 289
 290        /* convert to bit clock in Mhz */
 291        bit_mhz = (byte_clk_rate * 8) / 1000000;
 292
 293        if (bit_mhz < 125)
 294                return 64;
 295        else if (bit_mhz < 250)
 296                return 32;
 297        else if (bit_mhz < 600)
 298                return 16;
 299        else
 300                return 8;
 301}
 302
 303static long clk_bytediv_round_rate(struct clk_hw *hw, unsigned long rate,
 304                                   unsigned long *prate)
 305{
 306        unsigned long best_parent;
 307        unsigned int factor;
 308
 309        factor = get_vco_mul_factor(rate);
 310
 311        best_parent = rate * factor;
 312        *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
 313
 314        return *prate / factor;
 315}
 316
 317static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
 318                                unsigned long parent_rate)
 319{
 320        struct clk_bytediv *bytediv = to_clk_bytediv(hw);
 321        u32 val;
 322        unsigned int factor;
 323
 324        factor = get_vco_mul_factor(rate);
 325
 326        val = dsi_phy_read(bytediv->reg);
 327        val |= (factor - 1) & 0xff;
 328        dsi_phy_write(bytediv->reg, val);
 329
 330        return 0;
 331}
 332
 333/* Our special byte clock divider ops */
 334static const struct clk_ops clk_bytediv_ops = {
 335        .round_rate = clk_bytediv_round_rate,
 336        .set_rate = clk_bytediv_set_rate,
 337        .recalc_rate = clk_bytediv_recalc_rate,
 338};
 339
 340/*
 341 * PLL Callbacks
 342 */
 343static void dsi_28nm_pll_save_state(struct msm_dsi_phy *phy)
 344{
 345        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);
 346        struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
 347        void __iomem *base = pll_28nm->phy->pll_base;
 348
 349        cached_state->postdiv3 =
 350                        dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
 351        cached_state->postdiv2 =
 352                        dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
 353        cached_state->postdiv1 =
 354                        dsi_phy_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
 355
 356        cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);
 357}
 358
 359static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy)
 360{
 361        struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);
 362        struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
 363        void __iomem *base = pll_28nm->phy->pll_base;
 364        int ret;
 365
 366        ret = dsi_pll_28nm_clk_set_rate(phy->vco_hw,
 367                                        cached_state->vco_rate, 0);
 368        if (ret) {
 369                DRM_DEV_ERROR(&pll_28nm->phy->pdev->dev,
 370                        "restore vco rate failed. ret=%d\n", ret);
 371                return ret;
 372        }
 373
 374        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
 375                        cached_state->postdiv3);
 376        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9,
 377                        cached_state->postdiv2);
 378        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8,
 379                        cached_state->postdiv1);
 380
 381        return 0;
 382}
 383
 384static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks)
 385{
 386        char *clk_name, *parent_name, *vco_name;
 387        struct clk_init_data vco_init = {
 388                .parent_names = (const char *[]){ "pxo" },
 389                .num_parents = 1,
 390                .flags = CLK_IGNORE_UNUSED,
 391                .ops = &clk_ops_dsi_pll_28nm_vco,
 392        };
 393        struct device *dev = &pll_28nm->phy->pdev->dev;
 394        struct clk_hw *hw;
 395        struct clk_bytediv *bytediv;
 396        struct clk_init_data bytediv_init = { };
 397        int ret;
 398
 399        DBG("%d", pll_28nm->phy->id);
 400
 401        bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
 402        if (!bytediv)
 403                return -ENOMEM;
 404
 405        vco_name = devm_kzalloc(dev, 32, GFP_KERNEL);
 406        if (!vco_name)
 407                return -ENOMEM;
 408
 409        parent_name = devm_kzalloc(dev, 32, GFP_KERNEL);
 410        if (!parent_name)
 411                return -ENOMEM;
 412
 413        clk_name = devm_kzalloc(dev, 32, GFP_KERNEL);
 414        if (!clk_name)
 415                return -ENOMEM;
 416
 417        snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->phy->id);
 418        vco_init.name = vco_name;
 419
 420        pll_28nm->clk_hw.init = &vco_init;
 421
 422        ret = devm_clk_hw_register(dev, &pll_28nm->clk_hw);
 423        if (ret)
 424                return ret;
 425
 426        /* prepare and register bytediv */
 427        bytediv->hw.init = &bytediv_init;
 428        bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
 429
 430        snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->phy->id);
 431        snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id + 1);
 432
 433        bytediv_init.name = clk_name;
 434        bytediv_init.ops = &clk_bytediv_ops;
 435        bytediv_init.flags = CLK_SET_RATE_PARENT;
 436        bytediv_init.parent_names = (const char * const *) &parent_name;
 437        bytediv_init.num_parents = 1;
 438
 439        /* DIV2 */
 440        ret = devm_clk_hw_register(dev, &bytediv->hw);
 441        if (ret)
 442                return ret;
 443        provided_clocks[DSI_BYTE_PLL_CLK] = &bytediv->hw;
 444
 445        snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1);
 446        /* DIV3 */
 447        hw = devm_clk_hw_register_divider(dev, clk_name,
 448                                parent_name, 0, pll_28nm->phy->pll_base +
 449                                REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
 450                                0, 8, 0, NULL);
 451        if (IS_ERR(hw))
 452                return PTR_ERR(hw);
 453        provided_clocks[DSI_PIXEL_PLL_CLK] = hw;
 454
 455        return 0;
 456}
 457
 458static int dsi_pll_28nm_8960_init(struct msm_dsi_phy *phy)
 459{
 460        struct platform_device *pdev = phy->pdev;
 461        struct dsi_pll_28nm *pll_28nm;
 462        int ret;
 463
 464        if (!pdev)
 465                return -ENODEV;
 466
 467        pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
 468        if (!pll_28nm)
 469                return -ENOMEM;
 470
 471        pll_28nm->phy = phy;
 472
 473        ret = pll_28nm_register(pll_28nm, phy->provided_clocks->hws);
 474        if (ret) {
 475                DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
 476                return ret;
 477        }
 478
 479        phy->vco_hw = &pll_28nm->clk_hw;
 480
 481        return 0;
 482}
 483
 484static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
 485                struct msm_dsi_dphy_timing *timing)
 486{
 487        void __iomem *base = phy->base;
 488
 489        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0,
 490                DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
 491        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1,
 492                DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
 493        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2,
 494                DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
 495        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3, 0x0);
 496        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4,
 497                DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
 498        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5,
 499                DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
 500        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6,
 501                DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
 502        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7,
 503                DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
 504        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8,
 505                DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
 506        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9,
 507                DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
 508                DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
 509        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10,
 510                DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
 511        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11,
 512                DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
 513}
 514
 515static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy)
 516{
 517        void __iomem *base = phy->reg_base;
 518
 519        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
 520        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 1);
 521        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 1);
 522        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0);
 523        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4,
 524                0x100);
 525}
 526
 527static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy)
 528{
 529        void __iomem *base = phy->reg_base;
 530
 531        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
 532        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 0xa);
 533        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 0x4);
 534        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0x0);
 535        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4, 0x20);
 536}
 537
 538static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
 539{
 540        void __iomem *base = phy->reg_base;
 541        u32 status;
 542        int i = 5000;
 543
 544        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG,
 545                        0x3);
 546
 547        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2, 0x0);
 548        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1, 0x5a);
 549        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3, 0x10);
 550        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4, 0x1);
 551        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0, 0x1);
 552
 553        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x1);
 554        usleep_range(5000, 6000);
 555        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x0);
 556
 557        do {
 558                status = dsi_phy_read(base +
 559                                REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS);
 560
 561                if (!(status & DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY))
 562                        break;
 563
 564                udelay(1);
 565        } while (--i > 0);
 566}
 567
 568static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy)
 569{
 570        void __iomem *base = phy->base;
 571        int i;
 572
 573        for (i = 0; i < 4; i++) {
 574                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i), 0x80);
 575                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i), 0x45);
 576                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i), 0x00);
 577                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i),
 578                        0x00);
 579                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i),
 580                        0x01);
 581                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i),
 582                        0x66);
 583        }
 584
 585        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0, 0x40);
 586        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1, 0x67);
 587        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2, 0x0);
 588        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH, 0x0);
 589        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0, 0x1);
 590        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1, 0x88);
 591}
 592
 593static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
 594                                struct msm_dsi_phy_clk_request *clk_req)
 595{
 596        struct msm_dsi_dphy_timing *timing = &phy->timing;
 597        void __iomem *base = phy->base;
 598
 599        DBG("");
 600
 601        if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
 602                DRM_DEV_ERROR(&phy->pdev->dev,
 603                        "%s: D-PHY timing calculation failed\n", __func__);
 604                return -EINVAL;
 605        }
 606
 607        dsi_28nm_phy_regulator_init(phy);
 608
 609        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LDO_CTRL, 0x04);
 610
 611        /* strength control */
 612        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_0, 0xff);
 613        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_1, 0x00);
 614        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_2, 0x06);
 615
 616        /* phy ctrl */
 617        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x5f);
 618        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_1, 0x00);
 619        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_2, 0x00);
 620        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_3, 0x10);
 621
 622        dsi_28nm_phy_regulator_ctrl(phy);
 623
 624        dsi_28nm_phy_calibration(phy);
 625
 626        dsi_28nm_phy_lane_config(phy);
 627
 628        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0f);
 629        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1, 0x03);
 630        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0, 0x03);
 631        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0);
 632
 633        dsi_28nm_dphy_set_timing(phy, timing);
 634
 635        return 0;
 636}
 637
 638static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
 639{
 640        dsi_phy_write(phy->base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x0);
 641
 642        /*
 643         * Wait for the registers writes to complete in order to
 644         * ensure that the phy is completely disabled
 645         */
 646        wmb();
 647}
 648
 649const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = {
 650        .has_phy_regulator = true,
 651        .reg_cfg = {
 652                .num = 1,
 653                .regs = {
 654                        {"vddio", 100000, 100}, /* 1.8 V */
 655                },
 656        },
 657        .ops = {
 658                .enable = dsi_28nm_phy_enable,
 659                .disable = dsi_28nm_phy_disable,
 660                .pll_init = dsi_pll_28nm_8960_init,
 661                .save_pll_state = dsi_28nm_pll_save_state,
 662                .restore_pll_state = dsi_28nm_pll_restore_state,
 663        },
 664        .min_pll_rate = VCO_MIN_RATE,
 665        .max_pll_rate = VCO_MAX_RATE,
 666        .io_start = { 0x4700300, 0x5800300 },
 667        .num_dsi_phy = 2,
 668};
 669