1 /* 2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 4 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public 8 * License as published by the Free Software Foundation; 9 * either version 2, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even 13 * the implied warranty of MERCHANTABILITY or FITNESS FOR 14 * A PARTICULAR PURPOSE.See the GNU General Public License 15 * for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 */ 22 /* 23 * clock and PLL management functions 24 */ 25 26 #include <linux/kernel.h> 27 #include <linux/via-core.h> 28 29 #include "via_clock.h" 30 #include "global.h" 31 #include "debug.h" 32 33 static const char *via_slap = "Please slap VIA Technologies to motivate them " 34 "releasing full documentation for your platform!\n"; 35 36 static inline u32 cle266_encode_pll(struct via_pll_config pll) 37 { 38 return (pll.multiplier << 8) 39 | (pll.rshift << 6) 40 | pll.divisor; 41 } 42 43 static inline u32 k800_encode_pll(struct via_pll_config pll) 44 { 45 return ((pll.divisor - 2) << 16) 46 | (pll.rshift << 10) 47 | (pll.multiplier - 2); 48 } 49 50 static inline u32 vx855_encode_pll(struct via_pll_config pll) 51 { 52 return (pll.divisor << 16) 53 | (pll.rshift << 10) 54 | pll.multiplier; 55 } 56 57 static inline void cle266_set_primary_pll_encoded(u32 data) 58 { 59 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */ 60 via_write_reg(VIASR, 0x46, data & 0xFF); 61 via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF); 62 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */ 63 } 64 65 static inline void k800_set_primary_pll_encoded(u32 data) 66 { 67 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */ 68 via_write_reg(VIASR, 0x44, data & 0xFF); 69 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF); 70 via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF); 71 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */ 72 } 73 74 static inline void cle266_set_secondary_pll_encoded(u32 data) 75 { 76 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */ 77 via_write_reg(VIASR, 0x44, data & 0xFF); 78 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF); 79 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */ 80 } 81 82 static inline void k800_set_secondary_pll_encoded(u32 data) 83 { 84 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */ 85 via_write_reg(VIASR, 0x4A, data & 0xFF); 86 via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF); 87 via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF); 88 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */ 89 } 90 91 static inline void set_engine_pll_encoded(u32 data) 92 { 93 via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */ 94 via_write_reg(VIASR, 0x47, data & 0xFF); 95 via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF); 96 via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF); 97 via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */ 98 } 99 100 static void cle266_set_primary_pll(struct via_pll_config config) 101 { 102 cle266_set_primary_pll_encoded(cle266_encode_pll(config)); 103 } 104 105 static void k800_set_primary_pll(struct via_pll_config config) 106 { 107 k800_set_primary_pll_encoded(k800_encode_pll(config)); 108 } 109 110 static void vx855_set_primary_pll(struct via_pll_config config) 111 { 112 k800_set_primary_pll_encoded(vx855_encode_pll(config)); 113 } 114 115 static void cle266_set_secondary_pll(struct via_pll_config config) 116 { 117 cle266_set_secondary_pll_encoded(cle266_encode_pll(config)); 118 } 119 120 static void k800_set_secondary_pll(struct via_pll_config config) 121 { 122 k800_set_secondary_pll_encoded(k800_encode_pll(config)); 123 } 124 125 static void vx855_set_secondary_pll(struct via_pll_config config) 126 { 127 k800_set_secondary_pll_encoded(vx855_encode_pll(config)); 128 } 129 130 static void k800_set_engine_pll(struct via_pll_config config) 131 { 132 set_engine_pll_encoded(k800_encode_pll(config)); 133 } 134 135 static void vx855_set_engine_pll(struct via_pll_config config) 136 { 137 set_engine_pll_encoded(vx855_encode_pll(config)); 138 } 139 140 static void set_primary_pll_state(u8 state) 141 { 142 u8 value; 143 144 switch (state) { 145 case VIA_STATE_ON: 146 value = 0x20; 147 break; 148 case VIA_STATE_OFF: 149 value = 0x00; 150 break; 151 default: 152 return; 153 } 154 155 via_write_reg_mask(VIASR, 0x2D, value, 0x30); 156 } 157 158 static void set_secondary_pll_state(u8 state) 159 { 160 u8 value; 161 162 switch (state) { 163 case VIA_STATE_ON: 164 value = 0x08; 165 break; 166 case VIA_STATE_OFF: 167 value = 0x00; 168 break; 169 default: 170 return; 171 } 172 173 via_write_reg_mask(VIASR, 0x2D, value, 0x0C); 174 } 175 176 static void set_engine_pll_state(u8 state) 177 { 178 u8 value; 179 180 switch (state) { 181 case VIA_STATE_ON: 182 value = 0x02; 183 break; 184 case VIA_STATE_OFF: 185 value = 0x00; 186 break; 187 default: 188 return; 189 } 190 191 via_write_reg_mask(VIASR, 0x2D, value, 0x03); 192 } 193 194 static void set_primary_clock_state(u8 state) 195 { 196 u8 value; 197 198 switch (state) { 199 case VIA_STATE_ON: 200 value = 0x20; 201 break; 202 case VIA_STATE_OFF: 203 value = 0x00; 204 break; 205 default: 206 return; 207 } 208 209 via_write_reg_mask(VIASR, 0x1B, value, 0x30); 210 } 211 212 static void set_secondary_clock_state(u8 state) 213 { 214 u8 value; 215 216 switch (state) { 217 case VIA_STATE_ON: 218 value = 0x80; 219 break; 220 case VIA_STATE_OFF: 221 value = 0x00; 222 break; 223 default: 224 return; 225 } 226 227 via_write_reg_mask(VIASR, 0x1B, value, 0xC0); 228 } 229 230 static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll) 231 { 232 u8 data = 0; 233 234 switch (source) { 235 case VIA_CLKSRC_X1: 236 data = 0x00; 237 break; 238 case VIA_CLKSRC_TVX1: 239 data = 0x02; 240 break; 241 case VIA_CLKSRC_TVPLL: 242 data = 0x04; /* 0x06 should be the same */ 243 break; 244 case VIA_CLKSRC_DVP1TVCLKR: 245 data = 0x0A; 246 break; 247 case VIA_CLKSRC_CAP0: 248 data = 0xC; 249 break; 250 case VIA_CLKSRC_CAP1: 251 data = 0x0E; 252 break; 253 } 254 255 if (!use_pll) 256 data |= 1; 257 258 return data; 259 } 260 261 static void set_primary_clock_source(enum via_clksrc source, bool use_pll) 262 { 263 u8 data = set_clock_source_common(source, use_pll) << 4; 264 via_write_reg_mask(VIACR, 0x6C, data, 0xF0); 265 } 266 267 static void set_secondary_clock_source(enum via_clksrc source, bool use_pll) 268 { 269 u8 data = set_clock_source_common(source, use_pll); 270 via_write_reg_mask(VIACR, 0x6C, data, 0x0F); 271 } 272 273 static void dummy_set_clock_state(u8 state) 274 { 275 printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap); 276 } 277 278 static void dummy_set_clock_source(enum via_clksrc source, bool use_pll) 279 { 280 printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap); 281 } 282 283 static void dummy_set_pll_state(u8 state) 284 { 285 printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap); 286 } 287 288 static void dummy_set_pll(struct via_pll_config config) 289 { 290 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); 291 } 292 293 static void noop_set_clock_state(u8 state) 294 { 295 } 296 297 void via_clock_init(struct via_clock *clock, int gfx_chip) 298 { 299 switch (gfx_chip) { 300 case UNICHROME_CLE266: 301 case UNICHROME_K400: 302 clock->set_primary_clock_state = dummy_set_clock_state; 303 clock->set_primary_clock_source = dummy_set_clock_source; 304 clock->set_primary_pll_state = dummy_set_pll_state; 305 clock->set_primary_pll = cle266_set_primary_pll; 306 307 clock->set_secondary_clock_state = dummy_set_clock_state; 308 clock->set_secondary_clock_source = dummy_set_clock_source; 309 clock->set_secondary_pll_state = dummy_set_pll_state; 310 clock->set_secondary_pll = cle266_set_secondary_pll; 311 312 clock->set_engine_pll_state = dummy_set_pll_state; 313 clock->set_engine_pll = dummy_set_pll; 314 break; 315 case UNICHROME_K800: 316 case UNICHROME_PM800: 317 case UNICHROME_CN700: 318 case UNICHROME_CX700: 319 case UNICHROME_CN750: 320 case UNICHROME_K8M890: 321 case UNICHROME_P4M890: 322 case UNICHROME_P4M900: 323 case UNICHROME_VX800: 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 = k800_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 = k800_set_secondary_pll; 333 334 clock->set_engine_pll_state = set_engine_pll_state; 335 clock->set_engine_pll = k800_set_engine_pll; 336 break; 337 case UNICHROME_VX855: 338 case UNICHROME_VX900: 339 clock->set_primary_clock_state = set_primary_clock_state; 340 clock->set_primary_clock_source = set_primary_clock_source; 341 clock->set_primary_pll_state = set_primary_pll_state; 342 clock->set_primary_pll = vx855_set_primary_pll; 343 344 clock->set_secondary_clock_state = set_secondary_clock_state; 345 clock->set_secondary_clock_source = set_secondary_clock_source; 346 clock->set_secondary_pll_state = set_secondary_pll_state; 347 clock->set_secondary_pll = vx855_set_secondary_pll; 348 349 clock->set_engine_pll_state = set_engine_pll_state; 350 clock->set_engine_pll = vx855_set_engine_pll; 351 break; 352 353 } 354 355 if (machine_is_olpc()) { 356 /* The OLPC XO-1.5 cannot suspend/resume reliably if the 357 * IGA1/IGA2 clocks are set as on or off (memory rot 358 * occasionally happens during suspend under such 359 * configurations). 360 * 361 * The only known stable scenario is to leave this bits as-is, 362 * which in their default states are documented to enable the 363 * clock only when it is needed. 364 */ 365 clock->set_primary_clock_state = noop_set_clock_state; 366 clock->set_secondary_clock_state = noop_set_clock_state; 367 } 368 } 369