spear6xx.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * arch/arm/mach-spear6xx/spear6xx.c
  3. *
  4. * SPEAr6XX machines common source file
  5. *
  6. * Copyright (C) 2009 ST Microelectronics
  7. * Rajeev Kumar<rajeev-dlh.kumar@st.com>
  8. *
  9. * Copyright 2012 Stefan Roese <sr@denx.de>
  10. *
  11. * This file is licensed under the terms of the GNU General Public
  12. * License version 2. This program is licensed "as is" without any
  13. * warranty of any kind, whether express or implied.
  14. */
  15. #include <linux/amba/pl08x.h>
  16. #include <linux/clk.h>
  17. #include <linux/err.h>
  18. #include <linux/of.h>
  19. #include <linux/of_address.h>
  20. #include <linux/of_irq.h>
  21. #include <linux/of_platform.h>
  22. #include <asm/hardware/pl080.h>
  23. #include <asm/hardware/vic.h>
  24. #include <asm/mach/arch.h>
  25. #include <asm/mach/time.h>
  26. #include <asm/mach/map.h>
  27. #include <plat/pl080.h>
  28. #include <mach/generic.h>
  29. #include <mach/spear.h>
  30. /* dmac device registration */
  31. static struct pl08x_channel_data spear600_dma_info[] = {
  32. {
  33. .bus_id = "ssp1_rx",
  34. .min_signal = 0,
  35. .max_signal = 0,
  36. .muxval = 0,
  37. .cctl = 0,
  38. .periph_buses = PL08X_AHB1,
  39. }, {
  40. .bus_id = "ssp1_tx",
  41. .min_signal = 1,
  42. .max_signal = 1,
  43. .muxval = 0,
  44. .cctl = 0,
  45. .periph_buses = PL08X_AHB1,
  46. }, {
  47. .bus_id = "uart0_rx",
  48. .min_signal = 2,
  49. .max_signal = 2,
  50. .muxval = 0,
  51. .cctl = 0,
  52. .periph_buses = PL08X_AHB1,
  53. }, {
  54. .bus_id = "uart0_tx",
  55. .min_signal = 3,
  56. .max_signal = 3,
  57. .muxval = 0,
  58. .cctl = 0,
  59. .periph_buses = PL08X_AHB1,
  60. }, {
  61. .bus_id = "uart1_rx",
  62. .min_signal = 4,
  63. .max_signal = 4,
  64. .muxval = 0,
  65. .cctl = 0,
  66. .periph_buses = PL08X_AHB1,
  67. }, {
  68. .bus_id = "uart1_tx",
  69. .min_signal = 5,
  70. .max_signal = 5,
  71. .muxval = 0,
  72. .cctl = 0,
  73. .periph_buses = PL08X_AHB1,
  74. }, {
  75. .bus_id = "ssp2_rx",
  76. .min_signal = 6,
  77. .max_signal = 6,
  78. .muxval = 0,
  79. .cctl = 0,
  80. .periph_buses = PL08X_AHB2,
  81. }, {
  82. .bus_id = "ssp2_tx",
  83. .min_signal = 7,
  84. .max_signal = 7,
  85. .muxval = 0,
  86. .cctl = 0,
  87. .periph_buses = PL08X_AHB2,
  88. }, {
  89. .bus_id = "ssp0_rx",
  90. .min_signal = 8,
  91. .max_signal = 8,
  92. .muxval = 0,
  93. .cctl = 0,
  94. .periph_buses = PL08X_AHB1,
  95. }, {
  96. .bus_id = "ssp0_tx",
  97. .min_signal = 9,
  98. .max_signal = 9,
  99. .muxval = 0,
  100. .cctl = 0,
  101. .periph_buses = PL08X_AHB1,
  102. }, {
  103. .bus_id = "i2c_rx",
  104. .min_signal = 10,
  105. .max_signal = 10,
  106. .muxval = 0,
  107. .cctl = 0,
  108. .periph_buses = PL08X_AHB1,
  109. }, {
  110. .bus_id = "i2c_tx",
  111. .min_signal = 11,
  112. .max_signal = 11,
  113. .muxval = 0,
  114. .cctl = 0,
  115. .periph_buses = PL08X_AHB1,
  116. }, {
  117. .bus_id = "irda",
  118. .min_signal = 12,
  119. .max_signal = 12,
  120. .muxval = 0,
  121. .cctl = 0,
  122. .periph_buses = PL08X_AHB1,
  123. }, {
  124. .bus_id = "adc",
  125. .min_signal = 13,
  126. .max_signal = 13,
  127. .muxval = 0,
  128. .cctl = 0,
  129. .periph_buses = PL08X_AHB2,
  130. }, {
  131. .bus_id = "to_jpeg",
  132. .min_signal = 14,
  133. .max_signal = 14,
  134. .muxval = 0,
  135. .cctl = 0,
  136. .periph_buses = PL08X_AHB1,
  137. }, {
  138. .bus_id = "from_jpeg",
  139. .min_signal = 15,
  140. .max_signal = 15,
  141. .muxval = 0,
  142. .cctl = 0,
  143. .periph_buses = PL08X_AHB1,
  144. }, {
  145. .bus_id = "ras0_rx",
  146. .min_signal = 0,
  147. .max_signal = 0,
  148. .muxval = 1,
  149. .cctl = 0,
  150. .periph_buses = PL08X_AHB1,
  151. }, {
  152. .bus_id = "ras0_tx",
  153. .min_signal = 1,
  154. .max_signal = 1,
  155. .muxval = 1,
  156. .cctl = 0,
  157. .periph_buses = PL08X_AHB1,
  158. }, {
  159. .bus_id = "ras1_rx",
  160. .min_signal = 2,
  161. .max_signal = 2,
  162. .muxval = 1,
  163. .cctl = 0,
  164. .periph_buses = PL08X_AHB1,
  165. }, {
  166. .bus_id = "ras1_tx",
  167. .min_signal = 3,
  168. .max_signal = 3,
  169. .muxval = 1,
  170. .cctl = 0,
  171. .periph_buses = PL08X_AHB1,
  172. }, {
  173. .bus_id = "ras2_rx",
  174. .min_signal = 4,
  175. .max_signal = 4,
  176. .muxval = 1,
  177. .cctl = 0,
  178. .periph_buses = PL08X_AHB1,
  179. }, {
  180. .bus_id = "ras2_tx",
  181. .min_signal = 5,
  182. .max_signal = 5,
  183. .muxval = 1,
  184. .cctl = 0,
  185. .periph_buses = PL08X_AHB1,
  186. }, {
  187. .bus_id = "ras3_rx",
  188. .min_signal = 6,
  189. .max_signal = 6,
  190. .muxval = 1,
  191. .cctl = 0,
  192. .periph_buses = PL08X_AHB1,
  193. }, {
  194. .bus_id = "ras3_tx",
  195. .min_signal = 7,
  196. .max_signal = 7,
  197. .muxval = 1,
  198. .cctl = 0,
  199. .periph_buses = PL08X_AHB1,
  200. }, {
  201. .bus_id = "ras4_rx",
  202. .min_signal = 8,
  203. .max_signal = 8,
  204. .muxval = 1,
  205. .cctl = 0,
  206. .periph_buses = PL08X_AHB1,
  207. }, {
  208. .bus_id = "ras4_tx",
  209. .min_signal = 9,
  210. .max_signal = 9,
  211. .muxval = 1,
  212. .cctl = 0,
  213. .periph_buses = PL08X_AHB1,
  214. }, {
  215. .bus_id = "ras5_rx",
  216. .min_signal = 10,
  217. .max_signal = 10,
  218. .muxval = 1,
  219. .cctl = 0,
  220. .periph_buses = PL08X_AHB1,
  221. }, {
  222. .bus_id = "ras5_tx",
  223. .min_signal = 11,
  224. .max_signal = 11,
  225. .muxval = 1,
  226. .cctl = 0,
  227. .periph_buses = PL08X_AHB1,
  228. }, {
  229. .bus_id = "ras6_rx",
  230. .min_signal = 12,
  231. .max_signal = 12,
  232. .muxval = 1,
  233. .cctl = 0,
  234. .periph_buses = PL08X_AHB1,
  235. }, {
  236. .bus_id = "ras6_tx",
  237. .min_signal = 13,
  238. .max_signal = 13,
  239. .muxval = 1,
  240. .cctl = 0,
  241. .periph_buses = PL08X_AHB1,
  242. }, {
  243. .bus_id = "ras7_rx",
  244. .min_signal = 14,
  245. .max_signal = 14,
  246. .muxval = 1,
  247. .cctl = 0,
  248. .periph_buses = PL08X_AHB1,
  249. }, {
  250. .bus_id = "ras7_tx",
  251. .min_signal = 15,
  252. .max_signal = 15,
  253. .muxval = 1,
  254. .cctl = 0,
  255. .periph_buses = PL08X_AHB1,
  256. }, {
  257. .bus_id = "ext0_rx",
  258. .min_signal = 0,
  259. .max_signal = 0,
  260. .muxval = 2,
  261. .cctl = 0,
  262. .periph_buses = PL08X_AHB2,
  263. }, {
  264. .bus_id = "ext0_tx",
  265. .min_signal = 1,
  266. .max_signal = 1,
  267. .muxval = 2,
  268. .cctl = 0,
  269. .periph_buses = PL08X_AHB2,
  270. }, {
  271. .bus_id = "ext1_rx",
  272. .min_signal = 2,
  273. .max_signal = 2,
  274. .muxval = 2,
  275. .cctl = 0,
  276. .periph_buses = PL08X_AHB2,
  277. }, {
  278. .bus_id = "ext1_tx",
  279. .min_signal = 3,
  280. .max_signal = 3,
  281. .muxval = 2,
  282. .cctl = 0,
  283. .periph_buses = PL08X_AHB2,
  284. }, {
  285. .bus_id = "ext2_rx",
  286. .min_signal = 4,
  287. .max_signal = 4,
  288. .muxval = 2,
  289. .cctl = 0,
  290. .periph_buses = PL08X_AHB2,
  291. }, {
  292. .bus_id = "ext2_tx",
  293. .min_signal = 5,
  294. .max_signal = 5,
  295. .muxval = 2,
  296. .cctl = 0,
  297. .periph_buses = PL08X_AHB2,
  298. }, {
  299. .bus_id = "ext3_rx",
  300. .min_signal = 6,
  301. .max_signal = 6,
  302. .muxval = 2,
  303. .cctl = 0,
  304. .periph_buses = PL08X_AHB2,
  305. }, {
  306. .bus_id = "ext3_tx",
  307. .min_signal = 7,
  308. .max_signal = 7,
  309. .muxval = 2,
  310. .cctl = 0,
  311. .periph_buses = PL08X_AHB2,
  312. }, {
  313. .bus_id = "ext4_rx",
  314. .min_signal = 8,
  315. .max_signal = 8,
  316. .muxval = 2,
  317. .cctl = 0,
  318. .periph_buses = PL08X_AHB2,
  319. }, {
  320. .bus_id = "ext4_tx",
  321. .min_signal = 9,
  322. .max_signal = 9,
  323. .muxval = 2,
  324. .cctl = 0,
  325. .periph_buses = PL08X_AHB2,
  326. }, {
  327. .bus_id = "ext5_rx",
  328. .min_signal = 10,
  329. .max_signal = 10,
  330. .muxval = 2,
  331. .cctl = 0,
  332. .periph_buses = PL08X_AHB2,
  333. }, {
  334. .bus_id = "ext5_tx",
  335. .min_signal = 11,
  336. .max_signal = 11,
  337. .muxval = 2,
  338. .cctl = 0,
  339. .periph_buses = PL08X_AHB2,
  340. }, {
  341. .bus_id = "ext6_rx",
  342. .min_signal = 12,
  343. .max_signal = 12,
  344. .muxval = 2,
  345. .cctl = 0,
  346. .periph_buses = PL08X_AHB2,
  347. }, {
  348. .bus_id = "ext6_tx",
  349. .min_signal = 13,
  350. .max_signal = 13,
  351. .muxval = 2,
  352. .cctl = 0,
  353. .periph_buses = PL08X_AHB2,
  354. }, {
  355. .bus_id = "ext7_rx",
  356. .min_signal = 14,
  357. .max_signal = 14,
  358. .muxval = 2,
  359. .cctl = 0,
  360. .periph_buses = PL08X_AHB2,
  361. }, {
  362. .bus_id = "ext7_tx",
  363. .min_signal = 15,
  364. .max_signal = 15,
  365. .muxval = 2,
  366. .cctl = 0,
  367. .periph_buses = PL08X_AHB2,
  368. },
  369. };
  370. struct pl08x_platform_data pl080_plat_data = {
  371. .memcpy_channel = {
  372. .bus_id = "memcpy",
  373. .cctl = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
  374. PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
  375. PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
  376. PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
  377. PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
  378. PL080_CONTROL_PROT_SYS),
  379. },
  380. .lli_buses = PL08X_AHB1,
  381. .mem_buses = PL08X_AHB1,
  382. .get_signal = pl080_get_signal,
  383. .put_signal = pl080_put_signal,
  384. .slave_channels = spear600_dma_info,
  385. .num_slave_channels = ARRAY_SIZE(spear600_dma_info),
  386. };
  387. /*
  388. * Following will create 16MB static virtual/physical mappings
  389. * PHYSICAL VIRTUAL
  390. * 0xF0000000 0xF0000000
  391. * 0xF1000000 0xF1000000
  392. * 0xD0000000 0xFD000000
  393. * 0xFC000000 0xFC000000
  394. */
  395. struct map_desc spear6xx_io_desc[] __initdata = {
  396. {
  397. .virtual = VA_SPEAR6XX_ML_CPU_BASE,
  398. .pfn = __phys_to_pfn(SPEAR6XX_ML_CPU_BASE),
  399. .length = 2 * SZ_16M,
  400. .type = MT_DEVICE
  401. }, {
  402. .virtual = VA_SPEAR6XX_ICM1_BASE,
  403. .pfn = __phys_to_pfn(SPEAR6XX_ICM1_BASE),
  404. .length = SZ_16M,
  405. .type = MT_DEVICE
  406. }, {
  407. .virtual = VA_SPEAR6XX_ICM3_SMI_CTRL_BASE,
  408. .pfn = __phys_to_pfn(SPEAR6XX_ICM3_SMI_CTRL_BASE),
  409. .length = SZ_16M,
  410. .type = MT_DEVICE
  411. },
  412. };
  413. /* This will create static memory mapping for selected devices */
  414. void __init spear6xx_map_io(void)
  415. {
  416. iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
  417. }
  418. static void __init spear6xx_timer_init(void)
  419. {
  420. char pclk_name[] = "pll3_48m_clk";
  421. struct clk *gpt_clk, *pclk;
  422. spear6xx_clk_init();
  423. /* get the system timer clock */
  424. gpt_clk = clk_get_sys("gpt0", NULL);
  425. if (IS_ERR(gpt_clk)) {
  426. pr_err("%s:couldn't get clk for gpt\n", __func__);
  427. BUG();
  428. }
  429. /* get the suitable parent clock for timer*/
  430. pclk = clk_get(NULL, pclk_name);
  431. if (IS_ERR(pclk)) {
  432. pr_err("%s:couldn't get %s as parent for gpt\n",
  433. __func__, pclk_name);
  434. BUG();
  435. }
  436. clk_set_parent(gpt_clk, pclk);
  437. clk_put(gpt_clk);
  438. clk_put(pclk);
  439. spear_setup_of_timer();
  440. }
  441. struct sys_timer spear6xx_timer = {
  442. .init = spear6xx_timer_init,
  443. };
  444. /* Add auxdata to pass platform data */
  445. struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
  446. OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
  447. &pl080_plat_data),
  448. {}
  449. };
  450. static void __init spear600_dt_init(void)
  451. {
  452. of_platform_populate(NULL, of_default_bus_match_table,
  453. spear6xx_auxdata_lookup, NULL);
  454. }
  455. static const char *spear600_dt_board_compat[] = {
  456. "st,spear600",
  457. NULL
  458. };
  459. static const struct of_device_id vic_of_match[] __initconst = {
  460. { .compatible = "arm,pl190-vic", .data = vic_of_init, },
  461. { /* Sentinel */ }
  462. };
  463. static void __init spear6xx_dt_init_irq(void)
  464. {
  465. of_irq_init(vic_of_match);
  466. }
  467. DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
  468. .map_io = spear6xx_map_io,
  469. .init_irq = spear6xx_dt_init_irq,
  470. .handle_irq = vic_handle_irq,
  471. .timer = &spear6xx_timer,
  472. .init_machine = spear600_dt_init,
  473. .restart = spear_restart,
  474. .dt_compat = spear600_dt_board_compat,
  475. MACHINE_END