1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
4 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
5 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
8 * clock and PLL management functions
11 #include <linux/kernel.h>
12 #include <linux/via-core.h>
14 #include "via_clock.h"
18 static const char *via_slap
= "Please slap VIA Technologies to motivate them "
19 "releasing full documentation for your platform!\n";
21 static inline u32
cle266_encode_pll(struct via_pll_config pll
)
23 return (pll
.multiplier
<< 8)
28 static inline u32
k800_encode_pll(struct via_pll_config pll
)
30 return ((pll
.divisor
- 2) << 16)
32 | (pll
.multiplier
- 2);
35 static inline u32
vx855_encode_pll(struct via_pll_config pll
)
37 return (pll
.divisor
<< 16)
42 static inline void cle266_set_primary_pll_encoded(u32 data
)
44 via_write_reg_mask(VIASR
, 0x40, 0x02, 0x02); /* enable reset */
45 via_write_reg(VIASR
, 0x46, data
& 0xFF);
46 via_write_reg(VIASR
, 0x47, (data
>> 8) & 0xFF);
47 via_write_reg_mask(VIASR
, 0x40, 0x00, 0x02); /* disable reset */
50 static inline void k800_set_primary_pll_encoded(u32 data
)
52 via_write_reg_mask(VIASR
, 0x40, 0x02, 0x02); /* enable reset */
53 via_write_reg(VIASR
, 0x44, data
& 0xFF);
54 via_write_reg(VIASR
, 0x45, (data
>> 8) & 0xFF);
55 via_write_reg(VIASR
, 0x46, (data
>> 16) & 0xFF);
56 via_write_reg_mask(VIASR
, 0x40, 0x00, 0x02); /* disable reset */
59 static inline void cle266_set_secondary_pll_encoded(u32 data
)
61 via_write_reg_mask(VIASR
, 0x40, 0x04, 0x04); /* enable reset */
62 via_write_reg(VIASR
, 0x44, data
& 0xFF);
63 via_write_reg(VIASR
, 0x45, (data
>> 8) & 0xFF);
64 via_write_reg_mask(VIASR
, 0x40, 0x00, 0x04); /* disable reset */
67 static inline void k800_set_secondary_pll_encoded(u32 data
)
69 via_write_reg_mask(VIASR
, 0x40, 0x04, 0x04); /* enable reset */
70 via_write_reg(VIASR
, 0x4A, data
& 0xFF);
71 via_write_reg(VIASR
, 0x4B, (data
>> 8) & 0xFF);
72 via_write_reg(VIASR
, 0x4C, (data
>> 16) & 0xFF);
73 via_write_reg_mask(VIASR
, 0x40, 0x00, 0x04); /* disable reset */
76 static inline void set_engine_pll_encoded(u32 data
)
78 via_write_reg_mask(VIASR
, 0x40, 0x01, 0x01); /* enable reset */
79 via_write_reg(VIASR
, 0x47, data
& 0xFF);
80 via_write_reg(VIASR
, 0x48, (data
>> 8) & 0xFF);
81 via_write_reg(VIASR
, 0x49, (data
>> 16) & 0xFF);
82 via_write_reg_mask(VIASR
, 0x40, 0x00, 0x01); /* disable reset */
85 static void cle266_set_primary_pll(struct via_pll_config config
)
87 cle266_set_primary_pll_encoded(cle266_encode_pll(config
));
90 static void k800_set_primary_pll(struct via_pll_config config
)
92 k800_set_primary_pll_encoded(k800_encode_pll(config
));
95 static void vx855_set_primary_pll(struct via_pll_config config
)
97 k800_set_primary_pll_encoded(vx855_encode_pll(config
));
100 static void cle266_set_secondary_pll(struct via_pll_config config
)
102 cle266_set_secondary_pll_encoded(cle266_encode_pll(config
));
105 static void k800_set_secondary_pll(struct via_pll_config config
)
107 k800_set_secondary_pll_encoded(k800_encode_pll(config
));
110 static void vx855_set_secondary_pll(struct via_pll_config config
)
112 k800_set_secondary_pll_encoded(vx855_encode_pll(config
));
115 static void k800_set_engine_pll(struct via_pll_config config
)
117 set_engine_pll_encoded(k800_encode_pll(config
));
120 static void vx855_set_engine_pll(struct via_pll_config config
)
122 set_engine_pll_encoded(vx855_encode_pll(config
));
125 static void set_primary_pll_state(u8 state
)
140 via_write_reg_mask(VIASR
, 0x2D, value
, 0x30);
143 static void set_secondary_pll_state(u8 state
)
158 via_write_reg_mask(VIASR
, 0x2D, value
, 0x0C);
161 static void set_engine_pll_state(u8 state
)
176 via_write_reg_mask(VIASR
, 0x2D, value
, 0x03);
179 static void set_primary_clock_state(u8 state
)
194 via_write_reg_mask(VIASR
, 0x1B, value
, 0x30);
197 static void set_secondary_clock_state(u8 state
)
212 via_write_reg_mask(VIASR
, 0x1B, value
, 0xC0);
215 static inline u8
set_clock_source_common(enum via_clksrc source
, bool use_pll
)
223 case VIA_CLKSRC_TVX1
:
226 case VIA_CLKSRC_TVPLL
:
227 data
= 0x04; /* 0x06 should be the same */
229 case VIA_CLKSRC_DVP1TVCLKR
:
232 case VIA_CLKSRC_CAP0
:
235 case VIA_CLKSRC_CAP1
:
246 static void set_primary_clock_source(enum via_clksrc source
, bool use_pll
)
248 u8 data
= set_clock_source_common(source
, use_pll
) << 4;
249 via_write_reg_mask(VIACR
, 0x6C, data
, 0xF0);
252 static void set_secondary_clock_source(enum via_clksrc source
, bool use_pll
)
254 u8 data
= set_clock_source_common(source
, use_pll
);
255 via_write_reg_mask(VIACR
, 0x6C, data
, 0x0F);
258 static void dummy_set_clock_state(u8 state
)
260 printk(KERN_INFO
"Using undocumented set clock state.\n%s", via_slap
);
263 static void dummy_set_clock_source(enum via_clksrc source
, bool use_pll
)
265 printk(KERN_INFO
"Using undocumented set clock source.\n%s", via_slap
);
268 static void dummy_set_pll_state(u8 state
)
270 printk(KERN_INFO
"Using undocumented set PLL state.\n%s", via_slap
);
273 static void dummy_set_pll(struct via_pll_config config
)
275 printk(KERN_INFO
"Using undocumented set PLL.\n%s", via_slap
);
278 static void noop_set_clock_state(u8 state
)
282 void via_clock_init(struct via_clock
*clock
, int gfx_chip
)
285 case UNICHROME_CLE266
:
287 clock
->set_primary_clock_state
= dummy_set_clock_state
;
288 clock
->set_primary_clock_source
= dummy_set_clock_source
;
289 clock
->set_primary_pll_state
= dummy_set_pll_state
;
290 clock
->set_primary_pll
= cle266_set_primary_pll
;
292 clock
->set_secondary_clock_state
= dummy_set_clock_state
;
293 clock
->set_secondary_clock_source
= dummy_set_clock_source
;
294 clock
->set_secondary_pll_state
= dummy_set_pll_state
;
295 clock
->set_secondary_pll
= cle266_set_secondary_pll
;
297 clock
->set_engine_pll_state
= dummy_set_pll_state
;
298 clock
->set_engine_pll
= dummy_set_pll
;
301 case UNICHROME_PM800
:
302 case UNICHROME_CN700
:
303 case UNICHROME_CX700
:
304 case UNICHROME_CN750
:
305 case UNICHROME_K8M890
:
306 case UNICHROME_P4M890
:
307 case UNICHROME_P4M900
:
308 case UNICHROME_VX800
:
309 clock
->set_primary_clock_state
= set_primary_clock_state
;
310 clock
->set_primary_clock_source
= set_primary_clock_source
;
311 clock
->set_primary_pll_state
= set_primary_pll_state
;
312 clock
->set_primary_pll
= k800_set_primary_pll
;
314 clock
->set_secondary_clock_state
= set_secondary_clock_state
;
315 clock
->set_secondary_clock_source
= set_secondary_clock_source
;
316 clock
->set_secondary_pll_state
= set_secondary_pll_state
;
317 clock
->set_secondary_pll
= k800_set_secondary_pll
;
319 clock
->set_engine_pll_state
= set_engine_pll_state
;
320 clock
->set_engine_pll
= k800_set_engine_pll
;
322 case UNICHROME_VX855
:
323 case UNICHROME_VX900
:
324 clock
->set_primary_clock_state
= set_primary_clock_state
;
325 clock
->set_primary_clock_source
= set_primary_clock_source
;
326 clock
->set_primary_pll_state
= set_primary_pll_state
;
327 clock
->set_primary_pll
= vx855_set_primary_pll
;
329 clock
->set_secondary_clock_state
= set_secondary_clock_state
;
330 clock
->set_secondary_clock_source
= set_secondary_clock_source
;
331 clock
->set_secondary_pll_state
= set_secondary_pll_state
;
332 clock
->set_secondary_pll
= vx855_set_secondary_pll
;
334 clock
->set_engine_pll_state
= set_engine_pll_state
;
335 clock
->set_engine_pll
= vx855_set_engine_pll
;
340 if (machine_is_olpc()) {
341 /* The OLPC XO-1.5 cannot suspend/resume reliably if the
342 * IGA1/IGA2 clocks are set as on or off (memory rot
343 * occasionally happens during suspend under such
346 * The only known stable scenario is to leave this bits as-is,
347 * which in their default states are documented to enable the
348 * clock only when it is needed.
350 clock
->set_primary_clock_state
= noop_set_clock_state
;
351 clock
->set_secondary_clock_state
= noop_set_clock_state
;