1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 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> 6 */ 7 /* 8 * clock and PLL management functions 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/via-core.h> 13 14 #include "via_clock.h" 15 #include "global.h" 16 #include "debug.h" 17 18 static const char *via_slap = "Please slap VIA Technologies to motivate them " 19 "releasing full documentation for your platform!\n"; 20 21 static inline u32 cle266_encode_pll(struct via_pll_config pll) 22 { 23 return (pll.multiplier << 8) 24 | (pll.rshift << 6) 25 | pll.divisor; 26 } 27 28 static inline u32 k800_encode_pll(struct via_pll_config pll) 29 { 30 return ((pll.divisor - 2) << 16) 31 | (pll.rshift << 10) 32 | (pll.multiplier - 2); 33 } 34 35 static inline u32 vx855_encode_pll(struct via_pll_config pll) 36 { 37 return (pll.divisor << 16) 38 | (pll.rshift << 10) 39 | pll.multiplier; 40 } 41 42 static inline void cle266_set_primary_pll_encoded(u32 data) 43 { 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 */ 48 } 49 50 static inline void k800_set_primary_pll_encoded(u32 data) 51 { 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 */ 57 } 58 59 static inline void cle266_set_secondary_pll_encoded(u32 data) 60 { 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 */ 65 } 66 67 static inline void k800_set_secondary_pll_encoded(u32 data) 68 { 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 */ 74 } 75 76 static inline void set_engine_pll_encoded(u32 data) 77 { 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 */ 83 } 84 85 static void cle266_set_primary_pll(struct via_pll_config config) 86 { 87 cle266_set_primary_pll_encoded(cle266_encode_pll(config)); 88 } 89 90 static void k800_set_primary_pll(struct via_pll_config config) 91 { 92 k800_set_primary_pll_encoded(k800_encode_pll(config)); 93 } 94 95 static void vx855_set_primary_pll(struct via_pll_config config) 96 { 97 k800_set_primary_pll_encoded(vx855_encode_pll(config)); 98 } 99 100 static void cle266_set_secondary_pll(struct via_pll_config config) 101 { 102 cle266_set_secondary_pll_encoded(cle266_encode_pll(config)); 103 } 104 105 static void k800_set_secondary_pll(struct via_pll_config config) 106 { 107 k800_set_secondary_pll_encoded(k800_encode_pll(config)); 108 } 109 110 static void vx855_set_secondary_pll(struct via_pll_config config) 111 { 112 k800_set_secondary_pll_encoded(vx855_encode_pll(config)); 113 } 114 115 static void k800_set_engine_pll(struct via_pll_config config) 116 { 117 set_engine_pll_encoded(k800_encode_pll(config)); 118 } 119 120 static void vx855_set_engine_pll(struct via_pll_config config) 121 { 122 set_engine_pll_encoded(vx855_encode_pll(config)); 123 } 124 125 static void set_primary_pll_state(u8 state) 126 { 127 u8 value; 128 129 switch (state) { 130 case VIA_STATE_ON: 131 value = 0x20; 132 break; 133 case VIA_STATE_OFF: 134 value = 0x00; 135 break; 136 default: 137 return; 138 } 139 140 via_write_reg_mask(VIASR, 0x2D, value, 0x30); 141 } 142 143 static void set_secondary_pll_state(u8 state) 144 { 145 u8 value; 146 147 switch (state) { 148 case VIA_STATE_ON: 149 value = 0x08; 150 break; 151 case VIA_STATE_OFF: 152 value = 0x00; 153 break; 154 default: 155 return; 156 } 157 158 via_write_reg_mask(VIASR, 0x2D, value, 0x0C); 159 } 160 161 static void set_engine_pll_state(u8 state) 162 { 163 u8 value; 164 165 switch (state) { 166 case VIA_STATE_ON: 167 value = 0x02; 168 break; 169 case VIA_STATE_OFF: 170 value = 0x00; 171 break; 172 default: 173 return; 174 } 175 176 via_write_reg_mask(VIASR, 0x2D, value, 0x03); 177 } 178 179 static void set_primary_clock_state(u8 state) 180 { 181 u8 value; 182 183 switch (state) { 184 case VIA_STATE_ON: 185 value = 0x20; 186 break; 187 case VIA_STATE_OFF: 188 value = 0x00; 189 break; 190 default: 191 return; 192 } 193 194 via_write_reg_mask(VIASR, 0x1B, value, 0x30); 195 } 196 197 static void set_secondary_clock_state(u8 state) 198 { 199 u8 value; 200 201 switch (state) { 202 case VIA_STATE_ON: 203 value = 0x80; 204 break; 205 case VIA_STATE_OFF: 206 value = 0x00; 207 break; 208 default: 209 return; 210 } 211 212 via_write_reg_mask(VIASR, 0x1B, value, 0xC0); 213 } 214 215 static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll) 216 { 217 u8 data = 0; 218 219 switch (source) { 220 case VIA_CLKSRC_X1: 221 data = 0x00; 222 break; 223 case VIA_CLKSRC_TVX1: 224 data = 0x02; 225 break; 226 case VIA_CLKSRC_TVPLL: 227 data = 0x04; /* 0x06 should be the same */ 228 break; 229 case VIA_CLKSRC_DVP1TVCLKR: 230 data = 0x0A; 231 break; 232 case VIA_CLKSRC_CAP0: 233 data = 0xC; 234 break; 235 case VIA_CLKSRC_CAP1: 236 data = 0x0E; 237 break; 238 } 239 240 if (!use_pll) 241 data |= 1; 242 243 return data; 244 } 245 246 static void set_primary_clock_source(enum via_clksrc source, bool use_pll) 247 { 248 u8 data = set_clock_source_common(source, use_pll) << 4; 249 via_write_reg_mask(VIACR, 0x6C, data, 0xF0); 250 } 251 252 static void set_secondary_clock_source(enum via_clksrc source, bool use_pll) 253 { 254 u8 data = set_clock_source_common(source, use_pll); 255 via_write_reg_mask(VIACR, 0x6C, data, 0x0F); 256 } 257 258 static void dummy_set_clock_state(u8 state) 259 { 260 printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap); 261 } 262 263 static void dummy_set_clock_source(enum via_clksrc source, bool use_pll) 264 { 265 printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap); 266 } 267 268 static void dummy_set_pll_state(u8 state) 269 { 270 printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap); 271 } 272 273 static void dummy_set_pll(struct via_pll_config config) 274 { 275 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); 276 } 277 278 static void noop_set_clock_state(u8 state) 279 { 280 } 281 282 void via_clock_init(struct via_clock *clock, int gfx_chip) 283 { 284 switch (gfx_chip) { 285 case UNICHROME_CLE266: 286 case UNICHROME_K400: 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; 291 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; 296 297 clock->set_engine_pll_state = dummy_set_pll_state; 298 clock->set_engine_pll = dummy_set_pll; 299 break; 300 case UNICHROME_K800: 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; 313 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; 318 319 clock->set_engine_pll_state = set_engine_pll_state; 320 clock->set_engine_pll = k800_set_engine_pll; 321 break; 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; 328 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; 333 334 clock->set_engine_pll_state = set_engine_pll_state; 335 clock->set_engine_pll = vx855_set_engine_pll; 336 break; 337 338 } 339 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 344 * configurations). 345 * 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. 349 */ 350 clock->set_primary_clock_state = noop_set_clock_state; 351 clock->set_secondary_clock_state = noop_set_clock_state; 352 } 353 } 354