/arch/arm/mach-mv78xx0/common.c

https://github.com/AICP/kernel_asus_grouper · C · 403 lines · 250 code · 60 blank · 93 comment · 30 complexity · 895dfad4891bdac2998aa040a7d7e267 MD5 · raw file

  1. /*
  2. * arch/arm/mach-mv78xx0/common.c
  3. *
  4. * Core functions for Marvell MV78xx0 SoCs
  5. *
  6. * This file is licensed under the terms of the GNU General Public
  7. * License version 2. This program is licensed "as is" without any
  8. * warranty of any kind, whether express or implied.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/serial_8250.h>
  14. #include <linux/mbus.h>
  15. #include <linux/ata_platform.h>
  16. #include <linux/ethtool.h>
  17. #include <asm/mach/map.h>
  18. #include <asm/mach/time.h>
  19. #include <mach/mv78xx0.h>
  20. #include <mach/bridge-regs.h>
  21. #include <plat/cache-feroceon-l2.h>
  22. #include <plat/orion_nand.h>
  23. #include <plat/time.h>
  24. #include <plat/common.h>
  25. #include "common.h"
  26. static int get_tclk(void);
  27. /*****************************************************************************
  28. * Common bits
  29. ****************************************************************************/
  30. int mv78xx0_core_index(void)
  31. {
  32. u32 extra;
  33. /*
  34. * Read Extra Features register.
  35. */
  36. __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (extra));
  37. return !!(extra & 0x00004000);
  38. }
  39. static int get_hclk(void)
  40. {
  41. int hclk;
  42. /*
  43. * HCLK tick rate is configured by DEV_D[7:5] pins.
  44. */
  45. switch ((readl(SAMPLE_AT_RESET_LOW) >> 5) & 7) {
  46. case 0:
  47. hclk = 166666667;
  48. break;
  49. case 1:
  50. hclk = 200000000;
  51. break;
  52. case 2:
  53. hclk = 266666667;
  54. break;
  55. case 3:
  56. hclk = 333333333;
  57. break;
  58. case 4:
  59. hclk = 400000000;
  60. break;
  61. default:
  62. panic("unknown HCLK PLL setting: %.8x\n",
  63. readl(SAMPLE_AT_RESET_LOW));
  64. }
  65. return hclk;
  66. }
  67. static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk)
  68. {
  69. u32 cfg;
  70. /*
  71. * Core #0 PCLK/L2CLK is configured by bits [13:8], core #1
  72. * PCLK/L2CLK by bits [19:14].
  73. */
  74. if (core_index == 0) {
  75. cfg = (readl(SAMPLE_AT_RESET_LOW) >> 8) & 0x3f;
  76. } else {
  77. cfg = (readl(SAMPLE_AT_RESET_LOW) >> 14) & 0x3f;
  78. }
  79. /*
  80. * Bits [11:8] ([17:14] for core #1) configure the PCLK:HCLK
  81. * ratio (1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6).
  82. */
  83. *pclk = ((u64)hclk * (2 + (cfg & 0xf))) >> 1;
  84. /*
  85. * Bits [13:12] ([19:18] for core #1) configure the PCLK:L2CLK
  86. * ratio (1, 2, 3).
  87. */
  88. *l2clk = *pclk / (((cfg >> 4) & 3) + 1);
  89. }
  90. static int get_tclk(void)
  91. {
  92. int tclk;
  93. /*
  94. * TCLK tick rate is configured by DEV_A[2:0] strap pins.
  95. */
  96. switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) {
  97. case 1:
  98. tclk = 166666667;
  99. break;
  100. case 3:
  101. tclk = 200000000;
  102. break;
  103. default:
  104. panic("unknown TCLK PLL setting: %.8x\n",
  105. readl(SAMPLE_AT_RESET_HIGH));
  106. }
  107. return tclk;
  108. }
  109. /*****************************************************************************
  110. * I/O Address Mapping
  111. ****************************************************************************/
  112. static struct map_desc mv78xx0_io_desc[] __initdata = {
  113. {
  114. .virtual = MV78XX0_CORE_REGS_VIRT_BASE,
  115. .pfn = 0,
  116. .length = MV78XX0_CORE_REGS_SIZE,
  117. .type = MT_DEVICE,
  118. }, {
  119. .virtual = MV78XX0_PCIE_IO_VIRT_BASE(0),
  120. .pfn = __phys_to_pfn(MV78XX0_PCIE_IO_PHYS_BASE(0)),
  121. .length = MV78XX0_PCIE_IO_SIZE * 8,
  122. .type = MT_DEVICE,
  123. }, {
  124. .virtual = MV78XX0_REGS_VIRT_BASE,
  125. .pfn = __phys_to_pfn(MV78XX0_REGS_PHYS_BASE),
  126. .length = MV78XX0_REGS_SIZE,
  127. .type = MT_DEVICE,
  128. },
  129. };
  130. void __init mv78xx0_map_io(void)
  131. {
  132. unsigned long phys;
  133. /*
  134. * Map the right set of per-core registers depending on
  135. * which core we are running on.
  136. */
  137. if (mv78xx0_core_index() == 0) {
  138. phys = MV78XX0_CORE0_REGS_PHYS_BASE;
  139. } else {
  140. phys = MV78XX0_CORE1_REGS_PHYS_BASE;
  141. }
  142. mv78xx0_io_desc[0].pfn = __phys_to_pfn(phys);
  143. iotable_init(mv78xx0_io_desc, ARRAY_SIZE(mv78xx0_io_desc));
  144. }
  145. /*****************************************************************************
  146. * EHCI
  147. ****************************************************************************/
  148. void __init mv78xx0_ehci0_init(void)
  149. {
  150. orion_ehci_init(&mv78xx0_mbus_dram_info,
  151. USB0_PHYS_BASE, IRQ_MV78XX0_USB_0);
  152. }
  153. /*****************************************************************************
  154. * EHCI1
  155. ****************************************************************************/
  156. void __init mv78xx0_ehci1_init(void)
  157. {
  158. orion_ehci_1_init(&mv78xx0_mbus_dram_info,
  159. USB1_PHYS_BASE, IRQ_MV78XX0_USB_1);
  160. }
  161. /*****************************************************************************
  162. * EHCI2
  163. ****************************************************************************/
  164. void __init mv78xx0_ehci2_init(void)
  165. {
  166. orion_ehci_2_init(&mv78xx0_mbus_dram_info,
  167. USB2_PHYS_BASE, IRQ_MV78XX0_USB_2);
  168. }
  169. /*****************************************************************************
  170. * GE00
  171. ****************************************************************************/
  172. void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
  173. {
  174. orion_ge00_init(eth_data, &mv78xx0_mbus_dram_info,
  175. GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
  176. IRQ_MV78XX0_GE_ERR, get_tclk());
  177. }
  178. /*****************************************************************************
  179. * GE01
  180. ****************************************************************************/
  181. void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
  182. {
  183. orion_ge01_init(eth_data, &mv78xx0_mbus_dram_info,
  184. GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
  185. NO_IRQ, get_tclk());
  186. }
  187. /*****************************************************************************
  188. * GE10
  189. ****************************************************************************/
  190. void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
  191. {
  192. u32 dev, rev;
  193. /*
  194. * On the Z0, ge10 and ge11 are internally connected back
  195. * to back, and not brought out.
  196. */
  197. mv78xx0_pcie_id(&dev, &rev);
  198. if (dev == MV78X00_Z0_DEV_ID) {
  199. eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
  200. eth_data->speed = SPEED_1000;
  201. eth_data->duplex = DUPLEX_FULL;
  202. }
  203. orion_ge10_init(eth_data, &mv78xx0_mbus_dram_info,
  204. GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM,
  205. NO_IRQ, get_tclk());
  206. }
  207. /*****************************************************************************
  208. * GE11
  209. ****************************************************************************/
  210. void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
  211. {
  212. u32 dev, rev;
  213. /*
  214. * On the Z0, ge10 and ge11 are internally connected back
  215. * to back, and not brought out.
  216. */
  217. mv78xx0_pcie_id(&dev, &rev);
  218. if (dev == MV78X00_Z0_DEV_ID) {
  219. eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
  220. eth_data->speed = SPEED_1000;
  221. eth_data->duplex = DUPLEX_FULL;
  222. }
  223. orion_ge11_init(eth_data, &mv78xx0_mbus_dram_info,
  224. GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM,
  225. NO_IRQ, get_tclk());
  226. }
  227. /*****************************************************************************
  228. * I2C
  229. ****************************************************************************/
  230. void __init mv78xx0_i2c_init(void)
  231. {
  232. orion_i2c_init(I2C_0_PHYS_BASE, IRQ_MV78XX0_I2C_0, 8);
  233. orion_i2c_1_init(I2C_1_PHYS_BASE, IRQ_MV78XX0_I2C_1, 8);
  234. }
  235. /*****************************************************************************
  236. * SATA
  237. ****************************************************************************/
  238. void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data)
  239. {
  240. orion_sata_init(sata_data, &mv78xx0_mbus_dram_info,
  241. SATA_PHYS_BASE, IRQ_MV78XX0_SATA);
  242. }
  243. /*****************************************************************************
  244. * UART0
  245. ****************************************************************************/
  246. void __init mv78xx0_uart0_init(void)
  247. {
  248. orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
  249. IRQ_MV78XX0_UART_0, get_tclk());
  250. }
  251. /*****************************************************************************
  252. * UART1
  253. ****************************************************************************/
  254. void __init mv78xx0_uart1_init(void)
  255. {
  256. orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
  257. IRQ_MV78XX0_UART_1, get_tclk());
  258. }
  259. /*****************************************************************************
  260. * UART2
  261. ****************************************************************************/
  262. void __init mv78xx0_uart2_init(void)
  263. {
  264. orion_uart2_init(UART2_VIRT_BASE, UART2_PHYS_BASE,
  265. IRQ_MV78XX0_UART_2, get_tclk());
  266. }
  267. /*****************************************************************************
  268. * UART3
  269. ****************************************************************************/
  270. void __init mv78xx0_uart3_init(void)
  271. {
  272. orion_uart3_init(UART3_VIRT_BASE, UART3_PHYS_BASE,
  273. IRQ_MV78XX0_UART_3, get_tclk());
  274. }
  275. /*****************************************************************************
  276. * Time handling
  277. ****************************************************************************/
  278. void __init mv78xx0_init_early(void)
  279. {
  280. orion_time_set_base(TIMER_VIRT_BASE);
  281. }
  282. static void mv78xx0_timer_init(void)
  283. {
  284. orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
  285. IRQ_MV78XX0_TIMER_1, get_tclk());
  286. }
  287. struct sys_timer mv78xx0_timer = {
  288. .init = mv78xx0_timer_init,
  289. };
  290. /*****************************************************************************
  291. * General
  292. ****************************************************************************/
  293. static char * __init mv78xx0_id(void)
  294. {
  295. u32 dev, rev;
  296. mv78xx0_pcie_id(&dev, &rev);
  297. if (dev == MV78X00_Z0_DEV_ID) {
  298. if (rev == MV78X00_REV_Z0)
  299. return "MV78X00-Z0";
  300. else
  301. return "MV78X00-Rev-Unsupported";
  302. } else if (dev == MV78100_DEV_ID) {
  303. if (rev == MV78100_REV_A0)
  304. return "MV78100-A0";
  305. else if (rev == MV78100_REV_A1)
  306. return "MV78100-A1";
  307. else
  308. return "MV78100-Rev-Unsupported";
  309. } else if (dev == MV78200_DEV_ID) {
  310. if (rev == MV78100_REV_A0)
  311. return "MV78200-A0";
  312. else
  313. return "MV78200-Rev-Unsupported";
  314. } else {
  315. return "Device-Unknown";
  316. }
  317. }
  318. static int __init is_l2_writethrough(void)
  319. {
  320. return !!(readl(CPU_CONTROL) & L2_WRITETHROUGH);
  321. }
  322. void __init mv78xx0_init(void)
  323. {
  324. int core_index;
  325. int hclk;
  326. int pclk;
  327. int l2clk;
  328. int tclk;
  329. core_index = mv78xx0_core_index();
  330. hclk = get_hclk();
  331. get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
  332. tclk = get_tclk();
  333. printk(KERN_INFO "%s ", mv78xx0_id());
  334. printk("core #%d, ", core_index);
  335. printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
  336. printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
  337. printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
  338. printk("TCLK = %dMHz\n", (tclk + 499999) / 1000000);
  339. mv78xx0_setup_cpu_mbus();
  340. #ifdef CONFIG_CACHE_FEROCEON_L2
  341. feroceon_l2_init(is_l2_writethrough());
  342. #endif
  343. }