device-init.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * PS3 device registration routines.
  3. *
  4. * Copyright (C) 2007 Sony Computer Entertainment Inc.
  5. * Copyright 2007 Sony Corp.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <linux/delay.h>
  21. #include <linux/freezer.h>
  22. #include <linux/kernel.h>
  23. #include <linux/kthread.h>
  24. #include <linux/init.h>
  25. #include <asm/firmware.h>
  26. #include <asm/lv1call.h>
  27. #include "platform.h"
  28. /**
  29. * ps3_setup_gelic_device - Setup and register a gelic device instance.
  30. *
  31. * Allocates memory for a struct ps3_system_bus_device instance, initialises the
  32. * structure members, and registers the device instance with the system bus.
  33. */
  34. static int __init ps3_setup_gelic_device(
  35. const struct ps3_repository_device *repo)
  36. {
  37. int result;
  38. struct layout {
  39. struct ps3_system_bus_device dev;
  40. struct ps3_dma_region d_region;
  41. } *p;
  42. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  43. BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
  44. BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
  45. p = kzalloc(sizeof(struct layout), GFP_KERNEL);
  46. if (!p) {
  47. result = -ENOMEM;
  48. goto fail_malloc;
  49. }
  50. p->dev.match_id = PS3_MATCH_ID_GELIC;
  51. p->dev.dev_type = PS3_DEVICE_TYPE_SB;
  52. p->dev.bus_id = repo->bus_id;
  53. p->dev.dev_id = repo->dev_id;
  54. p->dev.d_region = &p->d_region;
  55. result = ps3_repository_find_interrupt(repo,
  56. PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
  57. if (result) {
  58. pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
  59. __func__, __LINE__);
  60. goto fail_find_interrupt;
  61. }
  62. BUG_ON(p->dev.interrupt_id != 0);
  63. result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
  64. PS3_DMA_OTHER, NULL, 0);
  65. if (result) {
  66. pr_debug("%s:%d ps3_dma_region_init failed\n",
  67. __func__, __LINE__);
  68. goto fail_dma_init;
  69. }
  70. result = ps3_system_bus_device_register(&p->dev);
  71. if (result) {
  72. pr_debug("%s:%d ps3_system_bus_device_register failed\n",
  73. __func__, __LINE__);
  74. goto fail_device_register;
  75. }
  76. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  77. return result;
  78. fail_device_register:
  79. fail_dma_init:
  80. fail_find_interrupt:
  81. kfree(p);
  82. fail_malloc:
  83. pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
  84. return result;
  85. }
  86. static int __init_refok ps3_setup_uhc_device(
  87. const struct ps3_repository_device *repo, enum ps3_match_id match_id,
  88. enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
  89. {
  90. int result;
  91. struct layout {
  92. struct ps3_system_bus_device dev;
  93. struct ps3_dma_region d_region;
  94. struct ps3_mmio_region m_region;
  95. } *p;
  96. u64 bus_addr;
  97. u64 len;
  98. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  99. BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
  100. BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
  101. p = kzalloc(sizeof(struct layout), GFP_KERNEL);
  102. if (!p) {
  103. result = -ENOMEM;
  104. goto fail_malloc;
  105. }
  106. p->dev.match_id = match_id;
  107. p->dev.dev_type = PS3_DEVICE_TYPE_SB;
  108. p->dev.bus_id = repo->bus_id;
  109. p->dev.dev_id = repo->dev_id;
  110. p->dev.d_region = &p->d_region;
  111. p->dev.m_region = &p->m_region;
  112. result = ps3_repository_find_interrupt(repo,
  113. interrupt_type, &p->dev.interrupt_id);
  114. if (result) {
  115. pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
  116. __func__, __LINE__);
  117. goto fail_find_interrupt;
  118. }
  119. result = ps3_repository_find_reg(repo, reg_type,
  120. &bus_addr, &len);
  121. if (result) {
  122. pr_debug("%s:%d ps3_repository_find_reg failed\n",
  123. __func__, __LINE__);
  124. goto fail_find_reg;
  125. }
  126. result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
  127. PS3_DMA_INTERNAL, NULL, 0);
  128. if (result) {
  129. pr_debug("%s:%d ps3_dma_region_init failed\n",
  130. __func__, __LINE__);
  131. goto fail_dma_init;
  132. }
  133. result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
  134. PS3_MMIO_4K);
  135. if (result) {
  136. pr_debug("%s:%d ps3_mmio_region_init failed\n",
  137. __func__, __LINE__);
  138. goto fail_mmio_init;
  139. }
  140. result = ps3_system_bus_device_register(&p->dev);
  141. if (result) {
  142. pr_debug("%s:%d ps3_system_bus_device_register failed\n",
  143. __func__, __LINE__);
  144. goto fail_device_register;
  145. }
  146. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  147. return result;
  148. fail_device_register:
  149. fail_mmio_init:
  150. fail_dma_init:
  151. fail_find_reg:
  152. fail_find_interrupt:
  153. kfree(p);
  154. fail_malloc:
  155. pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
  156. return result;
  157. }
  158. static int __init ps3_setup_ehci_device(
  159. const struct ps3_repository_device *repo)
  160. {
  161. return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
  162. PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
  163. }
  164. static int __init ps3_setup_ohci_device(
  165. const struct ps3_repository_device *repo)
  166. {
  167. return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
  168. PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
  169. }
  170. static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
  171. unsigned int port_number)
  172. {
  173. int result;
  174. struct layout {
  175. struct ps3_system_bus_device dev;
  176. } *p;
  177. pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
  178. match_id, port_number);
  179. p = kzalloc(sizeof(struct layout), GFP_KERNEL);
  180. if (!p)
  181. return -ENOMEM;
  182. p->dev.match_id = match_id;
  183. p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
  184. p->dev.port_number = port_number;
  185. result = ps3_system_bus_device_register(&p->dev);
  186. if (result)
  187. pr_debug("%s:%d ps3_system_bus_device_register failed\n",
  188. __func__, __LINE__);
  189. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  190. return result;
  191. }
  192. static int __init ps3_register_vuart_devices(void)
  193. {
  194. int result;
  195. unsigned int port_number;
  196. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  197. result = ps3_repository_read_vuart_av_port(&port_number);
  198. if (result)
  199. port_number = 0; /* av default */
  200. result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
  201. WARN_ON(result);
  202. result = ps3_repository_read_vuart_sysmgr_port(&port_number);
  203. if (result)
  204. port_number = 2; /* sysmgr default */
  205. result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
  206. port_number);
  207. WARN_ON(result);
  208. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  209. return result;
  210. }
  211. static int __init ps3_register_sound_devices(void)
  212. {
  213. int result;
  214. struct layout {
  215. struct ps3_system_bus_device dev;
  216. struct ps3_dma_region d_region;
  217. struct ps3_mmio_region m_region;
  218. } *p;
  219. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  220. p = kzalloc(sizeof(*p), GFP_KERNEL);
  221. if (!p)
  222. return -ENOMEM;
  223. p->dev.match_id = PS3_MATCH_ID_SOUND;
  224. p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
  225. p->dev.d_region = &p->d_region;
  226. p->dev.m_region = &p->m_region;
  227. result = ps3_system_bus_device_register(&p->dev);
  228. if (result)
  229. pr_debug("%s:%d ps3_system_bus_device_register failed\n",
  230. __func__, __LINE__);
  231. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  232. return result;
  233. }
  234. static int __init ps3_register_graphics_devices(void)
  235. {
  236. int result;
  237. struct layout {
  238. struct ps3_system_bus_device dev;
  239. } *p;
  240. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  241. p = kzalloc(sizeof(struct layout), GFP_KERNEL);
  242. if (!p)
  243. return -ENOMEM;
  244. p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
  245. p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
  246. result = ps3_system_bus_device_register(&p->dev);
  247. if (result)
  248. pr_debug("%s:%d ps3_system_bus_device_register failed\n",
  249. __func__, __LINE__);
  250. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  251. return result;
  252. }
  253. /**
  254. * ps3_register_repository_device - Register a device from the repositiory info.
  255. *
  256. */
  257. static int ps3_register_repository_device(
  258. const struct ps3_repository_device *repo)
  259. {
  260. int result;
  261. switch (repo->dev_type) {
  262. case PS3_DEV_TYPE_SB_GELIC:
  263. result = ps3_setup_gelic_device(repo);
  264. if (result) {
  265. pr_debug("%s:%d ps3_setup_gelic_device failed\n",
  266. __func__, __LINE__);
  267. }
  268. break;
  269. case PS3_DEV_TYPE_SB_USB:
  270. /* Each USB device has both an EHCI and an OHCI HC */
  271. result = ps3_setup_ehci_device(repo);
  272. if (result) {
  273. pr_debug("%s:%d ps3_setup_ehci_device failed\n",
  274. __func__, __LINE__);
  275. }
  276. result = ps3_setup_ohci_device(repo);
  277. if (result) {
  278. pr_debug("%s:%d ps3_setup_ohci_device failed\n",
  279. __func__, __LINE__);
  280. }
  281. break;
  282. default:
  283. result = 0;
  284. pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
  285. repo->dev_type);
  286. }
  287. return result;
  288. }
  289. /**
  290. * ps3_probe_thread - Background repository probing at system startup.
  291. *
  292. * This implementation only supports background probing on a single bus.
  293. */
  294. static int ps3_probe_thread(void *data)
  295. {
  296. struct ps3_repository_device *repo = data;
  297. int result;
  298. unsigned int ms = 250;
  299. pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
  300. do {
  301. try_to_freeze();
  302. pr_debug("%s:%u: probing...\n", __func__, __LINE__);
  303. do {
  304. result = ps3_repository_find_device(repo);
  305. if (result == -ENODEV)
  306. pr_debug("%s:%u: nothing new\n", __func__,
  307. __LINE__);
  308. else if (result)
  309. pr_debug("%s:%u: find device error.\n",
  310. __func__, __LINE__);
  311. else {
  312. pr_debug("%s:%u: found device\n", __func__,
  313. __LINE__);
  314. ps3_register_repository_device(repo);
  315. ps3_repository_bump_device(repo);
  316. ms = 250;
  317. }
  318. } while (!result);
  319. pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
  320. if ( ms > 60000)
  321. break;
  322. msleep_interruptible(ms);
  323. /* An exponential backoff. */
  324. ms <<= 1;
  325. } while (!kthread_should_stop());
  326. pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
  327. return 0;
  328. }
  329. /**
  330. * ps3_start_probe_thread - Starts the background probe thread.
  331. *
  332. */
  333. static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
  334. {
  335. int result;
  336. struct task_struct *task;
  337. static struct ps3_repository_device repo; /* must be static */
  338. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  339. memset(&repo, 0, sizeof(repo));
  340. repo.bus_type = bus_type;
  341. result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
  342. if (result) {
  343. printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
  344. return -ENODEV;
  345. }
  346. result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
  347. if (result) {
  348. printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
  349. result);
  350. return -ENODEV;
  351. }
  352. task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
  353. if (IS_ERR(task)) {
  354. result = PTR_ERR(task);
  355. printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
  356. result);
  357. return result;
  358. }
  359. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  360. return 0;
  361. }
  362. /**
  363. * ps3_register_devices - Probe the system and register devices found.
  364. *
  365. * A device_initcall() routine.
  366. */
  367. static int __init ps3_register_devices(void)
  368. {
  369. int result;
  370. if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
  371. return -ENODEV;
  372. pr_debug(" -> %s:%d\n", __func__, __LINE__);
  373. /* ps3_repository_dump_bus_info(); */
  374. result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
  375. ps3_register_vuart_devices();
  376. ps3_register_graphics_devices();
  377. ps3_repository_find_devices(PS3_BUS_TYPE_SB,
  378. ps3_register_repository_device);
  379. ps3_register_sound_devices();
  380. pr_debug(" <- %s:%d\n", __func__, __LINE__);
  381. return 0;
  382. }
  383. device_initcall(ps3_register_devices);