aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorDeng-Cheng Zhu <dengcheng.zhu@imgtec.com>2014-01-01 10:26:46 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-01-22 14:19:02 -0500
commit2c973ef0cc3f981bfb137c3e42e08de5e8f1cc18 (patch)
tree8f15ba20262f53e7465348db0581f16befb130db /arch/mips
parent17a1d523aa5826dec25f2362e1630be365167bda (diff)
MIPS: APRP: Split RTLX support into separate files.
Split the RTLX functionality in preparation for adding support for CMP platforms. Common functions remain in the original file and a new file contains code specific to platforms that do not have a CMP. Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@imgtec.com> Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com> Reviewed-by: Qais Yousef <Qais.Yousef@imgtec.com> Patchwork: http://patchwork.linux-mips.org/patch/6093/ Reviewed-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig5
-rw-r--r--arch/mips/include/asm/rtlx.h43
-rw-r--r--arch/mips/kernel/Makefile1
-rw-r--r--arch/mips/kernel/rtlx-mt.c148
-rw-r--r--arch/mips/kernel/rtlx.c142
5 files changed, 195 insertions, 144 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6395436c0569..ca24da83db4e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1956,6 +1956,11 @@ config MIPS_VPE_APSP_API
1956 depends on MIPS_VPE_LOADER 1956 depends on MIPS_VPE_LOADER
1957 help 1957 help
1958 1958
1959config MIPS_VPE_APSP_API_MT
1960 bool
1961 default "y"
1962 depends on MIPS_VPE_APSP_API && !MIPS_CMP
1963
1959config MIPS_CMP 1964config MIPS_CMP
1960 bool "MIPS CMP support" 1965 bool "MIPS CMP support"
1961 depends on SYS_SUPPORTS_MIPS_CMP && MIPS_MT_SMP 1966 depends on SYS_SUPPORTS_MIPS_CMP && MIPS_MT_SMP
diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h
index 90985b61dbd9..676602649358 100644
--- a/arch/mips/include/asm/rtlx.h
+++ b/arch/mips/include/asm/rtlx.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. 2 * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
3 * 3 * Copyright (C) 2013 Imagination Technologies Ltd.
4 */ 4 */
5 5
6#ifndef __ASM_RTLX_H_ 6#ifndef __ASM_RTLX_H_
@@ -8,6 +8,8 @@
8 8
9#include <irq.h> 9#include <irq.h>
10 10
11#define RTLX_MODULE_NAME "rtlx"
12
11#define LX_NODE_BASE 10 13#define LX_NODE_BASE 10
12 14
13#define MIPS_CPU_RTLX_IRQ 0 15#define MIPS_CPU_RTLX_IRQ 0
@@ -15,18 +17,31 @@
15#define RTLX_VERSION 2 17#define RTLX_VERSION 2
16#define RTLX_xID 0x12345600 18#define RTLX_xID 0x12345600
17#define RTLX_ID (RTLX_xID | RTLX_VERSION) 19#define RTLX_ID (RTLX_xID | RTLX_VERSION)
20#define RTLX_BUFFER_SIZE 2048
18#define RTLX_CHANNELS 8 21#define RTLX_CHANNELS 8
19 22
20#define RTLX_CHANNEL_STDIO 0 23#define RTLX_CHANNEL_STDIO 0
21#define RTLX_CHANNEL_DBG 1 24#define RTLX_CHANNEL_DBG 1
22#define RTLX_CHANNEL_SYSIO 2 25#define RTLX_CHANNEL_SYSIO 2
23 26
24extern int rtlx_open(int index, int can_sleep); 27void rtlx_starting(int vpe);
25extern int rtlx_release(int index); 28void rtlx_stopping(int vpe);
26extern ssize_t rtlx_read(int index, void __user *buff, size_t count); 29
27extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count); 30int rtlx_open(int index, int can_sleep);
28extern unsigned int rtlx_read_poll(int index, int can_sleep); 31int rtlx_release(int index);
29extern unsigned int rtlx_write_poll(int index); 32ssize_t rtlx_read(int index, void __user *buff, size_t count);
33ssize_t rtlx_write(int index, const void __user *buffer, size_t count);
34unsigned int rtlx_read_poll(int index, int can_sleep);
35unsigned int rtlx_write_poll(int index);
36
37int __init rtlx_module_init(void);
38void __exit rtlx_module_exit(void);
39
40void _interrupt_sp(void);
41
42extern struct vpe_notifications rtlx_notify;
43extern const struct file_operations rtlx_fops;
44extern void (*aprp_hook)(void);
30 45
31enum rtlx_state { 46enum rtlx_state {
32 RTLX_STATE_UNUSED = 0, 47 RTLX_STATE_UNUSED = 0,
@@ -35,10 +50,15 @@ enum rtlx_state {
35 RTLX_STATE_OPENED 50 RTLX_STATE_OPENED
36}; 51};
37 52
38#define RTLX_BUFFER_SIZE 2048 53extern struct chan_waitqueues {
54 wait_queue_head_t rt_queue;
55 wait_queue_head_t lx_queue;
56 atomic_t in_open;
57 struct mutex mutex;
58} channel_wqs[RTLX_CHANNELS];
39 59
40/* each channel supports read and write. 60/* each channel supports read and write.
41 linux (vpe0) reads lx_buffer and writes rt_buffer 61 linux (vpe0) reads lx_buffer and writes rt_buffer
42 SP (vpe1) reads rt_buffer and writes lx_buffer 62 SP (vpe1) reads rt_buffer and writes lx_buffer
43*/ 63*/
44struct rtlx_channel { 64struct rtlx_channel {
@@ -55,11 +75,10 @@ struct rtlx_channel {
55 char *lx_buffer; 75 char *lx_buffer;
56}; 76};
57 77
58struct rtlx_info { 78extern struct rtlx_info {
59 unsigned long id; 79 unsigned long id;
60 enum rtlx_state state; 80 enum rtlx_state state;
61 81
62 struct rtlx_channel channel[RTLX_CHANNELS]; 82 struct rtlx_channel channel[RTLX_CHANNELS];
63}; 83} *rtlx;
64
65#endif /* __ASM_RTLX_H_ */ 84#endif /* __ASM_RTLX_H_ */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index e5a73568aa56..3de44d89a046 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
59obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o 59obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
60obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o 60obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o
61obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o 61obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
62obj-$(CONFIG_MIPS_VPE_APSP_API_MT) += rtlx-mt.o
62 63
63obj-$(CONFIG_I8259) += i8259.o 64obj-$(CONFIG_I8259) += i8259.o
64obj-$(CONFIG_IRQ_CPU) += irq_cpu.o 65obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
diff --git a/arch/mips/kernel/rtlx-mt.c b/arch/mips/kernel/rtlx-mt.c
new file mode 100644
index 000000000000..91d61ba422b4
--- /dev/null
+++ b/arch/mips/kernel/rtlx-mt.c
@@ -0,0 +1,148 @@
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 MIPS Technologies, Inc. All rights reserved.
7 * Copyright (C) 2013 Imagination Technologies Ltd.
8 */
9#include <linux/device.h>
10#include <linux/fs.h>
11#include <linux/err.h>
12#include <linux/wait.h>
13#include <linux/sched.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16
17#include <asm/mips_mt.h>
18#include <asm/vpe.h>
19#include <asm/rtlx.h>
20
21static int major;
22
23static void rtlx_dispatch(void)
24{
25 if (read_c0_cause() & read_c0_status() & C_SW0)
26 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
27}
28
29/*
30 * Interrupt handler may be called before rtlx_init has otherwise had
31 * a chance to run.
32 */
33static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
34{
35 unsigned int vpeflags;
36 unsigned long flags;
37 int i;
38
39 /* Ought not to be strictly necessary for SMTC builds */
40 local_irq_save(flags);
41 vpeflags = dvpe();
42 set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ);
43 irq_enable_hazard();
44 evpe(vpeflags);
45 local_irq_restore(flags);
46
47 for (i = 0; i < RTLX_CHANNELS; i++) {
48 wake_up(&channel_wqs[i].lx_queue);
49 wake_up(&channel_wqs[i].rt_queue);
50 }
51
52 return IRQ_HANDLED;
53}
54
55static struct irqaction rtlx_irq = {
56 .handler = rtlx_interrupt,
57 .name = "RTLX",
58};
59
60static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
61
62void _interrupt_sp(void)
63{
64 unsigned long flags;
65
66 local_irq_save(flags);
67 dvpe();
68 settc(1);
69 write_vpe_c0_cause(read_vpe_c0_cause() | C_SW0);
70 evpe(EVPE_ENABLE);
71 local_irq_restore(flags);
72}
73
74int __init rtlx_module_init(void)
75{
76 struct device *dev;
77 int i, err;
78
79 if (!cpu_has_mipsmt) {
80 pr_warn("VPE loader: not a MIPS MT capable processor\n");
81 return -ENODEV;
82 }
83
84 if (aprp_cpu_index() == 0) {
85 pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"
86 "Pass maxtcs=<n> argument as kernel argument\n");
87
88 return -ENODEV;
89 }
90
91 major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);
92 if (major < 0) {
93 pr_err("rtlx_module_init: unable to register device\n");
94 return major;
95 }
96
97 /* initialise the wait queues */
98 for (i = 0; i < RTLX_CHANNELS; i++) {
99 init_waitqueue_head(&channel_wqs[i].rt_queue);
100 init_waitqueue_head(&channel_wqs[i].lx_queue);
101 atomic_set(&channel_wqs[i].in_open, 0);
102 mutex_init(&channel_wqs[i].mutex);
103
104 dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
105 "%s%d", RTLX_MODULE_NAME, i);
106 if (IS_ERR(dev)) {
107 err = PTR_ERR(dev);
108 goto out_chrdev;
109 }
110 }
111
112 /* set up notifiers */
113 rtlx_notify.start = rtlx_starting;
114 rtlx_notify.stop = rtlx_stopping;
115 vpe_notify(aprp_cpu_index(), &rtlx_notify);
116
117 if (cpu_has_vint) {
118 aprp_hook = rtlx_dispatch;
119 } else {
120 pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
121 err = -ENODEV;
122 goto out_class;
123 }
124
125 rtlx_irq.dev_id = rtlx;
126 err = setup_irq(rtlx_irq_num, &rtlx_irq);
127 if (err)
128 goto out_class;
129
130 return 0;
131
132out_class:
133 for (i = 0; i < RTLX_CHANNELS; i++)
134 device_destroy(mt_class, MKDEV(major, i));
135out_chrdev:
136 unregister_chrdev(major, RTLX_MODULE_NAME);
137
138 return err;
139}
140
141void __exit rtlx_module_exit(void)
142{
143 int i;
144
145 for (i = 0; i < RTLX_CHANNELS; i++)
146 device_destroy(mt_class, MKDEV(major, i));
147 unregister_chrdev(major, RTLX_MODULE_NAME);
148}
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 2c12ea1668d1..59db407d0499 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -42,52 +42,12 @@
42#include <asm/rtlx.h> 42#include <asm/rtlx.h>
43#include <asm/setup.h> 43#include <asm/setup.h>
44 44
45static struct rtlx_info *rtlx;
46static int major;
47static char module_name[] = "rtlx";
48
49static struct chan_waitqueues {
50 wait_queue_head_t rt_queue;
51 wait_queue_head_t lx_queue;
52 atomic_t in_open;
53 struct mutex mutex;
54} channel_wqs[RTLX_CHANNELS];
55
56static struct vpe_notifications notify;
57static int sp_stopping; 45static int sp_stopping;
58 46struct rtlx_info *rtlx;
59extern void *vpe_get_shared(int index); 47struct chan_waitqueues channel_wqs[RTLX_CHANNELS];
60 48struct vpe_notifications rtlx_notify;
61static void rtlx_dispatch(void) 49void (*aprp_hook)(void) = NULL;
62{ 50EXPORT_SYMBOL(aprp_hook);
63 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
64}
65
66
67/* Interrupt handler may be called before rtlx_init has otherwise had
68 a chance to run.
69*/
70static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
71{
72 unsigned int vpeflags;
73 unsigned long flags;
74 int i;
75
76 /* Ought not to be strictly necessary for SMTC builds */
77 local_irq_save(flags);
78 vpeflags = dvpe();
79 set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ);
80 irq_enable_hazard();
81 evpe(vpeflags);
82 local_irq_restore(flags);
83
84 for (i = 0; i < RTLX_CHANNELS; i++) {
85 wake_up(&channel_wqs[i].lx_queue);
86 wake_up(&channel_wqs[i].rt_queue);
87 }
88
89 return IRQ_HANDLED;
90}
91 51
92static void __used dump_rtlx(void) 52static void __used dump_rtlx(void)
93{ 53{
@@ -127,7 +87,7 @@ static int rtlx_init(struct rtlx_info *rtlxi)
127} 87}
128 88
129/* notifications */ 89/* notifications */
130static void starting(int vpe) 90void rtlx_starting(int vpe)
131{ 91{
132 int i; 92 int i;
133 sp_stopping = 0; 93 sp_stopping = 0;
@@ -140,7 +100,7 @@ static void starting(int vpe)
140 wake_up_interruptible(&channel_wqs[i].lx_queue); 100 wake_up_interruptible(&channel_wqs[i].lx_queue);
141} 101}
142 102
143static void stopping(int vpe) 103void rtlx_stopping(int vpe)
144{ 104{
145 int i; 105 int i;
146 106
@@ -384,6 +344,8 @@ out:
384 smp_wmb(); 344 smp_wmb();
385 mutex_unlock(&channel_wqs[index].mutex); 345 mutex_unlock(&channel_wqs[index].mutex);
386 346
347 _interrupt_sp();
348
387 return count; 349 return count;
388} 350}
389 351
@@ -454,7 +416,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
454 return rtlx_write(minor, buffer, count); 416 return rtlx_write(minor, buffer, count);
455} 417}
456 418
457static const struct file_operations rtlx_fops = { 419const struct file_operations rtlx_fops = {
458 .owner = THIS_MODULE, 420 .owner = THIS_MODULE,
459 .open = file_open, 421 .open = file_open,
460 .release = file_release, 422 .release = file_release,
@@ -464,90 +426,6 @@ static const struct file_operations rtlx_fops = {
464 .llseek = noop_llseek, 426 .llseek = noop_llseek,
465}; 427};
466 428
467static struct irqaction rtlx_irq = {
468 .handler = rtlx_interrupt,
469 .name = "RTLX",
470};
471
472static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
473
474static char register_chrdev_failed[] __initdata =
475 KERN_ERR "rtlx_module_init: unable to register device\n";
476
477static int __init rtlx_module_init(void)
478{
479 struct device *dev;
480 int i, err;
481
482 if (!cpu_has_mipsmt) {
483 printk("VPE loader: not a MIPS MT capable processor\n");
484 return -ENODEV;
485 }
486
487 if (tclimit == 0) {
488 printk(KERN_WARNING "No TCs reserved for AP/SP, not "
489 "initializing RTLX.\nPass maxtcs=<n> argument as kernel "
490 "argument\n");
491
492 return -ENODEV;
493 }
494
495 major = register_chrdev(0, module_name, &rtlx_fops);
496 if (major < 0) {
497 printk(register_chrdev_failed);
498 return major;
499 }
500
501 /* initialise the wait queues */
502 for (i = 0; i < RTLX_CHANNELS; i++) {
503 init_waitqueue_head(&channel_wqs[i].rt_queue);
504 init_waitqueue_head(&channel_wqs[i].lx_queue);
505 atomic_set(&channel_wqs[i].in_open, 0);
506 mutex_init(&channel_wqs[i].mutex);
507
508 dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
509 "%s%d", module_name, i);
510 if (IS_ERR(dev)) {
511 err = PTR_ERR(dev);
512 goto out_chrdev;
513 }
514 }
515
516 /* set up notifiers */
517 notify.start = starting;
518 notify.stop = stopping;
519 vpe_notify(tclimit, &notify);
520
521 if (cpu_has_vint)
522 set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
523 else {
524 pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
525 err = -ENODEV;
526 goto out_chrdev;
527 }
528
529 rtlx_irq.dev_id = rtlx;
530 setup_irq(rtlx_irq_num, &rtlx_irq);
531
532 return 0;
533
534out_chrdev:
535 for (i = 0; i < RTLX_CHANNELS; i++)
536 device_destroy(mt_class, MKDEV(major, i));
537
538 return err;
539}
540
541static void __exit rtlx_module_exit(void)
542{
543 int i;
544
545 for (i = 0; i < RTLX_CHANNELS; i++)
546 device_destroy(mt_class, MKDEV(major, i));
547
548 unregister_chrdev(major, module_name);
549}
550
551module_init(rtlx_module_init); 429module_init(rtlx_module_init);
552module_exit(rtlx_module_exit); 430module_exit(rtlx_module_exit);
553 431