octeon-platform.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2004-2010 Cavium Networks
  7. * Copyright (C) 2008 Wind River Systems
  8. */
  9. #include <linux/init.h>
  10. #include <linux/irq.h>
  11. #include <linux/i2c.h>
  12. #include <linux/usb.h>
  13. #include <linux/dma-mapping.h>
  14. #include <linux/module.h>
  15. #include <linux/platform_device.h>
  16. #include <asm/octeon/octeon.h>
  17. #include <asm/octeon/cvmx-rnm-defs.h>
  18. static struct octeon_cf_data octeon_cf_data;
  19. static int __init octeon_cf_device_init(void)
  20. {
  21. union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
  22. unsigned long base_ptr, region_base, region_size;
  23. struct platform_device *pd;
  24. struct resource cf_resources[3];
  25. unsigned int num_resources;
  26. int i;
  27. int ret = 0;
  28. /* Setup octeon-cf platform device if present. */
  29. base_ptr = 0;
  30. if (octeon_bootinfo->major_version == 1
  31. && octeon_bootinfo->minor_version >= 1) {
  32. if (octeon_bootinfo->compact_flash_common_base_addr)
  33. base_ptr =
  34. octeon_bootinfo->compact_flash_common_base_addr;
  35. } else {
  36. base_ptr = 0x1d000800;
  37. }
  38. if (!base_ptr)
  39. return ret;
  40. /* Find CS0 region. */
  41. for (i = 0; i < 8; i++) {
  42. mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i));
  43. region_base = mio_boot_reg_cfg.s.base << 16;
  44. region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
  45. if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
  46. && base_ptr < region_base + region_size)
  47. break;
  48. }
  49. if (i >= 7) {
  50. /* i and i + 1 are CS0 and CS1, both must be less than 8. */
  51. goto out;
  52. }
  53. octeon_cf_data.base_region = i;
  54. octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width;
  55. octeon_cf_data.base_region_bias = base_ptr - region_base;
  56. memset(cf_resources, 0, sizeof(cf_resources));
  57. num_resources = 0;
  58. cf_resources[num_resources].flags = IORESOURCE_MEM;
  59. cf_resources[num_resources].start = region_base;
  60. cf_resources[num_resources].end = region_base + region_size - 1;
  61. num_resources++;
  62. if (!(base_ptr & 0xfffful)) {
  63. /*
  64. * Boot loader signals availability of DMA (true_ide
  65. * mode) by setting low order bits of base_ptr to
  66. * zero.
  67. */
  68. /* Assume that CS1 immediately follows. */
  69. mio_boot_reg_cfg.u64 =
  70. cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1));
  71. region_base = mio_boot_reg_cfg.s.base << 16;
  72. region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
  73. if (!mio_boot_reg_cfg.s.en)
  74. goto out;
  75. cf_resources[num_resources].flags = IORESOURCE_MEM;
  76. cf_resources[num_resources].start = region_base;
  77. cf_resources[num_resources].end = region_base + region_size - 1;
  78. num_resources++;
  79. octeon_cf_data.dma_engine = 0;
  80. cf_resources[num_resources].flags = IORESOURCE_IRQ;
  81. cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA;
  82. cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA;
  83. num_resources++;
  84. } else {
  85. octeon_cf_data.dma_engine = -1;
  86. }
  87. pd = platform_device_alloc("pata_octeon_cf", -1);
  88. if (!pd) {
  89. ret = -ENOMEM;
  90. goto out;
  91. }
  92. pd->dev.platform_data = &octeon_cf_data;
  93. ret = platform_device_add_resources(pd, cf_resources, num_resources);
  94. if (ret)
  95. goto fail;
  96. ret = platform_device_add(pd);
  97. if (ret)
  98. goto fail;
  99. return ret;
  100. fail:
  101. platform_device_put(pd);
  102. out:
  103. return ret;
  104. }
  105. device_initcall(octeon_cf_device_init);
  106. /* Octeon Random Number Generator. */
  107. static int __init octeon_rng_device_init(void)
  108. {
  109. struct platform_device *pd;
  110. int ret = 0;
  111. struct resource rng_resources[] = {
  112. {
  113. .flags = IORESOURCE_MEM,
  114. .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
  115. .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
  116. }, {
  117. .flags = IORESOURCE_MEM,
  118. .start = cvmx_build_io_address(8, 0),
  119. .end = cvmx_build_io_address(8, 0) + 0x7
  120. }
  121. };
  122. pd = platform_device_alloc("octeon_rng", -1);
  123. if (!pd) {
  124. ret = -ENOMEM;
  125. goto out;
  126. }
  127. ret = platform_device_add_resources(pd, rng_resources,
  128. ARRAY_SIZE(rng_resources));
  129. if (ret)
  130. goto fail;
  131. ret = platform_device_add(pd);
  132. if (ret)
  133. goto fail;
  134. return ret;
  135. fail:
  136. platform_device_put(pd);
  137. out:
  138. return ret;
  139. }
  140. device_initcall(octeon_rng_device_init);
  141. static struct i2c_board_info __initdata octeon_i2c_devices[] = {
  142. {
  143. I2C_BOARD_INFO("ds1337", 0x68),
  144. },
  145. };
  146. static int __init octeon_i2c_devices_init(void)
  147. {
  148. return i2c_register_board_info(0, octeon_i2c_devices,
  149. ARRAY_SIZE(octeon_i2c_devices));
  150. }
  151. arch_initcall(octeon_i2c_devices_init);
  152. #define OCTEON_I2C_IO_BASE 0x1180000001000ull
  153. #define OCTEON_I2C_IO_UNIT_OFFSET 0x200
  154. static struct octeon_i2c_data octeon_i2c_data[2];
  155. static int __init octeon_i2c_device_init(void)
  156. {
  157. struct platform_device *pd;
  158. int ret = 0;
  159. int port, num_ports;
  160. struct resource i2c_resources[] = {
  161. {
  162. .flags = IORESOURCE_MEM,
  163. }, {
  164. .flags = IORESOURCE_IRQ,
  165. }
  166. };
  167. if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
  168. num_ports = 2;
  169. else
  170. num_ports = 1;
  171. for (port = 0; port < num_ports; port++) {
  172. octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate();
  173. /*FIXME: should be examined. At the moment is set for 100Khz */
  174. octeon_i2c_data[port].i2c_freq = 100000;
  175. pd = platform_device_alloc("i2c-octeon", port);
  176. if (!pd) {
  177. ret = -ENOMEM;
  178. goto out;
  179. }
  180. pd->dev.platform_data = octeon_i2c_data + port;
  181. i2c_resources[0].start =
  182. OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
  183. i2c_resources[0].end = i2c_resources[0].start + 0x1f;
  184. switch (port) {
  185. case 0:
  186. i2c_resources[1].start = OCTEON_IRQ_TWSI;
  187. i2c_resources[1].end = OCTEON_IRQ_TWSI;
  188. break;
  189. case 1:
  190. i2c_resources[1].start = OCTEON_IRQ_TWSI2;
  191. i2c_resources[1].end = OCTEON_IRQ_TWSI2;
  192. break;
  193. default:
  194. BUG();
  195. }
  196. ret = platform_device_add_resources(pd,
  197. i2c_resources,
  198. ARRAY_SIZE(i2c_resources));
  199. if (ret)
  200. goto fail;
  201. ret = platform_device_add(pd);
  202. if (ret)
  203. goto fail;
  204. }
  205. return ret;
  206. fail:
  207. platform_device_put(pd);
  208. out:
  209. return ret;
  210. }
  211. device_initcall(octeon_i2c_device_init);
  212. /* Octeon SMI/MDIO interface. */
  213. static int __init octeon_mdiobus_device_init(void)
  214. {
  215. struct platform_device *pd;
  216. int ret = 0;
  217. if (octeon_is_simulation())
  218. return 0; /* No mdio in the simulator. */
  219. /* The bus number is the platform_device id. */
  220. pd = platform_device_alloc("mdio-octeon", 0);
  221. if (!pd) {
  222. ret = -ENOMEM;
  223. goto out;
  224. }
  225. ret = platform_device_add(pd);
  226. if (ret)
  227. goto fail;
  228. return ret;
  229. fail:
  230. platform_device_put(pd);
  231. out:
  232. return ret;
  233. }
  234. device_initcall(octeon_mdiobus_device_init);
  235. /* Octeon mgmt port Ethernet interface. */
  236. static int __init octeon_mgmt_device_init(void)
  237. {
  238. struct platform_device *pd;
  239. int ret = 0;
  240. int port, num_ports;
  241. struct resource mgmt_port_resource = {
  242. .flags = IORESOURCE_IRQ,
  243. .start = -1,
  244. .end = -1
  245. };
  246. if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
  247. return 0;
  248. if (OCTEON_IS_MODEL(OCTEON_CN56XX))
  249. num_ports = 1;
  250. else
  251. num_ports = 2;
  252. for (port = 0; port < num_ports; port++) {
  253. pd = platform_device_alloc("octeon_mgmt", port);
  254. if (!pd) {
  255. ret = -ENOMEM;
  256. goto out;
  257. }
  258. /* No DMA restrictions */
  259. pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
  260. pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
  261. switch (port) {
  262. case 0:
  263. mgmt_port_resource.start = OCTEON_IRQ_MII0;
  264. break;
  265. case 1:
  266. mgmt_port_resource.start = OCTEON_IRQ_MII1;
  267. break;
  268. default:
  269. BUG();
  270. }
  271. mgmt_port_resource.end = mgmt_port_resource.start;
  272. ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
  273. if (ret)
  274. goto fail;
  275. ret = platform_device_add(pd);
  276. if (ret)
  277. goto fail;
  278. }
  279. return ret;
  280. fail:
  281. platform_device_put(pd);
  282. out:
  283. return ret;
  284. }
  285. device_initcall(octeon_mgmt_device_init);
  286. #ifdef CONFIG_USB
  287. static int __init octeon_ehci_device_init(void)
  288. {
  289. struct platform_device *pd;
  290. int ret = 0;
  291. struct resource usb_resources[] = {
  292. {
  293. .flags = IORESOURCE_MEM,
  294. }, {
  295. .flags = IORESOURCE_IRQ,
  296. }
  297. };
  298. /* Only Octeon2 has ehci/ohci */
  299. if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
  300. return 0;
  301. if (octeon_is_simulation() || usb_disabled())
  302. return 0; /* No USB in the simulator. */
  303. pd = platform_device_alloc("octeon-ehci", 0);
  304. if (!pd) {
  305. ret = -ENOMEM;
  306. goto out;
  307. }
  308. usb_resources[0].start = 0x00016F0000000000ULL;
  309. usb_resources[0].end = usb_resources[0].start + 0x100;
  310. usb_resources[1].start = OCTEON_IRQ_USB0;
  311. usb_resources[1].end = OCTEON_IRQ_USB0;
  312. ret = platform_device_add_resources(pd, usb_resources,
  313. ARRAY_SIZE(usb_resources));
  314. if (ret)
  315. goto fail;
  316. ret = platform_device_add(pd);
  317. if (ret)
  318. goto fail;
  319. return ret;
  320. fail:
  321. platform_device_put(pd);
  322. out:
  323. return ret;
  324. }
  325. device_initcall(octeon_ehci_device_init);
  326. static int __init octeon_ohci_device_init(void)
  327. {
  328. struct platform_device *pd;
  329. int ret = 0;
  330. struct resource usb_resources[] = {
  331. {
  332. .flags = IORESOURCE_MEM,
  333. }, {
  334. .flags = IORESOURCE_IRQ,
  335. }
  336. };
  337. /* Only Octeon2 has ehci/ohci */
  338. if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
  339. return 0;
  340. if (octeon_is_simulation() || usb_disabled())
  341. return 0; /* No USB in the simulator. */
  342. pd = platform_device_alloc("octeon-ohci", 0);
  343. if (!pd) {
  344. ret = -ENOMEM;
  345. goto out;
  346. }
  347. usb_resources[0].start = 0x00016F0000000400ULL;
  348. usb_resources[0].end = usb_resources[0].start + 0x100;
  349. usb_resources[1].start = OCTEON_IRQ_USB0;
  350. usb_resources[1].end = OCTEON_IRQ_USB0;
  351. ret = platform_device_add_resources(pd, usb_resources,
  352. ARRAY_SIZE(usb_resources));
  353. if (ret)
  354. goto fail;
  355. ret = platform_device_add(pd);
  356. if (ret)
  357. goto fail;
  358. return ret;
  359. fail:
  360. platform_device_put(pd);
  361. out:
  362. return ret;
  363. }
  364. device_initcall(octeon_ohci_device_init);
  365. #endif /* CONFIG_USB */
  366. MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
  367. MODULE_LICENSE("GPL");
  368. MODULE_DESCRIPTION("Platform driver for Octeon SOC");