octeon-platform.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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-2009 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/dma-mapping.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <asm/octeon/octeon.h>
  16. #include <asm/octeon/cvmx-rnm-defs.h>
  17. static struct octeon_cf_data octeon_cf_data;
  18. static int __init octeon_cf_device_init(void)
  19. {
  20. union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
  21. unsigned long base_ptr, region_base, region_size;
  22. struct platform_device *pd;
  23. struct resource cf_resources[3];
  24. unsigned int num_resources;
  25. int i;
  26. int ret = 0;
  27. /* Setup octeon-cf platform device if present. */
  28. base_ptr = 0;
  29. if (octeon_bootinfo->major_version == 1
  30. && octeon_bootinfo->minor_version >= 1) {
  31. if (octeon_bootinfo->compact_flash_common_base_addr)
  32. base_ptr =
  33. octeon_bootinfo->compact_flash_common_base_addr;
  34. } else {
  35. base_ptr = 0x1d000800;
  36. }
  37. if (!base_ptr)
  38. return ret;
  39. /* Find CS0 region. */
  40. for (i = 0; i < 8; i++) {
  41. mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i));
  42. region_base = mio_boot_reg_cfg.s.base << 16;
  43. region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
  44. if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
  45. && base_ptr < region_base + region_size)
  46. break;
  47. }
  48. if (i >= 7) {
  49. /* i and i + 1 are CS0 and CS1, both must be less than 8. */
  50. goto out;
  51. }
  52. octeon_cf_data.base_region = i;
  53. octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width;
  54. octeon_cf_data.base_region_bias = base_ptr - region_base;
  55. memset(cf_resources, 0, sizeof(cf_resources));
  56. num_resources = 0;
  57. cf_resources[num_resources].flags = IORESOURCE_MEM;
  58. cf_resources[num_resources].start = region_base;
  59. cf_resources[num_resources].end = region_base + region_size - 1;
  60. num_resources++;
  61. if (!(base_ptr & 0xfffful)) {
  62. /*
  63. * Boot loader signals availability of DMA (true_ide
  64. * mode) by setting low order bits of base_ptr to
  65. * zero.
  66. */
  67. /* Asume that CS1 immediately follows. */
  68. mio_boot_reg_cfg.u64 =
  69. cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1));
  70. region_base = mio_boot_reg_cfg.s.base << 16;
  71. region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
  72. if (!mio_boot_reg_cfg.s.en)
  73. goto out;
  74. cf_resources[num_resources].flags = IORESOURCE_MEM;
  75. cf_resources[num_resources].start = region_base;
  76. cf_resources[num_resources].end = region_base + region_size - 1;
  77. num_resources++;
  78. octeon_cf_data.dma_engine = 0;
  79. cf_resources[num_resources].flags = IORESOURCE_IRQ;
  80. cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA;
  81. cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA;
  82. num_resources++;
  83. } else {
  84. octeon_cf_data.dma_engine = -1;
  85. }
  86. pd = platform_device_alloc("pata_octeon_cf", -1);
  87. if (!pd) {
  88. ret = -ENOMEM;
  89. goto out;
  90. }
  91. pd->dev.platform_data = &octeon_cf_data;
  92. ret = platform_device_add_resources(pd, cf_resources, num_resources);
  93. if (ret)
  94. goto fail;
  95. ret = platform_device_add(pd);
  96. if (ret)
  97. goto fail;
  98. return ret;
  99. fail:
  100. platform_device_put(pd);
  101. out:
  102. return ret;
  103. }
  104. device_initcall(octeon_cf_device_init);
  105. /* Octeon Random Number Generator. */
  106. static int __init octeon_rng_device_init(void)
  107. {
  108. struct platform_device *pd;
  109. int ret = 0;
  110. struct resource rng_resources[] = {
  111. {
  112. .flags = IORESOURCE_MEM,
  113. .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
  114. .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
  115. }, {
  116. .flags = IORESOURCE_MEM,
  117. .start = cvmx_build_io_address(8, 0),
  118. .end = cvmx_build_io_address(8, 0) + 0x7
  119. }
  120. };
  121. pd = platform_device_alloc("octeon_rng", -1);
  122. if (!pd) {
  123. ret = -ENOMEM;
  124. goto out;
  125. }
  126. ret = platform_device_add_resources(pd, rng_resources,
  127. ARRAY_SIZE(rng_resources));
  128. if (ret)
  129. goto fail;
  130. ret = platform_device_add(pd);
  131. if (ret)
  132. goto fail;
  133. return ret;
  134. fail:
  135. platform_device_put(pd);
  136. out:
  137. return ret;
  138. }
  139. device_initcall(octeon_rng_device_init);
  140. static struct i2c_board_info __initdata octeon_i2c_devices[] = {
  141. {
  142. I2C_BOARD_INFO("ds1337", 0x68),
  143. },
  144. };
  145. static int __init octeon_i2c_devices_init(void)
  146. {
  147. return i2c_register_board_info(0, octeon_i2c_devices,
  148. ARRAY_SIZE(octeon_i2c_devices));
  149. }
  150. arch_initcall(octeon_i2c_devices_init);
  151. #define OCTEON_I2C_IO_BASE 0x1180000001000ull
  152. #define OCTEON_I2C_IO_UNIT_OFFSET 0x200
  153. static struct octeon_i2c_data octeon_i2c_data[2];
  154. static int __init octeon_i2c_device_init(void)
  155. {
  156. struct platform_device *pd;
  157. int ret = 0;
  158. int port, num_ports;
  159. struct resource i2c_resources[] = {
  160. {
  161. .flags = IORESOURCE_MEM,
  162. }, {
  163. .flags = IORESOURCE_IRQ,
  164. }
  165. };
  166. if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
  167. num_ports = 2;
  168. else
  169. num_ports = 1;
  170. for (port = 0; port < num_ports; port++) {
  171. octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate();
  172. /*FIXME: should be examined. At the moment is set for 100Khz */
  173. octeon_i2c_data[port].i2c_freq = 100000;
  174. pd = platform_device_alloc("i2c-octeon", port);
  175. if (!pd) {
  176. ret = -ENOMEM;
  177. goto out;
  178. }
  179. pd->dev.platform_data = octeon_i2c_data + port;
  180. i2c_resources[0].start =
  181. OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
  182. i2c_resources[0].end = i2c_resources[0].start + 0x1f;
  183. switch (port) {
  184. case 0:
  185. i2c_resources[1].start = OCTEON_IRQ_TWSI;
  186. i2c_resources[1].end = OCTEON_IRQ_TWSI;
  187. break;
  188. case 1:
  189. i2c_resources[1].start = OCTEON_IRQ_TWSI2;
  190. i2c_resources[1].end = OCTEON_IRQ_TWSI2;
  191. break;
  192. default:
  193. BUG();
  194. }
  195. ret = platform_device_add_resources(pd,
  196. i2c_resources,
  197. ARRAY_SIZE(i2c_resources));
  198. if (ret)
  199. goto fail;
  200. ret = platform_device_add(pd);
  201. if (ret)
  202. goto fail;
  203. }
  204. return ret;
  205. fail:
  206. platform_device_put(pd);
  207. out:
  208. return ret;
  209. }
  210. device_initcall(octeon_i2c_device_init);
  211. /* Octeon SMI/MDIO interface. */
  212. static int __init octeon_mdiobus_device_init(void)
  213. {
  214. struct platform_device *pd;
  215. int ret = 0;
  216. if (octeon_is_simulation())
  217. return 0; /* No mdio in the simulator. */
  218. /* The bus number is the platform_device id. */
  219. pd = platform_device_alloc("mdio-octeon", 0);
  220. if (!pd) {
  221. ret = -ENOMEM;
  222. goto out;
  223. }
  224. ret = platform_device_add(pd);
  225. if (ret)
  226. goto fail;
  227. return ret;
  228. fail:
  229. platform_device_put(pd);
  230. out:
  231. return ret;
  232. }
  233. device_initcall(octeon_mdiobus_device_init);
  234. /* Octeon mgmt port Ethernet interface. */
  235. static int __init octeon_mgmt_device_init(void)
  236. {
  237. struct platform_device *pd;
  238. int ret = 0;
  239. int port, num_ports;
  240. struct resource mgmt_port_resource = {
  241. .flags = IORESOURCE_IRQ,
  242. .start = -1,
  243. .end = -1
  244. };
  245. if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
  246. return 0;
  247. if (OCTEON_IS_MODEL(OCTEON_CN56XX))
  248. num_ports = 1;
  249. else
  250. num_ports = 2;
  251. for (port = 0; port < num_ports; port++) {
  252. pd = platform_device_alloc("octeon_mgmt", port);
  253. if (!pd) {
  254. ret = -ENOMEM;
  255. goto out;
  256. }
  257. /* No DMA restrictions */
  258. pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
  259. pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
  260. switch (port) {
  261. case 0:
  262. mgmt_port_resource.start = OCTEON_IRQ_MII0;
  263. break;
  264. case 1:
  265. mgmt_port_resource.start = OCTEON_IRQ_MII1;
  266. break;
  267. default:
  268. BUG();
  269. }
  270. mgmt_port_resource.end = mgmt_port_resource.start;
  271. ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
  272. if (ret)
  273. goto fail;
  274. ret = platform_device_add(pd);
  275. if (ret)
  276. goto fail;
  277. }
  278. return ret;
  279. fail:
  280. platform_device_put(pd);
  281. out:
  282. return ret;
  283. }
  284. device_initcall(octeon_mgmt_device_init);
  285. MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
  286. MODULE_LICENSE("GPL");
  287. MODULE_DESCRIPTION("Platform driver for Octeon SOC");