octeon-platform.c 7.4 KB

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