9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
14 #include <linux/capability.h>
15 #include <linux/device.h>
17 #include <asm/uaccess.h>
19 #include <asm/sn/addrs.h>
20 #include <asm/sn/io.h>
21 #include <asm/sn/types.h>
31 #define DEVICE_NAME "tiocx"
36 #define DBG(fmt...) printk(KERN_ALERT fmt)
52 struct cx_dev *cx_dev = to_cx_dev(dev);
53 struct cx_drv *cx_drv = to_cx_driver(drv);
54 const struct cx_device_id *ids = cx_drv->id_table;
59 while (ids->part_num) {
60 if (ids->part_num == cx_dev->cx_id.part_num)
73 static void tiocx_bus_release(
struct device *dev)
75 kfree(to_cx_dev(dev));
84 static const struct cx_device_id *cx_device_match(
const struct cx_device_id
86 struct cx_dev *cx_device)
94 while (ids->part_num && ids->mfg_num) {
95 if (ids->part_num == cx_device->cx_id.part_num &&
96 ids->mfg_num == cx_device->cx_id.mfg_num)
110 static int cx_device_probe(
struct device *dev)
112 const struct cx_device_id *
id;
113 struct cx_drv *cx_drv = to_cx_driver(dev->
driver);
114 struct cx_dev *cx_dev = to_cx_dev(dev);
117 if (!cx_dev->driver && cx_drv->probe) {
118 id = cx_device_match(cx_drv->id_table, cx_dev);
120 if ((error = cx_drv->probe(cx_dev,
id)) < 0)
123 cx_dev->driver = cx_drv;
134 static int cx_driver_remove(
struct device *dev)
136 struct cx_dev *cx_dev = to_cx_dev(dev);
137 struct cx_drv *cx_drv = cx_dev->driver;
139 cx_drv->remove(cx_dev);
140 cx_dev->driver =
NULL;
146 .match = tiocx_match,
147 .uevent = tiocx_uevent,
148 .probe = cx_device_probe,
149 .remove = cx_driver_remove,
163 cx_driver->driver.name = cx_driver->name;
192 struct cx_dev *cx_dev;
195 cx_dev = kzalloc(
sizeof(
struct cx_dev),
GFP_KERNEL);
196 DBG(
"cx_dev= 0x%p\n", cx_dev);
200 cx_dev->cx_id.part_num = part_num;
201 cx_dev->cx_id.mfg_num = mfg_num;
202 cx_dev->cx_id.nasid = nasid;
203 cx_dev->hubdev = hubdev;
206 cx_dev->dev.parent =
NULL;
208 cx_dev->dev.release = tiocx_bus_release;
242 static int cx_device_reload(
struct cx_dev *cx_dev)
246 cx_dev->cx_id.mfg_num, cx_dev->hubdev,
250 static inline u64 tiocx_intr_alloc(
nasid_t nasid,
int widget,
252 int req_irq,
nasid_t req_nasid,
261 widget, sn_irq_info, req_irq,
262 req_nasid, req_slice);
266 static inline void tiocx_intr_free(
nasid_t nasid,
int widget,
284 int sn_irq_size =
sizeof(
struct sn_irq_info);
286 if ((nasid & 1) == 0)
289 sn_irq_info = kzalloc(sn_irq_size,
GFP_KERNEL);
290 if (sn_irq_info ==
NULL)
293 status = tiocx_intr_alloc(nasid, widget,
__pa(sn_irq_info), irq,
311 tiocx_intr_free(nasid, widget, sn_irq_info);
336 static void tio_conveyor_set(
nasid_t nasid,
int enable_flag)
339 u64 disable_cb = (1ull << 61);
346 if (!(ice_frz & disable_cb))
348 ice_frz &= ~disable_cb;
350 if (ice_frz & disable_cb)
352 ice_frz |= disable_cb;
358 #define tio_conveyor_enable(nasid) tio_conveyor_set(nasid, 1)
359 #define tio_conveyor_disable(nasid) tio_conveyor_set(nasid, 0)
361 static void tio_corelet_reset(
nasid_t nasid,
int corelet)
372 static int is_fpga_tio(
int nasid,
int *
bt)
377 rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
384 switch (ioboard_type) {
395 static int bitstream_loaded(
nasid_t nasid)
399 cx_credits =
REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
400 cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
401 DBG(
"cx_credits= 0x%lx\n", cx_credits);
403 return (cx_credits == 0xf) ? 1 : 0;
406 static int tiocx_reload(
struct cx_dev *cx_dev)
410 nasid_t nasid = cx_dev->cx_id.nasid;
412 if (bitstream_loaded(nasid)) {
416 rv = ia64_sn_sysctl_tio_clock_reset(nasid);
420 cx_id = *(
volatile u64 *)
425 DBG(
"part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
427 if (part_num == TIO_CE_ASIC_PARTNUM)
432 cx_dev->cx_id.part_num = part_num;
433 cx_dev->cx_id.mfg_num = mfg_num;
442 return cx_device_reload(cx_dev);
447 struct cx_dev *cx_dev = to_cx_dev(dev);
449 return sprintf(buf,
"0x%x 0x%x 0x%x 0x%x\n",
451 cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
459 struct cx_dev *cx_dev = to_cx_dev(dev);
471 tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
472 tiocx_reload(cx_dev);
475 tiocx_reload(cx_dev);
478 tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
487 DEVICE_ATTR(cxdev_control, 0644, show_cxdev_control, store_cxdev_control);
489 static int __init tiocx_init(
void)
492 int found_tiocx_device = 0;
499 for (cnodeid = 0; cnodeid <
num_cnodes; cnodeid++) {
505 if ((nasid & 0x1) && is_fpga_tio(nasid, &bt)) {
509 DBG(
"Found TIO at nasid 0x%x\n", nasid);
517 if (widgetp->
xwi_hwid.part_num == TIO_CE_ASIC_PARTNUM)
520 tio_corelet_reset(nasid, TIOCX_CORELET);
525 widgetp->
xwi_hwid.mfg_num, hubdev, bt) < 0)
528 found_tiocx_device++;
533 DBG(
"found_tiocx_device= %d\n", found_tiocx_device);
538 static int cx_remove_device(
struct device * dev,
void *
data)
540 struct cx_dev *cx_dev = to_cx_dev(dev);
546 static void __exit tiocx_exit(
void)