common.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * linux/arch/arm/plat-omap/common.c
  3. *
  4. * Code common to all OMAP machines.
  5. * The file is created by Tony Lindgren <tony@atomide.com>
  6. *
  7. * Copyright (C) 2009 Texas Instruments
  8. * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/init.h>
  17. #include <linux/delay.h>
  18. #include <linux/console.h>
  19. #include <linux/serial.h>
  20. #include <linux/tty.h>
  21. #include <linux/serial_8250.h>
  22. #include <linux/serial_reg.h>
  23. #include <linux/clk.h>
  24. #include <linux/io.h>
  25. #include <mach/hardware.h>
  26. #include <asm/system.h>
  27. #include <asm/pgtable.h>
  28. #include <asm/mach/map.h>
  29. #include <asm/setup.h>
  30. #include <mach/common.h>
  31. #include <mach/board.h>
  32. #include <mach/control.h>
  33. #include <mach/mux.h>
  34. #include <mach/fpga.h>
  35. #include <mach/clock.h>
  36. #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
  37. # include "../mach-omap2/sdrc.h"
  38. #endif
  39. #define NO_LENGTH_CHECK 0xffffffff
  40. unsigned char omap_bootloader_tag[512];
  41. int omap_bootloader_tag_len;
  42. struct omap_board_config_kernel *omap_board_config;
  43. int omap_board_config_size;
  44. static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
  45. {
  46. struct omap_board_config_kernel *kinfo = NULL;
  47. int i;
  48. #ifdef CONFIG_OMAP_BOOT_TAG
  49. struct omap_board_config_entry *info = NULL;
  50. if (omap_bootloader_tag_len > 4)
  51. info = (struct omap_board_config_entry *) omap_bootloader_tag;
  52. while (info != NULL) {
  53. u8 *next;
  54. if (info->tag == tag) {
  55. if (skip == 0)
  56. break;
  57. skip--;
  58. }
  59. if ((info->len & 0x03) != 0) {
  60. /* We bail out to avoid an alignment fault */
  61. printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n",
  62. info->len, info->tag);
  63. return NULL;
  64. }
  65. next = (u8 *) info + sizeof(*info) + info->len;
  66. if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
  67. info = NULL;
  68. else
  69. info = (struct omap_board_config_entry *) next;
  70. }
  71. if (info != NULL) {
  72. /* Check the length as a lame attempt to check for
  73. * binary inconsistency. */
  74. if (len != NO_LENGTH_CHECK) {
  75. /* Word-align len */
  76. if (len & 0x03)
  77. len = (len + 3) & ~0x03;
  78. if (info->len != len) {
  79. printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
  80. tag, len, info->len);
  81. return NULL;
  82. }
  83. }
  84. if (len_out != NULL)
  85. *len_out = info->len;
  86. return info->data;
  87. }
  88. #endif
  89. /* Try to find the config from the board-specific structures
  90. * in the kernel. */
  91. for (i = 0; i < omap_board_config_size; i++) {
  92. if (omap_board_config[i].tag == tag) {
  93. if (skip == 0) {
  94. kinfo = &omap_board_config[i];
  95. break;
  96. } else {
  97. skip--;
  98. }
  99. }
  100. }
  101. if (kinfo == NULL)
  102. return NULL;
  103. return kinfo->data;
  104. }
  105. const void *__omap_get_config(u16 tag, size_t len, int nr)
  106. {
  107. return get_config(tag, len, nr, NULL);
  108. }
  109. EXPORT_SYMBOL(__omap_get_config);
  110. const void *omap_get_var_config(u16 tag, size_t *len)
  111. {
  112. return get_config(tag, NO_LENGTH_CHECK, 0, len);
  113. }
  114. EXPORT_SYMBOL(omap_get_var_config);
  115. static int __init omap_add_serial_console(void)
  116. {
  117. const struct omap_serial_console_config *con_info;
  118. const struct omap_uart_config *uart_info;
  119. static char speed[11], *opt = NULL;
  120. int line, i, uart_idx;
  121. uart_info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
  122. con_info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
  123. struct omap_serial_console_config);
  124. if (uart_info == NULL || con_info == NULL)
  125. return 0;
  126. if (con_info->console_uart == 0)
  127. return 0;
  128. if (con_info->console_speed) {
  129. snprintf(speed, sizeof(speed), "%u", con_info->console_speed);
  130. opt = speed;
  131. }
  132. uart_idx = con_info->console_uart - 1;
  133. if (uart_idx >= OMAP_MAX_NR_PORTS) {
  134. printk(KERN_INFO "Console: external UART#%d. "
  135. "Not adding it as console this time.\n",
  136. uart_idx + 1);
  137. return 0;
  138. }
  139. if (!(uart_info->enabled_uarts & (1 << uart_idx))) {
  140. printk(KERN_ERR "Console: Selected UART#%d is "
  141. "not enabled for this platform\n",
  142. uart_idx + 1);
  143. return -1;
  144. }
  145. line = 0;
  146. for (i = 0; i < uart_idx; i++) {
  147. if (uart_info->enabled_uarts & (1 << i))
  148. line++;
  149. }
  150. return add_preferred_console("ttyS", line, opt);
  151. }
  152. console_initcall(omap_add_serial_console);
  153. /*
  154. * 32KHz clocksource ... always available, on pretty most chips except
  155. * OMAP 730 and 1510. Other timers could be used as clocksources, with
  156. * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  157. * but systems won't necessarily want to spend resources that way.
  158. */
  159. #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410
  160. #if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
  161. #include <linux/clocksource.h>
  162. #ifdef CONFIG_ARCH_OMAP16XX
  163. static cycle_t omap16xx_32k_read(struct clocksource *cs)
  164. {
  165. return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED);
  166. }
  167. #else
  168. #define omap16xx_32k_read NULL
  169. #endif
  170. #ifdef CONFIG_ARCH_OMAP2420
  171. static cycle_t omap2420_32k_read(struct clocksource *cs)
  172. {
  173. return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10);
  174. }
  175. #else
  176. #define omap2420_32k_read NULL
  177. #endif
  178. #ifdef CONFIG_ARCH_OMAP2430
  179. static cycle_t omap2430_32k_read(struct clocksource *cs)
  180. {
  181. return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10);
  182. }
  183. #else
  184. #define omap2430_32k_read NULL
  185. #endif
  186. #ifdef CONFIG_ARCH_OMAP34XX
  187. static cycle_t omap34xx_32k_read(struct clocksource *cs)
  188. {
  189. return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10);
  190. }
  191. #else
  192. #define omap34xx_32k_read NULL
  193. #endif
  194. #ifdef CONFIG_ARCH_OMAP4
  195. static cycle_t omap44xx_32k_read(struct clocksource *cs)
  196. {
  197. return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10);
  198. }
  199. #else
  200. #define omap44xx_32k_read NULL
  201. #endif
  202. /*
  203. * Kernel assumes that sched_clock can be called early but may not have
  204. * things ready yet.
  205. */
  206. static cycle_t omap_32k_read_dummy(struct clocksource *cs)
  207. {
  208. return 0;
  209. }
  210. static struct clocksource clocksource_32k = {
  211. .name = "32k_counter",
  212. .rating = 250,
  213. .read = omap_32k_read_dummy,
  214. .mask = CLOCKSOURCE_MASK(32),
  215. .shift = 10,
  216. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  217. };
  218. /*
  219. * Returns current time from boot in nsecs. It's OK for this to wrap
  220. * around for now, as it's just a relative time stamp.
  221. */
  222. unsigned long long sched_clock(void)
  223. {
  224. unsigned long long ret;
  225. ret = (unsigned long long)clocksource_32k.read(&clocksource_32k);
  226. ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift;
  227. return ret;
  228. }
  229. static int __init omap_init_clocksource_32k(void)
  230. {
  231. static char err[] __initdata = KERN_ERR
  232. "%s: can't register clocksource!\n";
  233. if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
  234. struct clk *sync_32k_ick;
  235. if (cpu_is_omap16xx())
  236. clocksource_32k.read = omap16xx_32k_read;
  237. else if (cpu_is_omap2420())
  238. clocksource_32k.read = omap2420_32k_read;
  239. else if (cpu_is_omap2430())
  240. clocksource_32k.read = omap2430_32k_read;
  241. else if (cpu_is_omap34xx())
  242. clocksource_32k.read = omap34xx_32k_read;
  243. else if (cpu_is_omap44xx())
  244. clocksource_32k.read = omap44xx_32k_read;
  245. else
  246. return -ENODEV;
  247. sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
  248. if (sync_32k_ick)
  249. clk_enable(sync_32k_ick);
  250. clocksource_32k.mult = clocksource_hz2mult(32768,
  251. clocksource_32k.shift);
  252. if (clocksource_register(&clocksource_32k))
  253. printk(err, clocksource_32k.name);
  254. }
  255. return 0;
  256. }
  257. arch_initcall(omap_init_clocksource_32k);
  258. #endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
  259. /* Global address base setup code */
  260. #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
  261. static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
  262. {
  263. omap2_set_globals_tap(omap2_globals);
  264. omap2_set_globals_sdrc(omap2_globals);
  265. omap2_set_globals_control(omap2_globals);
  266. omap2_set_globals_prcm(omap2_globals);
  267. }
  268. #endif
  269. #if defined(CONFIG_ARCH_OMAP2420)
  270. static struct omap_globals omap242x_globals = {
  271. .class = OMAP242X_CLASS,
  272. .tap = OMAP2_IO_ADDRESS(0x48014000),
  273. .sdrc = OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE),
  274. .sms = OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE),
  275. .ctrl = OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE),
  276. .prm = OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE),
  277. .cm = OMAP2_IO_ADDRESS(OMAP2420_CM_BASE),
  278. };
  279. void __init omap2_set_globals_242x(void)
  280. {
  281. __omap2_set_globals(&omap242x_globals);
  282. }
  283. #endif
  284. #if defined(CONFIG_ARCH_OMAP2430)
  285. static struct omap_globals omap243x_globals = {
  286. .class = OMAP243X_CLASS,
  287. .tap = OMAP2_IO_ADDRESS(0x4900a000),
  288. .sdrc = OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE),
  289. .sms = OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE),
  290. .ctrl = OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE),
  291. .prm = OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE),
  292. .cm = OMAP2_IO_ADDRESS(OMAP2430_CM_BASE),
  293. };
  294. void __init omap2_set_globals_243x(void)
  295. {
  296. __omap2_set_globals(&omap243x_globals);
  297. }
  298. #endif
  299. #if defined(CONFIG_ARCH_OMAP3430)
  300. static struct omap_globals omap343x_globals = {
  301. .class = OMAP343X_CLASS,
  302. .tap = OMAP2_IO_ADDRESS(0x4830A000),
  303. .sdrc = OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE),
  304. .sms = OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE),
  305. .ctrl = OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE),
  306. .prm = OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE),
  307. .cm = OMAP2_IO_ADDRESS(OMAP3430_CM_BASE),
  308. };
  309. void __init omap2_set_globals_343x(void)
  310. {
  311. __omap2_set_globals(&omap343x_globals);
  312. }
  313. #endif
  314. #if defined(CONFIG_ARCH_OMAP4)
  315. static struct omap_globals omap4_globals = {
  316. .class = OMAP443X_CLASS,
  317. .tap = OMAP2_IO_ADDRESS(0x4830a000),
  318. .ctrl = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE),
  319. .prm = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE),
  320. .cm = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE),
  321. };
  322. void __init omap2_set_globals_443x(void)
  323. {
  324. omap2_set_globals_tap(&omap4_globals);
  325. omap2_set_globals_control(&omap4_globals);
  326. }
  327. #endif