blob: 3bb1a254ffb5d2bf3eda1aa88d513648242ea7de [file] [log] [blame]
Jagan Teki921e6b42024-01-17 13:21:48 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Rockchip Innosilicon HDMI PHY
4 *
5 * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
6 * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
7 */
8
9#include <clk-uclass.h>
10#include <dm.h>
11#include <div64.h>
12#include <dm/device_compat.h>
13#include <dm/device-internal.h>
14#include <dm/lists.h>
15#include <generic-phy.h>
16#include <asm/io.h>
17#include <linux/delay.h>
18#include <linux/iopoll.h>
19
20#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
21
22/* REG: 0x01 */
23#define RK3328_BYPASS_RXSENSE_EN BIT(2)
24#define RK3328_BYPASS_POWERON_EN BIT(1)
25#define RK3328_BYPASS_PLLPD_EN BIT(0)
26/* REG: 0x02 */
27#define RK3328_INT_POL_HIGH BIT(7)
28#define RK3328_BYPASS_PDATA_EN BIT(4)
29#define RK3328_PDATA_EN BIT(0)
30/* REG:0x05 */
31#define RK3328_INT_TMDS_CLK(x) UPDATE(x, 7, 4)
32#define RK3328_INT_TMDS_D2(x) UPDATE(x, 3, 0)
33/* REG:0x07 */
34#define RK3328_INT_TMDS_D1(x) UPDATE(x, 7, 4)
35#define RK3328_INT_TMDS_D0(x) UPDATE(x, 3, 0)
36/* for all RK3328_INT_TMDS_*, ESD_DET as defined in 0xc8-0xcb */
37#define RK3328_INT_AGND_LOW_PULSE_LOCKED BIT(3)
38#define RK3328_INT_RXSENSE_LOW_PULSE_LOCKED BIT(2)
39#define RK3328_INT_VSS_AGND_ESD_DET BIT(1)
40#define RK3328_INT_AGND_VSS_ESD_DET BIT(0)
41/* REG: 0xa0 */
42#define RK3328_PCLK_VCO_DIV_5_MASK BIT(1)
43#define RK3328_PCLK_VCO_DIV_5(x) UPDATE(x, 1, 1)
44#define RK3328_PRE_PLL_POWER_DOWN BIT(0)
45/* REG: 0xa1 */
46#define RK3328_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0)
47#define RK3328_PRE_PLL_PRE_DIV(x) UPDATE(x, 5, 0)
48/* REG: 0xa2 */
49/* unset means center spread */
50#define RK3328_SPREAD_SPECTRUM_MOD_DOWN BIT(7)
51#define RK3328_SPREAD_SPECTRUM_MOD_DISABLE BIT(6)
52#define RK3328_PRE_PLL_FRAC_DIV_DISABLE UPDATE(3, 5, 4)
53#define RK3328_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0)
54#define RK3328_PRE_PLL_FB_DIV_11_8(x) UPDATE((x) >> 8, 3, 0)
55/* REG: 0xa3 */
56#define RK3328_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
57/* REG: 0xa4*/
58#define RK3328_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(1, 0)
59#define RK3328_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 1, 0)
60#define RK3328_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(3, 2)
61#define RK3328_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 3, 2)
62#define RK3328_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(5, 4)
63#define RK3328_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 5, 4)
64/* REG: 0xa5 */
65#define RK3328_PRE_PLL_PCLK_DIV_B_SHIFT 5
66#define RK3328_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5)
67#define RK3328_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5)
68#define RK3328_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0)
69#define RK3328_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0)
70/* REG: 0xa6 */
71#define RK3328_PRE_PLL_PCLK_DIV_C_SHIFT 5
72#define RK3328_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5)
73#define RK3328_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5)
74#define RK3328_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0)
75#define RK3328_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0)
76/* REG: 0xa9 */
77#define RK3328_PRE_PLL_LOCK_STATUS BIT(0)
78/* REG: 0xaa */
79#define RK3328_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2)
80#define RK3328_POST_PLL_REFCLK_SEL_TMDS BIT(1)
81#define RK3328_POST_PLL_POWER_DOWN BIT(0)
82/* REG:0xab */
83#define RK3328_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7)
84#define RK3328_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
85/* REG: 0xac */
86#define RK3328_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
87/* REG: 0xad */
88#define RK3328_POST_PLL_POST_DIV_MASK GENMASK(1, 0)
89#define RK3328_POST_PLL_POST_DIV_2 0x0
90#define RK3328_POST_PLL_POST_DIV_4 0x1
91#define RK3328_POST_PLL_POST_DIV_8 0x3
92/* REG: 0xaf */
93#define RK3328_POST_PLL_LOCK_STATUS BIT(0)
94/* REG: 0xb0 */
95#define RK3328_BANDGAP_ENABLE BIT(2)
96/* REG: 0xb2 */
97#define RK3328_TMDS_CLK_DRIVER_EN BIT(3)
98#define RK3328_TMDS_D2_DRIVER_EN BIT(2)
99#define RK3328_TMDS_D1_DRIVER_EN BIT(1)
100#define RK3328_TMDS_D0_DRIVER_EN BIT(0)
101#define RK3328_TMDS_DRIVER_ENABLE (RK3328_TMDS_CLK_DRIVER_EN | \
102 RK3328_TMDS_D2_DRIVER_EN | \
103 RK3328_TMDS_D1_DRIVER_EN | \
104 RK3328_TMDS_D0_DRIVER_EN)
105/* REG:0xc5 */
106#define RK3328_BYPASS_TERM_RESISTOR_CALIB BIT(7)
107#define RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(x) UPDATE((x) >> 8, 6, 0)
108/* REG:0xc6 */
109#define RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(x) UPDATE(x, 7, 0)
110/* REG:0xc7 */
111#define RK3328_TERM_RESISTOR_50 UPDATE(0, 2, 1)
112#define RK3328_TERM_RESISTOR_62_5 UPDATE(1, 2, 1)
113#define RK3328_TERM_RESISTOR_75 UPDATE(2, 2, 1)
114#define RK3328_TERM_RESISTOR_100 UPDATE(3, 2, 1)
115/* REG 0xc8 - 0xcb */
116#define RK3328_ESD_DETECT_MASK GENMASK(7, 6)
117#define RK3328_ESD_DETECT_340MV (0x0 << 6)
118#define RK3328_ESD_DETECT_280MV (0x1 << 6)
119#define RK3328_ESD_DETECT_260MV (0x2 << 6)
120#define RK3328_ESD_DETECT_240MV (0x3 << 6)
121/* resistors can be used in parallel */
122#define RK3328_TMDS_TERM_RESIST_MASK GENMASK(5, 0)
123#define RK3328_TMDS_TERM_RESIST_75 BIT(5)
124#define RK3328_TMDS_TERM_RESIST_150 BIT(4)
125#define RK3328_TMDS_TERM_RESIST_300 BIT(3)
126#define RK3328_TMDS_TERM_RESIST_600 BIT(2)
127#define RK3328_TMDS_TERM_RESIST_1000 BIT(1)
128#define RK3328_TMDS_TERM_RESIST_2000 BIT(0)
129/* REG: 0xd1 */
130#define RK3328_PRE_PLL_FRAC_DIV_23_16(x) UPDATE((x) >> 16, 7, 0)
131/* REG: 0xd2 */
132#define RK3328_PRE_PLL_FRAC_DIV_15_8(x) UPDATE((x) >> 8, 7, 0)
133/* REG: 0xd3 */
134#define RK3328_PRE_PLL_FRAC_DIV_7_0(x) UPDATE(x, 7, 0)
135
136struct phy_config {
137 unsigned long tmdsclock;
138 u8 regs[14];
139};
140
141struct pre_pll_config {
142 unsigned long pixclock;
143 unsigned long tmdsclock;
144 u8 prediv;
145 u16 fbdiv;
146 u8 tmds_div_a;
147 u8 tmds_div_b;
148 u8 tmds_div_c;
149 u8 pclk_div_a;
150 u8 pclk_div_b;
151 u8 pclk_div_c;
152 u8 pclk_div_d;
153 u8 vco_div_5_en;
154 u32 fracdiv;
155};
156
157struct post_pll_config {
158 unsigned long tmdsclock;
159 u8 prediv;
160 u16 fbdiv;
161 u8 postdiv;
162 u8 version;
163};
164
165struct inno_hdmi_phy_plat_ops {
166 void (*init)(struct phy *phy);
167 int (*power_on)(struct phy *phy, const struct post_pll_config *cfg,
168 const struct phy_config *phy_cfg);
169 void (*power_off)(struct phy *phy);
170 void (*clk_enable)(struct phy *phy);
171 void (*clk_disable)(struct phy *phy);
172 unsigned long (*clk_recalc_rate)(struct phy *phy,
173 unsigned long parent_rate);
174 long (*clk_round_rate)(struct phy *phy, unsigned long rate);
175 int (*clk_set_rate)(struct phy *phy, unsigned long rate,
176 unsigned long parent_rate);
177};
178
179enum inno_hdmi_phy_type {
180 INNO_HDMI_PHY_RK3328,
181};
182
183struct inno_hdmi_phy_data {
184 enum inno_hdmi_phy_type phy_type;
185 const struct inno_hdmi_phy_plat_ops *plat_ops;
186 const struct phy_config *phy_cfg_table;
187};
188
189struct inno_hdmi_phy {
190 struct udevice *dev;
191 ofnode node;
192 void *regs;
193
194 struct clk refoclk;
195 struct clk sysclk;
196 unsigned long tmdsclock;
197 unsigned long pixclock;
198 u32 bus_width;
199 struct phy_config *phy_cfg;
200 const struct inno_hdmi_phy_data *data;
201};
202
203static const struct pre_pll_config pre_pll_cfg_table[] = {
204 { 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000},
205 { 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f},
206 { 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
207 { 27000000, 33750000, 1, 45, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
208 { 31500000, 31500000, 1, 42, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
209 { 31500000, 39375000, 1, 105, 1, 3, 3, 10, 0, 3, 4, 0, 0x0},
210 { 33750000, 33750000, 1, 45, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
211 { 33750000, 42187500, 1, 169, 2, 3, 3, 15, 0, 3, 4, 0, 0x0},
212 { 35500000, 35500000, 1, 71, 2, 2, 2, 6, 0, 3, 4, 0, 0x0},
213 { 35500000, 44375000, 1, 74, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
214 { 36000000, 36000000, 1, 36, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
215 { 36000000, 45000000, 1, 45, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
216 { 40000000, 40000000, 1, 40, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
217 { 40000000, 50000000, 1, 50, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
218 { 49500000, 49500000, 1, 66, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
219 { 49500000, 61875000, 1, 165, 1, 3, 3, 10, 0, 3, 4, 0, 0x0},
220 { 50000000, 50000000, 1, 50, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
221 { 50000000, 62500000, 1, 125, 2, 2, 2, 15, 0, 2, 2, 0, 0x0},
222 { 54000000, 54000000, 1, 36, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
223 { 54000000, 67500000, 1, 45, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
224 { 56250000, 56250000, 1, 75, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
225 { 56250000, 70312500, 1, 117, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
226 { 59341000, 59341000, 1, 118, 2, 2, 2, 6, 0, 3, 4, 0, 0xae978d},
227 { 59341000, 74176250, 2, 148, 2, 1, 1, 15, 0, 1, 1, 0, 0x5a3d70},
228 { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0x0},
229 { 59400000, 74250000, 1, 99, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
230 { 65000000, 65000000, 1, 65, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
231 { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
232 { 68250000, 68250000, 1, 91, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
233 { 68250000, 85312500, 1, 142, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
234 { 71000000, 71000000, 1, 71, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
235 { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
236 { 72000000, 72000000, 1, 36, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
237 { 72000000, 90000000, 1, 60, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
238 { 73250000, 73250000, 3, 293, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
239 { 73250000, 91562500, 1, 61, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
240 { 74176000, 74176000, 1, 37, 2, 0, 0, 1, 1, 2, 2, 0, 0x16872b},
241 { 74176000, 92720000, 2, 185, 2, 1, 1, 15, 0, 1, 1, 0, 0x70a3d7},
242 { 74250000, 74250000, 1, 99, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
243 { 74250000, 92812500, 4, 495, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
244 { 75000000, 75000000, 1, 50, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
245 { 75000000, 93750000, 1, 125, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
246 { 78750000, 78750000, 1, 105, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
247 { 78750000, 98437500, 1, 164, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
248 { 79500000, 79500000, 1, 53, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
249 { 79500000, 99375000, 1, 199, 2, 2, 2, 15, 0, 2, 2, 0, 0x0},
250 { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
251 { 83500000, 104375000, 1, 104, 2, 1, 1, 15, 0, 1, 1, 0, 0x600000},
252 { 85500000, 85500000, 1, 57, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
253 { 85500000, 106875000, 1, 178, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
254 { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
255 { 85750000, 107187500, 1, 143, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
256 { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
257 { 88750000, 110937500, 1, 110, 2, 1, 1, 15, 0, 1, 1, 0, 0xf00000},
258 { 94500000, 94500000, 1, 63, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
259 { 94500000, 118125000, 1, 197, 3, 1, 1, 25, 0, 1, 1, 0, 0x0},
260 {101000000, 101000000, 1, 101, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
261 {101000000, 126250000, 1, 42, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
262 {102250000, 102250000, 4, 409, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
263 {102250000, 127812500, 1, 128, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
264 {106500000, 106500000, 1, 71, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
265 {106500000, 133125000, 1, 133, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
266 {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
267 {108000000, 135000000, 1, 45, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
268 {115500000, 115500000, 1, 77, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
269 {115500000, 144375000, 1, 48, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
270 {117500000, 117500000, 2, 235, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
271 {117500000, 146875000, 1, 49, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
272 {119000000, 119000000, 1, 119, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
273 {119000000, 148750000, 3, 148, 0, 1, 1, 1, 3, 1, 1, 0, 0xc00000},
274 {121750000, 121750000, 4, 487, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
275 {121750000, 152187500, 1, 203, 0, 3, 3, 1, 3, 3, 4, 0, 0x0},
276 {122500000, 122500000, 2, 245, 2, 1, 1, 1, 1, 3, 4, 0, 0x0},
277 {122500000, 153125000, 1, 51, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
278 {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
279 {135000000, 168750000, 1, 169, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
280 {136750000, 136750000, 1, 68, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000},
281 {136750000, 170937500, 1, 113, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f},
282 {140250000, 140250000, 2, 187, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
283 {140250000, 175312500, 1, 117, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
284 {146250000, 146250000, 2, 195, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
285 {146250000, 182812500, 1, 61, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
286 {148250000, 148250000, 3, 222, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000},
287 {148250000, 185312500, 1, 123, 0, 2, 2, 1, 3, 2, 2, 0, 0x8aaab0},
288 {148352000, 148352000, 2, 148, 2, 0, 0, 1, 1, 2, 2, 0, 0x5a1cac},
289 {148352000, 185440000, 3, 185, 0, 1, 1, 1, 3, 1, 1, 0, 0x70a3d7},
290 {148500000, 148500000, 1, 99, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
291 {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
292 {154000000, 154000000, 1, 77, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
293 {154000000, 192500000, 1, 64, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
294 {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
295 {156000000, 195000000, 1, 65, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
296 {156750000, 156750000, 2, 209, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
297 {156750000, 195937500, 1, 196, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
298 {157000000, 157000000, 2, 157, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
299 {157000000, 196250000, 1, 131, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
300 {157500000, 157500000, 1, 105, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
301 {157500000, 196875000, 1, 197, 2, 1, 1, 15, 0, 1, 1, 0, 0x0},
302 {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
303 {162000000, 202500000, 2, 135, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
304 {175500000, 175500000, 1, 117, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
305 {175500000, 219375000, 1, 73, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
306 {179500000, 179500000, 3, 359, 0, 2, 2, 1, 0, 3, 4, 0, 0x0},
307 {179500000, 224375000, 1, 75, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
308 {182750000, 182750000, 1, 91, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000},
309 {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0},
310 {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0},
311 {187000000, 187000000, 2, 187, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
312 {187000000, 233750000, 1, 39, 0, 0, 0, 1, 3, 0, 0, 1, 0x0},
313 {187250000, 187250000, 3, 280, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000},
314 {187250000, 234062500, 1, 156, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0},
315 {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
316 {189000000, 236250000, 1, 79, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
317 {193250000, 193250000, 3, 289, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000},
318 {193250000, 241562500, 1, 161, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0},
319 {202500000, 202500000, 2, 135, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
320 {202500000, 253125000, 1, 169, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
321 {204750000, 204750000, 4, 273, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
322 {204750000, 255937500, 1, 171, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
323 {208000000, 208000000, 1, 104, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
324 {208000000, 260000000, 1, 173, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
325 {214750000, 214750000, 1, 107, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000},
326 {214750000, 268437500, 1, 178, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f},
327 {218250000, 218250000, 4, 291, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
328 {218250000, 272812500, 1, 91, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
329 {229500000, 229500000, 2, 153, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
330 {229500000, 286875000, 1, 191, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
331 {234000000, 234000000, 1, 39, 0, 0, 0, 1, 0, 1, 1, 0, 0x0},
332 {234000000, 292500000, 1, 195, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
333 {241500000, 241500000, 2, 161, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
334 {241500000, 301875000, 1, 201, 0, 2, 2, 1, 3, 2, 2, 0, 0x0},
335 {245250000, 245250000, 4, 327, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
336 {245250000, 306562500, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0},
337 {245500000, 245500000, 4, 491, 2, 0, 0, 1, 1, 2, 2, 0, 0x0},
338 {245500000, 306875000, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0},
339 {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
340 {261000000, 326250000, 1, 109, 0, 1, 1, 1, 3, 1, 1, 0, 0x0},
341 {268250000, 268250000, 9, 402, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000},
342 {268250000, 335312500, 1, 111, 0, 1, 1, 1, 3, 1, 1, 0, 0xc5554f},
343 {268500000, 268500000, 2, 179, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
344 {268500000, 335625000, 1, 56, 0, 0, 0, 1, 3, 0, 0, 1, 0x0},
345 {281250000, 281250000, 4, 375, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
346 {281250000, 351562500, 1, 117, 0, 3, 1, 1, 3, 1, 1, 0, 0x0},
347 {288000000, 288000000, 1, 48, 0, 0, 0, 1, 0, 1, 1, 0, 0x0},
348 {288000000, 360000000, 1, 60, 0, 2, 0, 1, 3, 0, 0, 1, 0x0},
349 {296703000, 296703000, 1, 49, 0, 0, 0, 1, 0, 1, 1, 0, 0x7353f7},
350 {296703000, 370878750, 1, 123, 0, 3, 1, 1, 3, 1, 1, 0, 0xa051eb},
351 {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
352 {297000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 1, 1, 0, 0x0},
353 {312250000, 312250000, 9, 468, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000},
354 {312250000, 390312500, 1, 130, 0, 3, 1, 1, 3, 1, 1, 0, 0x1aaab0},
355 {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0x0},
356 {317000000, 396250000, 1, 66, 0, 2, 0, 1, 3, 0, 0, 1, 0x0},
357 {319750000, 319750000, 3, 159, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000},
358 {319750000, 399687500, 3, 199, 0, 2, 0, 1, 3, 0, 0, 1, 0xd80000},
359 {333250000, 333250000, 9, 499, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000},
360 {333250000, 416562500, 1, 138, 0, 3, 1, 1, 3, 1, 1, 0, 0xdaaab0},
361 {348500000, 348500000, 9, 522, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000},
362 {348500000, 435625000, 1, 145, 0, 3, 1, 1, 3, 1, 1, 0, 0x35554f},
363 {356500000, 356500000, 9, 534, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000},
364 {356500000, 445625000, 1, 148, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0},
365 {380500000, 380500000, 9, 570, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000},
366 {380500000, 475625000, 1, 158, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0},
367 {443250000, 443250000, 1, 73, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000},
368 {443250000, 554062500, 1, 92, 0, 2, 0, 1, 3, 0, 0, 1, 0x580000},
369 {505250000, 505250000, 9, 757, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000},
370 {552750000, 552750000, 3, 276, 0, 2, 0, 1, 0, 1, 1, 0, 0x600000},
371 {593407000, 296703500, 3, 296, 0, 1, 1, 1, 0, 1, 1, 0, 0xb41893},
372 {593407000, 370879375, 4, 494, 0, 3, 1, 1, 3, 0, 0, 1, 0x817e4a},
373 {593407000, 593407000, 3, 296, 0, 2, 0, 1, 0, 1, 1, 0, 0xb41893},
374 {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0},
375 {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0},
376 {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0},
377 { /* sentinel */ }
378};
379
380static const struct post_pll_config post_pll_cfg_table[] = {
381 {33750000, 1, 40, 8, 1},
382 {33750000, 1, 80, 8, 2},
383 {74250000, 1, 40, 8, 1},
384 {74250000, 18, 80, 8, 2},
385 {148500000, 2, 40, 4, 3},
386 {297000000, 4, 40, 2, 3},
387 {594000000, 8, 40, 1, 3},
388 { /* sentinel */ }
389};
390
391/* phy tuning values for an undocumented set of registers */
392static const struct phy_config rk3328_phy_cfg[] = {
393 { 165000000, {
394 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
395 0x00, 0xac, 0xcc, 0xcc, 0xcc,
396 },
397 }, {
398 340000000, {
399 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
400 0x3f, 0xac, 0xcc, 0xcd, 0xdd,
401 },
402 }, {
403 594000000, {
404 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
405 0x00, 0xac, 0xcc, 0xcc, 0xcc,
406 },
407 }, { /* sentinel */ },
408};
409
410static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
411{
412 writel(val, inno->regs + (reg * 4));
413}
414
415static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
416{
417 u32 val;
418
419 val = readl(inno->regs + (reg * 4));
420
421 return val;
422}
423
424static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
425 u8 mask, u8 val)
426{
427 u32 tmp, orig;
428
429 orig = inno_read(inno, reg);
430 tmp = orig & ~mask;
431 tmp |= val & mask;
432 inno_write(inno, reg, tmp);
433}
434
435#define inno_poll(reg, val, cond, sleep_us, timeout_us) \
436 readl_poll_sleep_timeout((reg) * 4, val, cond, sleep_us, timeout_us)
437
438static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
439 unsigned long rate)
440{
441 int bus_width = inno->bus_width;
442
443 switch (bus_width) {
444 case 4:
445 case 5:
446 case 6:
447 case 10:
448 case 12:
449 case 16:
450 return (u64)rate * bus_width / 8;
451 default:
452 return rate;
453 }
454}
455
456static
457unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct phy *phy,
458 unsigned long parent_rate)
459{
460 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
461 unsigned long frac;
462 u8 nd, no_a, no_b, no_d;
463 u64 vco;
464 u16 nf;
465
466 nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
467 nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
468 nf |= inno_read(inno, 0xa3);
469 vco = parent_rate * nf;
470
471 if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
472 frac = inno_read(inno, 0xd3) |
473 (inno_read(inno, 0xd2) << 8) |
474 (inno_read(inno, 0xd1) << 16);
475 vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
476 }
477
478 if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
479 do_div(vco, nd * 5);
480 } else {
481 no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
482 no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
483 no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
484 no_b += 2;
485 no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
486
487 do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
488 }
489
490 inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
491
492 dev_info(phy->dev, "rate %lu vco %llu\n", inno->pixclock, vco);
493
494 return inno->pixclock;
495}
496
497static long inno_hdmi_phy_rk3328_clk_round_rate(struct phy *phy,
498 unsigned long rate)
499{
500 const struct pre_pll_config *cfg = pre_pll_cfg_table;
501
502 rate = (rate / 1000) * 1000;
503
504 for (; cfg->pixclock != 0; cfg++)
505 if (cfg->pixclock == rate)
506 break;
507
508 if (cfg->pixclock == 0)
509 return -EINVAL;
510
511 return cfg->pixclock;
512}
513
514static const
515struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
516 unsigned long rate)
517{
518 const struct pre_pll_config *cfg = pre_pll_cfg_table;
519 unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
520
521 for (; cfg->pixclock != 0; cfg++)
522 if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
523 break;
524
525 if (cfg->pixclock == 0)
526 return ERR_PTR(-EINVAL);
527
528 return cfg;
529}
530
531static int
532inno_hdmi_phy_rk3328_clk_set_rate(struct phy *phy,
533 unsigned long rate,
534 unsigned long parent_rate)
535{
536 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
537 unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
538 const struct pre_pll_config *cfg;
539 u32 val;
540 int ret;
541
542 dev_info(phy->dev, "rate %lu tmdsclk %lu\n", rate, tmdsclock);
543
544 if (inno->pixclock == rate && inno->tmdsclock == tmdsclock)
545 return 0;
546
547 cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate);
548 if (IS_ERR(cfg))
549 return PTR_ERR(cfg);
550
551 inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
552 RK3328_PRE_PLL_POWER_DOWN);
553
554 /* Configure pre-pll */
555 inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
556 RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
557 inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
558
559 val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
560 if (!cfg->fracdiv)
561 val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
562 inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
563 inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
564 inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
565 RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
566 inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
567 RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
568 inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
569 RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
570 RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
571 inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
572 inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
573 inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
574
575 inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
576
577 /* Wait for Pre-PLL lock */
578 ret = inno_poll(0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
579 1000, 10000);
580 if (ret) {
581 dev_err(phy->dev, "Pre-PLL locking failed\n");
582 return ret;
583 }
584
585 inno->pixclock = rate;
586 inno->tmdsclock = tmdsclock;
587
588 return 0;
589}
590
591static void inno_hdmi_phy_rk3328_clk_enable(struct phy *phy)
592{
593 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
594
595 inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
596}
597
598static void inno_hdmi_phy_rk3328_clk_disable(struct phy *phy)
599{
600 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
601
602 inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
603 RK3328_PRE_PLL_POWER_DOWN);
604}
605
606static int
607inno_hdmi_phy_rk3328_power_on(struct phy *phy,
608 const struct post_pll_config *cfg,
609 const struct phy_config *phy_cfg)
610{
611 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
612 int ret;
613 u32 v;
614
615 inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0);
616 inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN,
617 RK3328_POST_PLL_POWER_DOWN);
618
619 inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv));
620 if (cfg->postdiv == 1) {
621 inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
622 RK3328_POST_PLL_PRE_DIV(cfg->prediv));
623 inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS |
624 RK3328_POST_PLL_POWER_DOWN);
625 } else {
626 v = (cfg->postdiv / 2) - 1;
627 v &= RK3328_POST_PLL_POST_DIV_MASK;
628 inno_write(inno, 0xad, v);
629 inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
630 RK3328_POST_PLL_PRE_DIV(cfg->prediv));
631 inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE |
632 RK3328_POST_PLL_REFCLK_SEL_TMDS |
633 RK3328_POST_PLL_POWER_DOWN);
634 }
635
636 for (v = 0; v < 14; v++)
637 inno_write(inno, 0xb5 + v, phy_cfg->regs[v]);
638
639 /* set ESD detection threshold for TMDS CLK, D2, D1 and D0 */
640 for (v = 0; v < 4; v++)
641 inno_update_bits(inno, 0xc8 + v, RK3328_ESD_DETECT_MASK,
642 RK3328_ESD_DETECT_340MV);
643
644 if (phy_cfg->tmdsclock > 340000000) {
645 /* Set termination resistor to 100ohm */
646 v = clk_get_rate(&inno->sysclk) / 100000;
647 inno_write(inno, 0xc5, RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(v)
648 | RK3328_BYPASS_TERM_RESISTOR_CALIB);
649 inno_write(inno, 0xc6, RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(v));
650 inno_write(inno, 0xc7, RK3328_TERM_RESISTOR_100);
651 inno_update_bits(inno, 0xc5,
652 RK3328_BYPASS_TERM_RESISTOR_CALIB, 0);
653 } else {
654 inno_write(inno, 0xc5, RK3328_BYPASS_TERM_RESISTOR_CALIB);
655
656 /* clk termination resistor is 50ohm (parallel resistors) */
657 if (phy_cfg->tmdsclock > 165000000)
658 inno_update_bits(inno, 0xc8,
659 RK3328_TMDS_TERM_RESIST_MASK,
660 RK3328_TMDS_TERM_RESIST_75 |
661 RK3328_TMDS_TERM_RESIST_150);
662
663 /* data termination resistor for D2, D1 and D0 is 150ohm */
664 for (v = 0; v < 3; v++)
665 inno_update_bits(inno, 0xc9 + v,
666 RK3328_TMDS_TERM_RESIST_MASK,
667 RK3328_TMDS_TERM_RESIST_150);
668 }
669
670 inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN, 0);
671 inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE,
672 RK3328_BANDGAP_ENABLE);
673 inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE,
674 RK3328_TMDS_DRIVER_ENABLE);
675
676 /* Wait for post PLL lock */
677 ret = inno_poll(0xaf, v, v & RK3328_POST_PLL_LOCK_STATUS,
678 1000, 10000);
679 if (ret) {
680 dev_err(phy->dev, "Post-PLL locking failed\n");
681 return ret;
682 }
683
684 if (phy_cfg->tmdsclock > 340000000)
685 mdelay(100);
686
687 inno_update_bits(inno, 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN);
688
689 /* Enable PHY IRQ */
690 inno_write(inno, 0x05, RK3328_INT_TMDS_CLK(RK3328_INT_VSS_AGND_ESD_DET)
691 | RK3328_INT_TMDS_D2(RK3328_INT_VSS_AGND_ESD_DET));
692 inno_write(inno, 0x07, RK3328_INT_TMDS_D1(RK3328_INT_VSS_AGND_ESD_DET)
693 | RK3328_INT_TMDS_D0(RK3328_INT_VSS_AGND_ESD_DET));
694
695 return 0;
696}
697
698static void inno_hdmi_phy_rk3328_power_off(struct phy *phy)
699{
700 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
701
702 inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE, 0);
703 inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE, 0);
704 inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN,
705 RK3328_POST_PLL_POWER_DOWN);
706
707 /* Disable PHY IRQ */
708 inno_write(inno, 0x05, 0);
709 inno_write(inno, 0x07, 0);
710}
711
712static void inno_hdmi_phy_rk3328_init(struct phy *phy)
713{
714 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
715 const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
716
717 /*
718 * Use phy internal register control
719 * rxsense/poweron/pllpd/pdataen signal.
720 */
721 inno_write(inno, 0x01, RK3328_BYPASS_RXSENSE_EN |
722 RK3328_BYPASS_POWERON_EN |
723 RK3328_BYPASS_PLLPD_EN);
724 inno_write(inno, 0x02, RK3328_INT_POL_HIGH | RK3328_BYPASS_PDATA_EN |
725 RK3328_PDATA_EN);
726
727 /* Disable phy irq */
728 inno_write(inno, 0x05, 0);
729 inno_write(inno, 0x07, 0);
730
731 if (plat_ops->clk_recalc_rate)
732 plat_ops->clk_recalc_rate(phy, clk_get_rate(&inno->refoclk));
733
734 if (plat_ops->clk_round_rate)
735 plat_ops->clk_round_rate(phy, inno->pixclock);
736}
737
738static const struct inno_hdmi_phy_plat_ops rk3328_hdmi_phy_plat_ops = {
739 .init = inno_hdmi_phy_rk3328_init,
740 .power_on = inno_hdmi_phy_rk3328_power_on,
741 .power_off = inno_hdmi_phy_rk3328_power_off,
742 .clk_enable = inno_hdmi_phy_rk3328_clk_enable,
743 .clk_disable = inno_hdmi_phy_rk3328_clk_disable,
744 .clk_recalc_rate = inno_hdmi_phy_rk3328_clk_recalc_rate,
745 .clk_round_rate = inno_hdmi_phy_rk3328_clk_round_rate,
746 .clk_set_rate = inno_hdmi_phy_rk3328_clk_set_rate,
747};
748
749static int inno_hdmi_phy_power_on(struct phy *phy)
750{
751 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
752 const struct post_pll_config *cfg = post_pll_cfg_table;
753 const struct phy_config *phy_cfg = inno->data->phy_cfg_table;
754 u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
755 const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
756 int ret;
757
758 if (!tmdsclock) {
759 dev_err(phy->dev, "TMDS clock is zero!\n");
760 return -EINVAL;
761 }
762
763 if (!plat_ops->power_on)
764 return -EINVAL;
765
766 dev_info(phy->dev, "TMDS clock = %d\n", tmdsclock);
767
768 for (; cfg->tmdsclock != ~0UL; cfg++)
769 if (tmdsclock <= cfg->tmdsclock)
770 break;
771
772 for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
773 if (tmdsclock <= phy_cfg->tmdsclock)
774 break;
775
776 if (cfg->tmdsclock == 0 || phy_cfg->tmdsclock == 0)
777 return -EINVAL;
778
779 if (plat_ops->clk_set_rate) {
780 ret = plat_ops->clk_set_rate(phy, inno->pixclock, 24000000);
781 if (ret)
782 return ret;
783 }
784
785 if (plat_ops->clk_enable)
786 plat_ops->clk_enable(phy);
787
788 if (plat_ops->power_on) {
789 ret = plat_ops->power_on(phy, cfg, phy_cfg);
790 if (ret) {
791 if (plat_ops->clk_disable)
792 plat_ops->clk_disable(phy);
793 return ret;
794 }
795 }
796
797 return 0;
798}
799
800static int inno_hdmi_phy_power_off(struct phy *phy)
801{
802 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
803 const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
804
805 if (!plat_ops->power_off)
806 return -EINVAL;
807
808 plat_ops->power_off(phy);
809
810 if (plat_ops->clk_disable)
811 plat_ops->clk_disable(phy);
812
813 inno->tmdsclock = 0;
814
815 return 0;
816}
817
818static int inno_hdmi_phy_init(struct phy *phy)
819{
820 struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
821
822 if (inno->data->plat_ops->init)
823 inno->data->plat_ops->init(phy);
824
825 return 0;
826}
827
828static struct phy_ops inno_hdmi_phy_ops = {
829 .init = inno_hdmi_phy_init,
830 .power_on = inno_hdmi_phy_power_on,
831 .power_off = inno_hdmi_phy_power_off,
832};
833
834static int inno_hdmi_phy_probe(struct udevice *dev)
835{
836 struct inno_hdmi_phy *inno = dev_get_priv(dev);
837 int ret;
838
839 inno->regs = dev_read_addr_ptr(dev);
840 if (!inno->regs)
841 return -ENOMEM;
842
843 inno->data = (const struct inno_hdmi_phy_data *)dev_get_driver_data(dev);
844 if (!inno->data)
845 return -EINVAL;
846
847 inno->bus_width = 8;
848
849 ret = clk_get_by_name(dev, "refoclk", &inno->refoclk);
850 if (ret) {
851 dev_err(dev, "failed to get the refoclk (ret=%d)\n", ret);
852 return ret;
853 }
854
855 ret = clk_get_by_name(dev, "sysclk", &inno->sysclk);
856 if (ret) {
857 dev_err(dev, "failed to get the sysclk (ret=%d)\n", ret);
858 return ret;
859 }
860
861 return 0;
862}
863
864static const struct inno_hdmi_phy_data rk3328_inno_hdmi_phy_drv_data = {
865 .phy_type = INNO_HDMI_PHY_RK3328,
866 .plat_ops = &rk3328_hdmi_phy_plat_ops,
867 .phy_cfg_table = rk3328_phy_cfg,
868};
869
870static const struct udevice_id inno_hdmi_phy_ids[] = {
871 {
872 .compatible = "rockchip,rk3328-hdmi-phy",
873 .data = (ulong)&rk3328_inno_hdmi_phy_drv_data,
874 },
875 { /* sentile */ }
876};
877
878U_BOOT_DRIVER(inno_hdmi_phy) = {
879 .name = "inno_hdmi_phy",
880 .id = UCLASS_PHY,
881 .of_match = inno_hdmi_phy_ids,
882 .ops = &inno_hdmi_phy_ops,
883 .probe = inno_hdmi_phy_probe,
884 .priv_auto = sizeof(struct inno_hdmi_phy),
885};