tiocx.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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) 2005 Silicon Graphics, Inc. All rights reserved.
  7. */
  8. #include <linux/module.h>
  9. #include <linux/kernel.h>
  10. #include <linux/slab.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/proc_fs.h>
  13. #include <linux/capability.h>
  14. #include <linux/device.h>
  15. #include <linux/delay.h>
  16. #include <asm/uaccess.h>
  17. #include <asm/sn/sn_sal.h>
  18. #include <asm/sn/addrs.h>
  19. #include <asm/sn/io.h>
  20. #include <asm/sn/types.h>
  21. #include <asm/sn/shubio.h>
  22. #include <asm/sn/tiocx.h>
  23. #include <asm/sn/l1.h>
  24. #include <asm/sn/module.h>
  25. #include "tio.h"
  26. #include "xtalk/xwidgetdev.h"
  27. #include "xtalk/hubdev.h"
  28. #define CX_DEV_NONE 0
  29. #define DEVICE_NAME "tiocx"
  30. #define WIDGET_ID 0
  31. #define TIOCX_DEBUG 0
  32. #if TIOCX_DEBUG
  33. #define DBG(fmt...) printk(KERN_ALERT fmt)
  34. #else
  35. #define DBG(fmt...)
  36. #endif
  37. struct device_attribute dev_attr_cxdev_control;
  38. /**
  39. * tiocx_match - Try to match driver id list with device.
  40. * @dev: device pointer
  41. * @drv: driver pointer
  42. *
  43. * Returns 1 if match, 0 otherwise.
  44. */
  45. static int tiocx_match(struct device *dev, struct device_driver *drv)
  46. {
  47. struct cx_dev *cx_dev = to_cx_dev(dev);
  48. struct cx_drv *cx_drv = to_cx_driver(drv);
  49. const struct cx_device_id *ids = cx_drv->id_table;
  50. if (!ids)
  51. return 0;
  52. while (ids->part_num) {
  53. if (ids->part_num == cx_dev->cx_id.part_num)
  54. return 1;
  55. ids++;
  56. }
  57. return 0;
  58. }
  59. static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
  60. {
  61. return -ENODEV;
  62. }
  63. static void tiocx_bus_release(struct device *dev)
  64. {
  65. kfree(to_cx_dev(dev));
  66. }
  67. /**
  68. * cx_device_match - Find cx_device in the id table.
  69. * @ids: id table from driver
  70. * @cx_device: part/mfg id for the device
  71. *
  72. */
  73. static const struct cx_device_id *cx_device_match(const struct cx_device_id
  74. *ids,
  75. struct cx_dev *cx_device)
  76. {
  77. /*
  78. * NOTES: We may want to check for CX_ANY_ID too.
  79. * Do we want to match against nasid too?
  80. * CX_DEV_NONE == 0, if the driver tries to register for
  81. * part/mfg == 0 we should return no-match (NULL) here.
  82. */
  83. while (ids->part_num && ids->mfg_num) {
  84. if (ids->part_num == cx_device->cx_id.part_num &&
  85. ids->mfg_num == cx_device->cx_id.mfg_num)
  86. return ids;
  87. ids++;
  88. }
  89. return NULL;
  90. }
  91. /**
  92. * cx_device_probe - Look for matching device.
  93. * Call driver probe routine if found.
  94. * @cx_driver: driver table (cx_drv struct) from driver
  95. * @cx_device: part/mfg id for the device
  96. */
  97. static int cx_device_probe(struct device *dev)
  98. {
  99. const struct cx_device_id *id;
  100. struct cx_drv *cx_drv = to_cx_driver(dev->driver);
  101. struct cx_dev *cx_dev = to_cx_dev(dev);
  102. int error = 0;
  103. if (!cx_dev->driver && cx_drv->probe) {
  104. id = cx_device_match(cx_drv->id_table, cx_dev);
  105. if (id) {
  106. if ((error = cx_drv->probe(cx_dev, id)) < 0)
  107. return error;
  108. else
  109. cx_dev->driver = cx_drv;
  110. }
  111. }
  112. return error;
  113. }
  114. /**
  115. * cx_driver_remove - Remove driver from device struct.
  116. * @dev: device
  117. */
  118. static int cx_driver_remove(struct device *dev)
  119. {
  120. struct cx_dev *cx_dev = to_cx_dev(dev);
  121. struct cx_drv *cx_drv = cx_dev->driver;
  122. if (cx_drv->remove)
  123. cx_drv->remove(cx_dev);
  124. cx_dev->driver = NULL;
  125. return 0;
  126. }
  127. struct bus_type tiocx_bus_type = {
  128. .name = "tiocx",
  129. .match = tiocx_match,
  130. .uevent = tiocx_uevent,
  131. .probe = cx_device_probe,
  132. .remove = cx_driver_remove,
  133. };
  134. /**
  135. * cx_driver_register - Register the driver.
  136. * @cx_driver: driver table (cx_drv struct) from driver
  137. *
  138. * Called from the driver init routine to register a driver.
  139. * The cx_drv struct contains the driver name, a pointer to
  140. * a table of part/mfg numbers and a pointer to the driver's
  141. * probe/attach routine.
  142. */
  143. int cx_driver_register(struct cx_drv *cx_driver)
  144. {
  145. cx_driver->driver.name = cx_driver->name;
  146. cx_driver->driver.bus = &tiocx_bus_type;
  147. return driver_register(&cx_driver->driver);
  148. }
  149. /**
  150. * cx_driver_unregister - Unregister the driver.
  151. * @cx_driver: driver table (cx_drv struct) from driver
  152. */
  153. int cx_driver_unregister(struct cx_drv *cx_driver)
  154. {
  155. driver_unregister(&cx_driver->driver);
  156. return 0;
  157. }
  158. /**
  159. * cx_device_register - Register a device.
  160. * @nasid: device's nasid
  161. * @part_num: device's part number
  162. * @mfg_num: device's manufacturer number
  163. * @hubdev: hub info associated with this device
  164. * @bt: board type of the device
  165. *
  166. */
  167. int
  168. cx_device_register(nasid_t nasid, int part_num, int mfg_num,
  169. struct hubdev_info *hubdev, int bt)
  170. {
  171. struct cx_dev *cx_dev;
  172. int r;
  173. cx_dev = kzalloc(sizeof(struct cx_dev), GFP_KERNEL);
  174. DBG("cx_dev= 0x%p\n", cx_dev);
  175. if (cx_dev == NULL)
  176. return -ENOMEM;
  177. cx_dev->cx_id.part_num = part_num;
  178. cx_dev->cx_id.mfg_num = mfg_num;
  179. cx_dev->cx_id.nasid = nasid;
  180. cx_dev->hubdev = hubdev;
  181. cx_dev->bt = bt;
  182. cx_dev->dev.parent = NULL;
  183. cx_dev->dev.bus = &tiocx_bus_type;
  184. cx_dev->dev.release = tiocx_bus_release;
  185. dev_set_name(&cx_dev->dev, "%d", cx_dev->cx_id.nasid);
  186. r = device_register(&cx_dev->dev);
  187. if (r) {
  188. kfree(cx_dev);
  189. return r;
  190. }
  191. get_device(&cx_dev->dev);
  192. device_create_file(&cx_dev->dev, &dev_attr_cxdev_control);
  193. return 0;
  194. }
  195. /**
  196. * cx_device_unregister - Unregister a device.
  197. * @cx_dev: part/mfg id for the device
  198. */
  199. int cx_device_unregister(struct cx_dev *cx_dev)
  200. {
  201. put_device(&cx_dev->dev);
  202. device_unregister(&cx_dev->dev);
  203. return 0;
  204. }
  205. /**
  206. * cx_device_reload - Reload the device.
  207. * @nasid: device's nasid
  208. * @part_num: device's part number
  209. * @mfg_num: device's manufacturer number
  210. *
  211. * Remove the device associated with 'nasid' from device list and then
  212. * call device-register with the given part/mfg numbers.
  213. */
  214. static int cx_device_reload(struct cx_dev *cx_dev)
  215. {
  216. cx_device_unregister(cx_dev);
  217. return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
  218. cx_dev->cx_id.mfg_num, cx_dev->hubdev,
  219. cx_dev->bt);
  220. }
  221. static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget,
  222. u64 sn_irq_info,
  223. int req_irq, nasid_t req_nasid,
  224. int req_slice)
  225. {
  226. struct ia64_sal_retval rv;
  227. rv.status = 0;
  228. rv.v0 = 0;
  229. ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
  230. SAL_INTR_ALLOC, nasid,
  231. widget, sn_irq_info, req_irq,
  232. req_nasid, req_slice);
  233. return rv.status;
  234. }
  235. static inline void tiocx_intr_free(nasid_t nasid, int widget,
  236. struct sn_irq_info *sn_irq_info)
  237. {
  238. struct ia64_sal_retval rv;
  239. rv.status = 0;
  240. rv.v0 = 0;
  241. ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
  242. SAL_INTR_FREE, nasid,
  243. widget, sn_irq_info->irq_irq,
  244. sn_irq_info->irq_cookie, 0, 0);
  245. }
  246. struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
  247. nasid_t req_nasid, int slice)
  248. {
  249. struct sn_irq_info *sn_irq_info;
  250. int status;
  251. int sn_irq_size = sizeof(struct sn_irq_info);
  252. if ((nasid & 1) == 0)
  253. return NULL;
  254. sn_irq_info = kzalloc(sn_irq_size, GFP_KERNEL);
  255. if (sn_irq_info == NULL)
  256. return NULL;
  257. status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq,
  258. req_nasid, slice);
  259. if (status) {
  260. kfree(sn_irq_info);
  261. return NULL;
  262. } else {
  263. return sn_irq_info;
  264. }
  265. }
  266. void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
  267. {
  268. u64 bridge = (u64) sn_irq_info->irq_bridge;
  269. nasid_t nasid = NASID_GET(bridge);
  270. int widget;
  271. if (nasid & 1) {
  272. widget = TIO_SWIN_WIDGETNUM(bridge);
  273. tiocx_intr_free(nasid, widget, sn_irq_info);
  274. kfree(sn_irq_info);
  275. }
  276. }
  277. u64 tiocx_dma_addr(u64 addr)
  278. {
  279. return PHYS_TO_TIODMA(addr);
  280. }
  281. u64 tiocx_swin_base(int nasid)
  282. {
  283. return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
  284. }
  285. EXPORT_SYMBOL(cx_driver_register);
  286. EXPORT_SYMBOL(cx_driver_unregister);
  287. EXPORT_SYMBOL(cx_device_register);
  288. EXPORT_SYMBOL(cx_device_unregister);
  289. EXPORT_SYMBOL(tiocx_irq_alloc);
  290. EXPORT_SYMBOL(tiocx_irq_free);
  291. EXPORT_SYMBOL(tiocx_bus_type);
  292. EXPORT_SYMBOL(tiocx_dma_addr);
  293. EXPORT_SYMBOL(tiocx_swin_base);
  294. static void tio_conveyor_set(nasid_t nasid, int enable_flag)
  295. {
  296. u64 ice_frz;
  297. u64 disable_cb = (1ull << 61);
  298. if (!(nasid & 1))
  299. return;
  300. ice_frz = REMOTE_HUB_L(nasid, TIO_ICE_FRZ_CFG);
  301. if (enable_flag) {
  302. if (!(ice_frz & disable_cb)) /* already enabled */
  303. return;
  304. ice_frz &= ~disable_cb;
  305. } else {
  306. if (ice_frz & disable_cb) /* already disabled */
  307. return;
  308. ice_frz |= disable_cb;
  309. }
  310. DBG(KERN_ALERT "TIO_ICE_FRZ_CFG= 0x%lx\n", ice_frz);
  311. REMOTE_HUB_S(nasid, TIO_ICE_FRZ_CFG, ice_frz);
  312. }
  313. #define tio_conveyor_enable(nasid) tio_conveyor_set(nasid, 1)
  314. #define tio_conveyor_disable(nasid) tio_conveyor_set(nasid, 0)
  315. static void tio_corelet_reset(nasid_t nasid, int corelet)
  316. {
  317. if (!(nasid & 1))
  318. return;
  319. REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 1 << corelet);
  320. udelay(2000);
  321. REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 0);
  322. udelay(2000);
  323. }
  324. static int is_fpga_tio(int nasid, int *bt)
  325. {
  326. u16 uninitialized_var(ioboard_type); /* GCC be quiet */
  327. long rc;
  328. rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
  329. if (rc) {
  330. printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
  331. rc);
  332. return 0;
  333. }
  334. switch (ioboard_type) {
  335. case L1_BRICKTYPE_SA:
  336. case L1_BRICKTYPE_ATHENA:
  337. case L1_BOARDTYPE_DAYTONA:
  338. *bt = ioboard_type;
  339. return 1;
  340. }
  341. return 0;
  342. }
  343. static int bitstream_loaded(nasid_t nasid)
  344. {
  345. u64 cx_credits;
  346. cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
  347. cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
  348. DBG("cx_credits= 0x%lx\n", cx_credits);
  349. return (cx_credits == 0xf) ? 1 : 0;
  350. }
  351. static int tiocx_reload(struct cx_dev *cx_dev)
  352. {
  353. int part_num = CX_DEV_NONE;
  354. int mfg_num = CX_DEV_NONE;
  355. nasid_t nasid = cx_dev->cx_id.nasid;
  356. if (bitstream_loaded(nasid)) {
  357. u64 cx_id;
  358. int rv;
  359. rv = ia64_sn_sysctl_tio_clock_reset(nasid);
  360. if (rv) {
  361. printk(KERN_ALERT "CX port JTAG reset failed.\n");
  362. } else {
  363. cx_id = *(volatile u64 *)
  364. (TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
  365. WIDGET_ID);
  366. part_num = XWIDGET_PART_NUM(cx_id);
  367. mfg_num = XWIDGET_MFG_NUM(cx_id);
  368. DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
  369. /* just ignore it if it's a CE */
  370. if (part_num == TIO_CE_ASIC_PARTNUM)
  371. return 0;
  372. }
  373. }
  374. cx_dev->cx_id.part_num = part_num;
  375. cx_dev->cx_id.mfg_num = mfg_num;
  376. /*
  377. * Delete old device and register the new one. It's ok if
  378. * part_num/mfg_num == CX_DEV_NONE. We want to register
  379. * devices in the table even if a bitstream isn't loaded.
  380. * That allows use to see that a bitstream isn't loaded via
  381. * TIOCX_IOCTL_DEV_LIST.
  382. */
  383. return cx_device_reload(cx_dev);
  384. }
  385. static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf)
  386. {
  387. struct cx_dev *cx_dev = to_cx_dev(dev);
  388. return sprintf(buf, "0x%x 0x%x 0x%x 0x%x\n",
  389. cx_dev->cx_id.nasid,
  390. cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
  391. cx_dev->bt);
  392. }
  393. static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
  394. size_t count)
  395. {
  396. int n;
  397. struct cx_dev *cx_dev = to_cx_dev(dev);
  398. if (!capable(CAP_SYS_ADMIN))
  399. return -EPERM;
  400. if (count <= 0)
  401. return 0;
  402. n = simple_strtoul(buf, NULL, 0);
  403. switch (n) {
  404. case 1:
  405. tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
  406. tiocx_reload(cx_dev);
  407. break;
  408. case 2:
  409. tiocx_reload(cx_dev);
  410. break;
  411. case 3:
  412. tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
  413. break;
  414. default:
  415. break;
  416. }
  417. return count;
  418. }
  419. DEVICE_ATTR(cxdev_control, 0644, show_cxdev_control, store_cxdev_control);
  420. static int __init tiocx_init(void)
  421. {
  422. cnodeid_t cnodeid;
  423. int found_tiocx_device = 0;
  424. if (!ia64_platform_is("sn2"))
  425. return 0;
  426. bus_register(&tiocx_bus_type);
  427. for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
  428. nasid_t nasid;
  429. int bt;
  430. nasid = cnodeid_to_nasid(cnodeid);
  431. if ((nasid & 0x1) && is_fpga_tio(nasid, &bt)) {
  432. struct hubdev_info *hubdev;
  433. struct xwidget_info *widgetp;
  434. DBG("Found TIO at nasid 0x%x\n", nasid);
  435. hubdev =
  436. (struct hubdev_info *)(NODEPDA(cnodeid)->pdinfo);
  437. widgetp = &hubdev->hdi_xwidget_info[TIOCX_CORELET];
  438. /* The CE hangs off of the CX port but is not an FPGA */
  439. if (widgetp->xwi_hwid.part_num == TIO_CE_ASIC_PARTNUM)
  440. continue;
  441. tio_corelet_reset(nasid, TIOCX_CORELET);
  442. tio_conveyor_enable(nasid);
  443. if (cx_device_register
  444. (nasid, widgetp->xwi_hwid.part_num,
  445. widgetp->xwi_hwid.mfg_num, hubdev, bt) < 0)
  446. return -ENXIO;
  447. else
  448. found_tiocx_device++;
  449. }
  450. }
  451. /* It's ok if we find zero devices. */
  452. DBG("found_tiocx_device= %d\n", found_tiocx_device);
  453. return 0;
  454. }
  455. static int cx_remove_device(struct device * dev, void * data)
  456. {
  457. struct cx_dev *cx_dev = to_cx_dev(dev);
  458. device_remove_file(dev, &dev_attr_cxdev_control);
  459. cx_device_unregister(cx_dev);
  460. return 0;
  461. }
  462. static void __exit tiocx_exit(void)
  463. {
  464. DBG("tiocx_exit\n");
  465. /*
  466. * Unregister devices.
  467. */
  468. bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device);
  469. bus_unregister(&tiocx_bus_type);
  470. }
  471. fs_initcall(tiocx_init);
  472. module_exit(tiocx_exit);
  473. /************************************************************************
  474. * Module licensing and description
  475. ************************************************************************/
  476. MODULE_LICENSE("GPL");
  477. MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
  478. MODULE_DESCRIPTION("TIOCX module");
  479. MODULE_SUPPORTED_DEVICE(DEVICE_NAME);