1*90f80d95SChun-Kuang Hu // SPDX-License-Identifier: GPL-2.0
2*90f80d95SChun-Kuang Hu /*
3*90f80d95SChun-Kuang Hu  * Copyright (c) 2019 MediaTek Inc.
4*90f80d95SChun-Kuang Hu  * Author: jitao.shi <jitao.shi@mediatek.com>
5*90f80d95SChun-Kuang Hu  */
6*90f80d95SChun-Kuang Hu 
7*90f80d95SChun-Kuang Hu #include "phy-mtk-mipi-dsi.h"
8*90f80d95SChun-Kuang Hu 
9*90f80d95SChun-Kuang Hu #define MIPITX_LANE_CON		0x000c
10*90f80d95SChun-Kuang Hu #define RG_DSI_CPHY_T1DRV_EN		BIT(0)
11*90f80d95SChun-Kuang Hu #define RG_DSI_ANA_CK_SEL		BIT(1)
12*90f80d95SChun-Kuang Hu #define RG_DSI_PHY_CK_SEL		BIT(2)
13*90f80d95SChun-Kuang Hu #define RG_DSI_CPHY_EN			BIT(3)
14*90f80d95SChun-Kuang Hu #define RG_DSI_PHYCK_INV_EN		BIT(4)
15*90f80d95SChun-Kuang Hu #define RG_DSI_PWR04_EN			BIT(5)
16*90f80d95SChun-Kuang Hu #define RG_DSI_BG_LPF_EN		BIT(6)
17*90f80d95SChun-Kuang Hu #define RG_DSI_BG_CORE_EN		BIT(7)
18*90f80d95SChun-Kuang Hu #define RG_DSI_PAD_TIEL_SEL		BIT(8)
19*90f80d95SChun-Kuang Hu 
20*90f80d95SChun-Kuang Hu #define MIPITX_VOLTAGE_SEL	0x0010
21*90f80d95SChun-Kuang Hu #define RG_DSI_HSTX_LDO_REF_SEL		(0xf << 6)
22*90f80d95SChun-Kuang Hu 
23*90f80d95SChun-Kuang Hu #define MIPITX_PLL_PWR		0x0028
24*90f80d95SChun-Kuang Hu #define MIPITX_PLL_CON0		0x002c
25*90f80d95SChun-Kuang Hu #define MIPITX_PLL_CON1		0x0030
26*90f80d95SChun-Kuang Hu #define MIPITX_PLL_CON2		0x0034
27*90f80d95SChun-Kuang Hu #define MIPITX_PLL_CON3		0x0038
28*90f80d95SChun-Kuang Hu #define MIPITX_PLL_CON4		0x003c
29*90f80d95SChun-Kuang Hu #define RG_DSI_PLL_IBIAS		(3 << 10)
30*90f80d95SChun-Kuang Hu 
31*90f80d95SChun-Kuang Hu #define MIPITX_D2P_RTCODE	0x0100
32*90f80d95SChun-Kuang Hu #define MIPITX_D2_SW_CTL_EN	0x0144
33*90f80d95SChun-Kuang Hu #define MIPITX_D0_SW_CTL_EN	0x0244
34*90f80d95SChun-Kuang Hu #define MIPITX_CK_CKMODE_EN	0x0328
35*90f80d95SChun-Kuang Hu #define DSI_CK_CKMODE_EN		BIT(0)
36*90f80d95SChun-Kuang Hu #define MIPITX_CK_SW_CTL_EN	0x0344
37*90f80d95SChun-Kuang Hu #define MIPITX_D1_SW_CTL_EN	0x0444
38*90f80d95SChun-Kuang Hu #define MIPITX_D3_SW_CTL_EN	0x0544
39*90f80d95SChun-Kuang Hu #define DSI_SW_CTL_EN			BIT(0)
40*90f80d95SChun-Kuang Hu #define AD_DSI_PLL_SDM_PWR_ON		BIT(0)
41*90f80d95SChun-Kuang Hu #define AD_DSI_PLL_SDM_ISO_EN		BIT(1)
42*90f80d95SChun-Kuang Hu 
43*90f80d95SChun-Kuang Hu #define RG_DSI_PLL_EN			BIT(4)
44*90f80d95SChun-Kuang Hu #define RG_DSI_PLL_POSDIV		(0x7 << 8)
45*90f80d95SChun-Kuang Hu 
46*90f80d95SChun-Kuang Hu static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
47*90f80d95SChun-Kuang Hu {
48*90f80d95SChun-Kuang Hu 	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
49*90f80d95SChun-Kuang Hu 	unsigned int txdiv, txdiv0;
50*90f80d95SChun-Kuang Hu 	u64 pcw;
51*90f80d95SChun-Kuang Hu 
52*90f80d95SChun-Kuang Hu 	dev_dbg(mipi_tx->dev, "enable: %u bps\n", mipi_tx->data_rate);
53*90f80d95SChun-Kuang Hu 
54*90f80d95SChun-Kuang Hu 	if (mipi_tx->data_rate >= 2000000000) {
55*90f80d95SChun-Kuang Hu 		txdiv = 1;
56*90f80d95SChun-Kuang Hu 		txdiv0 = 0;
57*90f80d95SChun-Kuang Hu 	} else if (mipi_tx->data_rate >= 1000000000) {
58*90f80d95SChun-Kuang Hu 		txdiv = 2;
59*90f80d95SChun-Kuang Hu 		txdiv0 = 1;
60*90f80d95SChun-Kuang Hu 	} else if (mipi_tx->data_rate >= 500000000) {
61*90f80d95SChun-Kuang Hu 		txdiv = 4;
62*90f80d95SChun-Kuang Hu 		txdiv0 = 2;
63*90f80d95SChun-Kuang Hu 	} else if (mipi_tx->data_rate > 250000000) {
64*90f80d95SChun-Kuang Hu 		txdiv = 8;
65*90f80d95SChun-Kuang Hu 		txdiv0 = 3;
66*90f80d95SChun-Kuang Hu 	} else if (mipi_tx->data_rate >= 125000000) {
67*90f80d95SChun-Kuang Hu 		txdiv = 16;
68*90f80d95SChun-Kuang Hu 		txdiv0 = 4;
69*90f80d95SChun-Kuang Hu 	} else {
70*90f80d95SChun-Kuang Hu 		return -EINVAL;
71*90f80d95SChun-Kuang Hu 	}
72*90f80d95SChun-Kuang Hu 
73*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON4, RG_DSI_PLL_IBIAS);
74*90f80d95SChun-Kuang Hu 
75*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
76*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
77*90f80d95SChun-Kuang Hu 	udelay(1);
78*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
79*90f80d95SChun-Kuang Hu 	pcw = div_u64(((u64)mipi_tx->data_rate * txdiv) << 24, 26000000);
80*90f80d95SChun-Kuang Hu 	writel(pcw, mipi_tx->regs + MIPITX_PLL_CON0);
81*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV,
82*90f80d95SChun-Kuang Hu 				txdiv0 << 8);
83*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
84*90f80d95SChun-Kuang Hu 
85*90f80d95SChun-Kuang Hu 	return 0;
86*90f80d95SChun-Kuang Hu }
87*90f80d95SChun-Kuang Hu 
88*90f80d95SChun-Kuang Hu static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
89*90f80d95SChun-Kuang Hu {
90*90f80d95SChun-Kuang Hu 	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
91*90f80d95SChun-Kuang Hu 
92*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
93*90f80d95SChun-Kuang Hu 
94*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
95*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
96*90f80d95SChun-Kuang Hu }
97*90f80d95SChun-Kuang Hu 
98*90f80d95SChun-Kuang Hu static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
99*90f80d95SChun-Kuang Hu 				       unsigned long *prate)
100*90f80d95SChun-Kuang Hu {
101*90f80d95SChun-Kuang Hu 	return clamp_val(rate, 50000000, 1600000000);
102*90f80d95SChun-Kuang Hu }
103*90f80d95SChun-Kuang Hu 
104*90f80d95SChun-Kuang Hu static const struct clk_ops mtk_mipi_tx_pll_ops = {
105*90f80d95SChun-Kuang Hu 	.enable = mtk_mipi_tx_pll_enable,
106*90f80d95SChun-Kuang Hu 	.disable = mtk_mipi_tx_pll_disable,
107*90f80d95SChun-Kuang Hu 	.round_rate = mtk_mipi_tx_pll_round_rate,
108*90f80d95SChun-Kuang Hu 	.set_rate = mtk_mipi_tx_pll_set_rate,
109*90f80d95SChun-Kuang Hu 	.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
110*90f80d95SChun-Kuang Hu };
111*90f80d95SChun-Kuang Hu 
112*90f80d95SChun-Kuang Hu static void mtk_mipi_tx_config_calibration_data(struct mtk_mipi_tx *mipi_tx)
113*90f80d95SChun-Kuang Hu {
114*90f80d95SChun-Kuang Hu 	int i, j;
115*90f80d95SChun-Kuang Hu 
116*90f80d95SChun-Kuang Hu 	for (i = 0; i < 5; i++) {
117*90f80d95SChun-Kuang Hu 		if ((mipi_tx->rt_code[i] & 0x1f) == 0)
118*90f80d95SChun-Kuang Hu 			mipi_tx->rt_code[i] |= 0x10;
119*90f80d95SChun-Kuang Hu 
120*90f80d95SChun-Kuang Hu 		if ((mipi_tx->rt_code[i] >> 5 & 0x1f) == 0)
121*90f80d95SChun-Kuang Hu 			mipi_tx->rt_code[i] |= 0x10 << 5;
122*90f80d95SChun-Kuang Hu 
123*90f80d95SChun-Kuang Hu 		for (j = 0; j < 10; j++)
124*90f80d95SChun-Kuang Hu 			mtk_mipi_tx_update_bits(mipi_tx,
125*90f80d95SChun-Kuang Hu 				MIPITX_D2P_RTCODE * (i + 1) + j * 4,
126*90f80d95SChun-Kuang Hu 				1, mipi_tx->rt_code[i] >> j & 1);
127*90f80d95SChun-Kuang Hu 	}
128*90f80d95SChun-Kuang Hu }
129*90f80d95SChun-Kuang Hu 
130*90f80d95SChun-Kuang Hu static void mtk_mipi_tx_power_on_signal(struct phy *phy)
131*90f80d95SChun-Kuang Hu {
132*90f80d95SChun-Kuang Hu 	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
133*90f80d95SChun-Kuang Hu 
134*90f80d95SChun-Kuang Hu 	/* BG_LPF_EN / BG_CORE_EN */
135*90f80d95SChun-Kuang Hu 	writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
136*90f80d95SChun-Kuang Hu 	       mipi_tx->regs + MIPITX_LANE_CON);
137*90f80d95SChun-Kuang Hu 	usleep_range(30, 100);
138*90f80d95SChun-Kuang Hu 	writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN,
139*90f80d95SChun-Kuang Hu 	       mipi_tx->regs + MIPITX_LANE_CON);
140*90f80d95SChun-Kuang Hu 
141*90f80d95SChun-Kuang Hu 	/* Switch OFF each Lane */
142*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
143*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
144*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
145*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
146*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
147*90f80d95SChun-Kuang Hu 
148*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL,
149*90f80d95SChun-Kuang Hu 				RG_DSI_HSTX_LDO_REF_SEL,
150*90f80d95SChun-Kuang Hu 				(mipi_tx->mipitx_drive - 3000) / 200 << 6);
151*90f80d95SChun-Kuang Hu 
152*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_config_calibration_data(mipi_tx);
153*90f80d95SChun-Kuang Hu 
154*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
155*90f80d95SChun-Kuang Hu }
156*90f80d95SChun-Kuang Hu 
157*90f80d95SChun-Kuang Hu static void mtk_mipi_tx_power_off_signal(struct phy *phy)
158*90f80d95SChun-Kuang Hu {
159*90f80d95SChun-Kuang Hu 	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
160*90f80d95SChun-Kuang Hu 
161*90f80d95SChun-Kuang Hu 	/* Switch ON each Lane */
162*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
163*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
164*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
165*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
166*90f80d95SChun-Kuang Hu 	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
167*90f80d95SChun-Kuang Hu 
168*90f80d95SChun-Kuang Hu 	writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
169*90f80d95SChun-Kuang Hu 	       mipi_tx->regs + MIPITX_LANE_CON);
170*90f80d95SChun-Kuang Hu 	writel(RG_DSI_PAD_TIEL_SEL, mipi_tx->regs + MIPITX_LANE_CON);
171*90f80d95SChun-Kuang Hu }
172*90f80d95SChun-Kuang Hu 
173*90f80d95SChun-Kuang Hu const struct mtk_mipitx_data mt8183_mipitx_data = {
174*90f80d95SChun-Kuang Hu 	.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
175*90f80d95SChun-Kuang Hu 	.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
176*90f80d95SChun-Kuang Hu 	.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
177*90f80d95SChun-Kuang Hu };
178