1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright (c) 2017 Rockchip Electronics Co. Ltd. |
4 | * |
5 | * Author: Zheng Yang <zhengyang@rock-chips.com> |
6 | * Heiko Stuebner <heiko@sntech.de> |
7 | */ |
8 | |
9 | #include <linux/clk.h> |
10 | #include <linux/clk-provider.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/io.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/nvmem-consumer.h> |
17 | #include <linux/of.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/phy/phy.h> |
21 | #include <linux/slab.h> |
22 | |
23 | #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) |
24 | |
25 | /* REG: 0x00 */ |
26 | #define RK3228_PRE_PLL_REFCLK_SEL_PCLK BIT(0) |
27 | /* REG: 0x01 */ |
28 | #define RK3228_BYPASS_RXSENSE_EN BIT(2) |
29 | #define RK3228_BYPASS_PWRON_EN BIT(1) |
30 | #define RK3228_BYPASS_PLLPD_EN BIT(0) |
31 | /* REG: 0x02 */ |
32 | #define RK3228_BYPASS_PDATA_EN BIT(4) |
33 | #define RK3228_PDATAEN_DISABLE BIT(0) |
34 | /* REG: 0x03 */ |
35 | #define RK3228_BYPASS_AUTO_TERM_RES_CAL BIT(7) |
36 | #define RK3228_AUTO_TERM_RES_CAL_SPEED_14_8(x) UPDATE(x, 6, 0) |
37 | /* REG: 0x04 */ |
38 | #define RK3228_AUTO_TERM_RES_CAL_SPEED_7_0(x) UPDATE(x, 7, 0) |
39 | /* REG: 0xaa */ |
40 | #define RK3228_POST_PLL_CTRL_MANUAL BIT(0) |
41 | /* REG: 0xe0 */ |
42 | #define RK3228_POST_PLL_POWER_DOWN BIT(5) |
43 | #define RK3228_PRE_PLL_POWER_DOWN BIT(4) |
44 | #define RK3228_RXSENSE_CLK_CH_ENABLE BIT(3) |
45 | #define RK3228_RXSENSE_DATA_CH2_ENABLE BIT(2) |
46 | #define RK3228_RXSENSE_DATA_CH1_ENABLE BIT(1) |
47 | #define RK3228_RXSENSE_DATA_CH0_ENABLE BIT(0) |
48 | /* REG: 0xe1 */ |
49 | #define RK3228_BANDGAP_ENABLE BIT(4) |
50 | #define RK3228_TMDS_DRIVER_ENABLE GENMASK(3, 0) |
51 | /* REG: 0xe2 */ |
52 | #define RK3228_PRE_PLL_FB_DIV_8_MASK BIT(7) |
53 | #define RK3228_PRE_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) |
54 | #define RK3228_PCLK_VCO_DIV_5_MASK BIT(5) |
55 | #define RK3228_PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5) |
56 | #define RK3228_PRE_PLL_PRE_DIV_MASK GENMASK(4, 0) |
57 | #define RK3228_PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0) |
58 | /* REG: 0xe3 */ |
59 | #define RK3228_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) |
60 | /* REG: 0xe4 */ |
61 | #define RK3228_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5) |
62 | #define RK3228_PRE_PLL_PCLK_DIV_B_SHIFT 5 |
63 | #define RK3228_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5) |
64 | #define RK3228_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0) |
65 | #define RK3228_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0) |
66 | /* REG: 0xe5 */ |
67 | #define RK3228_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5) |
68 | #define RK3228_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5) |
69 | #define RK3228_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0) |
70 | #define RK3228_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0) |
71 | /* REG: 0xe6 */ |
72 | #define RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4) |
73 | #define RK3228_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4) |
74 | #define RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2) |
75 | #define RK3228_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2) |
76 | #define RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0) |
77 | #define RK3228_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0) |
78 | /* REG: 0xe8 */ |
79 | #define RK3228_PRE_PLL_LOCK_STATUS BIT(0) |
80 | /* REG: 0xe9 */ |
81 | #define RK3228_POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6) |
82 | #define RK3228_POST_PLL_PRE_DIV_MASK GENMASK(4, 0) |
83 | #define RK3228_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0) |
84 | /* REG: 0xea */ |
85 | #define RK3228_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) |
86 | /* REG: 0xeb */ |
87 | #define RK3228_POST_PLL_FB_DIV_8_MASK BIT(7) |
88 | #define RK3228_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) |
89 | #define RK3228_POST_PLL_POST_DIV_MASK GENMASK(5, 4) |
90 | #define RK3228_POST_PLL_POST_DIV(x) UPDATE(x, 5, 4) |
91 | #define RK3228_POST_PLL_LOCK_STATUS BIT(0) |
92 | /* REG: 0xee */ |
93 | #define RK3228_TMDS_CH_TA_ENABLE GENMASK(7, 4) |
94 | /* REG: 0xef */ |
95 | #define RK3228_TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6) |
96 | #define RK3228_TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4) |
97 | #define RK3228_TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2) |
98 | #define RK3228_TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0) |
99 | /* REG: 0xf0 */ |
100 | #define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4) |
101 | #define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4) |
102 | #define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2) |
103 | #define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2) |
104 | #define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0) |
105 | #define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0) |
106 | /* REG: 0xf1 */ |
107 | #define RK3228_TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4) |
108 | #define RK3228_TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0) |
109 | /* REG: 0xf2 */ |
110 | #define RK3228_TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4) |
111 | #define RK3228_TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0) |
112 | |
113 | /* REG: 0x01 */ |
114 | #define RK3328_BYPASS_RXSENSE_EN BIT(2) |
115 | #define RK3328_BYPASS_POWERON_EN BIT(1) |
116 | #define RK3328_BYPASS_PLLPD_EN BIT(0) |
117 | /* REG: 0x02 */ |
118 | #define RK3328_INT_POL_HIGH BIT(7) |
119 | #define RK3328_BYPASS_PDATA_EN BIT(4) |
120 | #define RK3328_PDATA_EN BIT(0) |
121 | /* REG:0x05 */ |
122 | #define RK3328_INT_TMDS_CLK(x) UPDATE(x, 7, 4) |
123 | #define RK3328_INT_TMDS_D2(x) UPDATE(x, 3, 0) |
124 | /* REG:0x07 */ |
125 | #define RK3328_INT_TMDS_D1(x) UPDATE(x, 7, 4) |
126 | #define RK3328_INT_TMDS_D0(x) UPDATE(x, 3, 0) |
127 | /* for all RK3328_INT_TMDS_*, ESD_DET as defined in 0xc8-0xcb */ |
128 | #define RK3328_INT_AGND_LOW_PULSE_LOCKED BIT(3) |
129 | #define RK3328_INT_RXSENSE_LOW_PULSE_LOCKED BIT(2) |
130 | #define RK3328_INT_VSS_AGND_ESD_DET BIT(1) |
131 | #define RK3328_INT_AGND_VSS_ESD_DET BIT(0) |
132 | /* REG: 0xa0 */ |
133 | #define RK3328_PCLK_VCO_DIV_5_MASK BIT(1) |
134 | #define RK3328_PCLK_VCO_DIV_5(x) UPDATE(x, 1, 1) |
135 | #define RK3328_PRE_PLL_POWER_DOWN BIT(0) |
136 | /* REG: 0xa1 */ |
137 | #define RK3328_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0) |
138 | #define RK3328_PRE_PLL_PRE_DIV(x) UPDATE(x, 5, 0) |
139 | /* REG: 0xa2 */ |
140 | /* unset means center spread */ |
141 | #define RK3328_SPREAD_SPECTRUM_MOD_DOWN BIT(7) |
142 | #define RK3328_SPREAD_SPECTRUM_MOD_DISABLE BIT(6) |
143 | #define RK3328_PRE_PLL_FRAC_DIV_DISABLE UPDATE(3, 5, 4) |
144 | #define RK3328_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0) |
145 | #define RK3328_PRE_PLL_FB_DIV_11_8(x) UPDATE((x) >> 8, 3, 0) |
146 | /* REG: 0xa3 */ |
147 | #define RK3328_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) |
148 | /* REG: 0xa4*/ |
149 | #define RK3328_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(1, 0) |
150 | #define RK3328_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 1, 0) |
151 | #define RK3328_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(3, 2) |
152 | #define RK3328_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 3, 2) |
153 | #define RK3328_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(5, 4) |
154 | #define RK3328_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 5, 4) |
155 | /* REG: 0xa5 */ |
156 | #define RK3328_PRE_PLL_PCLK_DIV_B_SHIFT 5 |
157 | #define RK3328_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5) |
158 | #define RK3328_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5) |
159 | #define RK3328_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0) |
160 | #define RK3328_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0) |
161 | /* REG: 0xa6 */ |
162 | #define RK3328_PRE_PLL_PCLK_DIV_C_SHIFT 5 |
163 | #define RK3328_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5) |
164 | #define RK3328_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5) |
165 | #define RK3328_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0) |
166 | #define RK3328_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0) |
167 | /* REG: 0xa9 */ |
168 | #define RK3328_PRE_PLL_LOCK_STATUS BIT(0) |
169 | /* REG: 0xaa */ |
170 | #define RK3328_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2) |
171 | #define RK3328_POST_PLL_REFCLK_SEL_TMDS BIT(1) |
172 | #define RK3328_POST_PLL_POWER_DOWN BIT(0) |
173 | /* REG:0xab */ |
174 | #define RK3328_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) |
175 | #define RK3328_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0) |
176 | /* REG: 0xac */ |
177 | #define RK3328_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) |
178 | /* REG: 0xad */ |
179 | #define RK3328_POST_PLL_POST_DIV_MASK GENMASK(1, 0) |
180 | #define RK3328_POST_PLL_POST_DIV_2 0x0 |
181 | #define RK3328_POST_PLL_POST_DIV_4 0x1 |
182 | #define RK3328_POST_PLL_POST_DIV_8 0x3 |
183 | /* REG: 0xaf */ |
184 | #define RK3328_POST_PLL_LOCK_STATUS BIT(0) |
185 | /* REG: 0xb0 */ |
186 | #define RK3328_BANDGAP_ENABLE BIT(2) |
187 | /* REG: 0xb2 */ |
188 | #define RK3328_TMDS_CLK_DRIVER_EN BIT(3) |
189 | #define RK3328_TMDS_D2_DRIVER_EN BIT(2) |
190 | #define RK3328_TMDS_D1_DRIVER_EN BIT(1) |
191 | #define RK3328_TMDS_D0_DRIVER_EN BIT(0) |
192 | #define RK3328_TMDS_DRIVER_ENABLE (RK3328_TMDS_CLK_DRIVER_EN | \ |
193 | RK3328_TMDS_D2_DRIVER_EN | \ |
194 | RK3328_TMDS_D1_DRIVER_EN | \ |
195 | RK3328_TMDS_D0_DRIVER_EN) |
196 | /* REG:0xc5 */ |
197 | #define RK3328_BYPASS_TERM_RESISTOR_CALIB BIT(7) |
198 | #define RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(x) UPDATE((x) >> 8, 6, 0) |
199 | /* REG:0xc6 */ |
200 | #define RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(x) UPDATE(x, 7, 0) |
201 | /* REG:0xc7 */ |
202 | #define RK3328_TERM_RESISTOR_50 UPDATE(0, 2, 1) |
203 | #define RK3328_TERM_RESISTOR_62_5 UPDATE(1, 2, 1) |
204 | #define RK3328_TERM_RESISTOR_75 UPDATE(2, 2, 1) |
205 | #define RK3328_TERM_RESISTOR_100 UPDATE(3, 2, 1) |
206 | /* REG 0xc8 - 0xcb */ |
207 | #define RK3328_ESD_DETECT_MASK GENMASK(7, 6) |
208 | #define RK3328_ESD_DETECT_340MV (0x0 << 6) |
209 | #define RK3328_ESD_DETECT_280MV (0x1 << 6) |
210 | #define RK3328_ESD_DETECT_260MV (0x2 << 6) |
211 | #define RK3328_ESD_DETECT_240MV (0x3 << 6) |
212 | /* resistors can be used in parallel */ |
213 | #define RK3328_TMDS_TERM_RESIST_MASK GENMASK(5, 0) |
214 | #define RK3328_TMDS_TERM_RESIST_75 BIT(5) |
215 | #define RK3328_TMDS_TERM_RESIST_150 BIT(4) |
216 | #define RK3328_TMDS_TERM_RESIST_300 BIT(3) |
217 | #define RK3328_TMDS_TERM_RESIST_600 BIT(2) |
218 | #define RK3328_TMDS_TERM_RESIST_1000 BIT(1) |
219 | #define RK3328_TMDS_TERM_RESIST_2000 BIT(0) |
220 | /* REG: 0xd1 */ |
221 | #define RK3328_PRE_PLL_FRAC_DIV_23_16(x) UPDATE((x) >> 16, 7, 0) |
222 | /* REG: 0xd2 */ |
223 | #define RK3328_PRE_PLL_FRAC_DIV_15_8(x) UPDATE((x) >> 8, 7, 0) |
224 | /* REG: 0xd3 */ |
225 | #define RK3328_PRE_PLL_FRAC_DIV_7_0(x) UPDATE(x, 7, 0) |
226 | |
227 | struct inno_hdmi_phy_drv_data; |
228 | |
229 | struct inno_hdmi_phy { |
230 | struct device *dev; |
231 | struct regmap *regmap; |
232 | int irq; |
233 | |
234 | struct phy *phy; |
235 | struct clk *sysclk; |
236 | struct clk *refoclk; |
237 | struct clk *refpclk; |
238 | |
239 | /* platform data */ |
240 | const struct inno_hdmi_phy_drv_data *plat_data; |
241 | int chip_version; |
242 | |
243 | /* clk provider */ |
244 | struct clk_hw hw; |
245 | struct clk *phyclk; |
246 | unsigned long pixclock; |
247 | unsigned long tmdsclock; |
248 | }; |
249 | |
250 | struct pre_pll_config { |
251 | unsigned long pixclock; |
252 | unsigned long tmdsclock; |
253 | u8 prediv; |
254 | u16 fbdiv; |
255 | u8 tmds_div_a; |
256 | u8 tmds_div_b; |
257 | u8 tmds_div_c; |
258 | u8 pclk_div_a; |
259 | u8 pclk_div_b; |
260 | u8 pclk_div_c; |
261 | u8 pclk_div_d; |
262 | u8 vco_div_5_en; |
263 | u32 fracdiv; |
264 | }; |
265 | |
266 | struct post_pll_config { |
267 | unsigned long tmdsclock; |
268 | u8 prediv; |
269 | u16 fbdiv; |
270 | u8 postdiv; |
271 | u8 version; |
272 | }; |
273 | |
274 | struct phy_config { |
275 | unsigned long tmdsclock; |
276 | u8 regs[14]; |
277 | }; |
278 | |
279 | struct inno_hdmi_phy_ops { |
280 | int (*init)(struct inno_hdmi_phy *inno); |
281 | int (*power_on)(struct inno_hdmi_phy *inno, |
282 | const struct post_pll_config *cfg, |
283 | const struct phy_config *phy_cfg); |
284 | void (*power_off)(struct inno_hdmi_phy *inno); |
285 | }; |
286 | |
287 | struct inno_hdmi_phy_drv_data { |
288 | const struct inno_hdmi_phy_ops *ops; |
289 | const struct clk_ops *clk_ops; |
290 | const struct phy_config *phy_cfg_table; |
291 | }; |
292 | |
293 | static const struct pre_pll_config pre_pll_cfg_table[] = { |
294 | { 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000}, |
295 | { 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f}, |
296 | { 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
297 | { 27000000, 33750000, 1, 45, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
298 | { 31500000, 31500000, 1, 42, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
299 | { 31500000, 39375000, 1, 105, 1, 3, 3, 10, 0, 3, 4, 0, 0x0}, |
300 | { 33750000, 33750000, 1, 45, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
301 | { 33750000, 42187500, 1, 169, 2, 3, 3, 15, 0, 3, 4, 0, 0x0}, |
302 | { 35500000, 35500000, 1, 71, 2, 2, 2, 6, 0, 3, 4, 0, 0x0}, |
303 | { 35500000, 44375000, 1, 74, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
304 | { 36000000, 36000000, 1, 36, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
305 | { 36000000, 45000000, 1, 45, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
306 | { 40000000, 40000000, 1, 40, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
307 | { 40000000, 50000000, 1, 50, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
308 | { 49500000, 49500000, 1, 66, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
309 | { 49500000, 61875000, 1, 165, 1, 3, 3, 10, 0, 3, 4, 0, 0x0}, |
310 | { 50000000, 50000000, 1, 50, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
311 | { 50000000, 62500000, 1, 125, 2, 2, 2, 15, 0, 2, 2, 0, 0x0}, |
312 | { 54000000, 54000000, 1, 36, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
313 | { 54000000, 67500000, 1, 45, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
314 | { 56250000, 56250000, 1, 75, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
315 | { 56250000, 70312500, 1, 117, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
316 | { 59341000, 59341000, 1, 118, 2, 2, 2, 6, 0, 3, 4, 0, 0xae978d}, |
317 | { 59341000, 74176250, 2, 148, 2, 1, 1, 15, 0, 1, 1, 0, 0x5a3d70}, |
318 | { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0x0}, |
319 | { 59400000, 74250000, 1, 99, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
320 | { 65000000, 65000000, 1, 65, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
321 | { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
322 | { 68250000, 68250000, 1, 91, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
323 | { 68250000, 85312500, 1, 142, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
324 | { 71000000, 71000000, 1, 71, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
325 | { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
326 | { 72000000, 72000000, 1, 36, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
327 | { 72000000, 90000000, 1, 60, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
328 | { 73250000, 73250000, 3, 293, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
329 | { 73250000, 91562500, 1, 61, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
330 | { 74176000, 74176000, 1, 37, 2, 0, 0, 1, 1, 2, 2, 0, 0x16872b}, |
331 | { 74176000, 92720000, 2, 185, 2, 1, 1, 15, 0, 1, 1, 0, 0x70a3d7}, |
332 | { 74250000, 74250000, 1, 99, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
333 | { 74250000, 92812500, 4, 495, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
334 | { 75000000, 75000000, 1, 50, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
335 | { 75000000, 93750000, 1, 125, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
336 | { 78750000, 78750000, 1, 105, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
337 | { 78750000, 98437500, 1, 164, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
338 | { 79500000, 79500000, 1, 53, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
339 | { 79500000, 99375000, 1, 199, 2, 2, 2, 15, 0, 2, 2, 0, 0x0}, |
340 | { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
341 | { 83500000, 104375000, 1, 104, 2, 1, 1, 15, 0, 1, 1, 0, 0x600000}, |
342 | { 85500000, 85500000, 1, 57, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
343 | { 85500000, 106875000, 1, 178, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
344 | { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
345 | { 85750000, 107187500, 1, 143, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
346 | { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, |
347 | { 88750000, 110937500, 1, 110, 2, 1, 1, 15, 0, 1, 1, 0, 0xf00000}, |
348 | { 94500000, 94500000, 1, 63, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
349 | { 94500000, 118125000, 1, 197, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, |
350 | {101000000, 101000000, 1, 101, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
351 | {101000000, 126250000, 1, 42, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
352 | {102250000, 102250000, 4, 409, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
353 | {102250000, 127812500, 1, 128, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
354 | {106500000, 106500000, 1, 71, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
355 | {106500000, 133125000, 1, 133, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
356 | {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
357 | {108000000, 135000000, 1, 45, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
358 | {115500000, 115500000, 1, 77, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
359 | {115500000, 144375000, 1, 48, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
360 | {117500000, 117500000, 2, 235, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
361 | {117500000, 146875000, 1, 49, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
362 | {119000000, 119000000, 1, 119, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
363 | {119000000, 148750000, 3, 148, 0, 1, 1, 1, 3, 1, 1, 0, 0xc00000}, |
364 | {121750000, 121750000, 4, 487, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
365 | {121750000, 152187500, 1, 203, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, |
366 | {122500000, 122500000, 2, 245, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, |
367 | {122500000, 153125000, 1, 51, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
368 | {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
369 | {135000000, 168750000, 1, 169, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
370 | {136750000, 136750000, 1, 68, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, |
371 | {136750000, 170937500, 1, 113, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f}, |
372 | {140250000, 140250000, 2, 187, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
373 | {140250000, 175312500, 1, 117, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
374 | {146250000, 146250000, 2, 195, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
375 | {146250000, 182812500, 1, 61, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
376 | {148250000, 148250000, 3, 222, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, |
377 | {148250000, 185312500, 1, 123, 0, 2, 2, 1, 3, 2, 2, 0, 0x8aaab0}, |
378 | {148352000, 148352000, 2, 148, 2, 0, 0, 1, 1, 2, 2, 0, 0x5a1cac}, |
379 | {148352000, 185440000, 3, 185, 0, 1, 1, 1, 3, 1, 1, 0, 0x70a3d7}, |
380 | {148500000, 148500000, 1, 99, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
381 | {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
382 | {154000000, 154000000, 1, 77, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
383 | {154000000, 192500000, 1, 64, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
384 | {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
385 | {156000000, 195000000, 1, 65, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
386 | {156750000, 156750000, 2, 209, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
387 | {156750000, 195937500, 1, 196, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
388 | {157000000, 157000000, 2, 157, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
389 | {157000000, 196250000, 1, 131, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
390 | {157500000, 157500000, 1, 105, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
391 | {157500000, 196875000, 1, 197, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, |
392 | {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
393 | {162000000, 202500000, 2, 135, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
394 | {175500000, 175500000, 1, 117, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
395 | {175500000, 219375000, 1, 73, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
396 | {179500000, 179500000, 3, 359, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, |
397 | {179500000, 224375000, 1, 75, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
398 | {182750000, 182750000, 1, 91, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, |
399 | {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0}, |
400 | {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0}, |
401 | {187000000, 187000000, 2, 187, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
402 | {187000000, 233750000, 1, 39, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, |
403 | {187250000, 187250000, 3, 280, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000}, |
404 | {187250000, 234062500, 1, 156, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0}, |
405 | {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
406 | {189000000, 236250000, 1, 79, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
407 | {193250000, 193250000, 3, 289, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000}, |
408 | {193250000, 241562500, 1, 161, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0}, |
409 | {202500000, 202500000, 2, 135, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
410 | {202500000, 253125000, 1, 169, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
411 | {204750000, 204750000, 4, 273, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
412 | {204750000, 255937500, 1, 171, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
413 | {208000000, 208000000, 1, 104, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
414 | {208000000, 260000000, 1, 173, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
415 | {214750000, 214750000, 1, 107, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, |
416 | {214750000, 268437500, 1, 178, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f}, |
417 | {218250000, 218250000, 4, 291, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
418 | {218250000, 272812500, 1, 91, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
419 | {229500000, 229500000, 2, 153, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
420 | {229500000, 286875000, 1, 191, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
421 | {234000000, 234000000, 1, 39, 0, 0, 0, 1, 0, 1, 1, 0, 0x0}, |
422 | {234000000, 292500000, 1, 195, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
423 | {241500000, 241500000, 2, 161, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
424 | {241500000, 301875000, 1, 201, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, |
425 | {245250000, 245250000, 4, 327, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
426 | {245250000, 306562500, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, |
427 | {245500000, 245500000, 4, 491, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, |
428 | {245500000, 306875000, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, |
429 | {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
430 | {261000000, 326250000, 1, 109, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, |
431 | {268250000, 268250000, 9, 402, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000}, |
432 | {268250000, 335312500, 1, 111, 0, 1, 1, 1, 3, 1, 1, 0, 0xc5554f}, |
433 | {268500000, 268500000, 2, 179, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
434 | {268500000, 335625000, 1, 56, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, |
435 | {281250000, 281250000, 4, 375, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
436 | {281250000, 351562500, 1, 117, 0, 3, 1, 1, 3, 1, 1, 0, 0x0}, |
437 | {288000000, 288000000, 1, 48, 0, 0, 0, 1, 0, 1, 1, 0, 0x0}, |
438 | {288000000, 360000000, 1, 60, 0, 2, 0, 1, 3, 0, 0, 1, 0x0}, |
439 | {296703000, 296703000, 1, 49, 0, 0, 0, 1, 0, 1, 1, 0, 0x7353f7}, |
440 | {296703000, 370878750, 1, 123, 0, 3, 1, 1, 3, 1, 1, 0, 0xa051eb}, |
441 | {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
442 | {297000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 1, 1, 0, 0x0}, |
443 | {312250000, 312250000, 9, 468, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000}, |
444 | {312250000, 390312500, 1, 130, 0, 3, 1, 1, 3, 1, 1, 0, 0x1aaab0}, |
445 | {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, |
446 | {317000000, 396250000, 1, 66, 0, 2, 0, 1, 3, 0, 0, 1, 0x0}, |
447 | {319750000, 319750000, 3, 159, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000}, |
448 | {319750000, 399687500, 3, 199, 0, 2, 0, 1, 3, 0, 0, 1, 0xd80000}, |
449 | {333250000, 333250000, 9, 499, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000}, |
450 | {333250000, 416562500, 1, 138, 0, 3, 1, 1, 3, 1, 1, 0, 0xdaaab0}, |
451 | {348500000, 348500000, 9, 522, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, |
452 | {348500000, 435625000, 1, 145, 0, 3, 1, 1, 3, 1, 1, 0, 0x35554f}, |
453 | {356500000, 356500000, 9, 534, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, |
454 | {356500000, 445625000, 1, 148, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0}, |
455 | {380500000, 380500000, 9, 570, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, |
456 | {380500000, 475625000, 1, 158, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0}, |
457 | {443250000, 443250000, 1, 73, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000}, |
458 | {443250000, 554062500, 1, 92, 0, 2, 0, 1, 3, 0, 0, 1, 0x580000}, |
459 | {505250000, 505250000, 9, 757, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000}, |
460 | {552750000, 552750000, 3, 276, 0, 2, 0, 1, 0, 1, 1, 0, 0x600000}, |
461 | {593407000, 296703500, 3, 296, 0, 1, 1, 1, 0, 1, 1, 0, 0xb41893}, |
462 | {593407000, 370879375, 4, 494, 0, 3, 1, 1, 3, 0, 0, 1, 0x817e4a}, |
463 | {593407000, 593407000, 3, 296, 0, 2, 0, 1, 0, 1, 1, 0, 0xb41893}, |
464 | {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0}, |
465 | {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0}, |
466 | {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0}, |
467 | { /* sentinel */ } |
468 | }; |
469 | |
470 | static const struct post_pll_config post_pll_cfg_table[] = { |
471 | {33750000, 1, 40, 8, 1}, |
472 | {33750000, 1, 80, 8, 2}, |
473 | {74250000, 1, 40, 8, 1}, |
474 | {74250000, 18, 80, 8, 2}, |
475 | {148500000, 2, 40, 4, 3}, |
476 | {297000000, 4, 40, 2, 3}, |
477 | {594000000, 8, 40, 1, 3}, |
478 | { /* sentinel */ } |
479 | }; |
480 | |
481 | /* phy tuning values for an undocumented set of registers */ |
482 | static const struct phy_config rk3228_phy_cfg[] = { |
483 | { 165000000, { |
484 | 0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, |
485 | 0x00, 0x00, 0x00, 0x00, 0x00, |
486 | }, |
487 | }, { |
488 | 340000000, { |
489 | 0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, |
490 | 0x00, 0x00, 0x00, 0x00, 0x00, |
491 | }, |
492 | }, { |
493 | 594000000, { |
494 | 0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, |
495 | 0x00, 0x00, 0x00, 0x00, 0x00, |
496 | }, |
497 | }, { /* sentinel */ }, |
498 | }; |
499 | |
500 | /* phy tuning values for an undocumented set of registers */ |
501 | static const struct phy_config rk3328_phy_cfg[] = { |
502 | { 165000000, { |
503 | 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08, |
504 | 0x00, 0xac, 0xcc, 0xcc, 0xcc, |
505 | }, |
506 | }, { |
507 | 340000000, { |
508 | 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08, |
509 | 0x3f, 0xac, 0xcc, 0xcd, 0xdd, |
510 | }, |
511 | }, { |
512 | 594000000, { |
513 | 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08, |
514 | 0x00, 0xac, 0xcc, 0xcc, 0xcc, |
515 | }, |
516 | }, { /* sentinel */ }, |
517 | }; |
518 | |
519 | static inline struct inno_hdmi_phy *to_inno_hdmi_phy(struct clk_hw *hw) |
520 | { |
521 | return container_of(hw, struct inno_hdmi_phy, hw); |
522 | } |
523 | |
524 | /* |
525 | * The register description of the IP block does not use any distinct names |
526 | * but instead the databook simply numbers the registers in one-increments. |
527 | * As the registers are obviously 32bit sized, the inno_* functions |
528 | * translate the databook register names to the actual registers addresses. |
529 | */ |
530 | static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val) |
531 | { |
532 | regmap_write(map: inno->regmap, reg: reg * 4, val); |
533 | } |
534 | |
535 | static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg) |
536 | { |
537 | u32 val; |
538 | |
539 | regmap_read(map: inno->regmap, reg: reg * 4, val: &val); |
540 | |
541 | return val; |
542 | } |
543 | |
544 | static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg, |
545 | u8 mask, u8 val) |
546 | { |
547 | regmap_update_bits(map: inno->regmap, reg: reg * 4, mask, val); |
548 | } |
549 | |
550 | #define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \ |
551 | regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \ |
552 | sleep_us, timeout_us) |
553 | |
554 | static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, |
555 | unsigned long rate) |
556 | { |
557 | int bus_width = phy_get_bus_width(phy: inno->phy); |
558 | |
559 | switch (bus_width) { |
560 | case 4: |
561 | case 5: |
562 | case 6: |
563 | case 10: |
564 | case 12: |
565 | case 16: |
566 | return (u64)rate * bus_width / 8; |
567 | default: |
568 | return rate; |
569 | } |
570 | } |
571 | |
572 | static irqreturn_t inno_hdmi_phy_rk3328_hardirq(int irq, void *dev_id) |
573 | { |
574 | struct inno_hdmi_phy *inno = dev_id; |
575 | int intr_stat1, intr_stat2, intr_stat3; |
576 | |
577 | intr_stat1 = inno_read(inno, reg: 0x04); |
578 | intr_stat2 = inno_read(inno, reg: 0x06); |
579 | intr_stat3 = inno_read(inno, reg: 0x08); |
580 | |
581 | if (intr_stat1) |
582 | inno_write(inno, reg: 0x04, val: intr_stat1); |
583 | if (intr_stat2) |
584 | inno_write(inno, reg: 0x06, val: intr_stat2); |
585 | if (intr_stat3) |
586 | inno_write(inno, reg: 0x08, val: intr_stat3); |
587 | |
588 | if (intr_stat1 || intr_stat2 || intr_stat3) |
589 | return IRQ_WAKE_THREAD; |
590 | |
591 | return IRQ_HANDLED; |
592 | } |
593 | |
594 | static irqreturn_t inno_hdmi_phy_rk3328_irq(int irq, void *dev_id) |
595 | { |
596 | struct inno_hdmi_phy *inno = dev_id; |
597 | |
598 | inno_update_bits(inno, reg: 0x02, RK3328_PDATA_EN, val: 0); |
599 | usleep_range(min: 10, max: 20); |
600 | inno_update_bits(inno, reg: 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN); |
601 | |
602 | return IRQ_HANDLED; |
603 | } |
604 | |
605 | static int inno_hdmi_phy_power_on(struct phy *phy) |
606 | { |
607 | struct inno_hdmi_phy *inno = phy_get_drvdata(phy); |
608 | const struct post_pll_config *cfg = post_pll_cfg_table; |
609 | const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table; |
610 | unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, |
611 | rate: inno->pixclock); |
612 | int ret; |
613 | |
614 | if (!tmdsclock) { |
615 | dev_err(inno->dev, "TMDS clock is zero!\n" ); |
616 | return -EINVAL; |
617 | } |
618 | |
619 | if (!inno->plat_data->ops->power_on) |
620 | return -EINVAL; |
621 | |
622 | for (; cfg->tmdsclock != 0; cfg++) |
623 | if (tmdsclock <= cfg->tmdsclock && |
624 | cfg->version & inno->chip_version) |
625 | break; |
626 | |
627 | for (; phy_cfg->tmdsclock != 0; phy_cfg++) |
628 | if (tmdsclock <= phy_cfg->tmdsclock) |
629 | break; |
630 | |
631 | if (cfg->tmdsclock == 0 || phy_cfg->tmdsclock == 0) |
632 | return -EINVAL; |
633 | |
634 | dev_dbg(inno->dev, "Inno HDMI PHY Power On\n" ); |
635 | |
636 | inno->plat_data->clk_ops->set_rate(&inno->hw, inno->pixclock, 24000000); |
637 | |
638 | ret = clk_prepare_enable(clk: inno->phyclk); |
639 | if (ret) |
640 | return ret; |
641 | |
642 | ret = inno->plat_data->ops->power_on(inno, cfg, phy_cfg); |
643 | if (ret) { |
644 | clk_disable_unprepare(clk: inno->phyclk); |
645 | return ret; |
646 | } |
647 | |
648 | return 0; |
649 | } |
650 | |
651 | static int inno_hdmi_phy_power_off(struct phy *phy) |
652 | { |
653 | struct inno_hdmi_phy *inno = phy_get_drvdata(phy); |
654 | |
655 | if (!inno->plat_data->ops->power_off) |
656 | return -EINVAL; |
657 | |
658 | inno->plat_data->ops->power_off(inno); |
659 | |
660 | clk_disable_unprepare(clk: inno->phyclk); |
661 | |
662 | inno->tmdsclock = 0; |
663 | |
664 | dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n" ); |
665 | |
666 | return 0; |
667 | } |
668 | |
669 | static const struct phy_ops inno_hdmi_phy_ops = { |
670 | .owner = THIS_MODULE, |
671 | .power_on = inno_hdmi_phy_power_on, |
672 | .power_off = inno_hdmi_phy_power_off, |
673 | }; |
674 | |
675 | static const |
676 | struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno, |
677 | unsigned long rate) |
678 | { |
679 | const struct pre_pll_config *cfg = pre_pll_cfg_table; |
680 | unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); |
681 | |
682 | for (; cfg->pixclock != 0; cfg++) |
683 | if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock) |
684 | break; |
685 | |
686 | if (cfg->pixclock == 0) |
687 | return ERR_PTR(error: -EINVAL); |
688 | |
689 | return cfg; |
690 | } |
691 | |
692 | static int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw) |
693 | { |
694 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
695 | u8 status; |
696 | |
697 | status = inno_read(inno, reg: 0xe0) & RK3228_PRE_PLL_POWER_DOWN; |
698 | return status ? 0 : 1; |
699 | } |
700 | |
701 | static int inno_hdmi_phy_rk3228_clk_prepare(struct clk_hw *hw) |
702 | { |
703 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
704 | |
705 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN, val: 0); |
706 | return 0; |
707 | } |
708 | |
709 | static void inno_hdmi_phy_rk3228_clk_unprepare(struct clk_hw *hw) |
710 | { |
711 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
712 | |
713 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN, |
714 | RK3228_PRE_PLL_POWER_DOWN); |
715 | } |
716 | |
717 | static |
718 | unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw, |
719 | unsigned long parent_rate) |
720 | { |
721 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
722 | u8 nd, no_a, no_b, no_d; |
723 | u64 vco; |
724 | u16 nf; |
725 | |
726 | nd = inno_read(inno, reg: 0xe2) & RK3228_PRE_PLL_PRE_DIV_MASK; |
727 | nf = (inno_read(inno, reg: 0xe2) & RK3228_PRE_PLL_FB_DIV_8_MASK) << 1; |
728 | nf |= inno_read(inno, reg: 0xe3); |
729 | vco = parent_rate * nf; |
730 | |
731 | if (inno_read(inno, reg: 0xe2) & RK3228_PCLK_VCO_DIV_5_MASK) { |
732 | do_div(vco, nd * 5); |
733 | } else { |
734 | no_a = inno_read(inno, reg: 0xe4) & RK3228_PRE_PLL_PCLK_DIV_A_MASK; |
735 | if (!no_a) |
736 | no_a = 1; |
737 | no_b = inno_read(inno, reg: 0xe4) & RK3228_PRE_PLL_PCLK_DIV_B_MASK; |
738 | no_b >>= RK3228_PRE_PLL_PCLK_DIV_B_SHIFT; |
739 | no_b += 2; |
740 | no_d = inno_read(inno, reg: 0xe5) & RK3228_PRE_PLL_PCLK_DIV_D_MASK; |
741 | |
742 | do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); |
743 | } |
744 | |
745 | inno->pixclock = vco; |
746 | |
747 | dev_dbg(inno->dev, "%s rate %lu\n" , __func__, inno->pixclock); |
748 | |
749 | return vco; |
750 | } |
751 | |
752 | static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw, |
753 | unsigned long rate, |
754 | unsigned long *parent_rate) |
755 | { |
756 | const struct pre_pll_config *cfg = pre_pll_cfg_table; |
757 | |
758 | rate = (rate / 1000) * 1000; |
759 | |
760 | for (; cfg->pixclock != 0; cfg++) |
761 | if (cfg->pixclock == rate && !cfg->fracdiv) |
762 | break; |
763 | |
764 | if (cfg->pixclock == 0) |
765 | return -EINVAL; |
766 | |
767 | return cfg->pixclock; |
768 | } |
769 | |
770 | static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, |
771 | unsigned long rate, |
772 | unsigned long parent_rate) |
773 | { |
774 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
775 | const struct pre_pll_config *cfg; |
776 | unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); |
777 | u32 v; |
778 | int ret; |
779 | |
780 | dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n" , |
781 | __func__, rate, tmdsclock); |
782 | |
783 | if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) |
784 | return 0; |
785 | |
786 | cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); |
787 | if (IS_ERR(ptr: cfg)) |
788 | return PTR_ERR(ptr: cfg); |
789 | |
790 | /* Power down PRE-PLL */ |
791 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN, |
792 | RK3228_PRE_PLL_POWER_DOWN); |
793 | |
794 | inno_update_bits(inno, reg: 0xe2, RK3228_PRE_PLL_FB_DIV_8_MASK | |
795 | RK3228_PCLK_VCO_DIV_5_MASK | |
796 | RK3228_PRE_PLL_PRE_DIV_MASK, |
797 | RK3228_PRE_PLL_FB_DIV_8(cfg->fbdiv) | |
798 | RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en) | |
799 | RK3228_PRE_PLL_PRE_DIV(cfg->prediv)); |
800 | inno_write(inno, reg: 0xe3, RK3228_PRE_PLL_FB_DIV_7_0(cfg->fbdiv)); |
801 | inno_update_bits(inno, reg: 0xe4, RK3228_PRE_PLL_PCLK_DIV_B_MASK | |
802 | RK3228_PRE_PLL_PCLK_DIV_A_MASK, |
803 | RK3228_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) | |
804 | RK3228_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a)); |
805 | inno_update_bits(inno, reg: 0xe5, RK3228_PRE_PLL_PCLK_DIV_C_MASK | |
806 | RK3228_PRE_PLL_PCLK_DIV_D_MASK, |
807 | RK3228_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) | |
808 | RK3228_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d)); |
809 | inno_update_bits(inno, reg: 0xe6, RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK | |
810 | RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK | |
811 | RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK, |
812 | RK3228_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) | |
813 | RK3228_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) | |
814 | RK3228_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b)); |
815 | |
816 | /* Power up PRE-PLL */ |
817 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN, val: 0); |
818 | |
819 | /* Wait for Pre-PLL lock */ |
820 | ret = inno_poll(inno, 0xe8, v, v & RK3228_PRE_PLL_LOCK_STATUS, |
821 | 100, 100000); |
822 | if (ret) { |
823 | dev_err(inno->dev, "Pre-PLL locking failed\n" ); |
824 | return ret; |
825 | } |
826 | |
827 | inno->pixclock = rate; |
828 | inno->tmdsclock = tmdsclock; |
829 | |
830 | return 0; |
831 | } |
832 | |
833 | static const struct clk_ops inno_hdmi_phy_rk3228_clk_ops = { |
834 | .prepare = inno_hdmi_phy_rk3228_clk_prepare, |
835 | .unprepare = inno_hdmi_phy_rk3228_clk_unprepare, |
836 | .is_prepared = inno_hdmi_phy_rk3228_clk_is_prepared, |
837 | .recalc_rate = inno_hdmi_phy_rk3228_clk_recalc_rate, |
838 | .round_rate = inno_hdmi_phy_rk3228_clk_round_rate, |
839 | .set_rate = inno_hdmi_phy_rk3228_clk_set_rate, |
840 | }; |
841 | |
842 | static int inno_hdmi_phy_rk3328_clk_is_prepared(struct clk_hw *hw) |
843 | { |
844 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
845 | u8 status; |
846 | |
847 | status = inno_read(inno, reg: 0xa0) & RK3328_PRE_PLL_POWER_DOWN; |
848 | return status ? 0 : 1; |
849 | } |
850 | |
851 | static int inno_hdmi_phy_rk3328_clk_prepare(struct clk_hw *hw) |
852 | { |
853 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
854 | |
855 | inno_update_bits(inno, reg: 0xa0, RK3328_PRE_PLL_POWER_DOWN, val: 0); |
856 | return 0; |
857 | } |
858 | |
859 | static void inno_hdmi_phy_rk3328_clk_unprepare(struct clk_hw *hw) |
860 | { |
861 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
862 | |
863 | inno_update_bits(inno, reg: 0xa0, RK3328_PRE_PLL_POWER_DOWN, |
864 | RK3328_PRE_PLL_POWER_DOWN); |
865 | } |
866 | |
867 | static |
868 | unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, |
869 | unsigned long parent_rate) |
870 | { |
871 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
872 | unsigned long frac; |
873 | u8 nd, no_a, no_b, no_d; |
874 | u64 vco; |
875 | u16 nf; |
876 | |
877 | nd = inno_read(inno, reg: 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK; |
878 | nf = ((inno_read(inno, reg: 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8); |
879 | nf |= inno_read(inno, reg: 0xa3); |
880 | vco = parent_rate * nf; |
881 | |
882 | if (!(inno_read(inno, reg: 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) { |
883 | frac = inno_read(inno, reg: 0xd3) | |
884 | (inno_read(inno, reg: 0xd2) << 8) | |
885 | (inno_read(inno, reg: 0xd1) << 16); |
886 | vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24)); |
887 | } |
888 | |
889 | if (inno_read(inno, reg: 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) { |
890 | do_div(vco, nd * 5); |
891 | } else { |
892 | no_a = inno_read(inno, reg: 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK; |
893 | no_b = inno_read(inno, reg: 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK; |
894 | no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT; |
895 | no_b += 2; |
896 | no_d = inno_read(inno, reg: 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK; |
897 | |
898 | do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); |
899 | } |
900 | |
901 | inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000; |
902 | |
903 | dev_dbg(inno->dev, "%s rate %lu vco %llu\n" , |
904 | __func__, inno->pixclock, vco); |
905 | |
906 | return inno->pixclock; |
907 | } |
908 | |
909 | static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, |
910 | unsigned long rate, |
911 | unsigned long *parent_rate) |
912 | { |
913 | const struct pre_pll_config *cfg = pre_pll_cfg_table; |
914 | |
915 | rate = (rate / 1000) * 1000; |
916 | |
917 | for (; cfg->pixclock != 0; cfg++) |
918 | if (cfg->pixclock == rate) |
919 | break; |
920 | |
921 | if (cfg->pixclock == 0) |
922 | return -EINVAL; |
923 | |
924 | return cfg->pixclock; |
925 | } |
926 | |
927 | static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, |
928 | unsigned long rate, |
929 | unsigned long parent_rate) |
930 | { |
931 | struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); |
932 | const struct pre_pll_config *cfg; |
933 | unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); |
934 | u32 val; |
935 | int ret; |
936 | |
937 | dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n" , |
938 | __func__, rate, tmdsclock); |
939 | |
940 | if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) |
941 | return 0; |
942 | |
943 | cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); |
944 | if (IS_ERR(ptr: cfg)) |
945 | return PTR_ERR(ptr: cfg); |
946 | |
947 | inno_update_bits(inno, reg: 0xa0, RK3328_PRE_PLL_POWER_DOWN, |
948 | RK3328_PRE_PLL_POWER_DOWN); |
949 | |
950 | /* Configure pre-pll */ |
951 | inno_update_bits(inno, reg: 0xa0, RK3328_PCLK_VCO_DIV_5_MASK, |
952 | RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); |
953 | inno_write(inno, reg: 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv)); |
954 | |
955 | val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE; |
956 | if (!cfg->fracdiv) |
957 | val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE; |
958 | inno_write(inno, reg: 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val); |
959 | inno_write(inno, reg: 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv)); |
960 | inno_write(inno, reg: 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) | |
961 | RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b)); |
962 | inno_write(inno, reg: 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) | |
963 | RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d)); |
964 | inno_write(inno, reg: 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) | |
965 | RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) | |
966 | RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b)); |
967 | inno_write(inno, reg: 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv)); |
968 | inno_write(inno, reg: 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv)); |
969 | inno_write(inno, reg: 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv)); |
970 | |
971 | inno_update_bits(inno, reg: 0xa0, RK3328_PRE_PLL_POWER_DOWN, val: 0); |
972 | |
973 | /* Wait for Pre-PLL lock */ |
974 | ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS, |
975 | 1000, 10000); |
976 | if (ret) { |
977 | dev_err(inno->dev, "Pre-PLL locking failed\n" ); |
978 | return ret; |
979 | } |
980 | |
981 | inno->pixclock = rate; |
982 | inno->tmdsclock = tmdsclock; |
983 | |
984 | return 0; |
985 | } |
986 | |
987 | static const struct clk_ops inno_hdmi_phy_rk3328_clk_ops = { |
988 | .prepare = inno_hdmi_phy_rk3328_clk_prepare, |
989 | .unprepare = inno_hdmi_phy_rk3328_clk_unprepare, |
990 | .is_prepared = inno_hdmi_phy_rk3328_clk_is_prepared, |
991 | .recalc_rate = inno_hdmi_phy_rk3328_clk_recalc_rate, |
992 | .round_rate = inno_hdmi_phy_rk3328_clk_round_rate, |
993 | .set_rate = inno_hdmi_phy_rk3328_clk_set_rate, |
994 | }; |
995 | |
996 | static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) |
997 | { |
998 | struct device *dev = inno->dev; |
999 | struct device_node *np = dev->of_node; |
1000 | struct clk_init_data init; |
1001 | const char *parent_name; |
1002 | int ret; |
1003 | |
1004 | parent_name = __clk_get_name(clk: inno->refoclk); |
1005 | |
1006 | init.parent_names = &parent_name; |
1007 | init.num_parents = 1; |
1008 | init.flags = 0; |
1009 | init.name = "pin_hd20_pclk" ; |
1010 | init.ops = inno->plat_data->clk_ops; |
1011 | |
1012 | /* optional override of the clock name */ |
1013 | of_property_read_string(np, propname: "clock-output-names" , out_string: &init.name); |
1014 | |
1015 | inno->hw.init = &init; |
1016 | |
1017 | inno->phyclk = devm_clk_register(dev, hw: &inno->hw); |
1018 | if (IS_ERR(ptr: inno->phyclk)) { |
1019 | ret = PTR_ERR(ptr: inno->phyclk); |
1020 | dev_err(dev, "failed to register clock: %d\n" , ret); |
1021 | return ret; |
1022 | } |
1023 | |
1024 | ret = of_clk_add_provider(np, clk_src_get: of_clk_src_simple_get, data: inno->phyclk); |
1025 | if (ret) { |
1026 | dev_err(dev, "failed to register clock provider: %d\n" , ret); |
1027 | return ret; |
1028 | } |
1029 | |
1030 | return 0; |
1031 | } |
1032 | |
1033 | static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) |
1034 | { |
1035 | /* |
1036 | * Use phy internal register control |
1037 | * rxsense/poweron/pllpd/pdataen signal. |
1038 | */ |
1039 | inno_write(inno, reg: 0x01, RK3228_BYPASS_RXSENSE_EN | |
1040 | RK3228_BYPASS_PWRON_EN | |
1041 | RK3228_BYPASS_PLLPD_EN); |
1042 | inno_update_bits(inno, reg: 0x02, RK3228_BYPASS_PDATA_EN, |
1043 | RK3228_BYPASS_PDATA_EN); |
1044 | |
1045 | /* manual power down post-PLL */ |
1046 | inno_update_bits(inno, reg: 0xaa, RK3228_POST_PLL_CTRL_MANUAL, |
1047 | RK3228_POST_PLL_CTRL_MANUAL); |
1048 | |
1049 | inno->chip_version = 1; |
1050 | |
1051 | return 0; |
1052 | } |
1053 | |
1054 | static int |
1055 | inno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno, |
1056 | const struct post_pll_config *cfg, |
1057 | const struct phy_config *phy_cfg) |
1058 | { |
1059 | int ret; |
1060 | u32 v; |
1061 | |
1062 | inno_update_bits(inno, reg: 0x02, RK3228_PDATAEN_DISABLE, |
1063 | RK3228_PDATAEN_DISABLE); |
1064 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN | |
1065 | RK3228_POST_PLL_POWER_DOWN, |
1066 | RK3228_PRE_PLL_POWER_DOWN | |
1067 | RK3228_POST_PLL_POWER_DOWN); |
1068 | |
1069 | /* Post-PLL update */ |
1070 | inno_update_bits(inno, reg: 0xe9, RK3228_POST_PLL_PRE_DIV_MASK, |
1071 | RK3228_POST_PLL_PRE_DIV(cfg->prediv)); |
1072 | inno_update_bits(inno, reg: 0xeb, RK3228_POST_PLL_FB_DIV_8_MASK, |
1073 | RK3228_POST_PLL_FB_DIV_8(cfg->fbdiv)); |
1074 | inno_write(inno, reg: 0xea, RK3228_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); |
1075 | |
1076 | if (cfg->postdiv == 1) { |
1077 | inno_update_bits(inno, reg: 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, |
1078 | val: 0); |
1079 | } else { |
1080 | int div = cfg->postdiv / 2 - 1; |
1081 | |
1082 | inno_update_bits(inno, reg: 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, |
1083 | RK3228_POST_PLL_POST_DIV_ENABLE); |
1084 | inno_update_bits(inno, reg: 0xeb, RK3228_POST_PLL_POST_DIV_MASK, |
1085 | RK3228_POST_PLL_POST_DIV(div)); |
1086 | } |
1087 | |
1088 | for (v = 0; v < 4; v++) |
1089 | inno_write(inno, reg: 0xef + v, val: phy_cfg->regs[v]); |
1090 | |
1091 | inno_update_bits(inno, reg: 0xe0, RK3228_PRE_PLL_POWER_DOWN | |
1092 | RK3228_POST_PLL_POWER_DOWN, val: 0); |
1093 | inno_update_bits(inno, reg: 0xe1, RK3228_BANDGAP_ENABLE, |
1094 | RK3228_BANDGAP_ENABLE); |
1095 | inno_update_bits(inno, reg: 0xe1, RK3228_TMDS_DRIVER_ENABLE, |
1096 | RK3228_TMDS_DRIVER_ENABLE); |
1097 | |
1098 | /* Wait for post PLL lock */ |
1099 | ret = inno_poll(inno, 0xeb, v, v & RK3228_POST_PLL_LOCK_STATUS, |
1100 | 100, 100000); |
1101 | if (ret) { |
1102 | dev_err(inno->dev, "Post-PLL locking failed\n" ); |
1103 | return ret; |
1104 | } |
1105 | |
1106 | if (cfg->tmdsclock > 340000000) |
1107 | msleep(msecs: 100); |
1108 | |
1109 | inno_update_bits(inno, reg: 0x02, RK3228_PDATAEN_DISABLE, val: 0); |
1110 | return 0; |
1111 | } |
1112 | |
1113 | static void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno) |
1114 | { |
1115 | inno_update_bits(inno, reg: 0xe1, RK3228_TMDS_DRIVER_ENABLE, val: 0); |
1116 | inno_update_bits(inno, reg: 0xe1, RK3228_BANDGAP_ENABLE, val: 0); |
1117 | inno_update_bits(inno, reg: 0xe0, RK3228_POST_PLL_POWER_DOWN, |
1118 | RK3228_POST_PLL_POWER_DOWN); |
1119 | } |
1120 | |
1121 | static const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = { |
1122 | .init = inno_hdmi_phy_rk3228_init, |
1123 | .power_on = inno_hdmi_phy_rk3228_power_on, |
1124 | .power_off = inno_hdmi_phy_rk3228_power_off, |
1125 | }; |
1126 | |
1127 | static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) |
1128 | { |
1129 | struct nvmem_cell *cell; |
1130 | unsigned char *efuse_buf; |
1131 | size_t len; |
1132 | |
1133 | /* |
1134 | * Use phy internal register control |
1135 | * rxsense/poweron/pllpd/pdataen signal. |
1136 | */ |
1137 | inno_write(inno, reg: 0x01, RK3328_BYPASS_RXSENSE_EN | |
1138 | RK3328_BYPASS_POWERON_EN | |
1139 | RK3328_BYPASS_PLLPD_EN); |
1140 | inno_write(inno, reg: 0x02, RK3328_INT_POL_HIGH | RK3328_BYPASS_PDATA_EN | |
1141 | RK3328_PDATA_EN); |
1142 | |
1143 | /* Disable phy irq */ |
1144 | inno_write(inno, reg: 0x05, val: 0); |
1145 | inno_write(inno, reg: 0x07, val: 0); |
1146 | |
1147 | /* try to read the chip-version */ |
1148 | inno->chip_version = 1; |
1149 | cell = nvmem_cell_get(dev: inno->dev, id: "cpu-version" ); |
1150 | if (IS_ERR(ptr: cell)) { |
1151 | if (PTR_ERR(ptr: cell) == -EPROBE_DEFER) |
1152 | return -EPROBE_DEFER; |
1153 | |
1154 | return 0; |
1155 | } |
1156 | |
1157 | efuse_buf = nvmem_cell_read(cell, len: &len); |
1158 | nvmem_cell_put(cell); |
1159 | |
1160 | if (IS_ERR(ptr: efuse_buf)) |
1161 | return 0; |
1162 | if (len == 1) |
1163 | inno->chip_version = efuse_buf[0] + 1; |
1164 | kfree(objp: efuse_buf); |
1165 | |
1166 | return 0; |
1167 | } |
1168 | |
1169 | static int |
1170 | inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, |
1171 | const struct post_pll_config *cfg, |
1172 | const struct phy_config *phy_cfg) |
1173 | { |
1174 | int ret; |
1175 | u32 v; |
1176 | |
1177 | inno_update_bits(inno, reg: 0x02, RK3328_PDATA_EN, val: 0); |
1178 | inno_update_bits(inno, reg: 0xaa, RK3328_POST_PLL_POWER_DOWN, |
1179 | RK3328_POST_PLL_POWER_DOWN); |
1180 | |
1181 | inno_write(inno, reg: 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); |
1182 | if (cfg->postdiv == 1) { |
1183 | inno_write(inno, reg: 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | |
1184 | RK3328_POST_PLL_PRE_DIV(cfg->prediv)); |
1185 | inno_write(inno, reg: 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS | |
1186 | RK3328_POST_PLL_POWER_DOWN); |
1187 | } else { |
1188 | v = (cfg->postdiv / 2) - 1; |
1189 | v &= RK3328_POST_PLL_POST_DIV_MASK; |
1190 | inno_write(inno, reg: 0xad, val: v); |
1191 | inno_write(inno, reg: 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | |
1192 | RK3328_POST_PLL_PRE_DIV(cfg->prediv)); |
1193 | inno_write(inno, reg: 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE | |
1194 | RK3328_POST_PLL_REFCLK_SEL_TMDS | |
1195 | RK3328_POST_PLL_POWER_DOWN); |
1196 | } |
1197 | |
1198 | for (v = 0; v < 14; v++) |
1199 | inno_write(inno, reg: 0xb5 + v, val: phy_cfg->regs[v]); |
1200 | |
1201 | /* set ESD detection threshold for TMDS CLK, D2, D1 and D0 */ |
1202 | for (v = 0; v < 4; v++) |
1203 | inno_update_bits(inno, reg: 0xc8 + v, RK3328_ESD_DETECT_MASK, |
1204 | RK3328_ESD_DETECT_340MV); |
1205 | |
1206 | if (phy_cfg->tmdsclock > 340000000) { |
1207 | /* Set termination resistor to 100ohm */ |
1208 | v = clk_get_rate(clk: inno->sysclk) / 100000; |
1209 | inno_write(inno, reg: 0xc5, RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(v) |
1210 | | RK3328_BYPASS_TERM_RESISTOR_CALIB); |
1211 | inno_write(inno, reg: 0xc6, RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(v)); |
1212 | inno_write(inno, reg: 0xc7, RK3328_TERM_RESISTOR_100); |
1213 | inno_update_bits(inno, reg: 0xc5, |
1214 | RK3328_BYPASS_TERM_RESISTOR_CALIB, val: 0); |
1215 | } else { |
1216 | inno_write(inno, reg: 0xc5, RK3328_BYPASS_TERM_RESISTOR_CALIB); |
1217 | |
1218 | /* clk termination resistor is 50ohm (parallel resistors) */ |
1219 | if (phy_cfg->tmdsclock > 165000000) |
1220 | inno_update_bits(inno, reg: 0xc8, |
1221 | RK3328_TMDS_TERM_RESIST_MASK, |
1222 | RK3328_TMDS_TERM_RESIST_75 | |
1223 | RK3328_TMDS_TERM_RESIST_150); |
1224 | |
1225 | /* data termination resistor for D2, D1 and D0 is 150ohm */ |
1226 | for (v = 0; v < 3; v++) |
1227 | inno_update_bits(inno, reg: 0xc9 + v, |
1228 | RK3328_TMDS_TERM_RESIST_MASK, |
1229 | RK3328_TMDS_TERM_RESIST_150); |
1230 | } |
1231 | |
1232 | inno_update_bits(inno, reg: 0xaa, RK3328_POST_PLL_POWER_DOWN, val: 0); |
1233 | inno_update_bits(inno, reg: 0xb0, RK3328_BANDGAP_ENABLE, |
1234 | RK3328_BANDGAP_ENABLE); |
1235 | inno_update_bits(inno, reg: 0xb2, RK3328_TMDS_DRIVER_ENABLE, |
1236 | RK3328_TMDS_DRIVER_ENABLE); |
1237 | |
1238 | /* Wait for post PLL lock */ |
1239 | ret = inno_poll(inno, 0xaf, v, v & RK3328_POST_PLL_LOCK_STATUS, |
1240 | 1000, 10000); |
1241 | if (ret) { |
1242 | dev_err(inno->dev, "Post-PLL locking failed\n" ); |
1243 | return ret; |
1244 | } |
1245 | |
1246 | if (phy_cfg->tmdsclock > 340000000) |
1247 | msleep(msecs: 100); |
1248 | |
1249 | inno_update_bits(inno, reg: 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN); |
1250 | |
1251 | /* Enable PHY IRQ */ |
1252 | inno_write(inno, reg: 0x05, RK3328_INT_TMDS_CLK(RK3328_INT_VSS_AGND_ESD_DET) |
1253 | | RK3328_INT_TMDS_D2(RK3328_INT_VSS_AGND_ESD_DET)); |
1254 | inno_write(inno, reg: 0x07, RK3328_INT_TMDS_D1(RK3328_INT_VSS_AGND_ESD_DET) |
1255 | | RK3328_INT_TMDS_D0(RK3328_INT_VSS_AGND_ESD_DET)); |
1256 | return 0; |
1257 | } |
1258 | |
1259 | static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno) |
1260 | { |
1261 | inno_update_bits(inno, reg: 0xb2, RK3328_TMDS_DRIVER_ENABLE, val: 0); |
1262 | inno_update_bits(inno, reg: 0xb0, RK3328_BANDGAP_ENABLE, val: 0); |
1263 | inno_update_bits(inno, reg: 0xaa, RK3328_POST_PLL_POWER_DOWN, |
1264 | RK3328_POST_PLL_POWER_DOWN); |
1265 | |
1266 | /* Disable PHY IRQ */ |
1267 | inno_write(inno, reg: 0x05, val: 0); |
1268 | inno_write(inno, reg: 0x07, val: 0); |
1269 | } |
1270 | |
1271 | static const struct inno_hdmi_phy_ops rk3328_hdmi_phy_ops = { |
1272 | .init = inno_hdmi_phy_rk3328_init, |
1273 | .power_on = inno_hdmi_phy_rk3328_power_on, |
1274 | .power_off = inno_hdmi_phy_rk3328_power_off, |
1275 | }; |
1276 | |
1277 | static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = { |
1278 | .ops = &rk3228_hdmi_phy_ops, |
1279 | .clk_ops = &inno_hdmi_phy_rk3228_clk_ops, |
1280 | .phy_cfg_table = rk3228_phy_cfg, |
1281 | }; |
1282 | |
1283 | static const struct inno_hdmi_phy_drv_data rk3328_hdmi_phy_drv_data = { |
1284 | .ops = &rk3328_hdmi_phy_ops, |
1285 | .clk_ops = &inno_hdmi_phy_rk3328_clk_ops, |
1286 | .phy_cfg_table = rk3328_phy_cfg, |
1287 | }; |
1288 | |
1289 | static const struct regmap_config inno_hdmi_phy_regmap_config = { |
1290 | .reg_bits = 32, |
1291 | .val_bits = 32, |
1292 | .reg_stride = 4, |
1293 | .max_register = 0x400, |
1294 | }; |
1295 | |
1296 | static void inno_hdmi_phy_action(void *data) |
1297 | { |
1298 | struct inno_hdmi_phy *inno = data; |
1299 | |
1300 | clk_disable_unprepare(clk: inno->refpclk); |
1301 | clk_disable_unprepare(clk: inno->sysclk); |
1302 | } |
1303 | |
1304 | static int inno_hdmi_phy_probe(struct platform_device *pdev) |
1305 | { |
1306 | struct inno_hdmi_phy *inno; |
1307 | struct phy_provider *phy_provider; |
1308 | void __iomem *regs; |
1309 | int ret; |
1310 | |
1311 | inno = devm_kzalloc(dev: &pdev->dev, size: sizeof(*inno), GFP_KERNEL); |
1312 | if (!inno) |
1313 | return -ENOMEM; |
1314 | |
1315 | inno->dev = &pdev->dev; |
1316 | |
1317 | inno->plat_data = of_device_get_match_data(dev: inno->dev); |
1318 | if (!inno->plat_data || !inno->plat_data->ops) |
1319 | return -EINVAL; |
1320 | |
1321 | regs = devm_platform_ioremap_resource(pdev, index: 0); |
1322 | if (IS_ERR(ptr: regs)) |
1323 | return PTR_ERR(ptr: regs); |
1324 | |
1325 | inno->sysclk = devm_clk_get(dev: inno->dev, id: "sysclk" ); |
1326 | if (IS_ERR(ptr: inno->sysclk)) { |
1327 | ret = PTR_ERR(ptr: inno->sysclk); |
1328 | dev_err(inno->dev, "failed to get sysclk: %d\n" , ret); |
1329 | return ret; |
1330 | } |
1331 | |
1332 | inno->refpclk = devm_clk_get(dev: inno->dev, id: "refpclk" ); |
1333 | if (IS_ERR(ptr: inno->refpclk)) { |
1334 | ret = PTR_ERR(ptr: inno->refpclk); |
1335 | dev_err(inno->dev, "failed to get ref clock: %d\n" , ret); |
1336 | return ret; |
1337 | } |
1338 | |
1339 | inno->refoclk = devm_clk_get(dev: inno->dev, id: "refoclk" ); |
1340 | if (IS_ERR(ptr: inno->refoclk)) { |
1341 | ret = PTR_ERR(ptr: inno->refoclk); |
1342 | dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n" , |
1343 | ret); |
1344 | return ret; |
1345 | } |
1346 | |
1347 | ret = clk_prepare_enable(clk: inno->sysclk); |
1348 | if (ret) { |
1349 | dev_err(inno->dev, "Cannot enable inno phy sysclk: %d\n" , ret); |
1350 | return ret; |
1351 | } |
1352 | |
1353 | /* |
1354 | * Refpclk needs to be on, on at least the rk3328 for still |
1355 | * unknown reasons. |
1356 | */ |
1357 | ret = clk_prepare_enable(clk: inno->refpclk); |
1358 | if (ret) { |
1359 | dev_err(inno->dev, "failed to enable refpclk\n" ); |
1360 | clk_disable_unprepare(clk: inno->sysclk); |
1361 | return ret; |
1362 | } |
1363 | |
1364 | ret = devm_add_action_or_reset(inno->dev, inno_hdmi_phy_action, |
1365 | inno); |
1366 | if (ret) |
1367 | return ret; |
1368 | |
1369 | inno->regmap = devm_regmap_init_mmio(inno->dev, regs, |
1370 | &inno_hdmi_phy_regmap_config); |
1371 | if (IS_ERR(ptr: inno->regmap)) |
1372 | return PTR_ERR(ptr: inno->regmap); |
1373 | |
1374 | /* only the newer rk3328 hdmiphy has an interrupt */ |
1375 | inno->irq = platform_get_irq(pdev, 0); |
1376 | if (inno->irq > 0) { |
1377 | ret = devm_request_threaded_irq(dev: inno->dev, irq: inno->irq, |
1378 | handler: inno_hdmi_phy_rk3328_hardirq, |
1379 | thread_fn: inno_hdmi_phy_rk3328_irq, |
1380 | IRQF_SHARED, |
1381 | devname: dev_name(dev: inno->dev), dev_id: inno); |
1382 | if (ret) |
1383 | return ret; |
1384 | } |
1385 | |
1386 | inno->phy = devm_phy_create(dev: inno->dev, NULL, ops: &inno_hdmi_phy_ops); |
1387 | if (IS_ERR(ptr: inno->phy)) { |
1388 | dev_err(inno->dev, "failed to create HDMI PHY\n" ); |
1389 | return PTR_ERR(ptr: inno->phy); |
1390 | } |
1391 | |
1392 | phy_set_drvdata(phy: inno->phy, data: inno); |
1393 | phy_set_bus_width(phy: inno->phy, bus_width: 8); |
1394 | |
1395 | if (inno->plat_data->ops->init) { |
1396 | ret = inno->plat_data->ops->init(inno); |
1397 | if (ret) |
1398 | return ret; |
1399 | } |
1400 | |
1401 | ret = inno_hdmi_phy_clk_register(inno); |
1402 | if (ret) |
1403 | return ret; |
1404 | |
1405 | phy_provider = devm_of_phy_provider_register(inno->dev, |
1406 | of_phy_simple_xlate); |
1407 | return PTR_ERR_OR_ZERO(ptr: phy_provider); |
1408 | } |
1409 | |
1410 | static void inno_hdmi_phy_remove(struct platform_device *pdev) |
1411 | { |
1412 | of_clk_del_provider(np: pdev->dev.of_node); |
1413 | } |
1414 | |
1415 | static const struct of_device_id inno_hdmi_phy_of_match[] = { |
1416 | { |
1417 | .compatible = "rockchip,rk3228-hdmi-phy" , |
1418 | .data = &rk3228_hdmi_phy_drv_data |
1419 | }, { |
1420 | .compatible = "rockchip,rk3328-hdmi-phy" , |
1421 | .data = &rk3328_hdmi_phy_drv_data |
1422 | }, { /* sentinel */ } |
1423 | }; |
1424 | MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match); |
1425 | |
1426 | static struct platform_driver inno_hdmi_phy_driver = { |
1427 | .probe = inno_hdmi_phy_probe, |
1428 | .remove_new = inno_hdmi_phy_remove, |
1429 | .driver = { |
1430 | .name = "inno-hdmi-phy" , |
1431 | .of_match_table = inno_hdmi_phy_of_match, |
1432 | }, |
1433 | }; |
1434 | module_platform_driver(inno_hdmi_phy_driver); |
1435 | |
1436 | MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>" ); |
1437 | MODULE_DESCRIPTION("Innosilion HDMI 2.0 Transmitter PHY Driver" ); |
1438 | MODULE_LICENSE("GPL v2" ); |
1439 | |