190f80d95SChun-Kuang Hu // SPDX-License-Identifier: GPL-2.0 290f80d95SChun-Kuang Hu /* 390f80d95SChun-Kuang Hu * Copyright (c) 2019 MediaTek Inc. 490f80d95SChun-Kuang Hu * Author: jitao.shi <jitao.shi@mediatek.com> 590f80d95SChun-Kuang Hu */ 690f80d95SChun-Kuang Hu 790f80d95SChun-Kuang Hu #include "phy-mtk-mipi-dsi.h" 890f80d95SChun-Kuang Hu 990f80d95SChun-Kuang Hu #define MIPITX_LANE_CON 0x000c 1090f80d95SChun-Kuang Hu #define RG_DSI_CPHY_T1DRV_EN BIT(0) 1190f80d95SChun-Kuang Hu #define RG_DSI_ANA_CK_SEL BIT(1) 1290f80d95SChun-Kuang Hu #define RG_DSI_PHY_CK_SEL BIT(2) 1390f80d95SChun-Kuang Hu #define RG_DSI_CPHY_EN BIT(3) 1490f80d95SChun-Kuang Hu #define RG_DSI_PHYCK_INV_EN BIT(4) 1590f80d95SChun-Kuang Hu #define RG_DSI_PWR04_EN BIT(5) 1690f80d95SChun-Kuang Hu #define RG_DSI_BG_LPF_EN BIT(6) 1790f80d95SChun-Kuang Hu #define RG_DSI_BG_CORE_EN BIT(7) 1890f80d95SChun-Kuang Hu #define RG_DSI_PAD_TIEL_SEL BIT(8) 1990f80d95SChun-Kuang Hu 2090f80d95SChun-Kuang Hu #define MIPITX_VOLTAGE_SEL 0x0010 21*d36d69a5SChunfeng Yun #define RG_DSI_HSTX_LDO_REF_SEL GENMASK(9, 6) 2290f80d95SChun-Kuang Hu 2390f80d95SChun-Kuang Hu #define MIPITX_PLL_PWR 0x0028 2490f80d95SChun-Kuang Hu #define MIPITX_PLL_CON0 0x002c 2590f80d95SChun-Kuang Hu #define MIPITX_PLL_CON1 0x0030 2690f80d95SChun-Kuang Hu #define MIPITX_PLL_CON2 0x0034 2790f80d95SChun-Kuang Hu #define MIPITX_PLL_CON3 0x0038 2890f80d95SChun-Kuang Hu #define MIPITX_PLL_CON4 0x003c 29*d36d69a5SChunfeng Yun #define RG_DSI_PLL_IBIAS GENMASK(11, 10) 3090f80d95SChun-Kuang Hu 3190f80d95SChun-Kuang Hu #define MIPITX_D2P_RTCODE 0x0100 3290f80d95SChun-Kuang Hu #define MIPITX_D2_SW_CTL_EN 0x0144 3390f80d95SChun-Kuang Hu #define MIPITX_D0_SW_CTL_EN 0x0244 3490f80d95SChun-Kuang Hu #define MIPITX_CK_CKMODE_EN 0x0328 3590f80d95SChun-Kuang Hu #define DSI_CK_CKMODE_EN BIT(0) 3690f80d95SChun-Kuang Hu #define MIPITX_CK_SW_CTL_EN 0x0344 3790f80d95SChun-Kuang Hu #define MIPITX_D1_SW_CTL_EN 0x0444 3890f80d95SChun-Kuang Hu #define MIPITX_D3_SW_CTL_EN 0x0544 3990f80d95SChun-Kuang Hu #define DSI_SW_CTL_EN BIT(0) 4090f80d95SChun-Kuang Hu #define AD_DSI_PLL_SDM_PWR_ON BIT(0) 4190f80d95SChun-Kuang Hu #define AD_DSI_PLL_SDM_ISO_EN BIT(1) 4290f80d95SChun-Kuang Hu 4390f80d95SChun-Kuang Hu #define RG_DSI_PLL_EN BIT(4) 44*d36d69a5SChunfeng Yun #define RG_DSI_PLL_POSDIV GENMASK(10, 8) 4590f80d95SChun-Kuang Hu 4690f80d95SChun-Kuang Hu static int mtk_mipi_tx_pll_enable(struct clk_hw *hw) 4790f80d95SChun-Kuang Hu { 4890f80d95SChun-Kuang Hu struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); 4990f80d95SChun-Kuang Hu unsigned int txdiv, txdiv0; 5090f80d95SChun-Kuang Hu u64 pcw; 5190f80d95SChun-Kuang Hu 5290f80d95SChun-Kuang Hu dev_dbg(mipi_tx->dev, "enable: %u bps\n", mipi_tx->data_rate); 5390f80d95SChun-Kuang Hu 5490f80d95SChun-Kuang Hu if (mipi_tx->data_rate >= 2000000000) { 5590f80d95SChun-Kuang Hu txdiv = 1; 5690f80d95SChun-Kuang Hu txdiv0 = 0; 5790f80d95SChun-Kuang Hu } else if (mipi_tx->data_rate >= 1000000000) { 5890f80d95SChun-Kuang Hu txdiv = 2; 5990f80d95SChun-Kuang Hu txdiv0 = 1; 6090f80d95SChun-Kuang Hu } else if (mipi_tx->data_rate >= 500000000) { 6190f80d95SChun-Kuang Hu txdiv = 4; 6290f80d95SChun-Kuang Hu txdiv0 = 2; 6390f80d95SChun-Kuang Hu } else if (mipi_tx->data_rate > 250000000) { 6490f80d95SChun-Kuang Hu txdiv = 8; 6590f80d95SChun-Kuang Hu txdiv0 = 3; 6690f80d95SChun-Kuang Hu } else if (mipi_tx->data_rate >= 125000000) { 6790f80d95SChun-Kuang Hu txdiv = 16; 6890f80d95SChun-Kuang Hu txdiv0 = 4; 6990f80d95SChun-Kuang Hu } else { 7090f80d95SChun-Kuang Hu return -EINVAL; 7190f80d95SChun-Kuang Hu } 7290f80d95SChun-Kuang Hu 7390f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON4, RG_DSI_PLL_IBIAS); 7490f80d95SChun-Kuang Hu 7590f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); 7690f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); 7790f80d95SChun-Kuang Hu udelay(1); 7890f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); 7990f80d95SChun-Kuang Hu pcw = div_u64(((u64)mipi_tx->data_rate * txdiv) << 24, 26000000); 8090f80d95SChun-Kuang Hu writel(pcw, mipi_tx->regs + MIPITX_PLL_CON0); 8190f80d95SChun-Kuang Hu mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV, 8290f80d95SChun-Kuang Hu txdiv0 << 8); 8390f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); 8490f80d95SChun-Kuang Hu 8590f80d95SChun-Kuang Hu return 0; 8690f80d95SChun-Kuang Hu } 8790f80d95SChun-Kuang Hu 8890f80d95SChun-Kuang Hu static void mtk_mipi_tx_pll_disable(struct clk_hw *hw) 8990f80d95SChun-Kuang Hu { 9090f80d95SChun-Kuang Hu struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); 9190f80d95SChun-Kuang Hu 9290f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN); 9390f80d95SChun-Kuang Hu 9490f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN); 9590f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON); 9690f80d95SChun-Kuang Hu } 9790f80d95SChun-Kuang Hu 9890f80d95SChun-Kuang Hu static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate, 9990f80d95SChun-Kuang Hu unsigned long *prate) 10090f80d95SChun-Kuang Hu { 10190f80d95SChun-Kuang Hu return clamp_val(rate, 50000000, 1600000000); 10290f80d95SChun-Kuang Hu } 10390f80d95SChun-Kuang Hu 10490f80d95SChun-Kuang Hu static const struct clk_ops mtk_mipi_tx_pll_ops = { 10590f80d95SChun-Kuang Hu .enable = mtk_mipi_tx_pll_enable, 10690f80d95SChun-Kuang Hu .disable = mtk_mipi_tx_pll_disable, 10790f80d95SChun-Kuang Hu .round_rate = mtk_mipi_tx_pll_round_rate, 10890f80d95SChun-Kuang Hu .set_rate = mtk_mipi_tx_pll_set_rate, 10990f80d95SChun-Kuang Hu .recalc_rate = mtk_mipi_tx_pll_recalc_rate, 11090f80d95SChun-Kuang Hu }; 11190f80d95SChun-Kuang Hu 11290f80d95SChun-Kuang Hu static void mtk_mipi_tx_config_calibration_data(struct mtk_mipi_tx *mipi_tx) 11390f80d95SChun-Kuang Hu { 11490f80d95SChun-Kuang Hu int i, j; 11590f80d95SChun-Kuang Hu 11690f80d95SChun-Kuang Hu for (i = 0; i < 5; i++) { 11790f80d95SChun-Kuang Hu if ((mipi_tx->rt_code[i] & 0x1f) == 0) 11890f80d95SChun-Kuang Hu mipi_tx->rt_code[i] |= 0x10; 11990f80d95SChun-Kuang Hu 12090f80d95SChun-Kuang Hu if ((mipi_tx->rt_code[i] >> 5 & 0x1f) == 0) 12190f80d95SChun-Kuang Hu mipi_tx->rt_code[i] |= 0x10 << 5; 12290f80d95SChun-Kuang Hu 12390f80d95SChun-Kuang Hu for (j = 0; j < 10; j++) 12490f80d95SChun-Kuang Hu mtk_mipi_tx_update_bits(mipi_tx, 12590f80d95SChun-Kuang Hu MIPITX_D2P_RTCODE * (i + 1) + j * 4, 12690f80d95SChun-Kuang Hu 1, mipi_tx->rt_code[i] >> j & 1); 12790f80d95SChun-Kuang Hu } 12890f80d95SChun-Kuang Hu } 12990f80d95SChun-Kuang Hu 13090f80d95SChun-Kuang Hu static void mtk_mipi_tx_power_on_signal(struct phy *phy) 13190f80d95SChun-Kuang Hu { 13290f80d95SChun-Kuang Hu struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); 13390f80d95SChun-Kuang Hu 13490f80d95SChun-Kuang Hu /* BG_LPF_EN / BG_CORE_EN */ 13590f80d95SChun-Kuang Hu writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, 13690f80d95SChun-Kuang Hu mipi_tx->regs + MIPITX_LANE_CON); 13790f80d95SChun-Kuang Hu usleep_range(30, 100); 13890f80d95SChun-Kuang Hu writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN, 13990f80d95SChun-Kuang Hu mipi_tx->regs + MIPITX_LANE_CON); 14090f80d95SChun-Kuang Hu 14190f80d95SChun-Kuang Hu /* Switch OFF each Lane */ 14290f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN); 14390f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN); 14490f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN); 14590f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN); 14690f80d95SChun-Kuang Hu mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN); 14790f80d95SChun-Kuang Hu 14890f80d95SChun-Kuang Hu mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL, 14990f80d95SChun-Kuang Hu RG_DSI_HSTX_LDO_REF_SEL, 15090f80d95SChun-Kuang Hu (mipi_tx->mipitx_drive - 3000) / 200 << 6); 15190f80d95SChun-Kuang Hu 15290f80d95SChun-Kuang Hu mtk_mipi_tx_config_calibration_data(mipi_tx); 15390f80d95SChun-Kuang Hu 15490f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN); 15590f80d95SChun-Kuang Hu } 15690f80d95SChun-Kuang Hu 15790f80d95SChun-Kuang Hu static void mtk_mipi_tx_power_off_signal(struct phy *phy) 15890f80d95SChun-Kuang Hu { 15990f80d95SChun-Kuang Hu struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); 16090f80d95SChun-Kuang Hu 16190f80d95SChun-Kuang Hu /* Switch ON each Lane */ 16290f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN); 16390f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN); 16490f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN); 16590f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN); 16690f80d95SChun-Kuang Hu mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN); 16790f80d95SChun-Kuang Hu 16890f80d95SChun-Kuang Hu writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, 16990f80d95SChun-Kuang Hu mipi_tx->regs + MIPITX_LANE_CON); 17090f80d95SChun-Kuang Hu writel(RG_DSI_PAD_TIEL_SEL, mipi_tx->regs + MIPITX_LANE_CON); 17190f80d95SChun-Kuang Hu } 17290f80d95SChun-Kuang Hu 17390f80d95SChun-Kuang Hu const struct mtk_mipitx_data mt8183_mipitx_data = { 17490f80d95SChun-Kuang Hu .mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops, 17590f80d95SChun-Kuang Hu .mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal, 17690f80d95SChun-Kuang Hu .mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal, 17790f80d95SChun-Kuang Hu }; 178