fsl_soc.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * FSL SoC setup code
  3. *
  4. * Maintained by Kumar Gala (see MAINTAINERS for contact information)
  5. *
  6. * 2006 (c) MontaVista Software, Inc.
  7. * Vitaly Bordug <vbordug@ru.mvista.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the
  11. * Free Software Foundation; either version 2 of the License, or (at your
  12. * option) any later version.
  13. */
  14. #include <linux/stddef.h>
  15. #include <linux/kernel.h>
  16. #include <linux/init.h>
  17. #include <linux/errno.h>
  18. #include <linux/major.h>
  19. #include <linux/delay.h>
  20. #include <linux/irq.h>
  21. #include <linux/module.h>
  22. #include <linux/device.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/of.h>
  25. #include <linux/of_platform.h>
  26. #include <linux/phy.h>
  27. #include <linux/phy_fixed.h>
  28. #include <linux/spi/spi.h>
  29. #include <linux/fsl_devices.h>
  30. #include <linux/fs_enet_pd.h>
  31. #include <linux/fs_uart_pd.h>
  32. #include <asm/system.h>
  33. #include <asm/atomic.h>
  34. #include <asm/io.h>
  35. #include <asm/irq.h>
  36. #include <asm/time.h>
  37. #include <asm/prom.h>
  38. #include <asm/machdep.h>
  39. #include <sysdev/fsl_soc.h>
  40. #include <mm/mmu_decl.h>
  41. #include <asm/cpm2.h>
  42. extern void init_fcc_ioports(struct fs_platform_info*);
  43. extern void init_fec_ioports(struct fs_platform_info*);
  44. extern void init_smc_ioports(struct fs_uart_platform_info*);
  45. static phys_addr_t immrbase = -1;
  46. phys_addr_t get_immrbase(void)
  47. {
  48. struct device_node *soc;
  49. if (immrbase != -1)
  50. return immrbase;
  51. soc = of_find_node_by_type(NULL, "soc");
  52. if (soc) {
  53. int size;
  54. u32 naddr;
  55. const u32 *prop = of_get_property(soc, "#address-cells", &size);
  56. if (prop && size == 4)
  57. naddr = *prop;
  58. else
  59. naddr = 2;
  60. prop = of_get_property(soc, "ranges", &size);
  61. if (prop)
  62. immrbase = of_translate_address(soc, prop + naddr);
  63. of_node_put(soc);
  64. }
  65. return immrbase;
  66. }
  67. EXPORT_SYMBOL(get_immrbase);
  68. static u32 sysfreq = -1;
  69. u32 fsl_get_sys_freq(void)
  70. {
  71. struct device_node *soc;
  72. const u32 *prop;
  73. int size;
  74. if (sysfreq != -1)
  75. return sysfreq;
  76. soc = of_find_node_by_type(NULL, "soc");
  77. if (!soc)
  78. return -1;
  79. prop = of_get_property(soc, "clock-frequency", &size);
  80. if (!prop || size != sizeof(*prop) || *prop == 0)
  81. prop = of_get_property(soc, "bus-frequency", &size);
  82. if (prop && size == sizeof(*prop))
  83. sysfreq = *prop;
  84. of_node_put(soc);
  85. return sysfreq;
  86. }
  87. EXPORT_SYMBOL(fsl_get_sys_freq);
  88. #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
  89. static u32 brgfreq = -1;
  90. u32 get_brgfreq(void)
  91. {
  92. struct device_node *node;
  93. const unsigned int *prop;
  94. int size;
  95. if (brgfreq != -1)
  96. return brgfreq;
  97. node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
  98. if (node) {
  99. prop = of_get_property(node, "clock-frequency", &size);
  100. if (prop && size == 4)
  101. brgfreq = *prop;
  102. of_node_put(node);
  103. return brgfreq;
  104. }
  105. /* Legacy device binding -- will go away when no users are left. */
  106. node = of_find_node_by_type(NULL, "cpm");
  107. if (!node)
  108. node = of_find_compatible_node(NULL, NULL, "fsl,qe");
  109. if (!node)
  110. node = of_find_node_by_type(NULL, "qe");
  111. if (node) {
  112. prop = of_get_property(node, "brg-frequency", &size);
  113. if (prop && size == 4)
  114. brgfreq = *prop;
  115. if (brgfreq == -1 || brgfreq == 0) {
  116. prop = of_get_property(node, "bus-frequency", &size);
  117. if (prop && size == 4)
  118. brgfreq = *prop / 2;
  119. }
  120. of_node_put(node);
  121. }
  122. return brgfreq;
  123. }
  124. EXPORT_SYMBOL(get_brgfreq);
  125. static u32 fs_baudrate = -1;
  126. u32 get_baudrate(void)
  127. {
  128. struct device_node *node;
  129. if (fs_baudrate != -1)
  130. return fs_baudrate;
  131. node = of_find_node_by_type(NULL, "serial");
  132. if (node) {
  133. int size;
  134. const unsigned int *prop = of_get_property(node,
  135. "current-speed", &size);
  136. if (prop)
  137. fs_baudrate = *prop;
  138. of_node_put(node);
  139. }
  140. return fs_baudrate;
  141. }
  142. EXPORT_SYMBOL(get_baudrate);
  143. #endif /* CONFIG_CPM2 */
  144. #ifdef CONFIG_FIXED_PHY
  145. static int __init of_add_fixed_phys(void)
  146. {
  147. int ret;
  148. struct device_node *np;
  149. u32 *fixed_link;
  150. struct fixed_phy_status status = {};
  151. for_each_node_by_name(np, "ethernet") {
  152. fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
  153. if (!fixed_link)
  154. continue;
  155. status.link = 1;
  156. status.duplex = fixed_link[1];
  157. status.speed = fixed_link[2];
  158. status.pause = fixed_link[3];
  159. status.asym_pause = fixed_link[4];
  160. ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
  161. if (ret) {
  162. of_node_put(np);
  163. return ret;
  164. }
  165. }
  166. return 0;
  167. }
  168. arch_initcall(of_add_fixed_phys);
  169. #endif /* CONFIG_FIXED_PHY */
  170. static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
  171. {
  172. if (!phy_type)
  173. return FSL_USB2_PHY_NONE;
  174. if (!strcasecmp(phy_type, "ulpi"))
  175. return FSL_USB2_PHY_ULPI;
  176. if (!strcasecmp(phy_type, "utmi"))
  177. return FSL_USB2_PHY_UTMI;
  178. if (!strcasecmp(phy_type, "utmi_wide"))
  179. return FSL_USB2_PHY_UTMI_WIDE;
  180. if (!strcasecmp(phy_type, "serial"))
  181. return FSL_USB2_PHY_SERIAL;
  182. return FSL_USB2_PHY_NONE;
  183. }
  184. static int __init fsl_usb_of_init(void)
  185. {
  186. struct device_node *np;
  187. unsigned int i = 0;
  188. struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
  189. *usb_dev_dr_client = NULL;
  190. int ret;
  191. for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
  192. struct resource r[2];
  193. struct fsl_usb2_platform_data usb_data;
  194. const unsigned char *prop = NULL;
  195. memset(&r, 0, sizeof(r));
  196. memset(&usb_data, 0, sizeof(usb_data));
  197. ret = of_address_to_resource(np, 0, &r[0]);
  198. if (ret)
  199. goto err;
  200. of_irq_to_resource(np, 0, &r[1]);
  201. usb_dev_mph =
  202. platform_device_register_simple("fsl-ehci", i, r, 2);
  203. if (IS_ERR(usb_dev_mph)) {
  204. ret = PTR_ERR(usb_dev_mph);
  205. goto err;
  206. }
  207. usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
  208. usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
  209. usb_data.operating_mode = FSL_USB2_MPH_HOST;
  210. prop = of_get_property(np, "port0", NULL);
  211. if (prop)
  212. usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
  213. prop = of_get_property(np, "port1", NULL);
  214. if (prop)
  215. usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
  216. prop = of_get_property(np, "phy_type", NULL);
  217. usb_data.phy_mode = determine_usb_phy(prop);
  218. ret =
  219. platform_device_add_data(usb_dev_mph, &usb_data,
  220. sizeof(struct
  221. fsl_usb2_platform_data));
  222. if (ret)
  223. goto unreg_mph;
  224. i++;
  225. }
  226. for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
  227. struct resource r[2];
  228. struct fsl_usb2_platform_data usb_data;
  229. const unsigned char *prop = NULL;
  230. if (!of_device_is_available(np))
  231. continue;
  232. memset(&r, 0, sizeof(r));
  233. memset(&usb_data, 0, sizeof(usb_data));
  234. ret = of_address_to_resource(np, 0, &r[0]);
  235. if (ret)
  236. goto unreg_mph;
  237. of_irq_to_resource(np, 0, &r[1]);
  238. prop = of_get_property(np, "dr_mode", NULL);
  239. if (!prop || !strcmp(prop, "host")) {
  240. usb_data.operating_mode = FSL_USB2_DR_HOST;
  241. usb_dev_dr_host = platform_device_register_simple(
  242. "fsl-ehci", i, r, 2);
  243. if (IS_ERR(usb_dev_dr_host)) {
  244. ret = PTR_ERR(usb_dev_dr_host);
  245. goto err;
  246. }
  247. } else if (prop && !strcmp(prop, "peripheral")) {
  248. usb_data.operating_mode = FSL_USB2_DR_DEVICE;
  249. usb_dev_dr_client = platform_device_register_simple(
  250. "fsl-usb2-udc", i, r, 2);
  251. if (IS_ERR(usb_dev_dr_client)) {
  252. ret = PTR_ERR(usb_dev_dr_client);
  253. goto err;
  254. }
  255. } else if (prop && !strcmp(prop, "otg")) {
  256. usb_data.operating_mode = FSL_USB2_DR_OTG;
  257. usb_dev_dr_host = platform_device_register_simple(
  258. "fsl-ehci", i, r, 2);
  259. if (IS_ERR(usb_dev_dr_host)) {
  260. ret = PTR_ERR(usb_dev_dr_host);
  261. goto err;
  262. }
  263. usb_dev_dr_client = platform_device_register_simple(
  264. "fsl-usb2-udc", i, r, 2);
  265. if (IS_ERR(usb_dev_dr_client)) {
  266. ret = PTR_ERR(usb_dev_dr_client);
  267. goto err;
  268. }
  269. } else {
  270. ret = -EINVAL;
  271. goto err;
  272. }
  273. prop = of_get_property(np, "phy_type", NULL);
  274. usb_data.phy_mode = determine_usb_phy(prop);
  275. if (usb_dev_dr_host) {
  276. usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
  277. usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
  278. dev.coherent_dma_mask;
  279. if ((ret = platform_device_add_data(usb_dev_dr_host,
  280. &usb_data, sizeof(struct
  281. fsl_usb2_platform_data))))
  282. goto unreg_dr;
  283. }
  284. if (usb_dev_dr_client) {
  285. usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
  286. usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
  287. dev.coherent_dma_mask;
  288. if ((ret = platform_device_add_data(usb_dev_dr_client,
  289. &usb_data, sizeof(struct
  290. fsl_usb2_platform_data))))
  291. goto unreg_dr;
  292. }
  293. i++;
  294. }
  295. return 0;
  296. unreg_dr:
  297. if (usb_dev_dr_host)
  298. platform_device_unregister(usb_dev_dr_host);
  299. if (usb_dev_dr_client)
  300. platform_device_unregister(usb_dev_dr_client);
  301. unreg_mph:
  302. if (usb_dev_mph)
  303. platform_device_unregister(usb_dev_mph);
  304. err:
  305. return ret;
  306. }
  307. arch_initcall(fsl_usb_of_init);
  308. #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
  309. static __be32 __iomem *rstcr;
  310. static int __init setup_rstcr(void)
  311. {
  312. struct device_node *np;
  313. np = of_find_node_by_name(NULL, "global-utilities");
  314. if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
  315. rstcr = of_iomap(np, 0) + 0xb0;
  316. if (!rstcr)
  317. printk (KERN_EMERG "Error: reset control register "
  318. "not mapped!\n");
  319. } else if (ppc_md.restart == fsl_rstcr_restart)
  320. printk(KERN_ERR "No RSTCR register, warm reboot won't work\n");
  321. if (np)
  322. of_node_put(np);
  323. return 0;
  324. }
  325. arch_initcall(setup_rstcr);
  326. void fsl_rstcr_restart(char *cmd)
  327. {
  328. local_irq_disable();
  329. if (rstcr)
  330. /* set reset control register */
  331. out_be32(rstcr, 0x2); /* HRESET_REQ */
  332. while (1) ;
  333. }
  334. #endif
  335. #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
  336. struct platform_diu_data_ops diu_ops;
  337. EXPORT_SYMBOL(diu_ops);
  338. #endif