1/* 2 * Copyright (c) 2006-2009 Simtec Electronics 3 * http://armlinux.simtec.co.uk/ 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * S3C24XX CPU Frequency scaling - IO timing for S3C2410/S3C2440/S3C2442 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11*/ 12 13#include <linux/init.h> 14#include <linux/kernel.h> 15#include <linux/errno.h> 16#include <linux/cpufreq.h> 17#include <linux/seq_file.h> 18#include <linux/io.h> 19#include <linux/slab.h> 20 21#include <mach/map.h> 22#include <mach/regs-clock.h> 23 24#include <plat/cpu-freq-core.h> 25 26#include "regs-mem.h" 27 28#define print_ns(x) ((x) / 10), ((x) % 10) 29 30/** 31 * s3c2410_print_timing - print bank timing data for debug purposes 32 * @pfx: The prefix to put on the output 33 * @timings: The timing inforamtion to print. 34*/ 35static void s3c2410_print_timing(const char *pfx, 36 struct s3c_iotimings *timings) 37{ 38 struct s3c2410_iobank_timing *bt; 39 int bank; 40 41 for (bank = 0; bank < MAX_BANKS; bank++) { 42 bt = timings->bank[bank].io_2410; 43 if (!bt) 44 continue; 45 46 printk(KERN_DEBUG "%s %d: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, " 47 "Tcoh=%d.%d, Tcah=%d.%d\n", pfx, bank, 48 print_ns(bt->tacs), 49 print_ns(bt->tcos), 50 print_ns(bt->tacc), 51 print_ns(bt->tcoh), 52 print_ns(bt->tcah)); 53 } 54} 55 56/** 57 * bank_reg - convert bank number to pointer to the control register. 58 * @bank: The IO bank number. 59 */ 60static inline void __iomem *bank_reg(unsigned int bank) 61{ 62 return S3C2410_BANKCON0 + (bank << 2); 63} 64 65/** 66 * bank_is_io - test whether bank is used for IO 67 * @bankcon: The bank control register. 68 * 69 * This is a simplistic test to see if any BANKCON[x] is not an IO 70 * bank. It currently does not take into account whether BWSCON has 71 * an illegal width-setting in it, or if the pin connected to nCS[x] 72 * is actually being handled as a chip-select. 73 */ 74static inline int bank_is_io(unsigned long bankcon) 75{ 76 return !(bankcon & S3C2410_BANKCON_SDRAM); 77} 78 79/** 80 * to_div - convert cycle time to divisor 81 * @cyc: The cycle time, in 10ths of nanoseconds. 82 * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. 83 * 84 * Convert the given cycle time into the divisor to use to obtain it from 85 * HCLK. 86*/ 87static inline unsigned int to_div(unsigned int cyc, unsigned int hclk_tns) 88{ 89 if (cyc == 0) 90 return 0; 91 92 return DIV_ROUND_UP(cyc, hclk_tns); 93} 94 95/** 96 * calc_0124 - calculate divisor control for divisors that do /0, /1. /2 and /4 97 * @cyc: The cycle time, in 10ths of nanoseconds. 98 * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. 99 * @v: Pointer to register to alter. 100 * @shift: The shift to get to the control bits. 101 * 102 * Calculate the divisor, and turn it into the correct control bits to 103 * set in the result, @v. 104 */ 105static unsigned int calc_0124(unsigned int cyc, unsigned long hclk_tns, 106 unsigned long *v, int shift) 107{ 108 unsigned int div = to_div(cyc, hclk_tns); 109 unsigned long val; 110 111 s3c_freq_iodbg("%s: cyc=%d, hclk=%lu, shift=%d => div %d\n", 112 __func__, cyc, hclk_tns, shift, div); 113 114 switch (div) { 115 case 0: 116 val = 0; 117 break; 118 case 1: 119 val = 1; 120 break; 121 case 2: 122 val = 2; 123 break; 124 case 3: 125 case 4: 126 val = 3; 127 break; 128 default: 129 return -1; 130 } 131 132 *v |= val << shift; 133 return 0; 134} 135 136int calc_tacp(unsigned int cyc, unsigned long hclk, unsigned long *v) 137{ 138 /* Currently no support for Tacp calculations. */ 139 return 0; 140} 141 142/** 143 * calc_tacc - calculate divisor control for tacc. 144 * @cyc: The cycle time, in 10ths of nanoseconds. 145 * @nwait_en: IS nWAIT enabled for this bank. 146 * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. 147 * @v: Pointer to register to alter. 148 * 149 * Calculate the divisor control for tACC, taking into account whether 150 * the bank has nWAIT enabled. The result is used to modify the value 151 * pointed to by @v. 152*/ 153static int calc_tacc(unsigned int cyc, int nwait_en, 154 unsigned long hclk_tns, unsigned long *v) 155{ 156 unsigned int div = to_div(cyc, hclk_tns); 157 unsigned long val; 158 159 s3c_freq_iodbg("%s: cyc=%u, nwait=%d, hclk=%lu => div=%u\n", 160 __func__, cyc, nwait_en, hclk_tns, div); 161 162 /* if nWait enabled on an bank, Tacc must be at-least 4 cycles. */ 163 if (nwait_en && div < 4) 164 div = 4; 165 166 switch (div) { 167 case 0: 168 val = 0; 169 break; 170 171 case 1: 172 case 2: 173 case 3: 174 case 4: 175 val = div - 1; 176 break; 177 178 case 5: 179 case 6: 180 val = 4; 181 break; 182 183 case 7: 184 case 8: 185 val = 5; 186 break; 187 188 case 9: 189 case 10: 190 val = 6; 191 break; 192 193 case 11: 194 case 12: 195 case 13: 196 case 14: 197 val = 7; 198 break; 199 200 default: 201 return -1; 202 } 203 204 *v |= val << 8; 205 return 0; 206} 207 208/** 209 * s3c2410_calc_bank - calculate bank timing infromation 210 * @cfg: The configuration we need to calculate for. 211 * @bt: The bank timing information. 212 * 213 * Given the cycle timine for a bank @bt, calculate the new BANKCON 214 * setting for the @cfg timing. This updates the timing information 215 * ready for the cpu frequency change. 216 */ 217static int s3c2410_calc_bank(struct s3c_cpufreq_config *cfg, 218 struct s3c2410_iobank_timing *bt) 219{ 220 unsigned long hclk = cfg->freq.hclk_tns; 221 unsigned long res; 222 int ret; 223 224 res = bt->bankcon; 225 res &= (S3C2410_BANKCON_SDRAM | S3C2410_BANKCON_PMC16); 226 227 /* tacp: 2,3,4,5 */ 228 /* tcah: 0,1,2,4 */ 229 /* tcoh: 0,1,2,4 */ 230 /* tacc: 1,2,3,4,6,7,10,14 (>4 for nwait) */ 231 /* tcos: 0,1,2,4 */ 232 /* tacs: 0,1,2,4 */ 233 234 ret = calc_0124(bt->tacs, hclk, &res, S3C2410_BANKCON_Tacs_SHIFT); 235 ret |= calc_0124(bt->tcos, hclk, &res, S3C2410_BANKCON_Tcos_SHIFT); 236 ret |= calc_0124(bt->tcah, hclk, &res, S3C2410_BANKCON_Tcah_SHIFT); 237 ret |= calc_0124(bt->tcoh, hclk, &res, S3C2410_BANKCON_Tcoh_SHIFT); 238 239 if (ret) 240 return -EINVAL; 241 242 ret |= calc_tacp(bt->tacp, hclk, &res); 243 ret |= calc_tacc(bt->tacc, bt->nwait_en, hclk, &res); 244 245 if (ret) 246 return -EINVAL; 247 248 bt->bankcon = res; 249 return 0; 250} 251 252static unsigned int tacc_tab[] = { 253 [0] = 1, 254 [1] = 2, 255 [2] = 3, 256 [3] = 4, 257 [4] = 6, 258 [5] = 9, 259 [6] = 10, 260 [7] = 14, 261}; 262 263/** 264 * get_tacc - turn tACC value into cycle time 265 * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. 266 * @val: The bank timing register value, shifed down. 267 */ 268static unsigned int get_tacc(unsigned long hclk_tns, 269 unsigned long val) 270{ 271 val &= 7; 272 return hclk_tns * tacc_tab[val]; 273} 274 275/** 276 * get_0124 - turn 0/1/2/4 divider into cycle time 277 * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. 278 * @val: The bank timing register value, shifed down. 279 */ 280static unsigned int get_0124(unsigned long hclk_tns, 281 unsigned long val) 282{ 283 val &= 3; 284 return hclk_tns * ((val == 3) ? 4 : val); 285} 286 287/** 288 * s3c2410_iotiming_getbank - turn BANKCON into cycle time information 289 * @cfg: The frequency configuration 290 * @bt: The bank timing to fill in (uses cached BANKCON) 291 * 292 * Given the BANKCON setting in @bt and the current frequency settings 293 * in @cfg, update the cycle timing information. 294 */ 295void s3c2410_iotiming_getbank(struct s3c_cpufreq_config *cfg, 296 struct s3c2410_iobank_timing *bt) 297{ 298 unsigned long bankcon = bt->bankcon; 299 unsigned long hclk = cfg->freq.hclk_tns; 300 301 bt->tcah = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcah_SHIFT); 302 bt->tcoh = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcoh_SHIFT); 303 bt->tcos = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcos_SHIFT); 304 bt->tacs = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tacs_SHIFT); 305 bt->tacc = get_tacc(hclk, bankcon >> S3C2410_BANKCON_Tacc_SHIFT); 306} 307 308/** 309 * s3c2410_iotiming_debugfs - debugfs show io bank timing information 310 * @seq: The seq_file to write output to using seq_printf(). 311 * @cfg: The current configuration. 312 * @iob: The IO bank information to decode. 313 */ 314void s3c2410_iotiming_debugfs(struct seq_file *seq, 315 struct s3c_cpufreq_config *cfg, 316 union s3c_iobank *iob) 317{ 318 struct s3c2410_iobank_timing *bt = iob->io_2410; 319 unsigned long bankcon = bt->bankcon; 320 unsigned long hclk = cfg->freq.hclk_tns; 321 unsigned int tacs; 322 unsigned int tcos; 323 unsigned int tacc; 324 unsigned int tcoh; 325 unsigned int tcah; 326 327 seq_printf(seq, "BANKCON=0x%08lx\n", bankcon); 328 329 tcah = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcah_SHIFT); 330 tcoh = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcoh_SHIFT); 331 tcos = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcos_SHIFT); 332 tacs = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tacs_SHIFT); 333 tacc = get_tacc(hclk, bankcon >> S3C2410_BANKCON_Tacc_SHIFT); 334 335 seq_printf(seq, 336 "\tRead: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", 337 print_ns(bt->tacs), 338 print_ns(bt->tcos), 339 print_ns(bt->tacc), 340 print_ns(bt->tcoh), 341 print_ns(bt->tcah)); 342 343 seq_printf(seq, 344 "\t Set: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", 345 print_ns(tacs), 346 print_ns(tcos), 347 print_ns(tacc), 348 print_ns(tcoh), 349 print_ns(tcah)); 350} 351 352/** 353 * s3c2410_iotiming_calc - Calculate bank timing for frequency change. 354 * @cfg: The frequency configuration 355 * @iot: The IO timing information to fill out. 356 * 357 * Calculate the new values for the banks in @iot based on the new 358 * frequency information in @cfg. This is then used by s3c2410_iotiming_set() 359 * to update the timing when necessary. 360 */ 361int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg, 362 struct s3c_iotimings *iot) 363{ 364 struct s3c2410_iobank_timing *bt; 365 unsigned long bankcon; 366 int bank; 367 int ret; 368 369 for (bank = 0; bank < MAX_BANKS; bank++) { 370 bankcon = __raw_readl(bank_reg(bank)); 371 bt = iot->bank[bank].io_2410; 372 373 if (!bt) 374 continue; 375 376 bt->bankcon = bankcon; 377 378 ret = s3c2410_calc_bank(cfg, bt); 379 if (ret) { 380 printk(KERN_ERR "%s: cannot calculate bank %d io\n", 381 __func__, bank); 382 goto err; 383 } 384 385 s3c_freq_iodbg("%s: bank %d: con=%08lx\n", 386 __func__, bank, bt->bankcon); 387 } 388 389 return 0; 390 err: 391 return ret; 392} 393 394/** 395 * s3c2410_iotiming_set - set the IO timings from the given setup. 396 * @cfg: The frequency configuration 397 * @iot: The IO timing information to use. 398 * 399 * Set all the currently used IO bank timing information generated 400 * by s3c2410_iotiming_calc() once the core has validated that all 401 * the new values are within permitted bounds. 402 */ 403void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg, 404 struct s3c_iotimings *iot) 405{ 406 struct s3c2410_iobank_timing *bt; 407 int bank; 408 409 /* set the io timings from the specifier */ 410 411 for (bank = 0; bank < MAX_BANKS; bank++) { 412 bt = iot->bank[bank].io_2410; 413 if (!bt) 414 continue; 415 416 __raw_writel(bt->bankcon, bank_reg(bank)); 417 } 418} 419 420/** 421 * s3c2410_iotiming_get - Get the timing information from current registers. 422 * @cfg: The frequency configuration 423 * @timings: The IO timing information to fill out. 424 * 425 * Calculate the @timings timing information from the current frequency 426 * information in @cfg, and the new frequency configur 427 * through all the IO banks, reading the state and then updating @iot 428 * as necessary. 429 * 430 * This is used at the moment on initialisation to get the current 431 * configuration so that boards do not have to carry their own setup 432 * if the timings are correct on initialisation. 433 */ 434 435int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg, 436 struct s3c_iotimings *timings) 437{ 438 struct s3c2410_iobank_timing *bt; 439 unsigned long bankcon; 440 unsigned long bwscon; 441 int bank; 442 443 bwscon = __raw_readl(S3C2410_BWSCON); 444 445 /* look through all banks to see what is currently set. */ 446 447 for (bank = 0; bank < MAX_BANKS; bank++) { 448 bankcon = __raw_readl(bank_reg(bank)); 449 450 if (!bank_is_io(bankcon)) 451 continue; 452 453 s3c_freq_iodbg("%s: bank %d: con %08lx\n", 454 __func__, bank, bankcon); 455 456 bt = kzalloc(sizeof(struct s3c2410_iobank_timing), GFP_KERNEL); 457 if (!bt) { 458 printk(KERN_ERR "%s: no memory for bank\n", __func__); 459 return -ENOMEM; 460 } 461 462 /* find out in nWait is enabled for bank. */ 463 464 if (bank != 0) { 465 unsigned long tmp = S3C2410_BWSCON_GET(bwscon, bank); 466 if (tmp & S3C2410_BWSCON_WS) 467 bt->nwait_en = 1; 468 } 469 470 timings->bank[bank].io_2410 = bt; 471 bt->bankcon = bankcon; 472 473 s3c2410_iotiming_getbank(cfg, bt); 474 } 475 476 s3c2410_print_timing("get", timings); 477 return 0; 478} 479