| Ben Dooks | 831a6fc | 2009-07-30 23:23:26 +0100 | [diff] [blame] | 1 | /* linux/arch/arm/plat-s3c24xx/s3c2410-iotiming.c | 
|  | 2 | * | 
| Ben Dooks | ccae941 | 2009-11-13 22:54:14 +0000 | [diff] [blame] | 3 | * Copyright (c) 2006-2009 Simtec Electronics | 
| Ben Dooks | 831a6fc | 2009-07-30 23:23:26 +0100 | [diff] [blame] | 4 | *	http://armlinux.simtec.co.uk/ | 
|  | 5 | *	Ben Dooks <ben@simtec.co.uk> | 
|  | 6 | * | 
|  | 7 | * S3C24XX CPU Frequency scaling - IO timing for S3C2410/S3C2440/S3C2442 | 
|  | 8 | * | 
|  | 9 | * This program is free software; you can redistribute it and/or modify | 
|  | 10 | * it under the terms of the GNU General Public License version 2 as | 
|  | 11 | * published by the Free Software Foundation. | 
|  | 12 | */ | 
|  | 13 |  | 
|  | 14 | #include <linux/init.h> | 
|  | 15 | #include <linux/kernel.h> | 
|  | 16 | #include <linux/errno.h> | 
|  | 17 | #include <linux/cpufreq.h> | 
| Ben Dooks | e6d197a | 2009-07-30 23:23:42 +0100 | [diff] [blame] | 18 | #include <linux/seq_file.h> | 
| Ben Dooks | 831a6fc | 2009-07-30 23:23:26 +0100 | [diff] [blame] | 19 | #include <linux/io.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 20 | #include <linux/slab.h> | 
| Ben Dooks | 831a6fc | 2009-07-30 23:23:26 +0100 | [diff] [blame] | 21 |  | 
|  | 22 | #include <mach/map.h> | 
|  | 23 | #include <mach/regs-mem.h> | 
|  | 24 | #include <mach/regs-clock.h> | 
|  | 25 |  | 
|  | 26 | #include <plat/cpu-freq-core.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 | */ | 
|  | 35 | static 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 | */ | 
|  | 60 | static 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 | */ | 
|  | 74 | static 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 | */ | 
|  | 87 | static 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 | */ | 
|  | 105 | static 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 |  | 
|  | 136 | int 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 | */ | 
|  | 153 | static 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 | */ | 
|  | 217 | static 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 |  | 
|  | 252 | static 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 | */ | 
|  | 268 | static 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 | */ | 
|  | 280 | static 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 | */ | 
|  | 295 | void 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 | /** | 
| Ben Dooks | e6d197a | 2009-07-30 23:23:42 +0100 | [diff] [blame] | 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 | */ | 
|  | 314 | void 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 | /** | 
| Ben Dooks | 831a6fc | 2009-07-30 23:23:26 +0100 | [diff] [blame] | 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 | */ | 
|  | 361 | int 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 | */ | 
|  | 403 | void 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 |  | 
|  | 435 | int 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 | } |