0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/fs.h>
0011 #include <linux/err.h>
0012 #include <linux/wait.h>
0013 #include <linux/sched.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irq.h>
0016
0017 #include <asm/mips_mt.h>
0018 #include <asm/vpe.h>
0019 #include <asm/rtlx.h>
0020
0021 static int major;
0022
0023 static void rtlx_dispatch(void)
0024 {
0025 if (read_c0_cause() & read_c0_status() & C_SW0)
0026 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
0027 }
0028
0029
0030
0031
0032
0033 static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
0034 {
0035 unsigned int vpeflags;
0036 unsigned long flags;
0037 int i;
0038
0039 local_irq_save(flags);
0040 vpeflags = dvpe();
0041 set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ);
0042 irq_enable_hazard();
0043 evpe(vpeflags);
0044 local_irq_restore(flags);
0045
0046 for (i = 0; i < RTLX_CHANNELS; i++) {
0047 wake_up(&channel_wqs[i].lx_queue);
0048 wake_up(&channel_wqs[i].rt_queue);
0049 }
0050
0051 return IRQ_HANDLED;
0052 }
0053
0054 static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
0055
0056 void _interrupt_sp(void)
0057 {
0058 unsigned long flags;
0059
0060 local_irq_save(flags);
0061 dvpe();
0062 settc(1);
0063 write_vpe_c0_cause(read_vpe_c0_cause() | C_SW0);
0064 evpe(EVPE_ENABLE);
0065 local_irq_restore(flags);
0066 }
0067
0068 int __init rtlx_module_init(void)
0069 {
0070 struct device *dev;
0071 int i, err;
0072
0073 if (!cpu_has_mipsmt) {
0074 pr_warn("VPE loader: not a MIPS MT capable processor\n");
0075 return -ENODEV;
0076 }
0077
0078 if (aprp_cpu_index() == 0) {
0079 pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"
0080 "Pass maxtcs=<n> argument as kernel argument\n");
0081
0082 return -ENODEV;
0083 }
0084
0085 major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);
0086 if (major < 0) {
0087 pr_err("rtlx_module_init: unable to register device\n");
0088 return major;
0089 }
0090
0091
0092 for (i = 0; i < RTLX_CHANNELS; i++) {
0093 init_waitqueue_head(&channel_wqs[i].rt_queue);
0094 init_waitqueue_head(&channel_wqs[i].lx_queue);
0095 atomic_set(&channel_wqs[i].in_open, 0);
0096 mutex_init(&channel_wqs[i].mutex);
0097
0098 dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
0099 "%s%d", RTLX_MODULE_NAME, i);
0100 if (IS_ERR(dev)) {
0101 while (i--)
0102 device_destroy(mt_class, MKDEV(major, i));
0103
0104 err = PTR_ERR(dev);
0105 goto out_chrdev;
0106 }
0107 }
0108
0109
0110 rtlx_notify.start = rtlx_starting;
0111 rtlx_notify.stop = rtlx_stopping;
0112 vpe_notify(aprp_cpu_index(), &rtlx_notify);
0113
0114 if (cpu_has_vint) {
0115 aprp_hook = rtlx_dispatch;
0116 } else {
0117 pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
0118 err = -ENODEV;
0119 goto out_class;
0120 }
0121
0122 err = request_irq(rtlx_irq_num, rtlx_interrupt, 0, "RTLX", rtlx);
0123 if (err)
0124 goto out_class;
0125
0126 return 0;
0127
0128 out_class:
0129 for (i = 0; i < RTLX_CHANNELS; i++)
0130 device_destroy(mt_class, MKDEV(major, i));
0131 out_chrdev:
0132 unregister_chrdev(major, RTLX_MODULE_NAME);
0133
0134 return err;
0135 }
0136
0137 void __exit rtlx_module_exit(void)
0138 {
0139 int i;
0140
0141 for (i = 0; i < RTLX_CHANNELS; i++)
0142 device_destroy(mt_class, MKDEV(major, i));
0143
0144 unregister_chrdev(major, RTLX_MODULE_NAME);
0145
0146 aprp_hook = NULL;
0147 }