s3c2410-iotiming.c 10 KB

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