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/delay.h>
   7
   8#include "dsi_phy.h"
   9#include "dsi.xml.h"
  10
  11static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
  12                struct msm_dsi_dphy_timing *timing)
  13{
  14        void __iomem *base = phy->base;
  15
  16        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0,
  17                DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
  18        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1,
  19                DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
  20        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2,
  21                DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
  22        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3, 0x0);
  23        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4,
  24                DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
  25        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5,
  26                DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
  27        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6,
  28                DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
  29        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7,
  30                DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
  31        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8,
  32                DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
  33        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9,
  34                DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
  35                DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
  36        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10,
  37                DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
  38        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11,
  39                DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
  40}
  41
  42static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy)
  43{
  44        void __iomem *base = phy->reg_base;
  45
  46        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
  47        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 1);
  48        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 1);
  49        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0);
  50        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4,
  51                0x100);
  52}
  53
  54static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy)
  55{
  56        void __iomem *base = phy->reg_base;
  57
  58        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0, 0x3);
  59        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1, 0xa);
  60        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2, 0x4);
  61        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3, 0x0);
  62        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4, 0x20);
  63}
  64
  65static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
  66{
  67        void __iomem *base = phy->reg_base;
  68        u32 status;
  69        int i = 5000;
  70
  71        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG,
  72                        0x3);
  73
  74        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2, 0x0);
  75        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1, 0x5a);
  76        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3, 0x10);
  77        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4, 0x1);
  78        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0, 0x1);
  79
  80        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x1);
  81        usleep_range(5000, 6000);
  82        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER, 0x0);
  83
  84        do {
  85                status = dsi_phy_read(base +
  86                                REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS);
  87
  88                if (!(status & DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY))
  89                        break;
  90
  91                udelay(1);
  92        } while (--i > 0);
  93}
  94
  95static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy)
  96{
  97        void __iomem *base = phy->base;
  98        int i;
  99
 100        for (i = 0; i < 4; i++) {
 101                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i), 0x80);
 102                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i), 0x45);
 103                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i), 0x00);
 104                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i),
 105                        0x00);
 106                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i),
 107                        0x01);
 108                dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i),
 109                        0x66);
 110        }
 111
 112        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0, 0x40);
 113        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1, 0x67);
 114        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2, 0x0);
 115        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH, 0x0);
 116        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0, 0x1);
 117        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1, 0x88);
 118}
 119
 120static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
 121                                struct msm_dsi_phy_clk_request *clk_req)
 122{
 123        struct msm_dsi_dphy_timing *timing = &phy->timing;
 124        void __iomem *base = phy->base;
 125
 126        DBG("");
 127
 128        if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
 129                DRM_DEV_ERROR(&phy->pdev->dev,
 130                        "%s: D-PHY timing calculation failed\n", __func__);
 131                return -EINVAL;
 132        }
 133
 134        dsi_28nm_phy_regulator_init(phy);
 135
 136        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_LDO_CTRL, 0x04);
 137
 138        /* strength control */
 139        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_0, 0xff);
 140        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_1, 0x00);
 141        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_STRENGTH_2, 0x06);
 142
 143        /* phy ctrl */
 144        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x5f);
 145        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_1, 0x00);
 146        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_2, 0x00);
 147        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_CTRL_3, 0x10);
 148
 149        dsi_28nm_phy_regulator_ctrl(phy);
 150
 151        dsi_28nm_phy_calibration(phy);
 152
 153        dsi_28nm_phy_lane_config(phy);
 154
 155        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0f);
 156        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1, 0x03);
 157        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0, 0x03);
 158        dsi_phy_write(base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4, 0x0);
 159
 160        dsi_28nm_dphy_set_timing(phy, timing);
 161
 162        return 0;
 163}
 164
 165static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
 166{
 167        dsi_phy_write(phy->base + REG_DSI_28nm_8960_PHY_CTRL_0, 0x0);
 168
 169        /*
 170         * Wait for the registers writes to complete in order to
 171         * ensure that the phy is completely disabled
 172         */
 173        wmb();
 174}
 175
 176const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = {
 177        .type = MSM_DSI_PHY_28NM_8960,
 178        .src_pll_truthtable = { {true, true}, {false, true} },
 179        .reg_cfg = {
 180                .num = 1,
 181                .regs = {
 182                        {"vddio", 100000, 100}, /* 1.8 V */
 183                },
 184        },
 185        .ops = {
 186                .enable = dsi_28nm_phy_enable,
 187                .disable = dsi_28nm_phy_disable,
 188                .init = msm_dsi_phy_init_common,
 189        },
 190        .io_start = { 0x4700300, 0x5800300 },
 191        .num_dsi_phy = 2,
 192};
 193